diff options
author | Joey Hess <joey@kitenet.net> | 2013-11-14 17:04:58 -0400 |
---|---|---|
committer | Joey Hess <joey@kitenet.net> | 2013-11-14 17:04:58 -0400 |
commit | 521ef9dfebd6a9418a5dce7d1686dbf353ddd0a0 (patch) | |
tree | afe6bb5d52e21a049f04020ae448afb81adc02a7 /Git/Fsck.hs | |
parent | f4b4f327b69189d24663a7db6407c1f7a6e48fdd (diff) | |
parent | 5c6f6e4d0abb9b4856908a500611044b3b7a48e6 (diff) |
Merge branch 'master' into tasty-tests
Conflicts:
Test.hs
Diffstat (limited to 'Git/Fsck.hs')
-rw-r--r-- | Git/Fsck.hs | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/Git/Fsck.hs b/Git/Fsck.hs new file mode 100644 index 000000000..2c9423005 --- /dev/null +++ b/Git/Fsck.hs @@ -0,0 +1,87 @@ +{- 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 Git.CatFile +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 = parseFsckOutput 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. + - + - Note that catting a corrupt object will cause cat-file to crash; + - this is detected and it's restarted. + -} +findMissing :: [Sha] -> Repo -> IO MissingObjects +findMissing objs r = go objs [] =<< start + where + start = catFileStart' False r + go [] c h = do + catFileStop h + return $ S.fromList c + go (o:os) c h = do + v <- tryIO $ isNothing <$> catObjectDetails h o + case v of + Left _ -> do + void $ tryIO $ catFileStop h + go os (o:c) =<< start + Right True -> go os (o:c) h + Right False -> go os c h + +parseFsckOutput :: String -> [Sha] +parseFsckOutput = catMaybes . map extractSha . concat . map words . lines + +fsckParams :: Repo -> [CommandParam] +fsckParams = gitCommandLine + [ Param "fsck" + , Param "--no-dangling" + , Param "--no-reflogs" + ] |