corrupt branch resetting (but not yet reflog walking)
This commit is contained in:
parent
fcd91be6f0
commit
18487c779f
3 changed files with 58 additions and 15 deletions
|
@ -169,11 +169,40 @@ copyObjects srcr destr = rsync
|
||||||
|
|
||||||
{- To deal with missing objects that cannot be recovered, resets any
|
{- To deal with missing objects that cannot be recovered, resets any
|
||||||
- local branches to point to an old commit before the missing
|
- local branches to point to an old commit before the missing
|
||||||
- objects.
|
- objects. Returns all branches that were changed, and deleted.
|
||||||
-}
|
-}
|
||||||
resetLocalBranches :: MissingObjects -> GoodCommits -> Repo -> IO [Branch]
|
resetLocalBranches :: MissingObjects -> GoodCommits -> Repo -> IO ([Branch], [Branch], GoodCommits)
|
||||||
resetLocalBranches missing goodcommits r = do
|
resetLocalBranches missing goodcommits r =
|
||||||
error "TODO"
|
go [] [] goodcommits =<< filter islocalbranch <$> getAllRefs r
|
||||||
|
where
|
||||||
|
islocalbranch b = "refs/heads/" `isPrefixOf` show b
|
||||||
|
go changed deleted gcs [] = return (changed, deleted, gcs)
|
||||||
|
go changed deleted gcs (b:bs) = do
|
||||||
|
(mc, gcs') <- findUncorruptedCommit missing gcs b r
|
||||||
|
case mc of
|
||||||
|
Just c
|
||||||
|
| c == b -> go changed deleted gcs' bs
|
||||||
|
| otherwise -> do
|
||||||
|
reset b c
|
||||||
|
go (b:changed) deleted gcs' bs
|
||||||
|
Nothing -> do
|
||||||
|
(mc', gcs'') <- findOldBranch missing gcs' b r
|
||||||
|
case mc' of
|
||||||
|
Just c
|
||||||
|
| c == b -> go changed deleted gcs' bs
|
||||||
|
| otherwise -> do
|
||||||
|
reset b c
|
||||||
|
go (b:changed) deleted gcs'' bs
|
||||||
|
Nothing -> do
|
||||||
|
nukeBranchRef b r
|
||||||
|
go changed (b:deleted) gcs'' bs
|
||||||
|
reset b c = do
|
||||||
|
nukeBranchRef b r
|
||||||
|
void $ runBool
|
||||||
|
[ Param "branch"
|
||||||
|
, Param (show $ Ref.base b)
|
||||||
|
, Param (show c)
|
||||||
|
] r
|
||||||
|
|
||||||
{- To deal with missing objects that cannot be recovered, removes
|
{- To deal with missing objects that cannot be recovered, removes
|
||||||
- any remote tracking branches that reference them. Returns a list of
|
- any remote tracking branches that reference them. Returns a list of
|
||||||
|
@ -255,6 +284,7 @@ findUncorruptedCommit missing goodcommits branch r = do
|
||||||
else do
|
else do
|
||||||
(ls, cleanup) <- pipeNullSplit
|
(ls, cleanup) <- pipeNullSplit
|
||||||
[ Param "log"
|
[ Param "log"
|
||||||
|
, Param "-z"
|
||||||
, Param "--format=%H"
|
, Param "--format=%H"
|
||||||
, Param (show branch)
|
, Param (show branch)
|
||||||
] r
|
] r
|
||||||
|
@ -284,11 +314,12 @@ verifyCommit missing goodcommits commit r
|
||||||
| otherwise = do
|
| otherwise = do
|
||||||
(ls, cleanup) <- pipeNullSplit
|
(ls, cleanup) <- pipeNullSplit
|
||||||
[ Param "log"
|
[ Param "log"
|
||||||
|
, Param "-z"
|
||||||
, Param "--format=%H %T"
|
, Param "--format=%H %T"
|
||||||
, Param (show commit)
|
, Param (show commit)
|
||||||
] r
|
] r
|
||||||
let committrees = map parse ls
|
let committrees = map parse ls
|
||||||
if any isNothing committrees
|
if any isNothing committrees || null committrees
|
||||||
then do
|
then do
|
||||||
void cleanup
|
void cleanup
|
||||||
return (False, goodcommits)
|
return (False, goodcommits)
|
||||||
|
@ -304,7 +335,7 @@ verifyCommit missing goodcommits commit r
|
||||||
<$> extractSha commitsha
|
<$> extractSha commitsha
|
||||||
<*> extractSha treesha
|
<*> extractSha treesha
|
||||||
_ -> Nothing
|
_ -> Nothing
|
||||||
check [] = return False
|
check [] = return True
|
||||||
check ((commit, tree):rest)
|
check ((commit, tree):rest)
|
||||||
| checkGoodCommit commit goodcommits = return True
|
| checkGoodCommit commit goodcommits = return True
|
||||||
| otherwise = verifyTree missing tree r <&&> check rest
|
| otherwise = verifyTree missing tree r <&&> check rest
|
||||||
|
|
|
@ -143,8 +143,7 @@ that was found for it.
|
||||||
`git annex fsck --fast` to fix up any object location info.
|
`git annex fsck --fast` to fix up any object location info.
|
||||||
* Remote tracking branches can just be removed, and then `git fetch`
|
* Remote tracking branches can just be removed, and then `git fetch`
|
||||||
from the remote, which will re-download missing objects from it and
|
from the remote, which will re-download missing objects from it and
|
||||||
reinstate the tracking branch.
|
reinstate the tracking branch. **done**
|
||||||
* For other branches (or tags), it's best to not rewrite them, because
|
* For other branches, reset them to last good commit, or delete
|
||||||
that could get really confusing. Instead, delete the old broken branch,
|
if none was found.
|
||||||
and make a "recovered/$branch" that holds the last good commit (if one
|
* (Decided not to touch tags.)
|
||||||
was found).
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ import Common
|
||||||
import qualified Git.CurrentRepo
|
import qualified Git.CurrentRepo
|
||||||
import qualified Git.RecoverRepository
|
import qualified Git.RecoverRepository
|
||||||
import qualified Git.Config
|
import qualified Git.Config
|
||||||
|
import qualified Git.Branch
|
||||||
|
|
||||||
header :: String
|
header :: String
|
||||||
header = "Usage: git-recover-repository"
|
header = "Usage: git-recover-repository"
|
||||||
|
@ -34,7 +35,7 @@ parseArgs = do
|
||||||
enableDebugOutput :: IO ()
|
enableDebugOutput :: IO ()
|
||||||
enableDebugOutput = do
|
enableDebugOutput = do
|
||||||
s <- setFormatter
|
s <- setFormatter
|
||||||
<$> streamHandler stderr NOTICE
|
<$> streamHandler stderr DEBUG -- NOTICE
|
||||||
<*> pure (simpleLogFormatter "$msg")
|
<*> pure (simpleLogFormatter "$msg")
|
||||||
updateGlobalLogger rootLoggerName (setLevel DEBUG . setHandlers [s])
|
updateGlobalLogger rootLoggerName (setLevel DEBUG . setHandlers [s])
|
||||||
|
|
||||||
|
@ -66,8 +67,20 @@ main = do
|
||||||
, show (length remotebranches)
|
, show (length remotebranches)
|
||||||
, "remote tracking branches that referred to missing objects"
|
, "remote tracking branches that referred to missing objects"
|
||||||
]
|
]
|
||||||
localbranches <- Git.RecoverRepository.resetLocalBranches stillmissing goodcommits g
|
(resetbranches, deletedbranches, _) <- Git.RecoverRepository.resetLocalBranches stillmissing goodcommits g
|
||||||
unless (null localbranches) $ do
|
unless (null resetbranches) $ do
|
||||||
putStrLn "Reset these local branches to old versions before the missing objects were committed:"
|
putStrLn "Reset these local branches to old versions before the missing objects were committed:"
|
||||||
putStr $ unlines $ map show localbranches
|
putStr $ unlines $ map show resetbranches
|
||||||
|
unless (null deletedbranches) $ do
|
||||||
|
putStrLn "Deleted these local branches, which could not be recovered due to missing objects:"
|
||||||
|
putStr $ unlines $ map show deletedbranches
|
||||||
|
mcurr <- Git.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!"
|
||||||
|
]
|
||||||
else putStrLn "To force a recovery to a usable state, run this command again with the --force parameter."
|
else putStrLn "To force a recovery to a usable state, run this command again with the --force parameter."
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue