diff options
| author | Bryce Kwon <bryce@brycekwon.com> | |
|---|---|---|
| committer | Bryce Kwon <bryce@brycekwon.com> | |
| commit | ||
| parent | ||
| tree | ||
| download | ||
Settle the snapshot v-prefix from the tag list
`compose_snapshot_prefix` dropped the leading v of a tag only when just
one of the names 1.2, v1.2 and V1.2 resolved as a tag, so that the
shorter snapshot name could always be traced back to one tag. Those
probes went through ref lookups, and on a case-insensitive filesystem
a lookup for V1.2 finds the loose file of v1.2, so every freshly made
tag counted as ambiguous and kept its v. Once git packed the refs the
lookups became exact and the same tag quietly changed its snapshot
names.
The claimants on a stripped name are now counted over the tag list
itself with exact string comparison, so the answer no longer depends
on how a ref is stored or on the filesystem underneath. Two tags that
really differ only by the letter's case still both keep it.
| -rw-r--r-- | source/ui-shared.c | 43 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -rwxr-xr-x | tests/t0110-snapshot.sh | 34 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2 files changed, 69 insertions, 8 deletions
diff --git a/source/ui-shared.c b/source/ui-shared.c index 58e7f03..2f0843c 100644 --- a/source/ui-shared.c +++ b/source/ui-shared.c @@ -1741,20 +1741,47 @@ void cgit_print_filemode(unsigned short mode) html_fileperm(mode); } -static void compose_snapshot_prefix(struct strbuf *filename, const char *base, const char *ref) +/* + * One tag's claim on a snapshot stem, the stem being the tag name with any + * leading v or V removed. Claims are counted over the tag list itself rather + * than by looking refs up by name, because a loose ref lookup on a + * case-insensitive filesystem finds v1.2 when asked for V1.2 and would call + * every tag still stored loose ambiguous. + */ +struct snapshot_stem { + const char *tag; + const char *stem; + int claimants; + int is_tag; +}; + +static int count_stem_claimants(const struct reference *ref, void *data) { - struct object_id oid; + struct snapshot_stem *probe = data; + const char *name = ref->name; + if (!strcmp(name, probe->tag)) + probe->is_tag = 1; + if (name[0] == 'v' || name[0] == 'V') + name++; + if (!strcmp(name, probe->stem)) + probe->claimants++; + return 0; +} + +static void compose_snapshot_prefix(struct strbuf *filename, const char *base, const char *ref) +{ // A tag named v1.2 or V1.2 gives its snapshot the prettier name 1.2, // but only where dropping the letter cannot land two different tags on // one name, so that a snapshot can still be traced back to the tag it // was made from. - if (repo_get_oid(the_repository, cgit_fmt("refs/tags/%s", ref), &oid) == 0 && - (ref[0] == 'v' || ref[0] == 'V') && isdigit((unsigned char)ref[1]) && - ((repo_get_oid(the_repository, cgit_fmt("refs/tags/%s", ref + 1), &oid) == 0) + - (repo_get_oid(the_repository, cgit_fmt("refs/tags/v%s", ref + 1), &oid) == 0) + - (repo_get_oid(the_repository, cgit_fmt("refs/tags/V%s", ref + 1), &oid) == 0) == 1)) - ref++; + if ((ref[0] == 'v' || ref[0] == 'V') && isdigit((unsigned char)ref[1])) { + struct snapshot_stem probe = { .tag = ref, .stem = ref + 1 }; + + refs_for_each_tag_ref(get_main_ref_store(the_repository), count_stem_claimants, &probe); + if (probe.is_tag && probe.claimants == 1) + ref++; + } strbuf_addf(filename, "%s-%s", base, ref); } diff --git a/tests/t0110-snapshot.sh b/tests/t0110-snapshot.sh index 9c8ce35..79fecef 100755 --- a/tests/t0110-snapshot.sh +++ b/tests/t0110-snapshot.sh @@ -112,4 +112,38 @@ test_expect_success UNZIP 'unzip and verify the content' ' test_line_count = 1 master/file-5 ' +# A tag named v1.0 sheds its v in the snapshot name unless dropping it would +# merge two tags. The first tag below stays a loose ref on purpose, because on +# a case-insensitive filesystem a ref lookup for V1.0 finds the loose v1.0 +# file, and deciding by lookups called every fresh tag ambiguous and kept its +# v until git happened to pack the refs. +test_expect_success 'set up a repo with a versioned tag' ' + mkrepo repos/vtags 2 && + git -C repos/vtags update-ref refs/tags/v1.0 HEAD && + { + echo "virtual-root=/" && + echo "cache-size=0" && + echo "snapshots=tar.gz" && + echo "repo.url=vtags" && + echo "repo.path=$PWD/repos/vtags/.git" + } >vtagsrc +' + +test_expect_success 'a loose v tag still sheds its v in the snapshot name' ' + CGIT_CONFIG="$PWD/vtagsrc" QUERY_STRING="url=vtags/refs/" cgit >tmp && + grep "vtags-1.0.tar.gz" tmp && + ! grep "vtags-v1.0.tar.gz" tmp +' + +# The second tag goes in only after the first is packed, since two loose files +# differing in case alone cannot coexist on a case-insensitive filesystem. +test_expect_success 'a real case collision keeps the v on both tags' ' + git -C repos/vtags pack-refs --all && + git -C repos/vtags update-ref refs/tags/V1.0 HEAD~1 && + CGIT_CONFIG="$PWD/vtagsrc" QUERY_STRING="url=vtags/refs/" cgit >tmp && + grep "vtags-v1.0.tar.gz" tmp && + grep "vtags-V1.0.tar.gz" tmp && + ! grep "vtags-1.0.tar.gz" tmp +' + test_done |
