This commit is contained in:
Joey Hess 2013-10-23 13:13:40 -04:00
parent 435ea52f3c
commit 1ab2ad86c7
3 changed files with 87 additions and 67 deletions

View file

@ -13,6 +13,7 @@ import qualified Annex
import qualified Git.Repair import qualified Git.Repair
import qualified Annex.Branch import qualified Annex.Branch
import Git.Fsck (MissingObjects) import Git.Fsck (MissingObjects)
import Git.Types
def :: [Command] def :: [Command]
def = [noCommit $ dontCheck repoExists $ def = [noCommit $ dontCheck repoExists $
@ -26,9 +27,10 @@ start = next $ next $ runRepair =<< Annex.getState Annex.force
runRepair :: Bool -> Annex Bool runRepair :: Bool -> Annex Bool
runRepair forced = do runRepair forced = do
(ok, stillmissing) <- inRepo $ Git.Repair.runRepair forced (ok, stillmissing, modifiedbranches) <- inRepo $
Git.Repair.runRepair forced
when ok $ when ok $
repairAnnexBranch stillmissing repairAnnexBranch stillmissing modifiedbranches
return ok return ok
{- After git repository repair, the .git/annex/index file could {- After git repository repair, the .git/annex/index file could
@ -36,23 +38,31 @@ runRepair forced = do
- its own. Since this index file is not used to stage things - its own. Since this index file is not used to stage things
- for long durations of time, it can safely be deleted if it is broken. - for long durations of time, it can safely be deleted if it is broken.
- -
- Otherwise, commit the index file to the git-annex branch. - Otherwise, if the git-annex branch was modified by the repair,
- commit the index file to the git-annex branch.
- This way, if the git-annex branch got rewound to an old version by - This way, if the git-annex branch got rewound to an old version by
- the repository repair, or was completely deleted, this will get it back - the repository repair, or was completely deleted, this will get it back
- to a good state. Note that in the unlikely case where the git-annex - to a good state. Note that in the unlikely case where the git-annex
- branch is ok, and has new changes from elsewhere not yet reflected in - branch was rewound to a state that, had new changes from elsewhere not
- the index, this does properly merge those into the index before - yet reflected in the index, this does properly merge those into the
- committing. - index before committing.
-} -}
repairAnnexBranch :: MissingObjects -> Annex () repairAnnexBranch :: MissingObjects -> [Branch] -> Annex ()
repairAnnexBranch missing = ifM okindex repairAnnexBranch missing modifiedbranches
( do | Annex.Branch.fullname `elem` modifiedbranches = ifM okindex
Annex.Branch.forceCommit "committing index after git repository repair" ( commitindex
liftIO $ putStrLn "Successfully recovered the git-annex branch using .git/annex/index"
, do , do
inRepo $ nukeFile . gitAnnexIndex nukeindex
liftIO $ putStrLn "Had to delete the .git/annex/index file as it was corrupt. It would be a very good idea to run: git annex fsck --fast" liftIO $ putStrLn "Had to delete the .git/annex/index file as it was corrupt. Since the git-annex branch is not up-to-date anymore. It would be a very good idea to run: git annex fsck --fast"
)
| otherwise = ifM okindex
( noop
, nukeindex
) )
where where
okindex = Annex.Branch.withIndex $ okindex = Annex.Branch.withIndex $
inRepo $ Git.Repair.checkIndex missing inRepo $ Git.Repair.checkIndex missing
commitindex = do
Annex.Branch.forceCommit "committing index after git repository repair"
liftIO $ putStrLn "Successfully recovered the git-annex branch using .git/annex/index"
nukeindex = inRepo $ nukeFile . gitAnnexIndex

View file

@ -421,21 +421,30 @@ displayList items header
| otherwise = items | otherwise = items
{- Put it all together. -} {- Put it all together. -}
runRepair :: Bool -> Repo -> IO (Bool, MissingObjects) runRepair :: Bool -> Repo -> IO (Bool, MissingObjects, [Branch])
runRepair forced g = do runRepair forced g = do
putStrLn "Running git fsck ..." putStrLn "Running git fsck ..."
fsckresult <- findBroken False g fsckresult <- findBroken False g
if foundBroken fsckresult
then makerepairs fsckresult
else do
putStrLn "No problems found."
return (True, S.empty, [])
where
makerepairs fsckresult = do
missing <- cleanCorruptObjects fsckresult g missing <- cleanCorruptObjects fsckresult g
stillmissing <- retrieveMissingObjects missing g stillmissing <- retrieveMissingObjects missing g
if S.null stillmissing if S.null stillmissing
then successfulfinish stillmissing then successfulfinish stillmissing []
else do else do
putStrLn $ unwords putStrLn $ unwords
[ show (S.size stillmissing) [ show (S.size stillmissing)
, "missing objects could not be recovered!" , "missing objects could not be recovered!"
] ]
if forced if forced
then do then continuerepairs stillmissing
else unsuccessfulfinish stillmissing
continuerepairs stillmissing = do
(remotebranches, goodcommits) <- removeTrackingBranches stillmissing emptyGoodCommits g (remotebranches, goodcommits) <- removeTrackingBranches stillmissing emptyGoodCommits g
unless (null remotebranches) $ unless (null remotebranches) $
putStrLn $ unwords putStrLn $ unwords
@ -451,14 +460,15 @@ runRepair forced g = do
deindexedfiles <- rewriteIndex stillmissing g deindexedfiles <- rewriteIndex stillmissing g
displayList deindexedfiles displayList deindexedfiles
"Removed these missing files from the index. You should look at what files are present in your working tree and git add them back to the index when appropriate." "Removed these missing files from the index. You should look at what files are present in your working tree and git add them back to the index when appropriate."
let modifiedbranches = resetbranches ++ deletedbranches
if null resetbranches && null deletedbranches if null resetbranches && null deletedbranches
then successfulfinish stillmissing then successfulfinish stillmissing modifiedbranches
else do else do
unless (repoIsLocalBare g) $ do unless (repoIsLocalBare g) $ do
mcurr <- Branch.currentUnsafe g mcurr <- Branch.currentUnsafe g
case mcurr of case mcurr of
Nothing -> return () Nothing -> return ()
Just curr -> when (any (== curr) (resetbranches ++ deletedbranches)) $ do Just curr -> when (any (== curr) modifiedbranches) $ do
putStrLn $ unwords putStrLn $ unwords
[ "You currently have" [ "You currently have"
, show curr , show curr
@ -466,19 +476,18 @@ runRepair forced g = do
] ]
putStrLn "Successfully recovered repository!" putStrLn "Successfully recovered repository!"
putStrLn "Please carefully check that the changes mentioned above are ok.." putStrLn "Please carefully check that the changes mentioned above are ok.."
return (True, stillmissing) return (True, stillmissing, modifiedbranches)
else do successfulfinish stillmissing modifiedbranches = do
if repoIsLocalBare g
then do
putStrLn "If you have a clone of this bare repository, you should add it as a remote of this repository, and re-run git-recover-repository."
putStrLn "If there are no clones of this repository, you can instead run git-recover-repository with the --force parameter to force recovery to a possibly usable state."
else putStrLn "To force a recovery to a usable state, run this command again with the --force parameter."
return (False, stillmissing)
where
successfulfinish stillmissing = do
mapM_ putStrLn mapM_ putStrLn
[ "Successfully recovered repository!" [ "Successfully recovered repository!"
, "You should run \"git fsck\" to make sure, but it looks like" , "You should run \"git fsck\" to make sure, but it looks like"
, "everything was recovered ok." , "everything was recovered ok."
] ]
return (True, stillmissing) return (True, stillmissing, modifiedbranches)
unsuccessfulfinish stillmissing = do
if repoIsLocalBare g
then do
putStrLn "If you have a clone of this bare repository, you should add it as a remote of this repository, and re-run git-recover-repository."
putStrLn "If there are no clones of this repository, you can instead run git-recover-repository with the --force parameter to force recovery to a possibly usable state."
else putStrLn "To force a recovery to a usable state, run this command again with the --force parameter."
return (False, stillmissing, [])

View file

@ -7,6 +7,7 @@
import System.Environment import System.Environment
import qualified Data.Set as S import qualified Data.Set as S
import Data.Tuple.Utils
import Common import Common
import qualified Git import qualified Git
@ -35,7 +36,7 @@ main = do
forced <- parseArgs forced <- parseArgs
g <- Git.Config.read =<< Git.CurrentRepo.get g <- Git.Config.read =<< Git.CurrentRepo.get
ifM (fst <$> Git.Repair.runRepair forced g) ifM (fst3 <$> Git.Repair.runRepair forced g)
( exitSuccess ( exitSuccess
, exitFailure , exitFailure
) )