From 9ed8dd6be036e79e3ec7f5781b9f7b8864e1bc0e Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 23 Oct 2013 13:13:40 -0400 Subject: minor --- Command/Repair.hs | 40 ++++++++++------- Git/Repair.hs | 109 +++++++++++++++++++++++++--------------------- git-recover-repository.hs | 3 +- 3 files changed, 86 insertions(+), 66 deletions(-) diff --git a/Command/Repair.hs b/Command/Repair.hs index b95934268..8808ef9de 100644 --- a/Command/Repair.hs +++ b/Command/Repair.hs @@ -13,6 +13,7 @@ import qualified Annex import qualified Git.Repair import qualified Annex.Branch import Git.Fsck (MissingObjects) +import Git.Types def :: [Command] def = [noCommit $ dontCheck repoExists $ @@ -26,9 +27,10 @@ start = next $ next $ runRepair =<< Annex.getState Annex.force runRepair :: Bool -> Annex Bool runRepair forced = do - (ok, stillmissing) <- inRepo $ Git.Repair.runRepair forced + (ok, stillmissing, modifiedbranches) <- inRepo $ + Git.Repair.runRepair forced when ok $ - repairAnnexBranch stillmissing + repairAnnexBranch stillmissing modifiedbranches return ok {- 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 - 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 - 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 - - branch is ok, and has new changes from elsewhere not yet reflected in - - the index, this does properly merge those into the index before - - committing. + - branch was rewound to a state that, had new changes from elsewhere not + - yet reflected in the index, this does properly merge those into the + - index before committing. -} -repairAnnexBranch :: MissingObjects -> Annex () -repairAnnexBranch missing = ifM okindex - ( do - Annex.Branch.forceCommit "committing index after git repository repair" - liftIO $ putStrLn "Successfully recovered the git-annex branch using .git/annex/index" - , do - inRepo $ nukeFile . gitAnnexIndex - 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" - ) +repairAnnexBranch :: MissingObjects -> [Branch] -> Annex () +repairAnnexBranch missing modifiedbranches + | Annex.Branch.fullname `elem` modifiedbranches = ifM okindex + ( commitindex + , do + nukeindex + 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 okindex = Annex.Branch.withIndex $ 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 diff --git a/Git/Repair.hs b/Git/Repair.hs index bb540fbd7..cc54e49dc 100644 --- a/Git/Repair.hs +++ b/Git/Repair.hs @@ -421,64 +421,73 @@ displayList items header | otherwise = items {- Put it all together. -} -runRepair :: Bool -> Repo -> IO (Bool, MissingObjects) +runRepair :: Bool -> Repo -> IO (Bool, MissingObjects, [Branch]) runRepair forced g = do putStrLn "Running git fsck ..." fsckresult <- findBroken False g - missing <- cleanCorruptObjects fsckresult g - stillmissing <- retrieveMissingObjects missing g - if S.null stillmissing - then successfulfinish stillmissing + if foundBroken fsckresult + then makerepairs fsckresult else do + putStrLn "No problems found." + return (True, S.empty, []) + where + makerepairs fsckresult = do + missing <- cleanCorruptObjects fsckresult g + stillmissing <- retrieveMissingObjects missing g + if S.null stillmissing + then successfulfinish stillmissing [] + else do + putStrLn $ unwords + [ show (S.size stillmissing) + , "missing objects could not be recovered!" + ] + if forced + then continuerepairs stillmissing + else unsuccessfulfinish stillmissing + continuerepairs stillmissing = do + (remotebranches, goodcommits) <- removeTrackingBranches stillmissing emptyGoodCommits g + unless (null remotebranches) $ putStrLn $ unwords - [ show (S.size stillmissing) - , "missing objects could not be recovered!" + [ "removed" + , show (length remotebranches) + , "remote tracking branches that referred to missing objects" ] - if forced - then do - (remotebranches, goodcommits) <- removeTrackingBranches stillmissing emptyGoodCommits g - unless (null remotebranches) $ - putStrLn $ unwords - [ "removed" - , show (length remotebranches) - , "remote tracking branches that referred to missing objects" - ] - (resetbranches, deletedbranches, _) <- resetLocalBranches stillmissing goodcommits g - displayList (map show resetbranches) - "Reset these local branches to old versions before the missing objects were committed:" - displayList (map show deletedbranches) - "Deleted these local branches, which could not be recovered due to missing objects:" - deindexedfiles <- rewriteIndex stillmissing g - 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." - if null resetbranches && null deletedbranches - then successfulfinish stillmissing - else do - unless (repoIsLocalBare g) $ do - mcurr <- Branch.currentUnsafe g - case mcurr of - Nothing -> return () - Just curr -> when (any (== curr) (resetbranches ++ deletedbranches)) $ do - putStrLn $ unwords - [ "You currently have" - , show curr - , "checked out. You may have staged changes in the index that can be committed to recover the lost state of this branch!" - ] - putStrLn "Successfully recovered repository!" - putStrLn "Please carefully check that the changes mentioned above are ok.." - return (True, stillmissing) - else 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 + (resetbranches, deletedbranches, _) <- resetLocalBranches stillmissing goodcommits g + displayList (map show resetbranches) + "Reset these local branches to old versions before the missing objects were committed:" + displayList (map show deletedbranches) + "Deleted these local branches, which could not be recovered due to missing objects:" + deindexedfiles <- rewriteIndex stillmissing g + 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." + let modifiedbranches = resetbranches ++ deletedbranches + if null resetbranches && null deletedbranches + then successfulfinish stillmissing modifiedbranches + else do + unless (repoIsLocalBare g) $ do + mcurr <- Branch.currentUnsafe g + case mcurr of + Nothing -> return () + Just curr -> when (any (== curr) modifiedbranches) $ do + putStrLn $ unwords + [ "You currently have" + , show curr + , "checked out. You may have staged changes in the index that can be committed to recover the lost state of this branch!" + ] + putStrLn "Successfully recovered repository!" + putStrLn "Please carefully check that the changes mentioned above are ok.." + return (True, stillmissing, modifiedbranches) + successfulfinish stillmissing modifiedbranches = do mapM_ putStrLn [ "Successfully recovered repository!" , "You should run \"git fsck\" to make sure, but it looks like" , "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, []) diff --git a/git-recover-repository.hs b/git-recover-repository.hs index 556e2a39b..3e348f5bb 100644 --- a/git-recover-repository.hs +++ b/git-recover-repository.hs @@ -7,6 +7,7 @@ import System.Environment import qualified Data.Set as S +import Data.Tuple.Utils import Common import qualified Git @@ -35,7 +36,7 @@ main = do forced <- parseArgs g <- Git.Config.read =<< Git.CurrentRepo.get - ifM (fst <$> Git.Repair.runRepair forced g) + ifM (fst3 <$> Git.Repair.runRepair forced g) ( exitSuccess , exitFailure ) -- cgit v1.2.3