summaryrefslogtreecommitdiff
path: root/refs.c
diff options
context:
space:
mode:
authorJeff King <peff@peff.net>2012-10-04 04:00:19 -0400
committerJunio C Hamano <gitster@pobox.com>2012-10-04 20:34:28 -0700
commite6dbffa67b8e4c463a8fe18e8599b8623d7f0485 (patch)
treebb12877b78a62a56414cf63c3c0a92ef5e111575 /refs.c
parent44da6f69ecc4200a488b0647be9f5cb75cae6c4d (diff)
downloadgit-e6dbffa67b8e4c463a8fe18e8599b8623d7f0485.tar.gz
peel_ref: do not return a null sha1
The idea of the peel_ref function is to dereference tag objects recursively until we hit a non-tag, and return the sha1. Conceptually, it should return 0 if it is successful (and fill in the sha1), or -1 if there was nothing to peel. However, the current behavior is much more confusing. For a regular loose ref, the behavior is as described above. But there is an optimization to reuse the peeled-ref value for a ref that came from a packed-refs file. If we have such a ref, we return its peeled value, even if that peeled value is null (indicating that we know the ref definitely does _not_ peel). It might seem like such information is useful to the caller, who would then know not to bother loading and trying to peel the object. Except that they should not bother loading and trying to peel the object _anyway_, because that fallback is already handled by peel_ref. In other words, the whole point of calling this function is that it handles those details internally, and you either get a sha1, or you know that it is not peel-able. This patch catches the null sha1 case internally and converts it into a -1 return value (i.e., there is nothing to peel). This simplifies callers, which do not need to bother checking themselves. Two callers are worth noting: - in pack-objects, a comment indicates that there is a difference between non-peelable tags and unannotated tags. But that is not the case (before or after this patch). Whether you get a null sha1 has to do with internal details of how peel_ref operated. - in show-ref, if peel_ref returns a failure, the caller tries to decide whether to try peeling manually based on whether the REF_ISPACKED flag is set. But this doesn't make any sense. If the flag is set, that does not necessarily mean the ref came from a packed-refs file with the "peeled" extension. But it doesn't matter, because even if it didn't, there's no point in trying to peel it ourselves, as peel_ref would already have done so. In other words, the fallback peeling is guaranteed to fail. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'refs.c')
-rw-r--r--refs.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/refs.c b/refs.c
index 0a916a0c2a..f672ad93a6 100644
--- a/refs.c
+++ b/refs.c
@@ -1202,6 +1202,8 @@ int peel_ref(const char *refname, unsigned char *sha1)
if (current_ref && (current_ref->name == refname
|| !strcmp(current_ref->name, refname))) {
if (current_ref->flag & REF_KNOWS_PEELED) {
+ if (is_null_sha1(current_ref->u.value.peeled))
+ return -1;
hashcpy(sha1, current_ref->u.value.peeled);
return 0;
}