aboutsummaryrefslogtreecommitdiff
path: root/Annex/Content.hs
diff options
context:
space:
mode:
authorGravatar Joey Hess <joeyh@joeyh.name>2015-12-22 15:20:03 -0400
committerGravatar Joey Hess <joeyh@joeyh.name>2015-12-22 15:20:03 -0400
commit00e240f3803384ae8761f2d5bc95319351f4e0fa (patch)
tree67a9639c72a8bd8239abb377d77962f4ba9c2a5a /Annex/Content.hs
parent0da2a837d1634164695591029072b88cd56b46e7 (diff)
make linkAnnex detect when the file changes as it's being copied/linked in
This fixes a race where the modified file ended up in annex/objects, and the InodeCache stored in the database was for the modified version, so git-annex didn't know it had gotten modified. The race could occur when the smudge filter was running; now it gets the InodeCache before generating the Key, which avoids the race.
Diffstat (limited to 'Annex/Content.hs')
-rw-r--r--Annex/Content.hs35
1 files changed, 24 insertions, 11 deletions
diff --git a/Annex/Content.hs b/Annex/Content.hs
index 4cd2b0259..c00863e31 100644
--- a/Annex/Content.hs
+++ b/Annex/Content.hs
@@ -521,30 +521,43 @@ populatePointerFile k obj f = go =<< isPointerFile f
- prevent losing the content if the source file is deleted, but does not
- guard against modifications.
-}
-linkAnnex :: Key -> FilePath -> Annex LinkAnnexResult
-linkAnnex key src = do
+linkAnnex :: Key -> FilePath -> Maybe InodeCache -> Annex LinkAnnexResult
+linkAnnex key src srcic = do
dest <- calcRepo (gitAnnexLocation key)
- modifyContent dest $ linkAnnex' key src dest
+ modifyContent dest $ linkAnnex' key src srcic dest
{- Hard links (or copies) src to dest, one of which should be the
- annex object. Updates inode cache for src and for dest when it's
- changed. -}
-linkAnnex' :: Key -> FilePath -> FilePath -> Annex LinkAnnexResult
-linkAnnex' key src dest =
+linkAnnex' :: Key -> FilePath -> Maybe InodeCache -> FilePath -> Annex LinkAnnexResult
+linkAnnex' _ _ Nothing _ = return LinkAnnexFailed
+linkAnnex' key src (Just srcic) dest =
ifM (liftIO $ doesFileExist dest)
( do
- Database.Keys.storeInodeCaches key [src]
+ Database.Keys.addInodeCaches key [srcic]
return LinkAnnexNoop
, ifM (linkAnnex'' key src dest)
( do
thawContent dest
- Database.Keys.storeInodeCaches key [dest, src]
- return LinkAnnexOk
- , do
- Database.Keys.storeInodeCaches key [src]
- return LinkAnnexFailed
+ -- src could have changed while being copied
+ -- to dest
+ mcache <- withTSDelta (liftIO . genInodeCache src)
+ case mcache of
+ Just srcic' | compareStrong srcic srcic' -> do
+ destic <- withTSDelta (liftIO . genInodeCache dest)
+ Database.Keys.addInodeCaches key $
+ catMaybes [destic, Just srcic]
+ return LinkAnnexOk
+ _ -> do
+ liftIO $ nukeFile dest
+ failed
+ , failed
)
)
+ where
+ failed = do
+ Database.Keys.addInodeCaches key [srcic]
+ return LinkAnnexFailed
data LinkAnnexResult = LinkAnnexOk | LinkAnnexFailed | LinkAnnexNoop