summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2010-03-16 05:12:55 (GMT)
committerJunio C Hamano <gitster@pobox.com>2010-03-16 06:37:42 (GMT)
commite01de1c9122c3cba118da19fe0ba0ce913fa7285 (patch)
tree771e254d2c8f33f3bb91512f6f04d68a17078f30
parent011c181cc656c8b3e48882729d1b6238e8c5c537 (diff)
downloadgit-e01de1c9122c3cba118da19fe0ba0ce913fa7285.zip
git-e01de1c9122c3cba118da19fe0ba0ce913fa7285.tar.gz
git-e01de1c9122c3cba118da19fe0ba0ce913fa7285.tar.bz2
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 <gitster@pobox.com>
-rw-r--r--refs.c11
-rwxr-xr-xt/t5505-remote.sh6
2 files changed, 10 insertions, 7 deletions
diff --git a/refs.c b/refs.c
index 3da3c8c..9c12f5e 100644
--- a/refs.c
+++ b/refs.c
@@ -6,6 +6,7 @@
/* ISSYMREF=01 and ISPACKED=02 are public interfaces */
#define REF_KNOWS_PEELED 04
+#define REF_BROKEN 010
struct ref_list {
struct ref_list *next;
@@ -275,8 +276,10 @@ static struct ref_list *get_ref_dir(const char *base, struct ref_list *list)
list = get_ref_dir(ref, list);
continue;
}
- if (!resolve_ref(ref, sha1, 1, &flag))
+ if (!resolve_ref(ref, sha1, 1, &flag)) {
hashclr(sha1);
+ flag |= REF_BROKEN;
+ }
list = add_ref(ref, sha1, flag, list, NULL);
}
free(ref);
@@ -531,10 +534,10 @@ static int do_one_ref(const char *base, each_ref_fn fn, int trim,
{
if (strncmp(base, entry->name, trim))
return 0;
- /* Is this a "negative ref" that represents a deleted ref? */
- if (is_null_sha1(entry->sha1))
- return 0;
+
if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN)) {
+ if (entry->flag & REF_BROKEN)
+ return 0; /* ignore dangling symref */
if (!has_sha1_file(entry->sha1)) {
error("%s does not point to a valid object!", entry->name);
return 0;
diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
index e70246b..98e8ec0 100755
--- a/t/t5505-remote.sh
+++ b/t/t5505-remote.sh
@@ -478,15 +478,15 @@ test_expect_success 'remote prune to cause a dangling symref' '
(
cd seven &&
git remote prune origin
- ) 2>err &&
+ ) >err 2>&1 &&
grep "has become dangling" err &&
- : And the dangling symref will not cause other annoying errors
+ : And the dangling symref will not cause other annoying errors &&
(
cd seven &&
git branch -a
) 2>err &&
- ! grep "points nowhere" err
+ ! grep "points nowhere" err &&
(
cd seven &&
test_must_fail git branch nomore origin