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.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)

View file

@ -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,

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
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