add: Fix error recovery rollback to not move the injested file content out of the annex back to the file, because other files may point to that same content. Instead, copy the injected file content out to recover.

That was not a data loss, but it came close!
This commit is contained in:
Joey Hess 2015-11-06 15:28:20 -04:00
parent d435a717e6
commit 7938b87864
Failed to extract signature
3 changed files with 11 additions and 16 deletions

View file

@ -27,7 +27,6 @@ module Annex.Content (
sendAnnex, sendAnnex,
prepSendAnnex, prepSendAnnex,
removeAnnex, removeAnnex,
fromAnnex,
moveBad, moveBad,
KeyLocation(..), KeyLocation(..),
getKeysPresent, getKeysPresent,
@ -573,13 +572,6 @@ secureErase file = maybe noop go =<< annexSecureEraseCommand <$> Annex.getGitCon
boolSystem "sh" [Param "-c", Param $ gencmd basecmd] boolSystem "sh" [Param "-c", Param $ gencmd basecmd]
gencmd = massReplace [ ("%file", shellEscape file) ] gencmd = massReplace [ ("%file", shellEscape file) ]
{- Moves a key's file out of .git/annex/objects/ -}
fromAnnex :: Key -> FilePath -> Annex ()
fromAnnex key dest = cleanObjectLoc key $ do
file <- calcRepo $ gitAnnexLocation key
thawContent file
liftIO $ moveFile file dest
{- Moves a key out of .git/annex/objects/ into .git/annex/bad, and {- Moves a key out of .git/annex/objects/ into .git/annex/bad, and
- returns the file it was moved to. -} - returns the file it was moved to. -}
moveBad :: Key -> Annex FilePath moveBad :: Key -> Annex FilePath

View file

@ -31,6 +31,7 @@ import Utility.InodeCache
import Annex.FileMatcher import Annex.FileMatcher
import Annex.ReplaceFile import Annex.ReplaceFile
import Utility.Tmp import Utility.Tmp
import Utility.CopyFile
import Control.Exception (IOException) import Control.Exception (IOException)
@ -244,15 +245,13 @@ undo :: FilePath -> Key -> SomeException -> Annex a
undo file key e = do undo file key e = do
whenM (inAnnex key) $ do whenM (inAnnex key) $ do
liftIO $ nukeFile file liftIO $ nukeFile file
catchNonAsync (fromAnnex key file) tryharder -- The key could be used by other files too, so leave the
logStatus key InfoMissing -- content in the annex, and make a copy back to the file.
obj <- calcRepo $ gitAnnexLocation key
unlessM (liftIO $ copyFileExternal CopyTimeStamps obj file) $
warning $ "Unable to restore content of " ++ file ++ "; it should be located in " ++ obj
thawContent file
throwM e throwM e
where
-- fromAnnex could fail if the file ownership is weird
tryharder :: SomeException -> Annex ()
tryharder _ = do
src <- calcRepo $ gitAnnexLocation key
liftIO $ moveFile src file
{- Creates the symlink to the annexed content, returns the link target. -} {- Creates the symlink to the annexed content, returns the link target. -}
link :: FilePath -> Key -> Maybe InodeCache -> Annex String link :: FilePath -> Key -> Maybe InodeCache -> Annex String

4
debian/changelog vendored
View file

@ -10,6 +10,10 @@ git-annex (5.20151102.2) UNRELEASED; urgency=medium
that moves file contents around. that moves file contents around.
* Fix race that could result in an annexed file's symlink not being * Fix race that could result in an annexed file's symlink not being
created, when eg, running concurrent git-annex adds. created, when eg, running concurrent git-annex adds.
* add: Fix error recovery rollback to not move the injested file content
out of the annex back to the file, because other files may point to
that same content. Instead, copy the injected file content out to
recover.
-- Joey Hess <id@joeyh.name> Wed, 04 Nov 2015 12:50:20 -0400 -- Joey Hess <id@joeyh.name> Wed, 04 Nov 2015 12:50:20 -0400