make git fsck batch-capable
This commit is contained in:
parent
657f9b98cb
commit
ff3f654cbe
4 changed files with 54 additions and 30 deletions
17
Git/Fsck.hs
17
Git/Fsck.hs
|
@ -16,6 +16,7 @@ import Git
|
||||||
import Git.Command
|
import Git.Command
|
||||||
import Git.Sha
|
import Git.Sha
|
||||||
import Git.CatFile
|
import Git.CatFile
|
||||||
|
import Utility.Batch
|
||||||
|
|
||||||
import qualified Data.Set as S
|
import qualified Data.Set as S
|
||||||
|
|
||||||
|
@ -31,17 +32,25 @@ type MissingObjects = S.Set Sha
|
||||||
- to be a git sha. Not all such shas are of broken objects, so ask git
|
- 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.
|
- to try to cat the object, and see if it fails.
|
||||||
-}
|
-}
|
||||||
findBroken :: Repo -> IO (Maybe MissingObjects)
|
findBroken :: Bool -> Repo -> IO (Maybe MissingObjects)
|
||||||
findBroken r = do
|
findBroken batchmode r = do
|
||||||
(output, fsckok) <- processTranscript "git" (toCommand $ fsckParams r) Nothing
|
(output, fsckok) <- processTranscript command' (toCommand params') Nothing
|
||||||
let objs = parseFsckOutput output
|
let objs = parseFsckOutput output
|
||||||
badobjs <- findMissing objs r
|
badobjs <- findMissing objs r
|
||||||
if S.null badobjs && not fsckok
|
if S.null badobjs && not fsckok
|
||||||
then return Nothing
|
then return Nothing
|
||||||
else return $ Just badobjs
|
else return $ Just badobjs
|
||||||
|
where
|
||||||
|
(command, params) = ("git", fsckParams r)
|
||||||
|
(command', params')
|
||||||
|
| batchmode = toBatchCommand (command, params)
|
||||||
|
| otherwise = (command, params)
|
||||||
|
|
||||||
{- Finds objects that are missing from the git repsitory, or are corrupt.
|
{- Finds objects that are missing from the git repsitory, or are corrupt.
|
||||||
- Note that catting a corrupt object will cause cat-file to crash. -}
|
-
|
||||||
|
- 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 :: [Sha] -> Repo -> IO MissingObjects
|
||||||
findMissing objs r = go objs [] =<< start
|
findMissing objs r = go objs [] =<< start
|
||||||
where
|
where
|
||||||
|
|
|
@ -36,22 +36,22 @@ import qualified Data.ByteString.Lazy as L
|
||||||
import System.Log.Logger
|
import System.Log.Logger
|
||||||
import Data.Tuple.Utils
|
import Data.Tuple.Utils
|
||||||
|
|
||||||
{- Finds and removes corrupt objects from the repository, returning a list
|
{- Given a set of bad objects found by git fsck, removes all
|
||||||
- of all such objects, which need to be found elsewhere to finish
|
- corrupt objects, and returns a list of missing objects,
|
||||||
- recovery.
|
- which need to be found elsewhere to finish recovery.
|
||||||
-
|
-
|
||||||
- Strategy: Run git fsck, remove objects it identifies as corrupt,
|
- Since git fsck may crash on corrupt objects, and so not
|
||||||
- and repeat until git fsck finds no new objects.
|
- report the full set of corrupt or missing objects,
|
||||||
|
- this removes corrupt objects, and re-runs fsck, until it
|
||||||
|
- stabalizes.
|
||||||
-
|
-
|
||||||
- To remove corrupt objects, unpack all packs, and remove the packs
|
- To remove corrupt objects, unpack all packs, and remove the packs
|
||||||
- (to handle corrupt packs), and remove loose object files.
|
- (to handle corrupt packs), and remove loose object files.
|
||||||
-}
|
-}
|
||||||
cleanCorruptObjects :: Repo -> IO MissingObjects
|
cleanCorruptObjects :: Maybe MissingObjects -> Repo -> IO MissingObjects
|
||||||
cleanCorruptObjects r = do
|
cleanCorruptObjects mmissing r = check mmissing
|
||||||
notice "Running git fsck ..."
|
|
||||||
check =<< findBroken r
|
|
||||||
where
|
where
|
||||||
check Nothing = do
|
check Nothing = do
|
||||||
notice "git fsck found a problem but no specific broken objects. Perhaps a corrupt pack file?"
|
notice "git fsck found a problem but no specific broken objects. Perhaps a corrupt pack file?"
|
||||||
ifM (explodePacks r)
|
ifM (explodePacks r)
|
||||||
( retry S.empty
|
( retry S.empty
|
||||||
|
@ -72,7 +72,7 @@ cleanCorruptObjects r = do
|
||||||
else return bad
|
else return bad
|
||||||
retry oldbad = do
|
retry oldbad = do
|
||||||
notice "Re-running git fsck to see if it finds more problems."
|
notice "Re-running git fsck to see if it finds more problems."
|
||||||
v <- findBroken r
|
v <- findBroken False r
|
||||||
case v of
|
case v of
|
||||||
Nothing -> error $ unwords
|
Nothing -> error $ unwords
|
||||||
[ "git fsck found a problem, which was not corrected after removing"
|
[ "git fsck found a problem, which was not corrected after removing"
|
||||||
|
|
|
@ -44,7 +44,28 @@ batch a = a
|
||||||
maxNice :: Int
|
maxNice :: Int
|
||||||
maxNice = 19
|
maxNice = 19
|
||||||
|
|
||||||
{- Runs a command in a way that's suitable for batch jobs.
|
{- Converts a command to run niced. -}
|
||||||
|
toBatchCommand :: (String, [CommandParam]) -> (String, [CommandParam])
|
||||||
|
toBatchCommand (command, params) = (command', params')
|
||||||
|
where
|
||||||
|
#ifndef mingw32_HOST_OS
|
||||||
|
commandline = unwords $ map shellEscape $ command : toCommand params
|
||||||
|
nicedcommand
|
||||||
|
| Build.SysConfig.nice = "nice " ++ commandline
|
||||||
|
| otherwise = commandline
|
||||||
|
command' = "sh"
|
||||||
|
params' =
|
||||||
|
[ Param "-c"
|
||||||
|
, Param $ "exec " ++ nicedcommand
|
||||||
|
]
|
||||||
|
#else
|
||||||
|
command' = command
|
||||||
|
params' = params
|
||||||
|
#endif
|
||||||
|
|
||||||
|
{- Runs a command in a way that's suitable for batch jobs that can be
|
||||||
|
- interrupted.
|
||||||
|
-
|
||||||
- The command is run niced. If the calling thread receives an async
|
- The command is run niced. If the calling thread receives an async
|
||||||
- exception, it sends the command a SIGTERM, and after the command
|
- exception, it sends the command a SIGTERM, and after the command
|
||||||
- finishes shuttting down, it re-raises the async exception. -}
|
- finishes shuttting down, it re-raises the async exception. -}
|
||||||
|
@ -63,15 +84,6 @@ batchCommandEnv command params environ = do
|
||||||
void $ waitForProcess pid
|
void $ waitForProcess pid
|
||||||
E.throwIO asyncexception
|
E.throwIO asyncexception
|
||||||
where
|
where
|
||||||
#ifndef mingw32_HOST_OS
|
(command', params') = toBatchCommand (command, params)
|
||||||
p = proc "sh"
|
p = proc command' $ toCommand params'
|
||||||
[ "-c"
|
|
||||||
, "exec " ++ nicedcommand
|
|
||||||
]
|
|
||||||
commandline = unwords $ map shellEscape $ command : toCommand params
|
|
||||||
nicedcommand
|
|
||||||
| Build.SysConfig.nice = "nice " ++ commandline
|
|
||||||
| otherwise = commandline
|
|
||||||
#else
|
|
||||||
p = proc command (toCommand params)
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{- git-recover-repository program
|
{- git-recover-repository program
|
||||||
-
|
-
|
||||||
- Copyright 2012 Joey Hess <joey@kitenet.net>
|
- Copyright 2013 Joey Hess <joey@kitenet.net>
|
||||||
-
|
-
|
||||||
- Licensed under the GNU GPL version 3 or higher.
|
- Licensed under the GNU GPL version 3 or higher.
|
||||||
-}
|
-}
|
||||||
|
@ -15,6 +15,7 @@ import qualified Data.Set as S
|
||||||
import Common
|
import Common
|
||||||
import qualified Git
|
import qualified Git
|
||||||
import qualified Git.CurrentRepo
|
import qualified Git.CurrentRepo
|
||||||
|
import qualified Git.Fsck
|
||||||
import qualified Git.RecoverRepository
|
import qualified Git.RecoverRepository
|
||||||
import qualified Git.Config
|
import qualified Git.Config
|
||||||
import qualified Git.Branch
|
import qualified Git.Branch
|
||||||
|
@ -46,7 +47,9 @@ main = do
|
||||||
forced <- parseArgs
|
forced <- parseArgs
|
||||||
|
|
||||||
g <- Git.Config.read =<< Git.CurrentRepo.get
|
g <- Git.Config.read =<< Git.CurrentRepo.get
|
||||||
missing <- Git.RecoverRepository.cleanCorruptObjects g
|
putStrLn "Running git fsck ..."
|
||||||
|
fsckresult <- Git.Fsck.findBroken False g
|
||||||
|
missing <- Git.RecoverRepository.cleanCorruptObjects fsckresult g
|
||||||
stillmissing <- Git.RecoverRepository.retrieveMissingObjects missing g
|
stillmissing <- Git.RecoverRepository.retrieveMissingObjects missing g
|
||||||
if S.null stillmissing
|
if S.null stillmissing
|
||||||
then putStr $ unlines
|
then putStr $ unlines
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue