Skip to content

Commit d1ed8d6

Browse files
peffgitster
authored andcommitted
load_ref_decorations(): fix decoration with tags
Commit 88473c8 ("load_ref_decorations(): avoid parsing non-tag objects", 2021-06-22) introduced a shortcut to `add_ref_decoration()`: Rather than calling `parse_object()`, we go for `oid_object_info()` and then `lookup_object_by_type()` using the type just discovered. As detailed in the commit message, this provides a significant time saving. Unfortunately, it also changes the behavior: We lose all annotated tags from the decoration. The reason this happens is in the loop where we try to peel the tags, we won't necessarily have parsed that first object. If we haven't, its `tagged` field will be NULL, so we won't actually add a decoration for the pointed-to object. Make sure to parse the tag object at the top of the peeling loop. This effectively restores the pre-88473c8bae parsing -- but only of tags, allowing us to keep most of the possible speedup from 88473c8. On my big ~220k ref test case (where it's mostly non-tags), the timings [using "git log -1 --decorate"] are: - before either patch: 2.945s - with my broken patch: 0.707s - with [this patch]: 0.788s The simplest way to do this is to just conditionally parse before the loop: if (obj->type == OBJ_TAG) parse_object(&obj->oid); But we can observe that our tag-peeling loop needs to peel already, to examine recursive tags-of-tags. So instead of introducing a new call to parse_object(), we can simply move the parsing higher in the loop: instead of parsing the new object before we loop, parse each tag object before we look at its "tagged" field. This has another beneficial side effect: if a tag points at a commit (or other non-tag type), we do not bother to parse the commit at all now. And we know it is a commit without calling oid_object_info(), because parsing the surrounding tag object will have created the correct in-core object based on the "type" field of the tag. Our test coverage for --decorate was obviously not good, since we missed this quite-basic regression. The new tests covers an annotated tag (showing the fix), but also that we correctly show annotations for lightweight tags and double-annotated tag-of-tags. Reported-by: Martin Ågren <[email protected]> Helped-by: Martin Ågren <[email protected]> Signed-off-by: Martin Ågren <[email protected]> Signed-off-by: Jeff King <[email protected]> Reviewed-by: Martin Ågren <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 6afb265 commit d1ed8d6

File tree

2 files changed

+16
-2
lines changed

2 files changed

+16
-2
lines changed

log-tree.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,11 +174,11 @@ static int add_ref_decoration(const char *refname, const struct object_id *oid,
174174

175175
add_name_decoration(deco_type, refname, obj);
176176
while (obj->type == OBJ_TAG) {
177+
if (!obj->parsed)
178+
parse_object(the_repository, &obj->oid);
177179
obj = ((struct tag *)obj)->tagged;
178180
if (!obj)
179181
break;
180-
if (!obj->parsed)
181-
parse_object(the_repository, &obj->oid);
182182
add_name_decoration(DECORATION_REF_TAG, refname, obj);
183183
}
184184
return 0;

t/t4202-log.sh

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1905,6 +1905,20 @@ test_expect_success '--exclude-promisor-objects does not BUG-crash' '
19051905
test_must_fail git log --exclude-promisor-objects source-a
19061906
'
19071907

1908+
test_expect_success 'log --decorate includes all levels of tag annotated tags' '
1909+
git checkout -b branch &&
1910+
git commit --allow-empty -m "new commit" &&
1911+
git tag lightweight HEAD &&
1912+
git tag -m annotated annotated HEAD &&
1913+
git tag -m double-0 double-0 HEAD &&
1914+
git tag -m double-1 double-1 double-0 &&
1915+
cat >expect <<-\EOF &&
1916+
HEAD -> branch, tag: lightweight, tag: double-1, tag: double-0, tag: annotated
1917+
EOF
1918+
git log -1 --format="%D" >actual &&
1919+
test_cmp expect actual
1920+
'
1921+
19081922
test_expect_success 'log --end-of-options' '
19091923
git update-ref refs/heads/--source HEAD &&
19101924
git log --end-of-options --source >actual &&

0 commit comments

Comments
 (0)