Skip to content

Commit e01de1c

Browse files
committed
refs: ref entry with NULL sha1 is can be a dangling symref
Brandon Casey noticed that t5505 had accidentally broken its && chain, hiding inconsistency between the code that writes the warning to the standard output and the test that expects to see the warning on the standard error, which was introduced by f8948e2 (remote prune: warn dangling symrefs, 2009-02-08). It turns out that the issue is deeper than that. After f8948e2, a symref that is dangling is marked with a NULL sha1, and the idea of using NULL sha1 to mean a deleted ref was scrapped, but somehow a follow-up eafb452 (do_one_ref(): null_sha1 check is not about broken ref, 2009-07-22) incorrectly reorganized do_one_ref(), still thinking NULL sha1 is never used in the code. Fix this by: - adopt Brandon's fix to t5505 test; - introduce REF_BROKEN flag to mark a ref that fails to resolve (dangling symref); - move the check for broken ref back inside the "if we are skipping dangling refs" code block. Signed-off-by: Junio C Hamano <[email protected]>
1 parent 011c181 commit e01de1c

File tree

2 files changed

+10
-7
lines changed

2 files changed

+10
-7
lines changed

refs.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
/* ISSYMREF=01 and ISPACKED=02 are public interfaces */
88
#define REF_KNOWS_PEELED 04
9+
#define REF_BROKEN 010
910

1011
struct ref_list {
1112
struct ref_list *next;
@@ -275,8 +276,10 @@ static struct ref_list *get_ref_dir(const char *base, struct ref_list *list)
275276
list = get_ref_dir(ref, list);
276277
continue;
277278
}
278-
if (!resolve_ref(ref, sha1, 1, &flag))
279+
if (!resolve_ref(ref, sha1, 1, &flag)) {
279280
hashclr(sha1);
281+
flag |= REF_BROKEN;
282+
}
280283
list = add_ref(ref, sha1, flag, list, NULL);
281284
}
282285
free(ref);
@@ -531,10 +534,10 @@ static int do_one_ref(const char *base, each_ref_fn fn, int trim,
531534
{
532535
if (strncmp(base, entry->name, trim))
533536
return 0;
534-
/* Is this a "negative ref" that represents a deleted ref? */
535-
if (is_null_sha1(entry->sha1))
536-
return 0;
537+
537538
if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN)) {
539+
if (entry->flag & REF_BROKEN)
540+
return 0; /* ignore dangling symref */
538541
if (!has_sha1_file(entry->sha1)) {
539542
error("%s does not point to a valid object!", entry->name);
540543
return 0;

t/t5505-remote.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -478,15 +478,15 @@ test_expect_success 'remote prune to cause a dangling symref' '
478478
(
479479
cd seven &&
480480
git remote prune origin
481-
) 2>err &&
481+
) >err 2>&1 &&
482482
grep "has become dangling" err &&
483483
484-
: And the dangling symref will not cause other annoying errors
484+
: And the dangling symref will not cause other annoying errors &&
485485
(
486486
cd seven &&
487487
git branch -a
488488
) 2>err &&
489-
! grep "points nowhere" err
489+
! grep "points nowhere" err &&
490490
(
491491
cd seven &&
492492
test_must_fail git branch nomore origin

0 commit comments

Comments
 (0)