From 7e592e1d6ed5e0b25b37215da7558c6324688d6f Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 22 Nov 2013 11:16:03 -0400 Subject: 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 --- Git/Fsck.hs | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 Git/Fsck.hs (limited to 'Git/Fsck.hs') 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 + - + - 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" + ] -- cgit v1.2.3