fix git-annex repair false positive
authorJoey Hess <joeyh@joeyh.name>
Wed, 4 May 2022 15:32:23 +0000 (11:32 -0400)
committerJoey Hess <joeyh@joeyh.name>
Wed, 4 May 2022 15:32:23 +0000 (11:32 -0400)
Avoid treating refs/annex/last-index or other refs that are not commit
objects as evidence of repository corruption.

The repair code checks to find bad refs by trying to run `git log` on
them, and assumes that no output means something is broken.  But git log
on a tree object is empty.

This was worth fixing generally, not as a special case, since it's certainly
possible that other things store tree or other objects in refs.

Sponsored-by: Max Thoursie on Patreon
CHANGELOG
Git/Repair.hs
doc/bugs/git_annex_repair_failed__58___missing_objects.mdwn
doc/bugs/git_annex_repair_failed__58___missing_objects/comment_3_317bee33fe675a5abb6fe65540a33d25._comment [new file with mode: 0644]

index 6f53e3e1ac9dc6da42d56fba40b85b4c709ab8de..4178427d62b796b65f724bd54546f6f2fe6c840f 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -14,6 +14,8 @@ git-annex (10.20220323) UNRELEASED; urgency=medium
   * rsync 3.2.4 broke backwards-compatability by preventing exposing
     filenames to the shell. Made the rsync and gcrypt special remotes
     detect this and disable shellescape. Closes: #1010397
+  * repair: Avoid treating refs/annex/last-index or other refs that
+    are not commit objects as evidence of repository corruption.
 
  -- Joey Hess <id@joeyh.name>  Mon, 28 Mar 2022 14:46:10 -0400
 
index 3e5c3fced01402c6d6ac9c6f91a89f8767168468..7d47f8461404ac061ed6aea5343275d8ca99ec01 100644 (file)
@@ -325,7 +325,11 @@ findUncorruptedCommit missing goodcommits branch r = do
  - the commit. Also adds to a set of commit shas that have been verified to
  - be good, which can be passed into subsequent calls to avoid
  - redundant work when eg, chasing down branches to find the first
- - uncorrupted commit. -}
+ - uncorrupted commit.
+ -
+ - When the sha is not a commit but some other git object, returns
+ - true, but does not add it to the set.
+ -}
 verifyCommit :: MissingObjects -> GoodCommits -> Sha -> Repo -> IO (Bool, GoodCommits)
 verifyCommit missing goodcommits commit r
        | checkGoodCommit commit goodcommits = return (True, goodcommits)
@@ -337,16 +341,23 @@ verifyCommit missing goodcommits commit r
                        , Param (fromRef commit)
                        ] r
                let committrees = map (parse . decodeBL) ls
-               if any isNothing committrees || null committrees
-                       then do
-                               void cleanup
-                               return (False, goodcommits)
-                       else do
-                               let cts = catMaybes committrees
-                               ifM (cleanup <&&> check cts)
-                                       ( return (True, addGoodCommits (map fst cts) goodcommits)
-                                       , return (False, goodcommits)
-                                       )
+               -- git log on an object that is not a commit will
+               -- succeed without any output
+               if null committrees
+                       then ifM cleanup
+                               ( return (True, goodcommits)
+                               , return (False, goodcommits)
+                               )
+                       else if any isNothing committrees
+                               then do
+                                       void cleanup
+                                       return (False, goodcommits)
+                               else do
+                                       let cts = catMaybes committrees
+                                       ifM (cleanup <&&> check cts)
+                                               ( return (True, addGoodCommits (map fst cts) goodcommits)
+                                               , return (False, goodcommits)
+                                               )
   where
        parse l = case words l of
                (commitsha:treesha:[]) -> (,)
index ac11a3a2be969544dabec28acf077b4647c32e93..687a81e9033aa4f3a60234503ad01f250bb9a856 100644 (file)
@@ -45,4 +45,4 @@ The bug is very easy to reproduce. This happens in a bigger repository of mine,
 
 Using it daily, with small-sized repositories.
 
-
+> [[fixed|done]] --[[Joey]] 
diff --git a/doc/bugs/git_annex_repair_failed__58___missing_objects/comment_3_317bee33fe675a5abb6fe65540a33d25._comment b/doc/bugs/git_annex_repair_failed__58___missing_objects/comment_3_317bee33fe675a5abb6fe65540a33d25._comment
new file mode 100644 (file)
index 0000000..3e971fa
--- /dev/null
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 3"""
+ date="2022-05-04T15:06:31Z"
+ content="""
+Thank you, your "Reproducible Example" worked for me to reproduce it!
+Great work finding this and tracking down an easy way to reproduce it.
+
+So the root of the problem is refs/annex/last-index,
+which contains a tree object, not a commit object. That is unusual for a ref,
+but git-annex has a good reason to record a tree's ref there. 
+
+Fixed
+"""]]