diff options
-rw-r--r-- | Command/Fsck.hs | 40 | ||||
-rw-r--r-- | Utility/CopyFile.hs | 7 | ||||
-rw-r--r-- | debian/changelog | 3 |
3 files changed, 41 insertions, 9 deletions
diff --git a/Command/Fsck.hs b/Command/Fsck.hs index 08753b612..74cff7491 100644 --- a/Command/Fsck.hs +++ b/Command/Fsck.hs @@ -31,6 +31,7 @@ import Config import Types.Key import Types.CleanupActions import Utility.HumanTime +import Utility.CopyFile import Git.FilePath import Utility.PID import qualified Database.Fsck as FsckDb @@ -273,7 +274,7 @@ checkKeySize key = ifM isDirect checkKeySizeRemote :: Key -> Remote -> Maybe FilePath -> Annex Bool checkKeySizeRemote _ _ Nothing = return True checkKeySizeRemote key remote (Just file) = - checkKeySizeOr (badContentRemote remote) key file + checkKeySizeOr (badContentRemote remote file) key file checkKeySizeOr :: (Key -> Annex String) -> Key -> FilePath -> Annex Bool checkKeySizeOr bad key file = case Types.Key.keySize key of @@ -318,7 +319,7 @@ checkBackend backend key mfile = go =<< isDirect checkBackendRemote :: Backend -> Key -> Remote -> Maybe FilePath -> Annex Bool checkBackendRemote backend key remote = maybe (return True) go where - go = checkBackendOr (badContentRemote remote) backend key + go file = checkBackendOr (badContentRemote remote file) backend key file checkBackendOr :: (Key -> Annex String) -> Backend -> Key -> FilePath -> Annex Bool checkBackendOr bad backend key file = @@ -380,13 +381,36 @@ badContentDirect file key = do logStatus key InfoMissing return "left in place for you to examine" -badContentRemote :: Remote -> Key -> Annex String -badContentRemote remote key = do - ok <- Remote.removeKey remote key - when ok $ +{- Bad content is dropped from the remote. We have downloaded a copy + - from the remote to a temp file already (in some cases, it's just a + - symlink to a file in the remote). To avoid any further data loss, + - that temp file is moved to the bad content directory unless + - the local annex has a copy of the content. -} +badContentRemote :: Remote -> FilePath -> Key -> Annex String +badContentRemote remote localcopy key = do + bad <- fromRepo gitAnnexBadDir + let destbad = bad </> key2file key + movedbad <- ifM (inAnnex key <||> liftIO (doesFileExist destbad)) + ( return False + , do + createAnnexDirectory (parentDir destbad) + liftIO $ catchDefaultIO False $ + ifM (isSymbolicLink <$> getSymbolicLinkStatus localcopy) + ( copyFileExternal CopyTimeStamps localcopy destbad + , do + moveFile localcopy destbad + return True + ) + ) + + dropped <- Remote.removeKey remote key + when dropped $ Remote.logStatus remote key InfoMissing - return $ (if ok then "dropped from " else "failed to drop from ") - ++ Remote.name remote + return $ case (movedbad, dropped) of + (True, True) -> "moved from " ++ Remote.name remote ++ + " to " ++ destbad + (False, True) -> "dropped from " ++ Remote.name remote + (_, False) -> "failed to drop from" ++ Remote.name remote runFsck :: Incremental -> FilePath -> Key -> Annex Bool -> CommandStart runFsck inc file key a = ifM (needFsck inc key) diff --git a/Utility/CopyFile.hs b/Utility/CopyFile.hs index b123d006d..1c07ca110 100644 --- a/Utility/CopyFile.hs +++ b/Utility/CopyFile.hs @@ -16,7 +16,12 @@ module Utility.CopyFile ( import Common import qualified Build.SysConfig as SysConfig -data CopyMetaData = CopyTimeStamps | CopyAllMetaData +data CopyMetaData + -- Copy timestamps when possible, but no other metadata, and + -- when copying a symlink, makes a copy of its content. + = CopyTimeStamps + -- Copy all metadata when possible. + | CopyAllMetaData deriving (Eq) {- The cp command is used, because I hate reinventing the wheel, diff --git a/debian/changelog b/debian/changelog index fc7c23d87..00aed03a0 100644 --- a/debian/changelog +++ b/debian/changelog @@ -17,6 +17,9 @@ git-annex (5.20150410) UNRELEASED; urgency=medium * Fix fsck --from a git remote in a local directory, and from a directory special remote. This was a reversion caused by the relative path changes in 5.20150113. + * fsck --from remote: When bad content is found in the remote, + and the local repo does not have a copy of the content, preserve + the bad content in .git/annex/bad/ to avoid further data loss. -- Joey Hess <id@joeyh.name> Thu, 09 Apr 2015 20:59:43 -0400 |