Skip to content

Commit 03a8edd

Browse files
peffgitster
authored andcommitted
pack-refs: write peeled entry for non-tags
When we pack an annotated tag ref, we write not only the sha1 of the tag object along with the ref, but also the sha1 obtained by peeling the tag. This lets readers of the pack-refs file know the peeled value without having to actually load the object, speeding up upload-pack's ref advertisement. The writer marks a packed-refs file with peeled refs using the "peeled" trait at the top of the file. When the reader sees this trait, it knows that each ref is either followed by its peeled value, or it is not an annotated tag. However, there is a mismatch between the assumptions of the reader and writer. The writer will only peel refs under refs/tags, but the reader does not know this; it will assume a ref without a peeled value must not be a tag object. Thus an annotated tag object placed outside of the refs/tags hierarchy will not have its peeled value printed by upload-pack. The simplest way to fix this is to start writing peel values for all refs. This matches what the reader expects for both new and old versions of git. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent f7892d1 commit 03a8edd

File tree

2 files changed

+50
-8
lines changed

2 files changed

+50
-8
lines changed

pack-refs.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ static int handle_one_ref(const char *path, const unsigned char *sha1,
2727
int flags, void *cb_data)
2828
{
2929
struct pack_refs_cb_data *cb = cb_data;
30+
struct object *o;
3031
int is_tag_ref;
3132

3233
/* Do not pack the symbolic refs */
@@ -39,14 +40,13 @@ static int handle_one_ref(const char *path, const unsigned char *sha1,
3940
return 0;
4041

4142
fprintf(cb->refs_file, "%s %s\n", sha1_to_hex(sha1), path);
42-
if (is_tag_ref) {
43-
struct object *o = parse_object_or_die(sha1, path);
44-
if (o->type == OBJ_TAG) {
45-
o = deref_tag(o, path, 0);
46-
if (o)
47-
fprintf(cb->refs_file, "^%s\n",
48-
sha1_to_hex(o->sha1));
49-
}
43+
44+
o = parse_object_or_die(sha1, path);
45+
if (o->type == OBJ_TAG) {
46+
o = deref_tag(o, path, 0);
47+
if (o)
48+
fprintf(cb->refs_file, "^%s\n",
49+
sha1_to_hex(o->sha1));
5050
}
5151

5252
if ((cb->flags & PACK_REFS_PRUNE) && !do_not_prune(flags)) {

t/t3211-peel-ref.sh

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#!/bin/sh
2+
3+
test_description='tests for the peel_ref optimization of packed-refs'
4+
. ./test-lib.sh
5+
6+
test_expect_success 'create annotated tag in refs/tags' '
7+
test_commit base &&
8+
git tag -m annotated foo
9+
'
10+
11+
test_expect_success 'create annotated tag outside of refs/tags' '
12+
git update-ref refs/outside/foo refs/tags/foo
13+
'
14+
15+
# This matches show-ref's output
16+
print_ref() {
17+
echo "$(git rev-parse "$1") $1"
18+
}
19+
20+
test_expect_success 'set up expected show-ref output' '
21+
{
22+
print_ref "refs/heads/master" &&
23+
print_ref "refs/outside/foo" &&
24+
print_ref "refs/outside/foo^{}" &&
25+
print_ref "refs/tags/base" &&
26+
print_ref "refs/tags/foo" &&
27+
print_ref "refs/tags/foo^{}"
28+
} >expect
29+
'
30+
31+
test_expect_success 'refs are peeled outside of refs/tags (loose)' '
32+
git show-ref -d >actual &&
33+
test_cmp expect actual
34+
'
35+
36+
test_expect_success 'refs are peeled outside of refs/tags (packed)' '
37+
git pack-refs --all &&
38+
git show-ref -d >actual &&
39+
test_cmp expect actual
40+
'
41+
42+
test_done

0 commit comments

Comments
 (0)