aboutsummaryrefslogtreecommitdiff
path: root/Git/Fsck.hs
diff options
context:
space:
mode:
authorGravatar Joey Hess <joey@kitenet.net>2013-10-20 17:50:51 -0400
committerGravatar Joey Hess <joey@kitenet.net>2013-10-20 17:50:51 -0400
commit66ccc37a99994f1206d308c0c0003ac2605d3c42 (patch)
tree17fd97ca91a7c963cf80ac1274c94ac841e8572c /Git/Fsck.hs
parent66e2c6e3a16480e25f82ef447cfebac16997aac5 (diff)
git-recover-repository 1/2 done
Diffstat (limited to 'Git/Fsck.hs')
-rw-r--r--Git/Fsck.hs66
1 files changed, 66 insertions, 0 deletions
diff --git a/Git/Fsck.hs b/Git/Fsck.hs
new file mode 100644
index 000000000..a43a84f3e
--- /dev/null
+++ b/Git/Fsck.hs
@@ -0,0 +1,66 @@
+{- git fsck interface
+ -
+ - Copyright 2013 Joey Hess <joey@kitenet.net>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+module Git.Fsck (
+ findBroken,
+ findMissing
+) where
+
+import Common
+import Git
+import Git.Command
+import Git.Sha
+import Git.CatFile
+
+import qualified Data.Set as S
+
+{- 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. If the fsck fails generally without
+ - finding any broken objects, returns Nothing.
+ -
+ - 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 :: Repo -> IO (Maybe (S.Set Sha))
+findBroken r = do
+ (output, fsckok) <- processTranscript "git" (toCommand $ fsckParams r) Nothing
+ let objs = parseFsckOutput output
+ badobjs <- findMissing objs r
+ if S.null badobjs && not fsckok
+ then return Nothing
+ else return $ Just badobjs
+
+{- Finds objects that are missing from the git repsitory, or are corrupt.
+ - Note that catting a corrupt object will cause cat-file to crash. -}
+findMissing :: [Sha] -> Repo -> IO (S.Set Sha)
+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"
+ ]