resume properly when copying a file to/from a local git remote is interrupted (take 2)
This method avoids breaking test_readonly. Just check if the dest file exists, and avoid CoW probing when it does, so when CoW probing fails, it can resume where the previous non-CoW copy left off. If CoW has been probed already to work, delete the dest file since a CoW copy will presumably work. It seems like it would be almost as good to just skip CoW copying in this case too, but consider that the dest file might have started to be copied from some other remote, not using CoW, but CoW has been probed to work to copy from the current place. Sponsored-by: Dartmouth College's Datalad project
This commit is contained in:
parent
7ccf642863
commit
b9aa2ce8d1
3 changed files with 26 additions and 8 deletions
|
@ -27,18 +27,32 @@ newtype CopyCoWTried = CopyCoWTried (MVar Bool)
|
|||
newCopyCoWTried :: IO CopyCoWTried
|
||||
newCopyCoWTried = CopyCoWTried <$> newEmptyMVar
|
||||
|
||||
{- Copies a file is copy-on-write is supported. Otherwise, returns False. -}
|
||||
{- Copies a file is copy-on-write is supported. Otherwise, returns False.
|
||||
-
|
||||
- The destination file must not exist yet, or it will fail to make a CoW copy,
|
||||
- and will return false.
|
||||
-}
|
||||
tryCopyCoW :: CopyCoWTried -> FilePath -> FilePath -> MeterUpdate -> IO Bool
|
||||
tryCopyCoW (CopyCoWTried copycowtried) src dest meterupdate =
|
||||
-- If multiple threads reach this at the same time, they
|
||||
-- will both try CoW, which is acceptable.
|
||||
ifM (isEmptyMVar copycowtried)
|
||||
( do
|
||||
ok <- docopycow
|
||||
void $ tryPutMVar copycowtried ok
|
||||
return ok
|
||||
-- If dest exists, don't try CoW, since it would
|
||||
-- have to be deleted first.
|
||||
( ifM (doesFileExist dest)
|
||||
( return False
|
||||
, do
|
||||
ok <- docopycow
|
||||
void $ tryPutMVar copycowtried ok
|
||||
return ok
|
||||
)
|
||||
, ifM (readMVar copycowtried)
|
||||
( docopycow
|
||||
( do
|
||||
-- CoW is known to work, so delete
|
||||
-- dest if it exists in order to do a fast
|
||||
-- CoW copy.
|
||||
void $ tryIO $ removeFile dest
|
||||
docopycow
|
||||
, return False
|
||||
)
|
||||
)
|
||||
|
|
|
@ -9,6 +9,8 @@ git-annex (8.20210904) UNRELEASED; urgency=medium
|
|||
* borg: Avoid trying to extract xattrs, ACLS, and bsdflags when
|
||||
retrieving from a borg repository.
|
||||
* Sped up git-annex smudge --clean by 25%.
|
||||
* Resume where it left off when copying a file to/from a local git remote
|
||||
was interrupted.
|
||||
|
||||
-- Joey Hess <id@joeyh.name> Fri, 03 Sep 2021 12:02:55 -0400
|
||||
|
||||
|
|
|
@ -56,11 +56,13 @@ copyFileExternal meta src dest = do
|
|||
| otherwise = copyMetaDataParams meta
|
||||
|
||||
{- When a filesystem supports CoW (and cp does), uses it to make
|
||||
- an efficient copy of a file. Otherwise, returns False. -}
|
||||
- an efficient copy of a file. Otherwise, returns False.
|
||||
-
|
||||
- The dest file must not exist yet, or it will fail to make a CoW copy,
|
||||
- and will return False. -}
|
||||
copyCoW :: CopyMetaData -> FilePath -> FilePath -> IO Bool
|
||||
copyCoW meta src dest
|
||||
| BuildInfo.cp_reflink_supported = do
|
||||
void $ tryIO $ removeFile dest
|
||||
-- When CoW is not supported, cp will complain to stderr,
|
||||
-- so have to discard its stderr.
|
||||
ok <- catchBoolIO $ withNullHandle $ \nullh ->
|
||||
|
|
Loading…
Reference in a new issue