1db49497e0
This commit was sponsored by Denis Dzyubenko on Patreon.
87 lines
3 KiB
Haskell
87 lines
3 KiB
Haskell
{- git-annex command
|
|
-
|
|
- Copyright 2013 Joey Hess <id@joeyh.name>
|
|
-
|
|
- Licensed under the GNU AGPL version 3 or higher.
|
|
-}
|
|
|
|
module Command.Repair where
|
|
|
|
import Command
|
|
import qualified Annex
|
|
import qualified Git.Repair
|
|
import qualified Annex.Branch
|
|
import qualified Git.Ref
|
|
import Git.Types
|
|
import Annex.Version
|
|
import qualified Utility.RawFilePath as R
|
|
|
|
cmd :: Command
|
|
cmd = noCommit $ dontCheck repoExists $
|
|
command "repair" SectionMaintenance
|
|
"recover broken git repository"
|
|
paramNothing (withParams seek)
|
|
|
|
seek :: CmdParams -> CommandSeek
|
|
seek = withNothing (commandAction start)
|
|
|
|
start :: CommandStart
|
|
start = starting "repair" (ActionItemOther Nothing) (SeekInput []) $
|
|
next $ runRepair =<< Annex.getState Annex.force
|
|
|
|
runRepair :: Bool -> Annex Bool
|
|
runRepair forced = do
|
|
(ok, modifiedbranches) <- inRepo $
|
|
Git.Repair.runRepair isAnnexSyncBranch forced
|
|
-- This command can be run in git repos not using git-annex,
|
|
-- so avoid git annex branch stuff in that case.
|
|
whenM (isJust <$> getVersion) $
|
|
repairAnnexBranch modifiedbranches
|
|
return ok
|
|
|
|
{- After git repository repair, the .git/annex/index file could
|
|
- still be broken, by pointing to bad objects, or might just be corrupt on
|
|
- 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, 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 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 :: [Branch] -> Annex ()
|
|
repairAnnexBranch modifiedbranches
|
|
| Annex.Branch.fullname `elem` modifiedbranches = ifM okindex
|
|
( commitindex
|
|
, do
|
|
nukeindex
|
|
missingbranch
|
|
)
|
|
| otherwise = ifM okindex
|
|
( noop
|
|
, do
|
|
nukeindex
|
|
ifM (null <$> inRepo (Git.Ref.matching [Annex.Branch.fullname]))
|
|
( missingbranch
|
|
, liftIO $ putStrLn "No data was lost."
|
|
)
|
|
)
|
|
where
|
|
okindex = Annex.Branch.withIndex $ inRepo Git.Repair.checkIndex
|
|
commitindex = do
|
|
Annex.Branch.forceCommit "committing index after git repository repair"
|
|
liftIO $ putStrLn "Successfully recovered the git-annex branch using .git/annex/index"
|
|
nukeindex = do
|
|
inRepo $ removeWhenExistsWith R.removeLink . gitAnnexIndex
|
|
liftIO $ putStrLn "Had to delete the .git/annex/index file as it was corrupt."
|
|
missingbranch = liftIO $ putStrLn "Since the git-annex branch is not up-to-date anymore. It would be a very good idea to run: git annex fsck --fast"
|
|
|
|
trackingOrSyncBranch :: Ref -> Bool
|
|
trackingOrSyncBranch b = Git.Repair.isTrackingBranch b || isAnnexSyncBranch b
|
|
|
|
isAnnexSyncBranch :: Ref -> Bool
|
|
isAnnexSyncBranch b = "refs/synced/" `isPrefixOf` fromRef b
|