|
diff --git a/shared.c b/shared.c index 1cd60a2..343a4f9 100644 --- a/ shared.c+++ b/ shared.c |
|
@@ -215,193 +215,194 @@ void cgit_global_config_cb(const char *name, const char *value) |
215 | |
215 | |
216 | void cgit_querystring_cb(const char *name, const char *value) |
216 | void cgit_querystring_cb(const char *name, const char *value) |
217 | { |
217 | { |
218 | if (!strcmp(name,"r")) { |
218 | if (!strcmp(name,"r")) { |
219 | cgit_query_repo = xstrdup(value); |
219 | cgit_query_repo = xstrdup(value); |
220 | cgit_repo = cgit_get_repoinfo(value); |
220 | cgit_repo = cgit_get_repoinfo(value); |
221 | } else if (!strcmp(name, "p")) { |
221 | } else if (!strcmp(name, "p")) { |
222 | cgit_query_page = xstrdup(value); |
222 | cgit_query_page = xstrdup(value); |
223 | cgit_cmd = cgit_get_cmd_index(value); |
223 | cgit_cmd = cgit_get_cmd_index(value); |
224 | } else if (!strcmp(name, "url")) { |
224 | } else if (!strcmp(name, "url")) { |
225 | cgit_parse_url(value); |
225 | cgit_parse_url(value); |
226 | } else if (!strcmp(name, "q")) { |
226 | } else if (!strcmp(name, "q")) { |
227 | cgit_query_search = xstrdup(value); |
227 | cgit_query_search = xstrdup(value); |
228 | } else if (!strcmp(name, "h")) { |
228 | } else if (!strcmp(name, "h")) { |
229 | cgit_query_head = xstrdup(value); |
229 | cgit_query_head = xstrdup(value); |
230 | cgit_query_has_symref = 1; |
230 | cgit_query_has_symref = 1; |
231 | } else if (!strcmp(name, "id")) { |
231 | } else if (!strcmp(name, "id")) { |
232 | cgit_query_sha1 = xstrdup(value); |
232 | cgit_query_sha1 = xstrdup(value); |
233 | cgit_query_has_sha1 = 1; |
233 | cgit_query_has_sha1 = 1; |
234 | } else if (!strcmp(name, "id2")) { |
234 | } else if (!strcmp(name, "id2")) { |
235 | cgit_query_sha2 = xstrdup(value); |
235 | cgit_query_sha2 = xstrdup(value); |
236 | cgit_query_has_sha1 = 1; |
236 | cgit_query_has_sha1 = 1; |
237 | } else if (!strcmp(name, "ofs")) { |
237 | } else if (!strcmp(name, "ofs")) { |
238 | cgit_query_ofs = atoi(value); |
238 | cgit_query_ofs = atoi(value); |
239 | } else if (!strcmp(name, "path")) { |
239 | } else if (!strcmp(name, "path")) { |
240 | cgit_query_path = trim_end(value, '/'); |
240 | cgit_query_path = trim_end(value, '/'); |
241 | } else if (!strcmp(name, "name")) { |
241 | } else if (!strcmp(name, "name")) { |
242 | cgit_query_name = xstrdup(value); |
242 | cgit_query_name = xstrdup(value); |
243 | } |
243 | } |
244 | } |
244 | } |
245 | |
245 | |
246 | void *cgit_free_commitinfo(struct commitinfo *info) |
246 | void *cgit_free_commitinfo(struct commitinfo *info) |
247 | { |
247 | { |
248 | free(info->author); |
248 | free(info->author); |
249 | free(info->author_email); |
249 | free(info->author_email); |
250 | free(info->committer); |
250 | free(info->committer); |
251 | free(info->committer_email); |
251 | free(info->committer_email); |
252 | free(info->subject); |
252 | free(info->subject); |
253 | free(info); |
253 | free(info); |
254 | return NULL; |
254 | return NULL; |
255 | } |
255 | } |
256 | |
256 | |
257 | int hextoint(char c) |
257 | int hextoint(char c) |
258 | { |
258 | { |
259 | if (c >= 'a' && c <= 'f') |
259 | if (c >= 'a' && c <= 'f') |
260 | return 10 + c - 'a'; |
260 | return 10 + c - 'a'; |
261 | else if (c >= 'A' && c <= 'F') |
261 | else if (c >= 'A' && c <= 'F') |
262 | return 10 + c - 'A'; |
262 | return 10 + c - 'A'; |
263 | else if (c >= '0' && c <= '9') |
263 | else if (c >= '0' && c <= '9') |
264 | return c - '0'; |
264 | return c - '0'; |
265 | else |
265 | else |
266 | return -1; |
266 | return -1; |
267 | } |
267 | } |
268 | |
268 | |
269 | char *trim_end(const char *str, char c) |
269 | char *trim_end(const char *str, char c) |
270 | { |
270 | { |
271 | int len; |
271 | int len; |
272 | char *s, *t; |
272 | char *s, *t; |
273 | |
273 | |
274 | if (str == NULL) |
274 | if (str == NULL) |
275 | return NULL; |
275 | return NULL; |
276 | t = (char *)str; |
276 | t = (char *)str; |
277 | len = strlen(t); |
277 | len = strlen(t); |
278 | while(len > 0 && t[len - 1] == c) |
278 | while(len > 0 && t[len - 1] == c) |
279 | len--; |
279 | len--; |
280 | |
280 | |
281 | if (len == 0) |
281 | if (len == 0) |
282 | return NULL; |
282 | return NULL; |
283 | |
283 | |
284 | c = t[len]; |
284 | c = t[len]; |
285 | t[len] = '\0'; |
285 | t[len] = '\0'; |
286 | s = xstrdup(t); |
286 | s = xstrdup(t); |
287 | t[len] = c; |
287 | t[len] = c; |
288 | return s; |
288 | return s; |
289 | } |
289 | } |
290 | |
290 | |
291 | void cgit_diff_tree_cb(struct diff_queue_struct *q, |
291 | void cgit_diff_tree_cb(struct diff_queue_struct *q, |
292 | struct diff_options *options, void *data) |
292 | struct diff_options *options, void *data) |
293 | { |
293 | { |
294 | int i; |
294 | int i; |
295 | |
295 | |
296 | for (i = 0; i < q->nr; i++) { |
296 | for (i = 0; i < q->nr; i++) { |
297 | if (q->queue[i]->status == 'U') |
297 | if (q->queue[i]->status == 'U') |
298 | continue; |
298 | continue; |
299 | ((filepair_fn)data)(q->queue[i]); |
299 | ((filepair_fn)data)(q->queue[i]); |
300 | } |
300 | } |
301 | } |
301 | } |
302 | |
302 | |
303 | static int load_mmfile(mmfile_t *file, const unsigned char *sha1) |
303 | static int load_mmfile(mmfile_t *file, const unsigned char *sha1) |
304 | { |
304 | { |
305 | enum object_type type; |
305 | enum object_type type; |
306 | |
306 | |
307 | if (is_null_sha1(sha1)) { |
307 | if (is_null_sha1(sha1)) { |
308 | file->ptr = (char *)""; |
308 | file->ptr = (char *)""; |
309 | file->size = 0; |
309 | file->size = 0; |
310 | } else { |
310 | } else { |
311 | file->ptr = read_sha1_file(sha1, &type, &file->size); |
311 | file->ptr = read_sha1_file(sha1, &type, |
| |
312 | (unsigned long *)&file->size); |
312 | } |
313 | } |
313 | return 1; |
314 | return 1; |
314 | } |
315 | } |
315 | |
316 | |
316 | /* |
317 | /* |
317 | * Receive diff-buffers from xdiff and concatenate them as |
318 | * Receive diff-buffers from xdiff and concatenate them as |
318 | * needed across multiple callbacks. |
319 | * needed across multiple callbacks. |
319 | * |
320 | * |
320 | * This is basically a copy of xdiff-interface.c/xdiff_outf(), |
321 | * This is basically a copy of xdiff-interface.c/xdiff_outf(), |
321 | * ripped from git and modified to use globals instead of |
322 | * ripped from git and modified to use globals instead of |
322 | * a special callback-struct. |
323 | * a special callback-struct. |
323 | */ |
324 | */ |
324 | char *diffbuf = NULL; |
325 | char *diffbuf = NULL; |
325 | int buflen = 0; |
326 | int buflen = 0; |
326 | |
327 | |
327 | int filediff_cb(void *priv, mmbuffer_t *mb, int nbuf) |
328 | int filediff_cb(void *priv, mmbuffer_t *mb, int nbuf) |
328 | { |
329 | { |
329 | int i; |
330 | int i; |
330 | |
331 | |
331 | for (i = 0; i < nbuf; i++) { |
332 | for (i = 0; i < nbuf; i++) { |
332 | if (mb[i].ptr[mb[i].size-1] != '\n') { |
333 | if (mb[i].ptr[mb[i].size-1] != '\n') { |
333 | /* Incomplete line */ |
334 | /* Incomplete line */ |
334 | diffbuf = xrealloc(diffbuf, buflen + mb[i].size); |
335 | diffbuf = xrealloc(diffbuf, buflen + mb[i].size); |
335 | memcpy(diffbuf + buflen, mb[i].ptr, mb[i].size); |
336 | memcpy(diffbuf + buflen, mb[i].ptr, mb[i].size); |
336 | buflen += mb[i].size; |
337 | buflen += mb[i].size; |
337 | continue; |
338 | continue; |
338 | } |
339 | } |
339 | |
340 | |
340 | /* we have a complete line */ |
341 | /* we have a complete line */ |
341 | if (!diffbuf) { |
342 | if (!diffbuf) { |
342 | ((linediff_fn)priv)(mb[i].ptr, mb[i].size); |
343 | ((linediff_fn)priv)(mb[i].ptr, mb[i].size); |
343 | continue; |
344 | continue; |
344 | } |
345 | } |
345 | diffbuf = xrealloc(diffbuf, buflen + mb[i].size); |
346 | diffbuf = xrealloc(diffbuf, buflen + mb[i].size); |
346 | memcpy(diffbuf + buflen, mb[i].ptr, mb[i].size); |
347 | memcpy(diffbuf + buflen, mb[i].ptr, mb[i].size); |
347 | ((linediff_fn)priv)(diffbuf, buflen + mb[i].size); |
348 | ((linediff_fn)priv)(diffbuf, buflen + mb[i].size); |
348 | free(diffbuf); |
349 | free(diffbuf); |
349 | diffbuf = NULL; |
350 | diffbuf = NULL; |
350 | buflen = 0; |
351 | buflen = 0; |
351 | } |
352 | } |
352 | if (diffbuf) { |
353 | if (diffbuf) { |
353 | ((linediff_fn)priv)(diffbuf, buflen); |
354 | ((linediff_fn)priv)(diffbuf, buflen); |
354 | free(diffbuf); |
355 | free(diffbuf); |
355 | diffbuf = NULL; |
356 | diffbuf = NULL; |
356 | buflen = 0; |
357 | buflen = 0; |
357 | } |
358 | } |
358 | return 0; |
359 | return 0; |
359 | } |
360 | } |
360 | |
361 | |
361 | int cgit_diff_files(const unsigned char *old_sha1, |
362 | int cgit_diff_files(const unsigned char *old_sha1, |
362 | const unsigned char *new_sha1, |
363 | const unsigned char *new_sha1, |
363 | linediff_fn fn) |
364 | linediff_fn fn) |
364 | { |
365 | { |
365 | mmfile_t file1, file2; |
366 | mmfile_t file1, file2; |
366 | xpparam_t diff_params; |
367 | xpparam_t diff_params; |
367 | xdemitconf_t emit_params; |
368 | xdemitconf_t emit_params; |
368 | xdemitcb_t emit_cb; |
369 | xdemitcb_t emit_cb; |
369 | |
370 | |
370 | if (!load_mmfile(&file1, old_sha1) || !load_mmfile(&file2, new_sha1)) |
371 | if (!load_mmfile(&file1, old_sha1) || !load_mmfile(&file2, new_sha1)) |
371 | return 1; |
372 | return 1; |
372 | |
373 | |
373 | diff_params.flags = XDF_NEED_MINIMAL; |
374 | diff_params.flags = XDF_NEED_MINIMAL; |
374 | emit_params.ctxlen = 3; |
375 | emit_params.ctxlen = 3; |
375 | emit_params.flags = XDL_EMIT_FUNCNAMES; |
376 | emit_params.flags = XDL_EMIT_FUNCNAMES; |
376 | emit_params.find_func = NULL; |
377 | emit_params.find_func = NULL; |
377 | emit_cb.outf = filediff_cb; |
378 | emit_cb.outf = filediff_cb; |
378 | emit_cb.priv = fn; |
379 | emit_cb.priv = fn; |
379 | xdl_diff(&file1, &file2, &diff_params, &emit_params, &emit_cb); |
380 | xdl_diff(&file1, &file2, &diff_params, &emit_params, &emit_cb); |
380 | return 0; |
381 | return 0; |
381 | } |
382 | } |
382 | |
383 | |
383 | void cgit_diff_tree(const unsigned char *old_sha1, |
384 | void cgit_diff_tree(const unsigned char *old_sha1, |
384 | const unsigned char *new_sha1, |
385 | const unsigned char *new_sha1, |
385 | filepair_fn fn) |
386 | filepair_fn fn) |
386 | { |
387 | { |
387 | struct diff_options opt; |
388 | struct diff_options opt; |
388 | int ret; |
389 | int ret; |
389 | |
390 | |
390 | diff_setup(&opt); |
391 | diff_setup(&opt); |
391 | opt.output_format = DIFF_FORMAT_CALLBACK; |
392 | opt.output_format = DIFF_FORMAT_CALLBACK; |
392 | opt.detect_rename = 1; |
393 | opt.detect_rename = 1; |
393 | opt.recursive = 1; |
394 | opt.recursive = 1; |
394 | opt.format_callback = cgit_diff_tree_cb; |
395 | opt.format_callback = cgit_diff_tree_cb; |
395 | opt.format_callback_data = fn; |
396 | opt.format_callback_data = fn; |
396 | diff_setup_done(&opt); |
397 | diff_setup_done(&opt); |
397 | |
398 | |
398 | if (old_sha1 && !is_null_sha1(old_sha1)) |
399 | if (old_sha1 && !is_null_sha1(old_sha1)) |
399 | ret = diff_tree_sha1(old_sha1, new_sha1, "", &opt); |
400 | ret = diff_tree_sha1(old_sha1, new_sha1, "", &opt); |
400 | else |
401 | else |
401 | ret = diff_root_tree_sha1(new_sha1, "", &opt); |
402 | ret = diff_root_tree_sha1(new_sha1, "", &opt); |
402 | diffcore_std(&opt); |
403 | diffcore_std(&opt); |
403 | diff_flush(&opt); |
404 | diff_flush(&opt); |
404 | } |
405 | } |
405 | |
406 | |
406 | void cgit_diff_commit(struct commit *commit, filepair_fn fn) |
407 | void cgit_diff_commit(struct commit *commit, filepair_fn fn) |
407 | { |
408 | { |
|
|
diff --git a/ui-tree.c b/ui-tree.c index 15d1f5a..d6bcec3 100644 --- a/ ui-tree.c+++ b/ ui-tree.c |
|
@@ -1,114 +1,114 @@ |
1 | /* ui-tree.c: functions for tree output |
1 | /* ui-tree.c: functions for tree output |
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 | char *curr_rev; |
11 | char *curr_rev; |
12 | char *match_path; |
12 | char *match_path; |
13 | int header = 0; |
13 | int header = 0; |
14 | |
14 | |
15 | static void print_object(const unsigned char *sha1, char *path) |
15 | static void print_object(const unsigned char *sha1, char *path) |
16 | { |
16 | { |
17 | enum object_type type; |
17 | enum object_type type; |
18 | unsigned char *buf; |
18 | char *buf; |
19 | unsigned long size, lineno, start, idx; |
19 | unsigned long size, lineno, start, idx; |
20 | const char *linefmt = "<tr><td class='no'><a name='%1$d'>%1$d</a></td><td class='txt'>"; |
20 | const char *linefmt = "<tr><td class='no'><a name='%1$d'>%1$d</a></td><td class='txt'>"; |
21 | |
21 | |
22 | type = sha1_object_info(sha1, &size); |
22 | type = sha1_object_info(sha1, &size); |
23 | if (type == OBJ_BAD) { |
23 | if (type == OBJ_BAD) { |
24 | cgit_print_error(fmt("Bad object name: %s", |
24 | cgit_print_error(fmt("Bad object name: %s", |
25 | sha1_to_hex(sha1))); |
25 | sha1_to_hex(sha1))); |
26 | return; |
26 | return; |
27 | } |
27 | } |
28 | |
28 | |
29 | buf = read_sha1_file(sha1, &type, &size); |
29 | buf = read_sha1_file(sha1, &type, &size); |
30 | if (!buf) { |
30 | if (!buf) { |
31 | cgit_print_error(fmt("Error reading object %s", |
31 | cgit_print_error(fmt("Error reading object %s", |
32 | sha1_to_hex(sha1))); |
32 | sha1_to_hex(sha1))); |
33 | return; |
33 | return; |
34 | } |
34 | } |
35 | |
35 | |
36 | html(" blob: <a href='"); |
36 | html(" blob: <a href='"); |
37 | html_attr(cgit_pageurl(cgit_query_repo, "blob", fmt("id=%s", sha1_to_hex(sha1)))); |
37 | html_attr(cgit_pageurl(cgit_query_repo, "blob", fmt("id=%s", sha1_to_hex(sha1)))); |
38 | htmlf("'>%s</a>",sha1_to_hex(sha1)); |
38 | htmlf("'>%s</a>",sha1_to_hex(sha1)); |
39 | |
39 | |
40 | html("<table class='blob'>\n"); |
40 | html("<table class='blob'>\n"); |
41 | idx = 0; |
41 | idx = 0; |
42 | start = 0; |
42 | start = 0; |
43 | lineno = 0; |
43 | lineno = 0; |
44 | while(idx < size) { |
44 | while(idx < size) { |
45 | if (buf[idx] == '\n') { |
45 | if (buf[idx] == '\n') { |
46 | buf[idx] = '\0'; |
46 | buf[idx] = '\0'; |
47 | htmlf(linefmt, ++lineno); |
47 | htmlf(linefmt, ++lineno); |
48 | html_txt(buf + start); |
48 | html_txt(buf + start); |
49 | html("</td></tr>\n"); |
49 | html("</td></tr>\n"); |
50 | start = idx + 1; |
50 | start = idx + 1; |
51 | } |
51 | } |
52 | idx++; |
52 | idx++; |
53 | } |
53 | } |
54 | htmlf(linefmt, ++lineno); |
54 | htmlf(linefmt, ++lineno); |
55 | html_txt(buf + start); |
55 | html_txt(buf + start); |
56 | html("</td></tr>\n"); |
56 | html("</td></tr>\n"); |
57 | html("</table>\n"); |
57 | html("</table>\n"); |
58 | } |
58 | } |
59 | |
59 | |
60 | |
60 | |
61 | static int ls_item(const unsigned char *sha1, const char *base, int baselen, |
61 | static int ls_item(const unsigned char *sha1, const char *base, int baselen, |
62 | const char *pathname, unsigned int mode, int stage) |
62 | const char *pathname, unsigned int mode, int stage) |
63 | { |
63 | { |
64 | char *name; |
64 | char *name; |
65 | char *fullpath; |
65 | char *fullpath; |
66 | enum object_type type; |
66 | enum object_type type; |
67 | unsigned long size = 0; |
67 | unsigned long size = 0; |
68 | |
68 | |
69 | name = xstrdup(pathname); |
69 | name = xstrdup(pathname); |
70 | fullpath = fmt("%s%s%s", cgit_query_path ? cgit_query_path : "", |
70 | fullpath = fmt("%s%s%s", cgit_query_path ? cgit_query_path : "", |
71 | cgit_query_path ? "/" : "", name); |
71 | cgit_query_path ? "/" : "", name); |
72 | |
72 | |
73 | type = sha1_object_info(sha1, &size); |
73 | type = sha1_object_info(sha1, &size); |
74 | if (type == OBJ_BAD && !S_ISGITLINK(mode)) { |
74 | if (type == OBJ_BAD && !S_ISGITLINK(mode)) { |
75 | htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>", |
75 | htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>", |
76 | name, |
76 | name, |
77 | sha1_to_hex(sha1)); |
77 | sha1_to_hex(sha1)); |
78 | return 0; |
78 | return 0; |
79 | } |
79 | } |
80 | |
80 | |
81 | html("<tr><td class='ls-mode'>"); |
81 | html("<tr><td class='ls-mode'>"); |
82 | html_filemode(mode); |
82 | html_filemode(mode); |
83 | html("</td><td>"); |
83 | html("</td><td>"); |
84 | if (S_ISGITLINK(mode)) { |
84 | if (S_ISGITLINK(mode)) { |
85 | htmlf("<a class='ls-mod' href='"); |
85 | htmlf("<a class='ls-mod' href='"); |
86 | html_attr(fmt(cgit_repo->module_link, |
86 | html_attr(fmt(cgit_repo->module_link, |
87 | name, |
87 | name, |
88 | sha1_to_hex(sha1))); |
88 | sha1_to_hex(sha1))); |
89 | html("'>"); |
89 | html("'>"); |
90 | html_txt(name); |
90 | html_txt(name); |
91 | html("</a>"); |
91 | html("</a>"); |
92 | } else if (S_ISDIR(mode)) { |
92 | } else if (S_ISDIR(mode)) { |
93 | cgit_tree_link(name, NULL, "ls-dir", cgit_query_head, |
93 | cgit_tree_link(name, NULL, "ls-dir", cgit_query_head, |
94 | curr_rev, fullpath); |
94 | curr_rev, fullpath); |
95 | } else { |
95 | } else { |
96 | cgit_tree_link(name, NULL, "ls-blob", cgit_query_head, |
96 | cgit_tree_link(name, NULL, "ls-blob", cgit_query_head, |
97 | curr_rev, fullpath); |
97 | curr_rev, fullpath); |
98 | } |
98 | } |
99 | htmlf("</td><td class='ls-size'>%li</td>", size); |
99 | htmlf("</td><td class='ls-size'>%li</td>", size); |
100 | |
100 | |
101 | html("<td>"); |
101 | html("<td>"); |
102 | cgit_log_link("log", NULL, "button", cgit_query_head, curr_rev, |
102 | cgit_log_link("log", NULL, "button", cgit_query_head, curr_rev, |
103 | fullpath, 0); |
103 | fullpath, 0); |
104 | html("</td></tr>\n"); |
104 | html("</td></tr>\n"); |
105 | free(name); |
105 | free(name); |
106 | return 0; |
106 | return 0; |
107 | } |
107 | } |
108 | |
108 | |
109 | static void ls_head() |
109 | static void ls_head() |
110 | { |
110 | { |
111 | html("<table class='list'>\n"); |
111 | html("<table class='list'>\n"); |
112 | html("<tr class='nohover'>"); |
112 | html("<tr class='nohover'>"); |
113 | html("<th class='left'>Mode</th>"); |
113 | html("<th class='left'>Mode</th>"); |
114 | html("<th class='left'>Name</th>"); |
114 | html("<th class='left'>Name</th>"); |
|