summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Command/Fsck.hs40
-rw-r--r--Utility/CopyFile.hs7
-rw-r--r--debian/changelog3
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