about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorLukas Fleischer2016-05-24 18:15:18 +0200
committerJason A. Donenfeld2016-07-05 16:14:40 +0200
commit9984e7ab49c59e49a0d7e62c3435e7133f7a53ec (patch)
tree1f3a53622746e5fe43e9d5c7c9bc27ab2da22761
parentgit: update to v2.9.0 (diff)
downloadcgit-9984e7ab49c59e49a0d7e62c3435e7133f7a53ec.tar.gz
cgit-9984e7ab49c59e49a0d7e62c3435e7133f7a53ec.zip
Avoid ambiguities when prettifying snapshot names
When composing snapshot file names for a tag with a prefix of the form
v[0-9] (resp. V[0-9]), the leading "v" (resp. "V") is stripped. This
leads to conflicts if a tag with the stripped name already exists or if
there are tags only differing in the capitalization of the leading "v".
Make sure we do not strip the "v" in these cases.

Reported-by: Juuso Lapinlampi <wub@partyvan.eu>
Signed-off-by: Lukas Fleischer <lfleischer@lfos.de>
-rw-r--r--ui-refs.c24
-rw-r--r--ui-shared.c26
-rw-r--r--ui-shared.h2
3 files changed, 32 insertions, 20 deletions
diff --git a/ui-refs.c b/ui-refs.c index 5b4530e..75f2789 100644 --- a/ui-refs.c +++ b/ui-refs.c
@@ -93,34 +93,28 @@ static void print_tag_header(void)
93static void print_tag_downloads(const struct cgit_repo *repo, const char *ref) 93static void print_tag_downloads(const struct cgit_repo *repo, const char *ref)
94{ 94{
95 const struct cgit_snapshot_format* f; 95 const struct cgit_snapshot_format* f;
96 struct strbuf filename = STRBUF_INIT;
97 const char *basename; 96 const char *basename;
98 int free_ref = 0; 97 struct strbuf filename = STRBUF_INIT;
98 size_t prefixlen;
99 99
100 if (!ref || strlen(ref) < 1) 100 if (!ref || strlen(ref) < 1)
101 return; 101 return;
102 102
103 basename = cgit_repobasename(repo->url); 103 basename = cgit_repobasename(repo->url);
104 if (!starts_with(ref, basename)) { 104 if (starts_with(ref, basename))
105 if ((ref[0] == 'v' || ref[0] == 'V') && isdigit(ref[1])) 105 strbuf_addstr(&filename, ref);
106 ref++; 106 else
107 if (isdigit(ref[0])) { 107 cgit_compose_snapshot_prefix(&filename, basename, ref);
108 ref = fmtalloc("%s-%s", basename, ref); 108 prefixlen = filename.len;
109 free_ref = 1;
110 }
111 }
112
113 for (f = cgit_snapshot_formats; f->suffix; f++) { 109 for (f = cgit_snapshot_formats; f->suffix; f++) {
114 if (!(repo->snapshots & f->bit)) 110 if (!(repo->snapshots & f->bit))
115 continue; 111 continue;
116 strbuf_reset(&filename); 112 strbuf_setlen(&filename, prefixlen);
117 strbuf_addf(&filename, "%s%s", ref, f->suffix); 113 strbuf_addstr(&filename, f->suffix);
118 cgit_snapshot_link(filename.buf, NULL, NULL, NULL, NULL, filename.buf); 114 cgit_snapshot_link(filename.buf, NULL, NULL, NULL, NULL, filename.buf);
119 html("&nbsp;&nbsp;"); 115 html("&nbsp;&nbsp;");
120 } 116 }
121 117
122 if (free_ref)
123 free((char *)ref);
124 strbuf_release(&filename); 118 strbuf_release(&filename);
125} 119}
126 120
diff --git a/ui-shared.c b/ui-shared.c index 562fa0e..b1a6c46 100644 --- a/ui-shared.c +++ b/ui-shared.c
@@ -1069,18 +1069,34 @@ void cgit_print_filemode(unsigned short mode)
1069 html_fileperm(mode); 1069 html_fileperm(mode);
1070} 1070}
1071 1071
1072void cgit_compose_snapshot_prefix(struct strbuf *filename, const char *base,
1073 const char *ref)
1074{
1075 unsigned char sha1[20];
1076
1077 /*
1078 * Prettify snapshot names by stripping leading "v" or "V" if the tag
1079 * name starts with {v,V}[0-9] and the prettify mapping is injective,
1080 * i.e. each stripped tag can be inverted without ambiguities.
1081 */
1082 if (get_sha1(fmt("refs/tags/%s", ref), sha1) == 0 &&
1083 (ref[0] == 'v' || ref[0] == 'V') && isdigit(ref[1]) &&
1084 ((get_sha1(fmt("refs/tags/%s", ref + 1), sha1) == 0) +
1085 (get_sha1(fmt("refs/tags/v%s", ref + 1), sha1) == 0) +
1086 (get_sha1(fmt("refs/tags/V%s", ref + 1), sha1) == 0) == 1))
1087 ref++;
1088
1089 strbuf_addf(filename, "%s-%s", base, ref);
1090}
1091
1072void cgit_print_snapshot_links(const char *repo, const char *head, 1092void cgit_print_snapshot_links(const char *repo, const char *head,
1073 const char *hex, int snapshots) 1093 const char *hex, int snapshots)
1074{ 1094{
1075 const struct cgit_snapshot_format* f; 1095 const struct cgit_snapshot_format* f;
1076 struct strbuf filename = STRBUF_INIT; 1096 struct strbuf filename = STRBUF_INIT;
1077 size_t prefixlen; 1097 size_t prefixlen;
1078 unsigned char sha1[20];
1079 1098
1080 if (get_sha1(fmt("refs/tags/%s", hex), sha1) == 0 && 1099 cgit_compose_snapshot_prefix(&filename, cgit_repobasename(repo), hex);
1081 (hex[0] == 'v' || hex[0] == 'V') && isdigit(hex[1]))
1082 hex++;
1083 strbuf_addf(&filename, "%s-%s", cgit_repobasename(repo), hex);
1084 prefixlen = filename.len; 1100 prefixlen = filename.len;
1085 for (f = cgit_snapshot_formats; f->suffix; f++) { 1101 for (f = cgit_snapshot_formats; f->suffix; f++) {
1086 if (!(snapshots & f->bit)) 1102 if (!(snapshots & f->bit))
diff --git a/ui-shared.h b/ui-shared.h index b457c97..87799f1 100644 --- a/ui-shared.h +++ b/ui-shared.h
@@ -71,6 +71,8 @@ __attribute__((format (printf,3,4)))
71extern void cgit_print_error_page(int code, const char *msg, const char *fmt, ...); 71extern void cgit_print_error_page(int code, const char *msg, const char *fmt, ...);
72extern void cgit_print_pageheader(void); 72extern void cgit_print_pageheader(void);
73extern void cgit_print_filemode(unsigned short mode); 73extern void cgit_print_filemode(unsigned short mode);
74extern void cgit_compose_snapshot_prefix(struct strbuf *filename,
75 const char *base, const char *ref);
74extern void cgit_print_snapshot_links(const char *repo, const char *head, 76extern void cgit_print_snapshot_links(const char *repo, const char *head,
75 const char *hex, int snapshots); 77 const char *hex, int snapshots);
76extern void cgit_add_hidden_formfields(int incl_head, int incl_search, 78extern void cgit_add_hidden_formfields(int incl_head, int incl_search,