reflog expire --stale-fix: be generous about missing objects

Whenever a user runs `git reflog expire --stale-fix`, the most likely reason is that their repository is at least _somewhat_ corrupt. Which means that it is more than just possible that some objects are missing. If that is the case, that can currently let the command abort through the phase where it tries to mark all reachable objects. Instead of adding insult to injury, let's be gentle and continue as best as we can in such a scenario, simply by ignoring the missing objects and moving on. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Johannes Schindelin committed Feb 10, 2021 at 16:11 UTC c809798b2acf1afdeeea02a9175677590ad8d689
2 files changed +29
builtin/reflog.c
+3
@@ -602,6 +602,9 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
602 */
603 if (cb.cmd.stalefix) {
604 repo_init_revisions(the_repository, &cb.cmd.revs, prefix);
605 + cb.cmd.revs.do_not_die_on_missing_tree = 1;
606 + cb.cmd.revs.ignore_missing = 1;
607 + cb.cmd.revs.ignore_missing_links = 1;
608 if (flags & EXPIRE_REFLOGS_VERBOSE)
609 printf(_("Marking reachable objects..."));
610 mark_reachable_objects(&cb.cmd.revs, 0, 0, NULL);
t/t1410-reflog.sh
+26
@@ -158,6 +158,32 @@ test_expect_success 'reflog expire' '
158 check_fsck "dangling commit $K"
159 '
160
161 +test_expect_success '--stale-fix handles missing objects generously' '
162 + git -c core.logAllRefUpdates=false fast-import --date-format=now <<-EOS &&
163 + commit refs/heads/stale-fix
164 + mark :1
165 + committer Author <a@uth.or> now
166 + data <<EOF
167 + start stale fix
168 + EOF
169 + M 100644 inline file
170 + data <<EOF
171 + contents
172 + EOF
173 + commit refs/heads/stale-fix
174 + committer Author <a@uth.or> now
175 + data <<EOF
176 + stale fix branch tip
177 + EOF
178 + from :1
179 + EOS
180 +
181 + parent_oid=$(git rev-parse stale-fix^) &&
182 + test_when_finished "recover $parent_oid" &&
183 + corrupt $parent_oid &&
184 + git reflog expire --stale-fix
185 +'
186 +
187 test_expect_success 'prune and fsck' '
188
189 git prune &&