about summary refs log tree commit diff stats
path: root/ui-snapshot.c
diff options
context:
space:
mode:
Diffstat (limited to 'ui-snapshot.c')
-rw-r--r--ui-snapshot.c60
1 files changed, 43 insertions, 17 deletions
diff --git a/ui-snapshot.c b/ui-snapshot.c index a47884e..8e76977 100644 --- a/ui-snapshot.c +++ b/ui-snapshot.c
@@ -15,14 +15,33 @@
15static int write_archive_type(const char *format, const char *hex, const char *prefix) 15static int write_archive_type(const char *format, const char *hex, const char *prefix)
16{ 16{
17 struct argv_array argv = ARGV_ARRAY_INIT; 17 struct argv_array argv = ARGV_ARRAY_INIT;
18 const char **nargv;
19 int result;
18 argv_array_push(&argv, "snapshot"); 20 argv_array_push(&argv, "snapshot");
19 argv_array_push(&argv, format); 21 argv_array_push(&argv, format);
20 if (prefix) { 22 if (prefix) {
23 struct strbuf buf = STRBUF_INIT;
24 strbuf_addstr(&buf, prefix);
25 strbuf_addch(&buf, '/');
21 argv_array_push(&argv, "--prefix"); 26 argv_array_push(&argv, "--prefix");
22 argv_array_push(&argv, fmt("%s/", prefix)); 27 argv_array_push(&argv, buf.buf);
28 strbuf_release(&buf);
23 } 29 }
24 argv_array_push(&argv, hex); 30 argv_array_push(&argv, hex);
25 return write_archive(argv.argc, argv.argv, NULL, 1, NULL, 0); 31 /*
32 * Now we need to copy the pointers to arguments into a new
33 * structure because write_archive will rearrange its arguments
34 * which may result in duplicated/missing entries causing leaks
35 * or double-frees in argv_array_clear.
36 */
37 nargv = xmalloc(sizeof(char *) * (argv.argc + 1));
38 /* argv_array guarantees a trailing NULL entry. */
39 memcpy(nargv, argv.argv, sizeof(char *) * (argv.argc + 1));
40
41 result = write_archive(argv.argc, nargv, NULL, 1, NULL, 0);
42 argv_array_clear(&argv);
43 free(nargv);
44 return result;
26} 45}
27 46
28static int write_tar_archive(const char *hex, const char *prefix) 47static int write_tar_archive(const char *hex, const char *prefix)
@@ -129,29 +148,36 @@ static const char *get_ref_from_filename(const char *url, const char *filename,
129{ 148{
130 const char *reponame; 149 const char *reponame;
131 unsigned char sha1[20]; 150 unsigned char sha1[20];
132 char *snapshot; 151 struct strbuf snapshot = STRBUF_INIT;
152 int result = 1;
133 153
134 snapshot = xstrdup(filename); 154 strbuf_addstr(&snapshot, filename);
135 snapshot[strlen(snapshot) - strlen(format->suffix)] = '\0'; 155 strbuf_setlen(&snapshot, snapshot.len - strlen(format->suffix));
136 156
137 if (get_sha1(snapshot, sha1) == 0) 157 if (get_sha1(snapshot.buf, sha1) == 0)
138 return snapshot; 158 goto out;
139 159
140 reponame = cgit_repobasename(url); 160 reponame = cgit_repobasename(url);
141 if (prefixcmp(snapshot, reponame) == 0) { 161 if (prefixcmp(snapshot.buf, reponame) == 0) {
142 snapshot += strlen(reponame); 162 const char *new_start = snapshot.buf;
143 while (snapshot && (*snapshot == '-' || *snapshot == '_')) 163 new_start += strlen(reponame);
144 snapshot++; 164 while (new_start && (*new_start == '-' || *new_start == '_'))
165 new_start++;
166 strbuf_splice(&snapshot, 0, new_start - snapshot.buf, "", 0);
145 } 167 }
146 168
147 if (get_sha1(snapshot, sha1) == 0) 169 if (get_sha1(snapshot.buf, sha1) == 0)
148 return snapshot; 170 goto out;
149 171
150 snapshot = fmt("v%s", snapshot); 172 strbuf_insert(&snapshot, 0, "v", 1);
151 if (get_sha1(snapshot, sha1) == 0) 173 if (get_sha1(snapshot.buf, sha1) == 0)
152 return snapshot; 174 goto out;
153 175
154 return NULL; 176 result = 0;
177 strbuf_release(&snapshot);
178
179out:
180 return result ? strbuf_detach(&snapshot, NULL) : NULL;
155} 181}
156 182
157__attribute__((format (printf, 1, 2))) 183__attribute__((format (printf, 1, 2)))