Diffstat (limited to 'ui-diff.c')
| -rw-r--r-- | ui-diff.c | 88 |
1 files changed, 86 insertions, 2 deletions
@@ -8,6 +8,9 @@ #include "cgit.h" +char *diff_buffer; +int diff_buffer_size; + /* * print a single line returned from xdiff @@ -31,6 +34,88 @@ static void print_line(char *line, int len) line[len-1] = c; } +/* + * Receive diff-buffers from xdiff and concatenate them as + * needed across multiple callbacks. + * + * This is basically a copy of xdiff-interface.c/xdiff_outf(), + * ripped from git and modified to use globals instead of + * a special callback-struct. + */ +int diff_cb(void *priv_, mmbuffer_t *mb, int nbuf) +{ + int i; + + for (i = 0; i < nbuf; i++) { + if (mb[i].ptr[mb[i].size-1] != '\n') { + /* Incomplete line */ + diff_buffer = xrealloc(diff_buffer, + diff_buffer_size + mb[i].size); + memcpy(diff_buffer + diff_buffer_size, + mb[i].ptr, mb[i].size); + diff_buffer_size += mb[i].size; + continue; + } + + /* we have a complete line */ + if (!diff_buffer) { + print_line(mb[i].ptr, mb[i].size); + continue; + } + diff_buffer = xrealloc(diff_buffer, + diff_buffer_size + mb[i].size); + memcpy(diff_buffer + diff_buffer_size, mb[i].ptr, mb[i].size); + print_line(diff_buffer, diff_buffer_size + mb[i].size); + free(diff_buffer); + diff_buffer = NULL; + diff_buffer_size = 0; + } + if (diff_buffer) { + print_line(diff_buffer, diff_buffer_size); + free(diff_buffer); + diff_buffer = NULL; + diff_buffer_size = 0; + } + return 0; +} + +static int load_mmfile(mmfile_t *file, const unsigned char *sha1) +{ + enum object_type type; + + if (is_null_sha1(sha1)) { + file->ptr = (char *)""; + file->size = 0; + } else { + file->ptr = read_sha1_file(sha1, &type, &file->size); + } + return 1; +} + +static void run_diff(const unsigned char *sha1, const unsigned char *sha2) +{ + mmfile_t file1, file2; + xpparam_t diff_params; + xdemitconf_t emit_params; + xdemitcb_t emit_cb; + + if (!load_mmfile(&file1, sha1) || !load_mmfile(&file2, sha2)) { + cgit_print_error("Unable to load files for diff"); + return; + } + + diff_params.flags = XDF_NEED_MINIMAL; + + emit_params.ctxlen = 3; + emit_params.flags = XDL_EMIT_FUNCNAMES; + + emit_cb.outf = diff_cb; + + xdl_diff(&file1, &file2, &diff_params, &emit_params, &emit_cb); +} + + + void cgit_print_diff(const char *old_hex, const char *new_hex) { unsigned char sha1[20], sha2[20]; @@ -39,7 +124,6 @@ void cgit_print_diff(const char *old_hex, const char *new_hex) get_sha1(new_hex, sha2); html("<table class='diff'><tr><td>"); - if (cgit_diff_files(sha1, sha2, print_line)) - cgit_print_error("Error running diff"); + run_diff(sha1, sha2); html("</td></tr></table>"); } |