]> granicus.if.org Git - git/commitdiff
peel_ref(): fix return value for non-peelable, not-current reference
authorMichael Haggerty <mhagger@alum.mit.edu>
Mon, 22 Apr 2013 19:52:21 +0000 (21:52 +0200)
committerJunio C Hamano <gitster@pobox.com>
Wed, 1 May 2013 22:33:10 +0000 (15:33 -0700)
The old version was inconsistent: when a reference was
REF_KNOWS_PEELED but with a null peeled value, it returned non-zero
for the current reference but zero for other references.  Change the
behavior for non-current references to match that of current_ref,
which is what callers expect.  Document the behavior.

Current callers only call peel_ref() from within a for_each_ref-style
iteration and only for the current ref; therefore, the buggy code path
was never reached.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
refs.c
refs.h

diff --git a/refs.c b/refs.c
index 7405d1c9625201d7c7fff3f0e8a45c9b2d7e2583..787db21dfc1033082e98a10b0310b8a12c9f6c43 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -119,7 +119,8 @@ struct ref_value {
        /*
         * If REF_KNOWS_PEELED, then this field holds the peeled value
         * of this reference, or null if the reference is known not to
-        * be peelable.
+        * be peelable.  See the documentation for peel_ref() for an
+        * exact definition of "peelable".
         */
        unsigned char peeled[20];
 };
@@ -1340,6 +1341,8 @@ int peel_ref(const char *refname, unsigned char *sha1)
                struct ref_entry *r = get_packed_ref(refname);
 
                if (r && (r->flag & REF_KNOWS_PEELED)) {
+                       if (is_null_sha1(r->u.value.peeled))
+                           return -1;
                        hashcpy(sha1, r->u.value.peeled);
                        return 0;
                }
diff --git a/refs.h b/refs.h
index f111024a18049c6bca36aa1e03f67a6d9475c42e..3fc97a2e4af5f1fd923dd9c41f1b73ac9c66624c 100644 (file)
--- a/refs.h
+++ b/refs.h
@@ -74,6 +74,14 @@ extern void add_packed_ref(const char *refname, const unsigned char *sha1);
 
 extern int ref_exists(const char *);
 
+/*
+ * If refname is a non-symbolic reference that refers to a tag object,
+ * and the tag can be (recursively) dereferenced to a non-tag object,
+ * store the SHA1 of the referred-to object to sha1 and return 0.  If
+ * any of these conditions are not met, return a non-zero value.
+ * Symbolic references are considered unpeelable, even if they
+ * ultimately resolve to a peelable tag.
+ */
 extern int peel_ref(const char *refname, unsigned char *sha1);
 
 /** Locks a "refs/" ref returning the lock on success and NULL on failure. **/