summaryrefslogtreecommitdiff
path: root/Git/Fsck.hs
diff options
context:
space:
mode:
authorJoey Hess <joeyh@debian.org>2013-11-22 11:16:03 -0400
committerJoey Hess <joeyh@debian.org>2013-11-22 11:16:03 -0400
commit7e592e1d6ed5e0b25b37215da7558c6324688d6f (patch)
tree75a86ff02e9311bcff817f2dcfe9b0a6ca1b5708 /Git/Fsck.hs
downloadgit-repair-7e592e1d6ed5e0b25b37215da7558c6324688d6f.tar.gz
git-repair (1.20131122) unstable; urgency=low
* Added test mode, which can be used to randomly corrupt test repositories, in reproducible ways, which allows easy corruption-driven-development. * Improve repair code in the case where the index file is corrupt, and this hides other problems. * Write a dummy .git/HEAD if the file is missing or corrupt, as git otherwise will not treat the repository as a git repo. * Improve fsck code to find badly corrupted objects that crash git fsck before it can complain about them. * Fixed crashes on bad file encodings. * Can now run 10000 tests (git-repair --test -n 10000 --force) with 0 failures. # imported from the archive
Diffstat (limited to 'Git/Fsck.hs')
-rw-r--r--Git/Fsck.hs79
1 files changed, 79 insertions, 0 deletions
diff --git a/Git/Fsck.hs b/Git/Fsck.hs
new file mode 100644
index 0000000..8bfddb4
--- /dev/null
+++ b/Git/Fsck.hs
@@ -0,0 +1,79 @@
+{- git fsck interface
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Git.Fsck (
+ FsckResults,
+ MissingObjects,
+ findBroken,
+ foundBroken,
+ findMissing,
+) where
+
+import Common
+import Git
+import Git.Command
+import Git.Sha
+import Utility.Batch
+
+import qualified Data.Set as S
+
+type MissingObjects = S.Set Sha
+
+{- If fsck succeeded, Just a set of missing objects it found.
+ - If it failed, Nothing. -}
+type FsckResults = Maybe MissingObjects
+
+{- Runs fsck to find some of the broken objects in the repository.
+ - May not find all broken objects, if fsck fails on bad data in some of
+ - the broken objects it does find.
+ -
+ - Strategy: Rather than parsing fsck's current specific output,
+ - look for anything in its output (both stdout and stderr) that appears
+ - to be a git sha. Not all such shas are of broken objects, so ask git
+ - to try to cat the object, and see if it fails.
+ -}
+findBroken :: Bool -> Repo -> IO FsckResults
+findBroken batchmode r = do
+ (output, fsckok) <- processTranscript command' (toCommand params') Nothing
+ let objs = findShas output
+ badobjs <- findMissing objs r
+ if S.null badobjs && not fsckok
+ then return Nothing
+ else return $ Just badobjs
+ where
+ (command, params) = ("git", fsckParams r)
+ (command', params')
+ | batchmode = toBatchCommand (command, params)
+ | otherwise = (command, params)
+
+foundBroken :: FsckResults -> Bool
+foundBroken Nothing = True
+foundBroken (Just s) = not (S.null s)
+
+{- Finds objects that are missing from the git repsitory, or are corrupt.
+ -
+ - This does not use git cat-file --batch, because catting a corrupt
+ - object can cause it to crash, or to report incorrect size information.a
+ -}
+findMissing :: [Sha] -> Repo -> IO MissingObjects
+findMissing objs r = S.fromList <$> filterM (not <$$> present) objs
+ where
+ present o = either (const False) (const True) <$> tryIO (dump o)
+ dump o = runQuiet
+ [ Param "show"
+ , Param (show o)
+ ] r
+
+findShas :: String -> [Sha]
+findShas = catMaybes . map extractSha . concat . map words . lines
+
+fsckParams :: Repo -> [CommandParam]
+fsckParams = gitCommandLine $
+ [ Param "fsck"
+ , Param "--no-dangling"
+ , Param "--no-reflogs"
+ ]