Looks good aside from a couple of minor points mentioned below. On 03/16/2013 10:01 AM, Jeff King wrote: > 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 <peff@xxxxxxxx> I like your explanation of the problem. > --- > pack-refs.c | 16 ++++++++-------- > t/t3211-peel-ref.sh | 42 ++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 50 insertions(+), 8 deletions(-) > create mode 100755 t/t3211-peel-ref.sh > > diff --git a/pack-refs.c b/pack-refs.c > index f09a054..10832d7 100644 > --- a/pack-refs.c > +++ b/pack-refs.c > @@ -27,6 +27,7 @@ static int handle_one_ref(const char *path, const unsigned char *sha1, > int flags, void *cb_data) > { > struct pack_refs_cb_data *cb = cb_data; > + struct object *o; > int is_tag_ref; > > /* Do not pack the symbolic refs */ > @@ -39,14 +40,13 @@ static int handle_one_ref(const char *path, const unsigned char *sha1, > return 0; > > fprintf(cb->refs_file, "%s %s\n", sha1_to_hex(sha1), path); > - if (is_tag_ref) { > - struct object *o = parse_object(sha1); > - if (o->type == OBJ_TAG) { > - o = deref_tag(o, path, 0); > - if (o) > - fprintf(cb->refs_file, "^%s\n", > - sha1_to_hex(o->sha1)); > - } > + > + o = parse_object(sha1); > + if (o->type == OBJ_TAG) { You suggested that I add a test (o != NULL) at the equivalent place in my code (which was derived from this code). Granted, my code was explicitly intending to pass invalid SHA1 values to parse_object(). But wouldn't it be a good defensive step to add the same check here? > + o = deref_tag(o, path, 0); > + if (o) > + fprintf(cb->refs_file, "^%s\n", > + sha1_to_hex(o->sha1)); > } > > if ((cb->flags & PACK_REFS_PRUNE) && !do_not_prune(flags)) { > diff --git a/t/t3211-peel-ref.sh b/t/t3211-peel-ref.sh > new file mode 100755 > index 0000000..dd5b48b > --- /dev/null > +++ b/t/t3211-peel-ref.sh > @@ -0,0 +1,42 @@ > +#!/bin/sh > + > +test_description='tests for the peel_ref optimization of packed-refs' > +. ./test-lib.sh > + > +test_expect_success 'create annotated tag in refs/tags' ' > + test_commit base && > + git tag -m annotated foo > +' > + > +test_expect_success 'create annotated tag outside of refs/tags' ' > + git update-ref refs/outside/foo refs/tags/foo > +' > + > +# This matches show-ref's output > +print_ref() { > + echo "`git rev-parse "$1"` $1" > +} > + CodingGuidelines prefers $() over ``. > +test_expect_success 'set up expected show-ref output' ' > + { > + print_ref "refs/heads/master" && > + print_ref "refs/outside/foo" && > + print_ref "refs/outside/foo^{}" && > + print_ref "refs/tags/base" && > + print_ref "refs/tags/foo" && > + print_ref "refs/tags/foo^{}" > + } >expect > +' > + > +test_expect_success 'refs are peeled outside of refs/tags (loose)' ' > + git show-ref -d >actual && > + test_cmp expect actual > +' > + > +test_expect_success 'refs are peeled outside of refs/tags (packed)' ' > + git pack-refs --all && > + git show-ref -d >actual && > + test_cmp expect actual > +' > + > +test_done > -- Michael Haggerty mhagger@xxxxxxxxxxxx http://softwareswirl.blogspot.com/ -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html