diff options
author | Joey Hess <joeyh@joeyh.name> | 2021-01-11 21:52:32 -0400 |
---|---|---|
committer | Joey Hess <joeyh@joeyh.name> | 2021-01-11 21:52:32 -0400 |
commit | ad48349741384ed0e49fab9cf13ac7f90aba0dd1 (patch) | |
tree | 6b8c894ce1057d069f89e7209c266f00ea43ec66 /Utility/MoveFile.hs | |
parent | b3e72e94efbce652f25fb99d6c6ace8beb2a52d4 (diff) | |
download | git-repair-ad48349741384ed0e49fab9cf13ac7f90aba0dd1.tar.gz |
Merge from git-annex.
Diffstat (limited to 'Utility/MoveFile.hs')
-rw-r--r-- | Utility/MoveFile.hs | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/Utility/MoveFile.hs b/Utility/MoveFile.hs new file mode 100644 index 0000000..3ea17e8 --- /dev/null +++ b/Utility/MoveFile.hs @@ -0,0 +1,74 @@ +{- moving files + - + - Copyright 2011-2020 Joey Hess <id@joeyh.name> + - + - License: BSD-2-clause + -} + +{-# LANGUAGE CPP #-} +{-# LANGUAGE LambdaCase #-} +{-# OPTIONS_GHC -fno-warn-tabs #-} + +module Utility.MoveFile ( + moveFile, +) where + +import Control.Monad +import System.FilePath +import System.PosixCompat.Files hiding (removeLink) +import System.IO.Error +import Prelude + +#ifndef mingw32_HOST_OS +import Control.Monad.IfElse +import Utility.SafeCommand +#endif + +import Utility.SystemDirectory +import Utility.Tmp +import Utility.Exception +import Utility.Monad + +{- Moves one filename to another. + - First tries a rename, but falls back to moving across devices if needed. -} +moveFile :: FilePath -> FilePath -> IO () +moveFile src dest = tryIO (rename src dest) >>= onrename + where + onrename (Right _) = noop + onrename (Left e) + | isPermissionError e = rethrow + | isDoesNotExistError e = rethrow + | otherwise = viaTmp mv dest () + where + rethrow = throwM e + + mv tmp () = do + -- copyFile is likely not as optimised as + -- the mv command, so we'll use the command. + -- + -- But, while Windows has a "mv", it does not seem very + -- reliable, so use copyFile there. +#ifndef mingw32_HOST_OS + -- If dest is a directory, mv would move the file + -- into it, which is not desired. + whenM (isdir dest) rethrow + ok <- boolSystem "mv" [Param "-f", Param src, Param tmp] + let e' = e +#else + r <- tryIO $ copyFile src tmp + let (ok, e') = case r of + Left err -> (False, err) + Right _ -> (True, e) +#endif + unless ok $ do + -- delete any partial + _ <- tryIO $ removeFile tmp + throwM e' + +#ifndef mingw32_HOST_OS + isdir f = do + r <- tryIO $ getFileStatus f + case r of + (Left _) -> return False + (Right s) -> return $ isDirectory s +#endif |