author | Lars Hjemli <hjemli@gmail.com> | 2008-12-06 16:38:19 (UTC) |
---|---|---|
committer | Lars Hjemli <hjemli@gmail.com> | 2008-12-06 16:38:19 (UTC) |
commit | f86a23ff537258d36bf8f1876fa7a4bede6673d8 (patch) (unidiff) | |
tree | 8328d415416058cdc5b0fd2c6564ddcab5766c7a /shared.c | |
parent | 140012d7a8e51df5a9f9c556696778b86ade4fc9 (diff) | |
download | cgit-f86a23ff537258d36bf8f1876fa7a4bede6673d8.zip cgit-f86a23ff537258d36bf8f1876fa7a4bede6673d8.tar.gz cgit-f86a23ff537258d36bf8f1876fa7a4bede6673d8.tar.bz2 |
Add a 'stats' page to each repo
This new page, which is disabled by default, can be used to print some
statistics about the number of commits per period in the repository,
where period can be either weeks, months, quarters or years.
The function can be activated globally by setting 'enable-stats=1' in
cgitrc and disabled for individual repos by setting 'repo.enable-stats=0'.
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
-rw-r--r-- | shared.c | 1 |
1 files changed, 1 insertions, 0 deletions
@@ -1,344 +1,345 @@ | |||
1 | /* shared.c: global vars + some callback functions | 1 | /* shared.c: global vars + some callback functions |
2 | * | 2 | * |
3 | * Copyright (C) 2006 Lars Hjemli | 3 | * Copyright (C) 2006 Lars Hjemli |
4 | * | 4 | * |
5 | * Licensed under GNU General Public License v2 | 5 | * Licensed under GNU General Public License v2 |
6 | * (see COPYING for full license text) | 6 | * (see COPYING for full license text) |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include "cgit.h" | 9 | #include "cgit.h" |
10 | 10 | ||
11 | struct cgit_repolist cgit_repolist; | 11 | struct cgit_repolist cgit_repolist; |
12 | struct cgit_context ctx; | 12 | struct cgit_context ctx; |
13 | int cgit_cmd; | 13 | int cgit_cmd; |
14 | 14 | ||
15 | int chk_zero(int result, char *msg) | 15 | int chk_zero(int result, char *msg) |
16 | { | 16 | { |
17 | if (result != 0) | 17 | if (result != 0) |
18 | die("%s: %s", msg, strerror(errno)); | 18 | die("%s: %s", msg, strerror(errno)); |
19 | return result; | 19 | return result; |
20 | } | 20 | } |
21 | 21 | ||
22 | int chk_positive(int result, char *msg) | 22 | int chk_positive(int result, char *msg) |
23 | { | 23 | { |
24 | if (result <= 0) | 24 | if (result <= 0) |
25 | die("%s: %s", msg, strerror(errno)); | 25 | die("%s: %s", msg, strerror(errno)); |
26 | return result; | 26 | return result; |
27 | } | 27 | } |
28 | 28 | ||
29 | int chk_non_negative(int result, char *msg) | 29 | int chk_non_negative(int result, char *msg) |
30 | { | 30 | { |
31 | if (result < 0) | 31 | if (result < 0) |
32 | die("%s: %s",msg, strerror(errno)); | 32 | die("%s: %s",msg, strerror(errno)); |
33 | return result; | 33 | return result; |
34 | } | 34 | } |
35 | 35 | ||
36 | struct cgit_repo *cgit_add_repo(const char *url) | 36 | struct cgit_repo *cgit_add_repo(const char *url) |
37 | { | 37 | { |
38 | struct cgit_repo *ret; | 38 | struct cgit_repo *ret; |
39 | 39 | ||
40 | if (++cgit_repolist.count > cgit_repolist.length) { | 40 | if (++cgit_repolist.count > cgit_repolist.length) { |
41 | if (cgit_repolist.length == 0) | 41 | if (cgit_repolist.length == 0) |
42 | cgit_repolist.length = 8; | 42 | cgit_repolist.length = 8; |
43 | else | 43 | else |
44 | cgit_repolist.length *= 2; | 44 | cgit_repolist.length *= 2; |
45 | cgit_repolist.repos = xrealloc(cgit_repolist.repos, | 45 | cgit_repolist.repos = xrealloc(cgit_repolist.repos, |
46 | cgit_repolist.length * | 46 | cgit_repolist.length * |
47 | sizeof(struct cgit_repo)); | 47 | sizeof(struct cgit_repo)); |
48 | } | 48 | } |
49 | 49 | ||
50 | ret = &cgit_repolist.repos[cgit_repolist.count-1]; | 50 | ret = &cgit_repolist.repos[cgit_repolist.count-1]; |
51 | ret->url = trim_end(url, '/'); | 51 | ret->url = trim_end(url, '/'); |
52 | ret->name = ret->url; | 52 | ret->name = ret->url; |
53 | ret->path = NULL; | 53 | ret->path = NULL; |
54 | ret->desc = "[no description]"; | 54 | ret->desc = "[no description]"; |
55 | ret->owner = NULL; | 55 | ret->owner = NULL; |
56 | ret->group = ctx.cfg.repo_group; | 56 | ret->group = ctx.cfg.repo_group; |
57 | ret->defbranch = "master"; | 57 | ret->defbranch = "master"; |
58 | ret->snapshots = ctx.cfg.snapshots; | 58 | ret->snapshots = ctx.cfg.snapshots; |
59 | ret->enable_log_filecount = ctx.cfg.enable_log_filecount; | 59 | ret->enable_log_filecount = ctx.cfg.enable_log_filecount; |
60 | ret->enable_log_linecount = ctx.cfg.enable_log_linecount; | 60 | ret->enable_log_linecount = ctx.cfg.enable_log_linecount; |
61 | ret->enable_stats = ctx.cfg.enable_stats; | ||
61 | ret->module_link = ctx.cfg.module_link; | 62 | ret->module_link = ctx.cfg.module_link; |
62 | ret->readme = NULL; | 63 | ret->readme = NULL; |
63 | return ret; | 64 | return ret; |
64 | } | 65 | } |
65 | 66 | ||
66 | struct cgit_repo *cgit_get_repoinfo(const char *url) | 67 | struct cgit_repo *cgit_get_repoinfo(const char *url) |
67 | { | 68 | { |
68 | int i; | 69 | int i; |
69 | struct cgit_repo *repo; | 70 | struct cgit_repo *repo; |
70 | 71 | ||
71 | for (i=0; i<cgit_repolist.count; i++) { | 72 | for (i=0; i<cgit_repolist.count; i++) { |
72 | repo = &cgit_repolist.repos[i]; | 73 | repo = &cgit_repolist.repos[i]; |
73 | if (!strcmp(repo->url, url)) | 74 | if (!strcmp(repo->url, url)) |
74 | return repo; | 75 | return repo; |
75 | } | 76 | } |
76 | return NULL; | 77 | return NULL; |
77 | } | 78 | } |
78 | 79 | ||
79 | void *cgit_free_commitinfo(struct commitinfo *info) | 80 | void *cgit_free_commitinfo(struct commitinfo *info) |
80 | { | 81 | { |
81 | free(info->author); | 82 | free(info->author); |
82 | free(info->author_email); | 83 | free(info->author_email); |
83 | free(info->committer); | 84 | free(info->committer); |
84 | free(info->committer_email); | 85 | free(info->committer_email); |
85 | free(info->subject); | 86 | free(info->subject); |
86 | free(info->msg); | 87 | free(info->msg); |
87 | free(info->msg_encoding); | 88 | free(info->msg_encoding); |
88 | free(info); | 89 | free(info); |
89 | return NULL; | 90 | return NULL; |
90 | } | 91 | } |
91 | 92 | ||
92 | char *trim_end(const char *str, char c) | 93 | char *trim_end(const char *str, char c) |
93 | { | 94 | { |
94 | int len; | 95 | int len; |
95 | char *s, *t; | 96 | char *s, *t; |
96 | 97 | ||
97 | if (str == NULL) | 98 | if (str == NULL) |
98 | return NULL; | 99 | return NULL; |
99 | t = (char *)str; | 100 | t = (char *)str; |
100 | len = strlen(t); | 101 | len = strlen(t); |
101 | while(len > 0 && t[len - 1] == c) | 102 | while(len > 0 && t[len - 1] == c) |
102 | len--; | 103 | len--; |
103 | 104 | ||
104 | if (len == 0) | 105 | if (len == 0) |
105 | return NULL; | 106 | return NULL; |
106 | 107 | ||
107 | c = t[len]; | 108 | c = t[len]; |
108 | t[len] = '\0'; | 109 | t[len] = '\0'; |
109 | s = xstrdup(t); | 110 | s = xstrdup(t); |
110 | t[len] = c; | 111 | t[len] = c; |
111 | return s; | 112 | return s; |
112 | } | 113 | } |
113 | 114 | ||
114 | char *strlpart(char *txt, int maxlen) | 115 | char *strlpart(char *txt, int maxlen) |
115 | { | 116 | { |
116 | char *result; | 117 | char *result; |
117 | 118 | ||
118 | if (!txt) | 119 | if (!txt) |
119 | return txt; | 120 | return txt; |
120 | 121 | ||
121 | if (strlen(txt) <= maxlen) | 122 | if (strlen(txt) <= maxlen) |
122 | return txt; | 123 | return txt; |
123 | result = xmalloc(maxlen + 1); | 124 | result = xmalloc(maxlen + 1); |
124 | memcpy(result, txt, maxlen - 3); | 125 | memcpy(result, txt, maxlen - 3); |
125 | result[maxlen-1] = result[maxlen-2] = result[maxlen-3] = '.'; | 126 | result[maxlen-1] = result[maxlen-2] = result[maxlen-3] = '.'; |
126 | result[maxlen] = '\0'; | 127 | result[maxlen] = '\0'; |
127 | return result; | 128 | return result; |
128 | } | 129 | } |
129 | 130 | ||
130 | char *strrpart(char *txt, int maxlen) | 131 | char *strrpart(char *txt, int maxlen) |
131 | { | 132 | { |
132 | char *result; | 133 | char *result; |
133 | 134 | ||
134 | if (!txt) | 135 | if (!txt) |
135 | return txt; | 136 | return txt; |
136 | 137 | ||
137 | if (strlen(txt) <= maxlen) | 138 | if (strlen(txt) <= maxlen) |
138 | return txt; | 139 | return txt; |
139 | result = xmalloc(maxlen + 1); | 140 | result = xmalloc(maxlen + 1); |
140 | memcpy(result + 3, txt + strlen(txt) - maxlen + 4, maxlen - 3); | 141 | memcpy(result + 3, txt + strlen(txt) - maxlen + 4, maxlen - 3); |
141 | result[0] = result[1] = result[2] = '.'; | 142 | result[0] = result[1] = result[2] = '.'; |
142 | return result; | 143 | return result; |
143 | } | 144 | } |
144 | 145 | ||
145 | void cgit_add_ref(struct reflist *list, struct refinfo *ref) | 146 | void cgit_add_ref(struct reflist *list, struct refinfo *ref) |
146 | { | 147 | { |
147 | size_t size; | 148 | size_t size; |
148 | 149 | ||
149 | if (list->count >= list->alloc) { | 150 | if (list->count >= list->alloc) { |
150 | list->alloc += (list->alloc ? list->alloc : 4); | 151 | list->alloc += (list->alloc ? list->alloc : 4); |
151 | size = list->alloc * sizeof(struct refinfo *); | 152 | size = list->alloc * sizeof(struct refinfo *); |
152 | list->refs = xrealloc(list->refs, size); | 153 | list->refs = xrealloc(list->refs, size); |
153 | } | 154 | } |
154 | list->refs[list->count++] = ref; | 155 | list->refs[list->count++] = ref; |
155 | } | 156 | } |
156 | 157 | ||
157 | struct refinfo *cgit_mk_refinfo(const char *refname, const unsigned char *sha1) | 158 | struct refinfo *cgit_mk_refinfo(const char *refname, const unsigned char *sha1) |
158 | { | 159 | { |
159 | struct refinfo *ref; | 160 | struct refinfo *ref; |
160 | 161 | ||
161 | ref = xmalloc(sizeof (struct refinfo)); | 162 | ref = xmalloc(sizeof (struct refinfo)); |
162 | ref->refname = xstrdup(refname); | 163 | ref->refname = xstrdup(refname); |
163 | ref->object = parse_object(sha1); | 164 | ref->object = parse_object(sha1); |
164 | switch (ref->object->type) { | 165 | switch (ref->object->type) { |
165 | case OBJ_TAG: | 166 | case OBJ_TAG: |
166 | ref->tag = cgit_parse_tag((struct tag *)ref->object); | 167 | ref->tag = cgit_parse_tag((struct tag *)ref->object); |
167 | break; | 168 | break; |
168 | case OBJ_COMMIT: | 169 | case OBJ_COMMIT: |
169 | ref->commit = cgit_parse_commit((struct commit *)ref->object); | 170 | ref->commit = cgit_parse_commit((struct commit *)ref->object); |
170 | break; | 171 | break; |
171 | } | 172 | } |
172 | return ref; | 173 | return ref; |
173 | } | 174 | } |
174 | 175 | ||
175 | int cgit_refs_cb(const char *refname, const unsigned char *sha1, int flags, | 176 | int cgit_refs_cb(const char *refname, const unsigned char *sha1, int flags, |
176 | void *cb_data) | 177 | void *cb_data) |
177 | { | 178 | { |
178 | struct reflist *list = (struct reflist *)cb_data; | 179 | struct reflist *list = (struct reflist *)cb_data; |
179 | struct refinfo *info = cgit_mk_refinfo(refname, sha1); | 180 | struct refinfo *info = cgit_mk_refinfo(refname, sha1); |
180 | 181 | ||
181 | if (info) | 182 | if (info) |
182 | cgit_add_ref(list, info); | 183 | cgit_add_ref(list, info); |
183 | return 0; | 184 | return 0; |
184 | } | 185 | } |
185 | 186 | ||
186 | void cgit_diff_tree_cb(struct diff_queue_struct *q, | 187 | void cgit_diff_tree_cb(struct diff_queue_struct *q, |
187 | struct diff_options *options, void *data) | 188 | struct diff_options *options, void *data) |
188 | { | 189 | { |
189 | int i; | 190 | int i; |
190 | 191 | ||
191 | for (i = 0; i < q->nr; i++) { | 192 | for (i = 0; i < q->nr; i++) { |
192 | if (q->queue[i]->status == 'U') | 193 | if (q->queue[i]->status == 'U') |
193 | continue; | 194 | continue; |
194 | ((filepair_fn)data)(q->queue[i]); | 195 | ((filepair_fn)data)(q->queue[i]); |
195 | } | 196 | } |
196 | } | 197 | } |
197 | 198 | ||
198 | static int load_mmfile(mmfile_t *file, const unsigned char *sha1) | 199 | static int load_mmfile(mmfile_t *file, const unsigned char *sha1) |
199 | { | 200 | { |
200 | enum object_type type; | 201 | enum object_type type; |
201 | 202 | ||
202 | if (is_null_sha1(sha1)) { | 203 | if (is_null_sha1(sha1)) { |
203 | file->ptr = (char *)""; | 204 | file->ptr = (char *)""; |
204 | file->size = 0; | 205 | file->size = 0; |
205 | } else { | 206 | } else { |
206 | file->ptr = read_sha1_file(sha1, &type, | 207 | file->ptr = read_sha1_file(sha1, &type, |
207 | (unsigned long *)&file->size); | 208 | (unsigned long *)&file->size); |
208 | } | 209 | } |
209 | return 1; | 210 | return 1; |
210 | } | 211 | } |
211 | 212 | ||
212 | /* | 213 | /* |
213 | * Receive diff-buffers from xdiff and concatenate them as | 214 | * Receive diff-buffers from xdiff and concatenate them as |
214 | * needed across multiple callbacks. | 215 | * needed across multiple callbacks. |
215 | * | 216 | * |
216 | * This is basically a copy of xdiff-interface.c/xdiff_outf(), | 217 | * This is basically a copy of xdiff-interface.c/xdiff_outf(), |
217 | * ripped from git and modified to use globals instead of | 218 | * ripped from git and modified to use globals instead of |
218 | * a special callback-struct. | 219 | * a special callback-struct. |
219 | */ | 220 | */ |
220 | char *diffbuf = NULL; | 221 | char *diffbuf = NULL; |
221 | int buflen = 0; | 222 | int buflen = 0; |
222 | 223 | ||
223 | int filediff_cb(void *priv, mmbuffer_t *mb, int nbuf) | 224 | int filediff_cb(void *priv, mmbuffer_t *mb, int nbuf) |
224 | { | 225 | { |
225 | int i; | 226 | int i; |
226 | 227 | ||
227 | for (i = 0; i < nbuf; i++) { | 228 | for (i = 0; i < nbuf; i++) { |
228 | if (mb[i].ptr[mb[i].size-1] != '\n') { | 229 | if (mb[i].ptr[mb[i].size-1] != '\n') { |
229 | /* Incomplete line */ | 230 | /* Incomplete line */ |
230 | diffbuf = xrealloc(diffbuf, buflen + mb[i].size); | 231 | diffbuf = xrealloc(diffbuf, buflen + mb[i].size); |
231 | memcpy(diffbuf + buflen, mb[i].ptr, mb[i].size); | 232 | memcpy(diffbuf + buflen, mb[i].ptr, mb[i].size); |
232 | buflen += mb[i].size; | 233 | buflen += mb[i].size; |
233 | continue; | 234 | continue; |
234 | } | 235 | } |
235 | 236 | ||
236 | /* we have a complete line */ | 237 | /* we have a complete line */ |
237 | if (!diffbuf) { | 238 | if (!diffbuf) { |
238 | ((linediff_fn)priv)(mb[i].ptr, mb[i].size); | 239 | ((linediff_fn)priv)(mb[i].ptr, mb[i].size); |
239 | continue; | 240 | continue; |
240 | } | 241 | } |
241 | diffbuf = xrealloc(diffbuf, buflen + mb[i].size); | 242 | diffbuf = xrealloc(diffbuf, buflen + mb[i].size); |
242 | memcpy(diffbuf + buflen, mb[i].ptr, mb[i].size); | 243 | memcpy(diffbuf + buflen, mb[i].ptr, mb[i].size); |
243 | ((linediff_fn)priv)(diffbuf, buflen + mb[i].size); | 244 | ((linediff_fn)priv)(diffbuf, buflen + mb[i].size); |
244 | free(diffbuf); | 245 | free(diffbuf); |
245 | diffbuf = NULL; | 246 | diffbuf = NULL; |
246 | buflen = 0; | 247 | buflen = 0; |
247 | } | 248 | } |
248 | if (diffbuf) { | 249 | if (diffbuf) { |
249 | ((linediff_fn)priv)(diffbuf, buflen); | 250 | ((linediff_fn)priv)(diffbuf, buflen); |
250 | free(diffbuf); | 251 | free(diffbuf); |
251 | diffbuf = NULL; | 252 | diffbuf = NULL; |
252 | buflen = 0; | 253 | buflen = 0; |
253 | } | 254 | } |
254 | return 0; | 255 | return 0; |
255 | } | 256 | } |
256 | 257 | ||
257 | int cgit_diff_files(const unsigned char *old_sha1, | 258 | int cgit_diff_files(const unsigned char *old_sha1, |
258 | const unsigned char *new_sha1, | 259 | const unsigned char *new_sha1, |
259 | linediff_fn fn) | 260 | linediff_fn fn) |
260 | { | 261 | { |
261 | mmfile_t file1, file2; | 262 | mmfile_t file1, file2; |
262 | xpparam_t diff_params; | 263 | xpparam_t diff_params; |
263 | xdemitconf_t emit_params; | 264 | xdemitconf_t emit_params; |
264 | xdemitcb_t emit_cb; | 265 | xdemitcb_t emit_cb; |
265 | 266 | ||
266 | if (!load_mmfile(&file1, old_sha1) || !load_mmfile(&file2, new_sha1)) | 267 | if (!load_mmfile(&file1, old_sha1) || !load_mmfile(&file2, new_sha1)) |
267 | return 1; | 268 | return 1; |
268 | 269 | ||
269 | diff_params.flags = XDF_NEED_MINIMAL; | 270 | diff_params.flags = XDF_NEED_MINIMAL; |
270 | emit_params.ctxlen = 3; | 271 | emit_params.ctxlen = 3; |
271 | emit_params.flags = XDL_EMIT_FUNCNAMES; | 272 | emit_params.flags = XDL_EMIT_FUNCNAMES; |
272 | emit_params.find_func = NULL; | 273 | emit_params.find_func = NULL; |
273 | emit_cb.outf = filediff_cb; | 274 | emit_cb.outf = filediff_cb; |
274 | emit_cb.priv = fn; | 275 | emit_cb.priv = fn; |
275 | xdl_diff(&file1, &file2, &diff_params, &emit_params, &emit_cb); | 276 | xdl_diff(&file1, &file2, &diff_params, &emit_params, &emit_cb); |
276 | return 0; | 277 | return 0; |
277 | } | 278 | } |
278 | 279 | ||
279 | void cgit_diff_tree(const unsigned char *old_sha1, | 280 | void cgit_diff_tree(const unsigned char *old_sha1, |
280 | const unsigned char *new_sha1, | 281 | const unsigned char *new_sha1, |
281 | filepair_fn fn, const char *prefix) | 282 | filepair_fn fn, const char *prefix) |
282 | { | 283 | { |
283 | struct diff_options opt; | 284 | struct diff_options opt; |
284 | int ret; | 285 | int ret; |
285 | int prefixlen; | 286 | int prefixlen; |
286 | 287 | ||
287 | diff_setup(&opt); | 288 | diff_setup(&opt); |
288 | opt.output_format = DIFF_FORMAT_CALLBACK; | 289 | opt.output_format = DIFF_FORMAT_CALLBACK; |
289 | opt.detect_rename = 1; | 290 | opt.detect_rename = 1; |
290 | opt.rename_limit = ctx.cfg.renamelimit; | 291 | opt.rename_limit = ctx.cfg.renamelimit; |
291 | DIFF_OPT_SET(&opt, RECURSIVE); | 292 | DIFF_OPT_SET(&opt, RECURSIVE); |
292 | opt.format_callback = cgit_diff_tree_cb; | 293 | opt.format_callback = cgit_diff_tree_cb; |
293 | opt.format_callback_data = fn; | 294 | opt.format_callback_data = fn; |
294 | if (prefix) { | 295 | if (prefix) { |
295 | opt.nr_paths = 1; | 296 | opt.nr_paths = 1; |
296 | opt.paths = &prefix; | 297 | opt.paths = &prefix; |
297 | prefixlen = strlen(prefix); | 298 | prefixlen = strlen(prefix); |
298 | opt.pathlens = &prefixlen; | 299 | opt.pathlens = &prefixlen; |
299 | } | 300 | } |
300 | diff_setup_done(&opt); | 301 | diff_setup_done(&opt); |
301 | 302 | ||
302 | if (old_sha1 && !is_null_sha1(old_sha1)) | 303 | if (old_sha1 && !is_null_sha1(old_sha1)) |
303 | ret = diff_tree_sha1(old_sha1, new_sha1, "", &opt); | 304 | ret = diff_tree_sha1(old_sha1, new_sha1, "", &opt); |
304 | else | 305 | else |
305 | ret = diff_root_tree_sha1(new_sha1, "", &opt); | 306 | ret = diff_root_tree_sha1(new_sha1, "", &opt); |
306 | diffcore_std(&opt); | 307 | diffcore_std(&opt); |
307 | diff_flush(&opt); | 308 | diff_flush(&opt); |
308 | } | 309 | } |
309 | 310 | ||
310 | void cgit_diff_commit(struct commit *commit, filepair_fn fn) | 311 | void cgit_diff_commit(struct commit *commit, filepair_fn fn) |
311 | { | 312 | { |
312 | unsigned char *old_sha1 = NULL; | 313 | unsigned char *old_sha1 = NULL; |
313 | 314 | ||
314 | if (commit->parents) | 315 | if (commit->parents) |
315 | old_sha1 = commit->parents->item->object.sha1; | 316 | old_sha1 = commit->parents->item->object.sha1; |
316 | cgit_diff_tree(old_sha1, commit->object.sha1, fn, NULL); | 317 | cgit_diff_tree(old_sha1, commit->object.sha1, fn, NULL); |
317 | } | 318 | } |
318 | 319 | ||
319 | int cgit_parse_snapshots_mask(const char *str) | 320 | int cgit_parse_snapshots_mask(const char *str) |
320 | { | 321 | { |
321 | const struct cgit_snapshot_format *f; | 322 | const struct cgit_snapshot_format *f; |
322 | static const char *delim = " \t,:/|;"; | 323 | static const char *delim = " \t,:/|;"; |
323 | int tl, sl, rv = 0; | 324 | int tl, sl, rv = 0; |
324 | 325 | ||
325 | /* favor legacy setting */ | 326 | /* favor legacy setting */ |
326 | if(atoi(str)) | 327 | if(atoi(str)) |
327 | return 1; | 328 | return 1; |
328 | for(;;) { | 329 | for(;;) { |
329 | str += strspn(str,delim); | 330 | str += strspn(str,delim); |
330 | tl = strcspn(str,delim); | 331 | tl = strcspn(str,delim); |
331 | if (!tl) | 332 | if (!tl) |
332 | break; | 333 | break; |
333 | for (f = cgit_snapshot_formats; f->suffix; f++) { | 334 | for (f = cgit_snapshot_formats; f->suffix; f++) { |
334 | sl = strlen(f->suffix); | 335 | sl = strlen(f->suffix); |
335 | if((tl == sl && !strncmp(f->suffix, str, tl)) || | 336 | if((tl == sl && !strncmp(f->suffix, str, tl)) || |
336 | (tl == sl-1 && !strncmp(f->suffix+1, str, tl-1))) { | 337 | (tl == sl-1 && !strncmp(f->suffix+1, str, tl-1))) { |
337 | rv |= f->bit; | 338 | rv |= f->bit; |
338 | break; | 339 | break; |
339 | } | 340 | } |
340 | } | 341 | } |
341 | str += tl; | 342 | str += tl; |
342 | } | 343 | } |
343 | return rv; | 344 | return rv; |
344 | } | 345 | } |