Skip to content

Commit e6dbffa

Browse files
peffgitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 44da6f6 commit e6dbffa

File tree

4 files changed

+6
-22
lines changed

4 files changed

+6
-22
lines changed

builtin/describe.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ static int get_name(const char *path, const unsigned char *sha1, int flag, void
144144
if (!all && !might_be_tag)
145145
return 0;
146146

147-
if (!peel_ref(path, peeled) && !is_null_sha1(peeled)) {
147+
if (!peel_ref(path, peeled)) {
148148
is_tag = !!hashcmp(sha1, peeled);
149149
} else {
150150
hashcpy(peeled, sha1);

builtin/pack-objects.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2033,7 +2033,6 @@ static int add_ref_tag(const char *path, const unsigned char *sha1, int flag, vo
20332033

20342034
if (!prefixcmp(path, "refs/tags/") && /* is a tag? */
20352035
!peel_ref(path, peeled) && /* peelable? */
2036-
!is_null_sha1(peeled) && /* annotated tag? */
20372036
locate_object_entry(peeled)) /* object packed? */
20382037
add_object_entry(sha1, OBJ_TAG, NULL, 0);
20392038
return 0;

builtin/show-ref.c

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ static void show_one(const char *refname, const unsigned char *sha1)
2828

2929
static int show_ref(const char *refname, const unsigned char *sha1, int flag, void *cbdata)
3030
{
31-
struct object *obj;
3231
const char *hex;
3332
unsigned char peeled[20];
3433

@@ -79,25 +78,9 @@ static int show_ref(const char *refname, const unsigned char *sha1, int flag, vo
7978
if (!deref_tags)
8079
return 0;
8180

82-
if ((flag & REF_ISPACKED) && !peel_ref(refname, peeled)) {
83-
if (!is_null_sha1(peeled)) {
84-
hex = find_unique_abbrev(peeled, abbrev);
85-
printf("%s %s^{}\n", hex, refname);
86-
}
87-
}
88-
else {
89-
obj = parse_object(sha1);
90-
if (!obj)
91-
die("git show-ref: bad ref %s (%s)", refname,
92-
sha1_to_hex(sha1));
93-
if (obj->type == OBJ_TAG) {
94-
obj = deref_tag(obj, refname, 0);
95-
if (!obj)
96-
die("git show-ref: bad tag at ref %s (%s)", refname,
97-
sha1_to_hex(sha1));
98-
hex = find_unique_abbrev(obj->sha1, abbrev);
99-
printf("%s %s^{}\n", hex, refname);
100-
}
81+
if (!peel_ref(refname, peeled)) {
82+
hex = find_unique_abbrev(peeled, abbrev);
83+
printf("%s %s^{}\n", hex, refname);
10184
}
10285
return 0;
10386
}

refs.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,6 +1202,8 @@ int peel_ref(const char *refname, unsigned char *sha1)
12021202
if (current_ref && (current_ref->name == refname
12031203
|| !strcmp(current_ref->name, refname))) {
12041204
if (current_ref->flag & REF_KNOWS_PEELED) {
1205+
if (is_null_sha1(current_ref->u.value.peeled))
1206+
return -1;
12051207
hashcpy(sha1, current_ref->u.value.peeled);
12061208
return 0;
12071209
}

0 commit comments

Comments
 (0)