diff options
Diffstat (limited to '')
| -rw-r--r-- | ui-diff.c | 145 | 
1 files changed, 145 insertions, 0 deletions
| @@ -13,6 +13,149 @@  unsigned char old_rev_sha1[20];  unsigned char new_rev_sha1[20]; +static int files, slots; +static int total_adds, total_rems, max_changes; +static int lines_added, lines_removed; +static char *curr_rev; + +static struct fileinfo { +	char status; +	unsigned char old_sha1[20]; +	unsigned char new_sha1[20]; +	unsigned short old_mode; +	unsigned short new_mode; +	char *old_path; +	char *new_path; +	unsigned int added; +	unsigned int removed; +} *items; + + +static void print_fileinfo(struct fileinfo *info) +{ +	char *class; + +	switch (info->status) { +	case DIFF_STATUS_ADDED: +		class = "add"; +		break; +	case DIFF_STATUS_COPIED: +		class = "cpy"; +		break; +	case DIFF_STATUS_DELETED: +		class = "del"; +		break; +	case DIFF_STATUS_MODIFIED: +		class = "upd"; +		break; +	case DIFF_STATUS_RENAMED: +		class = "mov"; +		break; +	case DIFF_STATUS_TYPE_CHANGED: +		class = "typ"; +		break; +	case DIFF_STATUS_UNKNOWN: +		class = "unk"; +		break; +	case DIFF_STATUS_UNMERGED: +		class = "stg"; +		break; +	default: +		die("bug: unhandled diff status %c", info->status); +	} + +	html("<tr>"); +	htmlf("<td class='mode'>"); +	if (is_null_sha1(info->new_sha1)) { +		cgit_print_filemode(info->old_mode); +	} else { +		cgit_print_filemode(info->new_mode); +	} + +	if (info->old_mode != info->new_mode && +	    !is_null_sha1(info->old_sha1) && +	    !is_null_sha1(info->new_sha1)) { +		html("<span class='modechange'>["); +		cgit_print_filemode(info->old_mode); +		html("]</span>"); +	} +	htmlf("</td><td class='%s'>", class); +	cgit_diff_link(info->new_path, NULL, NULL, ctx.qry.head, curr_rev, +		       NULL, info->new_path); +	if (info->status == DIFF_STATUS_COPIED || info->status == DIFF_STATUS_RENAMED) +		htmlf(" (%s from %s)", +		      info->status == DIFF_STATUS_COPIED ? "copied" : "renamed", +		      info->old_path); +	html("</td><td class='right'>"); +	htmlf("%d", info->added + info->removed); +	html("</td><td class='graph'>"); +	htmlf("<table summary='file diffstat' width='%d%%'><tr>", (max_changes > 100 ? 100 : max_changes)); +	htmlf("<td class='add' style='width: %.1f%%;'/>", +	      info->added * 100.0 / max_changes); +	htmlf("<td class='rem' style='width: %.1f%%;'/>", +	      info->removed * 100.0 / max_changes); +	htmlf("<td class='none' style='width: %.1f%%;'/>", +	      (max_changes - info->removed - info->added) * 100.0 / max_changes); +	html("</tr></table></td></tr>\n"); +} + +static void count_diff_lines(char *line, int len) +{ +	if (line && (len > 0)) { +		if (line[0] == '+') +			lines_added++; +		else if (line[0] == '-') +			lines_removed++; +	} +} + +static void inspect_filepair(struct diff_filepair *pair) +{ +	files++; +	lines_added = 0; +	lines_removed = 0; +	cgit_diff_files(pair->one->sha1, pair->two->sha1, count_diff_lines); +	if (files >= slots) { +		if (slots == 0) +			slots = 4; +		else +			slots = slots * 2; +		items = xrealloc(items, slots * sizeof(struct fileinfo)); +	} +	items[files-1].status = pair->status; +	hashcpy(items[files-1].old_sha1, pair->one->sha1); +	hashcpy(items[files-1].new_sha1, pair->two->sha1); +	items[files-1].old_mode = pair->one->mode; +	items[files-1].new_mode = pair->two->mode; +	items[files-1].old_path = xstrdup(pair->one->path); +	items[files-1].new_path = xstrdup(pair->two->path); +	items[files-1].added = lines_added; +	items[files-1].removed = lines_removed; +	if (lines_added + lines_removed > max_changes) +		max_changes = lines_added + lines_removed; +	total_adds += lines_added; +	total_rems += lines_removed; +} + +void cgit_print_diffstat(const unsigned char *old_sha1, +			 const unsigned char *new_sha1) +{ +	int i; + +	html("<div class='diffstat-header'>Diffstat</div>"); +	html("<table summary='diffstat' class='diffstat'>"); +	max_changes = 0; +	cgit_diff_tree(old_sha1, new_sha1, inspect_filepair, NULL); +	for(i = 0; i<files; i++) +		print_fileinfo(&items[i]); +	html("</table>"); +	html("<div class='diffstat-summary'>"); +	htmlf("%d files changed, %d insertions, %d deletions", +	      files, total_adds, total_rems); +	html("</div>"); +} + +  /*   * print a single line returned from xdiff   */ @@ -142,6 +285,8 @@ void cgit_print_diff(const char *new_rev, const char *old_rev, const char *prefi  		if (!commit2 || parse_commit(commit2))  			cgit_print_error(fmt("Bad commit: %s", sha1_to_hex(old_rev_sha1)));  	} +	cgit_print_diffstat(old_rev_sha1, new_rev_sha1); +  	html("<table summary='diff' class='diff'>");  	html("<tr><td>");  	cgit_diff_tree(old_rev_sha1, new_rev_sha1, filepair_cb, prefix); | 
