diff options
| -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 |
