diff options
Diffstat (limited to '')
| -rw-r--r-- | ui-diff.c | 131 | 
1 files changed, 131 insertions, 0 deletions
| diff --git a/ui-diff.c b/ui-diff.c new file mode 100644 index 0000000..0bd9ade --- /dev/null +++ b/ui-diff.c @@ -0,0 +1,131 @@ +/* ui-diff.c: show diff between two blobs + * + * Copyright (C) 2006 Lars Hjemli + * + * Licensed under GNU General Public License v2 + *   (see COPYING for full license text) + */ + +#include "cgit.h" +#include "xdiff.h" + +char *diff_buffer; +int diff_buffer_size; + + +/* + * print a single line returned from xdiff + */ +static void print_line(char *line, int len) +{ +	char *class = "ctx"; +	char c = line[len-1]; + +	if (line[0] == '+') +		class = "add"; +	else if (line[0] == '-') +		class = "del"; +	else if (line[0] == '@') +		class = "hunk"; + +	htmlf("<div class='%s'>", class); +	line[len-1] = '\0'; +	html_txt(line); +	html("</div>"); +	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) +{ +	char type[20]; + +	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]; + +	get_sha1(old_hex, sha1); +	get_sha1(new_hex, sha2); + +	html("<h2>diff</h2>\n"); +	html("<table class='diff'><tr><td>"); +	run_diff(sha1, sha2); +	html("</td></tr></table>"); +} | 
