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.

This commit is contained in:
Joey Hess 2015-04-18 14:13:07 -04:00
parent 0def1f0b53
commit 8489057e8d
3 changed files with 41 additions and 9 deletions

View file

@ -31,6 +31,7 @@ import Config
import Types.Key import Types.Key
import Types.CleanupActions import Types.CleanupActions
import Utility.HumanTime import Utility.HumanTime
import Utility.CopyFile
import Git.FilePath import Git.FilePath
import Utility.PID import Utility.PID
import qualified Database.Fsck as FsckDb import qualified Database.Fsck as FsckDb
@ -273,7 +274,7 @@ checkKeySize key = ifM isDirect
checkKeySizeRemote :: Key -> Remote -> Maybe FilePath -> Annex Bool checkKeySizeRemote :: Key -> Remote -> Maybe FilePath -> Annex Bool
checkKeySizeRemote _ _ Nothing = return True checkKeySizeRemote _ _ Nothing = return True
checkKeySizeRemote key remote (Just file) = 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 :: (Key -> Annex String) -> Key -> FilePath -> Annex Bool
checkKeySizeOr bad key file = case Types.Key.keySize key of 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 FilePath -> Annex Bool
checkBackendRemote backend key remote = maybe (return True) go checkBackendRemote backend key remote = maybe (return True) go
where 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 :: (Key -> Annex String) -> Backend -> Key -> FilePath -> Annex Bool
checkBackendOr bad backend key file = checkBackendOr bad backend key file =
@ -380,13 +381,36 @@ badContentDirect file key = do
logStatus key InfoMissing logStatus key InfoMissing
return "left in place for you to examine" return "left in place for you to examine"
badContentRemote :: Remote -> Key -> Annex String {- Bad content is dropped from the remote. We have downloaded a copy
badContentRemote remote key = do - from the remote to a temp file already (in some cases, it's just a
ok <- Remote.removeKey remote key - symlink to a file in the remote). To avoid any further data loss,
when ok $ - 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 Remote.logStatus remote key InfoMissing
return $ (if ok then "dropped from " else "failed to drop from ") return $ case (movedbad, dropped) of
++ Remote.name remote (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 :: Incremental -> FilePath -> Key -> Annex Bool -> CommandStart
runFsck inc file key a = ifM (needFsck inc key) runFsck inc file key a = ifM (needFsck inc key)

View file

@ -16,7 +16,12 @@ module Utility.CopyFile (
import Common import Common
import qualified Build.SysConfig as SysConfig 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) deriving (Eq)
{- The cp command is used, because I hate reinventing the wheel, {- The cp command is used, because I hate reinventing the wheel,

3
debian/changelog vendored
View file

@ -17,6 +17,9 @@ git-annex (5.20150410) UNRELEASED; urgency=medium
* Fix fsck --from a git remote in a local directory, and from * Fix fsck --from a git remote in a local directory, and from
a directory special remote. a directory special remote.
This was a reversion caused by the relative path changes in 5.20150113. 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 -- Joey Hess <id@joeyh.name> Thu, 09 Apr 2015 20:59:43 -0400