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>
This commit is contained in:
Johannes Schindelin 2021-02-10 16:11:38 +00:00 committed by Junio C Hamano
parent c6102b7585
commit c809798b2a
2 changed files with 29 additions and 0 deletions

View File

@ -602,6 +602,9 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
*/ */
if (cb.cmd.stalefix) { if (cb.cmd.stalefix) {
repo_init_revisions(the_repository, &cb.cmd.revs, prefix); repo_init_revisions(the_repository, &cb.cmd.revs, prefix);
cb.cmd.revs.do_not_die_on_missing_tree = 1;
cb.cmd.revs.ignore_missing = 1;
cb.cmd.revs.ignore_missing_links = 1;
if (flags & EXPIRE_REFLOGS_VERBOSE) if (flags & EXPIRE_REFLOGS_VERBOSE)
printf(_("Marking reachable objects...")); printf(_("Marking reachable objects..."));
mark_reachable_objects(&cb.cmd.revs, 0, 0, NULL); mark_reachable_objects(&cb.cmd.revs, 0, 0, NULL);

View File

@ -158,6 +158,32 @@ test_expect_success 'reflog expire' '
check_fsck "dangling commit $K" check_fsck "dangling commit $K"
' '
test_expect_success '--stale-fix handles missing objects generously' '
git -c core.logAllRefUpdates=false fast-import --date-format=now <<-EOS &&
commit refs/heads/stale-fix
mark :1
committer Author <a@uth.or> now
data <<EOF
start stale fix
EOF
M 100644 inline file
data <<EOF
contents
EOF
commit refs/heads/stale-fix
committer Author <a@uth.or> now
data <<EOF
stale fix branch tip
EOF
from :1
EOS
parent_oid=$(git rev-parse stale-fix^) &&
test_when_finished "recover $parent_oid" &&
corrupt $parent_oid &&
git reflog expire --stale-fix
'
test_expect_success 'prune and fsck' ' test_expect_success 'prune and fsck' '
git prune && git prune &&