diff options
-rw-r--r-- | Command/SendKey.hs | 4 | ||||
-rw-r--r-- | Command/TransferKey.hs | 2 | ||||
-rw-r--r-- | Git/Repair.hs | 24 | ||||
-rw-r--r-- | Utility/Misc.hs | 5 | ||||
-rw-r--r-- | Utility/Tmp.hs | 2 | ||||
-rw-r--r-- | debian/changelog | 4 | ||||
-rw-r--r-- | doc/devblog/day_60__damage_driven_development.mdwn | 36 |
7 files changed, 65 insertions, 12 deletions
diff --git a/Command/SendKey.hs b/Command/SendKey.hs index 039a3d7ca..24b1821c3 100644 --- a/Command/SendKey.hs +++ b/Command/SendKey.hs @@ -46,6 +46,4 @@ fieldTransfer direction key a = do ok <- maybe (a $ const noop) (\u -> runTransfer (Transfer direction (toUUID u) key) afile noRetry a) =<< Fields.getField Fields.remoteUUID - liftIO $ if ok - then exitSuccess - else exitFailure + liftIO $ exitBool ok diff --git a/Command/TransferKey.hs b/Command/TransferKey.hs index 3270ad8f7..5bb53d98d 100644 --- a/Command/TransferKey.hs +++ b/Command/TransferKey.hs @@ -56,4 +56,4 @@ fromPerform remote key file = go $ getViaTmp key $ \t -> Remote.retrieveKeyFile remote key file t p go :: Annex Bool -> CommandPerform -go a = ifM a ( liftIO exitSuccess, liftIO exitFailure) +go a = a >>= liftIO . exitBool diff --git a/Git/Repair.hs b/Git/Repair.hs index 270b04182..3e731aa55 100644 --- a/Git/Repair.hs +++ b/Git/Repair.hs @@ -8,6 +8,7 @@ module Git.Repair ( runRepair, runRepairOf, + successfulRepair, cleanCorruptObjects, retrieveMissingObjects, resetLocalBranches, @@ -47,7 +48,7 @@ import Data.Tuple.Utils - Since git fsck may crash on corrupt objects, and so not - report the full set of corrupt or missing objects, - this removes corrupt objects, and re-runs fsck, until it - - stabalizes. + - stabilizes. - - To remove corrupt objects, unpack all packs, and remove the packs - (to handle corrupt packs), and remove loose object files. @@ -78,11 +79,13 @@ cleanCorruptObjects mmissing r = check mmissing putStrLn "Re-running git fsck to see if it finds more problems." v <- findBroken False r case v of - Nothing -> error $ unwords - [ "git fsck found a problem, which was not corrected after removing" - , show (S.size oldbad) - , "corrupt objects." - ] + Nothing -> do + hPutStrLn stderr $ unwords + [ "git fsck found a problem, which was not corrected after removing" + , show (S.size oldbad) + , "corrupt objects." + ] + return S.empty Just newbad -> do removed <- removeLoose r newbad let s = S.union oldbad newbad @@ -452,6 +455,9 @@ runRepair forced g = do putStrLn "No problems found." return (True, S.empty, []) +successfulRepair :: (Bool, MissingObjects, [Branch]) -> Bool +successfulRepair = fst3 + runRepairOf :: FsckResults -> Bool -> Maybe FilePath -> Repo -> IO (Bool, MissingObjects, [Branch]) runRepairOf fsckresult forced referencerepo g = do missing <- cleanCorruptObjects fsckresult g @@ -512,8 +518,12 @@ runRepairOf fsckresult forced referencerepo g = do corruptedindex = do nukeIndex g + -- The corrupted index can prevent fsck from finding other + -- problems, so re-run repair. + fsckresult' <- findBroken False g + result <- runRepairOf fsckresult' forced referencerepo g putStrLn "Removed the corrupted index file. You should look at what files are present in your working tree and git add them back to the index when appropriate." - return (True, S.empty, []) + return result successfulfinish stillmissing modifiedbranches = do mapM_ putStrLn diff --git a/Utility/Misc.hs b/Utility/Misc.hs index a2c9c8184..4b0e9a1e4 100644 --- a/Utility/Misc.hs +++ b/Utility/Misc.hs @@ -15,6 +15,7 @@ import Foreign import Data.Char import Data.List import Control.Applicative +import System.Exit #ifndef mingw32_HOST_OS import System.Posix.Process (getAnyProcessStatus) import Utility.Exception @@ -136,3 +137,7 @@ reapZombies = do #else reapZombies = return () #endif + +exitBool :: Bool -> IO a +exitBool False = exitFailure +exitBool True = exitSuccess diff --git a/Utility/Tmp.hs b/Utility/Tmp.hs index 186cd121a..37706545a 100644 --- a/Utility/Tmp.hs +++ b/Utility/Tmp.hs @@ -62,7 +62,7 @@ withTmpDirIn :: FilePath -> Template -> (FilePath -> IO a) -> IO a withTmpDirIn tmpdir template = bracket create remove where remove d = whenM (doesDirectoryExist d) $ - removeDirectoryRecursive d + return () -- removeDirectoryRecursive d create = do createDirectoryIfMissing True tmpdir makenewdir (tmpdir </> template) (0 :: Int) diff --git a/debian/changelog b/debian/changelog index 919407551..4807b0281 100644 --- a/debian/changelog +++ b/debian/changelog @@ -5,6 +5,10 @@ git-annex (5.20131119) UNRELEASED; urgency=low * Ensure execute bit is set on directories when core.sharedrepository is set. * Ensure that core.sharedrepository is honored when creating the .git/annex directory. + * Improve repair code in the case where the index file is corrupt, + and this hides other problems. + * Fix Debian package to not try to run test suite, since haskell-tasty + is not out of new or in Build-Depends yet. -- Joey Hess <joeyh@debian.org> Mon, 18 Nov 2013 17:09:21 -0400 diff --git a/doc/devblog/day_60__damage_driven_development.mdwn b/doc/devblog/day_60__damage_driven_development.mdwn new file mode 100644 index 000000000..64460e86a --- /dev/null +++ b/doc/devblog/day_60__damage_driven_development.mdwn @@ -0,0 +1,36 @@ +Wrote some evil code you don't want to run today. Git.Destroyer randomly +generates Damage, and applies it to a git repository, in a way that is +reproducible -- applying the same Damage to clones of the same git repo +will always yeild the same result. + +This let me build a test harness for git-repair, which repeatedly clones, +damages, and repairs a repository. And when it fails, I can just ask it to +retry after fixing the bug and it'll re-run every attempt it's logged. + +This is already yeilding improvements to the git-repair code. +The first randomly constructed Damage that it failed to recover +turned out to be a truncated index file that hid some other +corrupted object files from being repaired. + + [Damage Empty (FileSelector 1), + Damage Empty (FileSelector 2), + Damage Empty (FileSelector 3), + Damage Reverse (FileSelector 3), + Damage (ScrambleFileMode 3) (FileSelector 5), + Damage Delete (FileSelector 9), + Damage (PrependGarbage "¥SOH¥STX¥ENQ¥f¥a¥ACK¥b¥DLE¥n") (FileSelector 9), + Damage Empty (FileSelector 12), + Damage (CorruptByte 11 25) (FileSelector 6), + Damage Empty (FileSelector 5), + Damage (ScrambleFileMode 4294967281) (FileSelector 14) + ] + +I need to improve the ranges of files that it damages -- currently QuickCheck +seems to only be selecting one of the first 20 or so files. Also, it's quite +common that it will damage `.git/config` so badly that git thinks it's not +a git repository anymore. I am not sure if that is something `git-repair` +should try to deal with. + +--- + +Today's work was sponsored by the WikiMedia Foundation. |