blob: 5d18296862c19ac33606cc7a12d01da416215ec8 [file] [log] [blame]
Lars Hjemli36aba002006-12-20 22:48:27 +01001/* ui-diff.c: show diff between two blobs
2 *
Lukas Fleischerf7f26f82014-01-08 15:10:49 +01003 * Copyright (C) 2006-2014 cgit Development Team <cgit@lists.zx2c4.com>
Lars Hjemli36aba002006-12-20 22:48:27 +01004 *
5 * Licensed under GNU General Public License v2
6 * (see COPYING for full license text)
7 */
8
9#include "cgit.h"
John Keeping8f208792013-04-06 11:37:59 +010010#include "ui-diff.h"
Lars Hjemlib1f9b9c2008-02-23 22:45:33 +010011#include "html.h"
Lars Hjemlia4d1ca12008-03-24 16:50:57 +010012#include "ui-shared.h"
Ragnar Ouchterlony40e174d2009-09-13 19:36:35 +020013#include "ui-ssdiff.h"
Lars Hjemli36aba002006-12-20 22:48:27 +010014
Lars Hjemlie238ebe2007-10-01 12:30:29 +020015unsigned char old_rev_sha1[20];
16unsigned char new_rev_sha1[20];
17
Lars Hjemlife1230d2008-04-24 23:32:02 +020018static int files, slots;
19static int total_adds, total_rems, max_changes;
20static int lines_added, lines_removed;
Lars Hjemlife1230d2008-04-24 23:32:02 +020021
22static struct fileinfo {
23 char status;
24 unsigned char old_sha1[20];
25 unsigned char new_sha1[20];
26 unsigned short old_mode;
27 unsigned short new_mode;
28 char *old_path;
29 char *new_path;
30 unsigned int added;
31 unsigned int removed;
Lars Hjemlic495cf02009-01-31 10:40:40 +010032 unsigned long old_size;
33 unsigned long new_size;
John Keeping12d3d4c2015-03-08 16:32:17 +000034 unsigned int binary:1;
Lars Hjemlife1230d2008-04-24 23:32:02 +020035} *items;
36
Ragnar Ouchterlony40e174d2009-09-13 19:36:35 +020037static int use_ssdiff = 0;
Bernhard Reutner-Fischere52040b2010-12-23 12:47:55 +010038static struct diff_filepair *current_filepair;
John Keeping30304d82015-08-12 15:55:28 +010039static const char *current_prefix;
Bernhard Reutner-Fischere52040b2010-12-23 12:47:55 +010040
41struct diff_filespec *cgit_get_current_old_file(void)
42{
43 return current_filepair->one;
44}
45
46struct diff_filespec *cgit_get_current_new_file(void)
47{
48 return current_filepair->two;
49}
Lars Hjemlife1230d2008-04-24 23:32:02 +020050
51static void print_fileinfo(struct fileinfo *info)
52{
53 char *class;
54
55 switch (info->status) {
56 case DIFF_STATUS_ADDED:
57 class = "add";
58 break;
59 case DIFF_STATUS_COPIED:
60 class = "cpy";
61 break;
62 case DIFF_STATUS_DELETED:
63 class = "del";
64 break;
65 case DIFF_STATUS_MODIFIED:
66 class = "upd";
67 break;
68 case DIFF_STATUS_RENAMED:
69 class = "mov";
70 break;
71 case DIFF_STATUS_TYPE_CHANGED:
72 class = "typ";
73 break;
74 case DIFF_STATUS_UNKNOWN:
75 class = "unk";
76 break;
77 case DIFF_STATUS_UNMERGED:
78 class = "stg";
79 break;
80 default:
81 die("bug: unhandled diff status %c", info->status);
82 }
83
84 html("<tr>");
85 htmlf("<td class='mode'>");
86 if (is_null_sha1(info->new_sha1)) {
87 cgit_print_filemode(info->old_mode);
88 } else {
89 cgit_print_filemode(info->new_mode);
90 }
91
92 if (info->old_mode != info->new_mode &&
93 !is_null_sha1(info->old_sha1) &&
94 !is_null_sha1(info->new_sha1)) {
95 html("<span class='modechange'>[");
96 cgit_print_filemode(info->old_mode);
97 html("]</span>");
98 }
99 htmlf("</td><td class='%s'>", class);
Lars Hjemli04619c92008-09-23 17:47:26 +0200100 cgit_diff_link(info->new_path, NULL, NULL, ctx.qry.head, ctx.qry.sha1,
John Keeping03f537f2014-10-05 10:59:03 +0100101 ctx.qry.sha2, info->new_path);
Lukas Fleischerbebe89d2011-07-22 13:47:19 +0200102 if (info->status == DIFF_STATUS_COPIED || info->status == DIFF_STATUS_RENAMED) {
103 htmlf(" (%s from ",
104 info->status == DIFF_STATUS_COPIED ? "copied" : "renamed");
105 html_txt(info->old_path);
106 html(")");
107 }
Lars Hjemlife1230d2008-04-24 23:32:02 +0200108 html("</td><td class='right'>");
Lars Hjemlic495cf02009-01-31 10:40:40 +0100109 if (info->binary) {
Mark Lodatoe4ddc8f2010-09-04 11:30:18 -0400110 htmlf("bin</td><td class='graph'>%ld -> %ld bytes",
Lars Hjemlic495cf02009-01-31 10:40:40 +0100111 info->old_size, info->new_size);
112 return;
113 }
Lars Hjemlife1230d2008-04-24 23:32:02 +0200114 htmlf("%d", info->added + info->removed);
115 html("</td><td class='graph'>");
116 htmlf("<table summary='file diffstat' width='%d%%'><tr>", (max_changes > 100 ? 100 : max_changes));
117 htmlf("<td class='add' style='width: %.1f%%;'/>",
118 info->added * 100.0 / max_changes);
119 htmlf("<td class='rem' style='width: %.1f%%;'/>",
120 info->removed * 100.0 / max_changes);
121 htmlf("<td class='none' style='width: %.1f%%;'/>",
122 (max_changes - info->removed - info->added) * 100.0 / max_changes);
123 html("</tr></table></td></tr>\n");
124}
125
126static void count_diff_lines(char *line, int len)
127{
128 if (line && (len > 0)) {
129 if (line[0] == '+')
130 lines_added++;
131 else if (line[0] == '-')
132 lines_removed++;
133 }
134}
135
John Keeping30304d82015-08-12 15:55:28 +0100136static int show_filepair(struct diff_filepair *pair)
137{
138 /* Always show if we have no limiting prefix. */
139 if (!current_prefix)
140 return 1;
141
142 /* Show if either path in the pair begins with the prefix. */
143 if (starts_with(pair->one->path, current_prefix) ||
144 starts_with(pair->two->path, current_prefix))
145 return 1;
146
147 /* Otherwise we don't want to show this filepair. */
148 return 0;
149}
150
Lars Hjemlife1230d2008-04-24 23:32:02 +0200151static void inspect_filepair(struct diff_filepair *pair)
152{
Lars Hjemlic495cf02009-01-31 10:40:40 +0100153 int binary = 0;
154 unsigned long old_size = 0;
155 unsigned long new_size = 0;
John Keeping30304d82015-08-12 15:55:28 +0100156
157 if (!show_filepair(pair))
158 return;
159
Lars Hjemlife1230d2008-04-24 23:32:02 +0200160 files++;
161 lines_added = 0;
162 lines_removed = 0;
Lars Hjemlic495cf02009-01-31 10:40:40 +0100163 cgit_diff_files(pair->one->sha1, pair->two->sha1, &old_size, &new_size,
Johan Herland2cc8b992010-06-24 17:52:57 +0200164 &binary, 0, ctx.qry.ignorews, count_diff_lines);
Lars Hjemlife1230d2008-04-24 23:32:02 +0200165 if (files >= slots) {
166 if (slots == 0)
167 slots = 4;
168 else
169 slots = slots * 2;
170 items = xrealloc(items, slots * sizeof(struct fileinfo));
171 }
172 items[files-1].status = pair->status;
173 hashcpy(items[files-1].old_sha1, pair->one->sha1);
174 hashcpy(items[files-1].new_sha1, pair->two->sha1);
175 items[files-1].old_mode = pair->one->mode;
176 items[files-1].new_mode = pair->two->mode;
177 items[files-1].old_path = xstrdup(pair->one->path);
178 items[files-1].new_path = xstrdup(pair->two->path);
179 items[files-1].added = lines_added;
180 items[files-1].removed = lines_removed;
Lars Hjemlic495cf02009-01-31 10:40:40 +0100181 items[files-1].old_size = old_size;
182 items[files-1].new_size = new_size;
183 items[files-1].binary = binary;
Lars Hjemlife1230d2008-04-24 23:32:02 +0200184 if (lines_added + lines_removed > max_changes)
185 max_changes = lines_added + lines_removed;
186 total_adds += lines_added;
187 total_rems += lines_removed;
188}
189
Lukas Fleischerbafab422013-03-04 08:52:33 +0100190static void cgit_print_diffstat(const unsigned char *old_sha1,
191 const unsigned char *new_sha1,
192 const char *prefix)
Lars Hjemlife1230d2008-04-24 23:32:02 +0200193{
Lars Hjemli962a2482011-03-06 23:59:56 +0100194 int i;
Lars Hjemlife1230d2008-04-24 23:32:02 +0200195
Lars Hjemlif82b1942008-09-23 17:54:45 +0200196 html("<div class='diffstat-header'>");
197 cgit_diff_link("Diffstat", NULL, NULL, ctx.qry.head, ctx.qry.sha1,
John Keeping03f537f2014-10-05 10:59:03 +0100198 ctx.qry.sha2, NULL);
Lukasz Janyst7f3c6e02011-03-05 14:10:55 +0100199 if (prefix) {
200 html(" (limited to '");
201 html_txt(prefix);
202 html("')");
203 }
Lars Hjemlif82b1942008-09-23 17:54:45 +0200204 html("</div>");
Lars Hjemlife1230d2008-04-24 23:32:02 +0200205 html("<table summary='diffstat' class='diffstat'>");
206 max_changes = 0;
Johan Herland2cc8b992010-06-24 17:52:57 +0200207 cgit_diff_tree(old_sha1, new_sha1, inspect_filepair, prefix,
208 ctx.qry.ignorews);
Jason A. Donenfeldbdae1d82013-03-03 23:21:33 -0500209 for (i = 0; i<files; i++)
Lars Hjemlife1230d2008-04-24 23:32:02 +0200210 print_fileinfo(&items[i]);
211 html("</table>");
212 html("<div class='diffstat-summary'>");
213 htmlf("%d files changed, %d insertions, %d deletions",
214 files, total_adds, total_rems);
215 html("</div>");
216}
217
218
Lars Hjemli36aba002006-12-20 22:48:27 +0100219/*
220 * print a single line returned from xdiff
221 */
222static void print_line(char *line, int len)
223{
224 char *class = "ctx";
225 char c = line[len-1];
226
227 if (line[0] == '+')
228 class = "add";
229 else if (line[0] == '-')
230 class = "del";
231 else if (line[0] == '@')
232 class = "hunk";
233
234 htmlf("<div class='%s'>", class);
235 line[len-1] = '\0';
236 html_txt(line);
237 html("</div>");
238 line[len-1] = c;
239}
240
Lars Hjemlif4f13392007-05-16 04:21:06 +0200241static void header(unsigned char *sha1, char *path1, int mode1,
242 unsigned char *sha2, char *path2, int mode2)
Lars Hjemlia342ac62007-05-14 18:31:05 +0200243{
244 char *abbrev1, *abbrev2;
Lars Hjemlif4f13392007-05-16 04:21:06 +0200245 int subproject;
246
Jeffrey C. Olliee651cb02007-06-04 12:28:56 -0500247 subproject = (S_ISGITLINK(mode1) || S_ISGITLINK(mode2));
Lars Hjemlia342ac62007-05-14 18:31:05 +0200248 html("<div class='head'>");
249 html("diff --git a/");
250 html_txt(path1);
251 html(" b/");
252 html_txt(path2);
Lars Hjemlif4f13392007-05-16 04:21:06 +0200253
Lars Hjemlif4f13392007-05-16 04:21:06 +0200254 if (mode1 == 0)
255 htmlf("<br/>new file mode %.6o", mode2);
256
257 if (mode2 == 0)
258 htmlf("<br/>deleted file mode %.6o", mode1);
259
260 if (!subproject) {
261 abbrev1 = xstrdup(find_unique_abbrev(sha1, DEFAULT_ABBREV));
262 abbrev2 = xstrdup(find_unique_abbrev(sha2, DEFAULT_ABBREV));
263 htmlf("<br/>index %s..%s", abbrev1, abbrev2);
264 free(abbrev1);
265 free(abbrev2);
266 if (mode1 != 0 && mode2 != 0) {
267 htmlf(" %.6o", mode1);
268 if (mode2 != mode1)
269 htmlf("..%.6o", mode2);
270 }
Michael Halstead62a40c72012-11-14 12:41:01 -0800271 if (is_null_sha1(sha1)) {
272 path1 = "dev/null";
273 html("<br/>--- /");
274 } else
275 html("<br/>--- a/");
Lars Hjemlie238ebe2007-10-01 12:30:29 +0200276 if (mode1 != 0)
Lars Hjemlid14d77f2008-02-16 11:53:40 +0100277 cgit_tree_link(path1, NULL, NULL, ctx.qry.head,
Lars Hjemlie238ebe2007-10-01 12:30:29 +0200278 sha1_to_hex(old_rev_sha1), path1);
279 else
280 html_txt(path1);
Michael Halstead62a40c72012-11-14 12:41:01 -0800281 if (is_null_sha1(sha2)) {
282 path2 = "dev/null";
283 html("<br/>+++ /");
284 } else
285 html("<br/>+++ b/");
Lars Hjemlie238ebe2007-10-01 12:30:29 +0200286 if (mode2 != 0)
Lars Hjemlid14d77f2008-02-16 11:53:40 +0100287 cgit_tree_link(path2, NULL, NULL, ctx.qry.head,
Lars Hjemlie238ebe2007-10-01 12:30:29 +0200288 sha1_to_hex(new_rev_sha1), path2);
289 else
290 html_txt(path2);
Lars Hjemlif4f13392007-05-16 04:21:06 +0200291 }
Lars Hjemlia342ac62007-05-14 18:31:05 +0200292 html("</div>");
293}
294
Lars Hjemli6a8749d2007-05-13 23:13:12 +0200295static void filepair_cb(struct diff_filepair *pair)
296{
Lars Hjemlic495cf02009-01-31 10:40:40 +0100297 unsigned long old_size = 0;
298 unsigned long new_size = 0;
299 int binary = 0;
Ragnar Ouchterlony40e174d2009-09-13 19:36:35 +0200300 linediff_fn print_line_fn = print_line;
Lars Hjemlic495cf02009-01-31 10:40:40 +0100301
John Keeping30304d82015-08-12 15:55:28 +0100302 if (!show_filepair(pair))
303 return;
304
Bernhard Reutner-Fischere52040b2010-12-23 12:47:55 +0100305 current_filepair = pair;
Ragnar Ouchterlony40e174d2009-09-13 19:36:35 +0200306 if (use_ssdiff) {
Ragnar Ouchterlony207cc342009-09-15 19:44:37 +0200307 cgit_ssdiff_header_begin();
Ragnar Ouchterlony40e174d2009-09-13 19:36:35 +0200308 print_line_fn = cgit_ssdiff_line_cb;
309 }
Ragnar Ouchterlony207cc342009-09-15 19:44:37 +0200310 header(pair->one->sha1, pair->one->path, pair->one->mode,
311 pair->two->sha1, pair->two->path, pair->two->mode);
312 if (use_ssdiff)
313 cgit_ssdiff_header_end();
Jeffrey C. Olliee651cb02007-06-04 12:28:56 -0500314 if (S_ISGITLINK(pair->one->mode) || S_ISGITLINK(pair->two->mode)) {
315 if (S_ISGITLINK(pair->one->mode))
Ragnar Ouchterlony207cc342009-09-15 19:44:37 +0200316 print_line_fn(fmt("-Subproject %s", sha1_to_hex(pair->one->sha1)), 52);
Jeffrey C. Olliee651cb02007-06-04 12:28:56 -0500317 if (S_ISGITLINK(pair->two->mode))
Ragnar Ouchterlony207cc342009-09-15 19:44:37 +0200318 print_line_fn(fmt("+Subproject %s", sha1_to_hex(pair->two->sha1)), 52);
Ragnar Ouchterlony4a198e42009-09-16 18:56:26 +0200319 if (use_ssdiff)
320 cgit_ssdiff_footer();
Lars Hjemlif4f13392007-05-16 04:21:06 +0200321 return;
322 }
Ragnar Ouchterlony40e174d2009-09-13 19:36:35 +0200323 if (cgit_diff_files(pair->one->sha1, pair->two->sha1, &old_size,
Johan Herland2cc8b992010-06-24 17:52:57 +0200324 &new_size, &binary, ctx.qry.context,
325 ctx.qry.ignorews, print_line_fn))
Lars Hjemli6a8749d2007-05-13 23:13:12 +0200326 cgit_print_error("Error running diff");
Ragnar Ouchterlony4a198e42009-09-16 18:56:26 +0200327 if (binary) {
328 if (use_ssdiff)
329 html("<tr><td colspan='4'>Binary files differ</td></tr>");
330 else
331 html("Binary files differ");
332 }
Ragnar Ouchterlony40e174d2009-09-13 19:36:35 +0200333 if (use_ssdiff)
334 cgit_ssdiff_footer();
Lars Hjemli6a8749d2007-05-13 23:13:12 +0200335}
336
John Keepinge3d3fff2015-03-08 16:32:16 +0000337void cgit_print_diff_ctrls(void)
Lars Hjemli962a2482011-03-06 23:59:56 +0100338{
339 int i, curr;
340
341 html("<div class='cgit-panel'>");
342 html("<b>diff options</b>");
343 html("<form method='get' action='.'>");
344 cgit_add_hidden_formfields(1, 0, ctx.qry.page);
345 html("<table>");
346 html("<tr><td colspan='2'/></tr>");
347 html("<tr>");
348 html("<td class='label'>context:</td>");
349 html("<td class='ctrl'>");
350 html("<select name='context' onchange='this.form.submit();'>");
351 curr = ctx.qry.context;
352 if (!curr)
353 curr = 3;
354 for (i = 1; i <= 10; i++)
355 html_intoption(i, fmt("%d", i), curr);
356 for (i = 15; i <= 40; i += 5)
357 html_intoption(i, fmt("%d", i), curr);
358 html("</select>");
359 html("</td>");
360 html("</tr><tr>");
361 html("<td class='label'>space:</td>");
362 html("<td class='ctrl'>");
363 html("<select name='ignorews' onchange='this.form.submit();'>");
364 html_intoption(0, "include", ctx.qry.ignorews);
365 html_intoption(1, "ignore", ctx.qry.ignorews);
366 html("</select>");
367 html("</td>");
368 html("</tr><tr>");
369 html("<td class='label'>mode:</td>");
370 html("<td class='ctrl'>");
John Keeping18302712014-10-05 10:59:04 +0100371 html("<select name='dt' onchange='this.form.submit();'>");
372 curr = ctx.qry.has_difftype ? ctx.qry.difftype : ctx.cfg.difftype;
Lars Hjemli962a2482011-03-06 23:59:56 +0100373 html_intoption(0, "unified", curr);
374 html_intoption(1, "ssdiff", curr);
John Keepingddfaef62014-10-05 10:59:05 +0100375 html_intoption(2, "stat only", curr);
Lars Hjemli962a2482011-03-06 23:59:56 +0100376 html("</select></td></tr>");
377 html("<tr><td/><td class='ctrl'>");
378 html("<noscript><input type='submit' value='reload'/></noscript>");
379 html("</td></tr></table>");
380 html("</form>");
381 html("</div>");
382}
383
384void cgit_print_diff(const char *new_rev, const char *old_rev,
Lukas Fleischer9003cc12013-08-14 10:50:32 +0200385 const char *prefix, int show_ctrls, int raw)
Lars Hjemli36aba002006-12-20 22:48:27 +0100386{
Lars Hjemli4a0be582007-06-17 18:12:03 +0200387 struct commit *commit, *commit2;
Lukas Fleischer2da46fe2013-08-27 10:40:50 +0200388 const unsigned char *old_tree_sha1, *new_tree_sha1;
John Keeping18302712014-10-05 10:59:04 +0100389 diff_type difftype;
Lars Hjemlif9ff7df2007-05-16 00:58:35 +0200390
John Keeping30304d82015-08-12 15:55:28 +0100391 /*
392 * If "follow" is set then the diff machinery needs to examine the
393 * entire commit to detect renames so we must limit the paths in our
394 * own callbacks and not pass the prefix to the diff machinery.
395 */
396 if (ctx.qry.follow && ctx.cfg.enable_follow_links) {
397 current_prefix = prefix;
398 prefix = "";
399 } else {
400 current_prefix = NULL;
401 }
402
Lars Hjemli4a0be582007-06-17 18:12:03 +0200403 if (!new_rev)
Lars Hjemlid14d77f2008-02-16 11:53:40 +0100404 new_rev = ctx.qry.head;
Lukas Fleischer01db0832013-08-20 18:56:12 +0200405 if (get_sha1(new_rev, new_rev_sha1)) {
John Keeping3b220eb2015-08-14 12:47:14 +0100406 cgit_print_error_page(404, "Not found",
407 "Bad object name: %s", new_rev);
Lars Hjemli4a0be582007-06-17 18:12:03 +0200408 return;
409 }
Lars Hjemlie238ebe2007-10-01 12:30:29 +0200410 commit = lookup_commit_reference(new_rev_sha1);
Lukas Fleischer9afc8832011-04-05 10:38:53 +0200411 if (!commit || parse_commit(commit)) {
John Keeping3b220eb2015-08-14 12:47:14 +0100412 cgit_print_error_page(404, "Not found",
413 "Bad commit: %s", sha1_to_hex(new_rev_sha1));
Lukas Fleischer9afc8832011-04-05 10:38:53 +0200414 return;
415 }
Lukas Fleischer2da46fe2013-08-27 10:40:50 +0200416 new_tree_sha1 = commit->tree->object.sha1;
Lars Hjemli36aba002006-12-20 22:48:27 +0100417
Lukas Fleischer01db0832013-08-20 18:56:12 +0200418 if (old_rev) {
419 if (get_sha1(old_rev, old_rev_sha1)) {
John Keeping3b220eb2015-08-14 12:47:14 +0100420 cgit_print_error_page(404, "Not found",
421 "Bad object name: %s", old_rev);
Lars Hjemli6a8749d2007-05-13 23:13:12 +0200422 return;
423 }
Lukas Fleischer01db0832013-08-20 18:56:12 +0200424 } else if (commit->parents && commit->parents->item) {
425 hashcpy(old_rev_sha1, commit->parents->item->object.sha1);
426 } else {
427 hashclr(old_rev_sha1);
428 }
429
430 if (!is_null_sha1(old_rev_sha1)) {
Lars Hjemlie238ebe2007-10-01 12:30:29 +0200431 commit2 = lookup_commit_reference(old_rev_sha1);
Lukas Fleischer9afc8832011-04-05 10:38:53 +0200432 if (!commit2 || parse_commit(commit2)) {
John Keeping3b220eb2015-08-14 12:47:14 +0100433 cgit_print_error_page(404, "Not found",
434 "Bad commit: %s", sha1_to_hex(old_rev_sha1));
Lukas Fleischer9afc8832011-04-05 10:38:53 +0200435 return;
436 }
Lukas Fleischer2da46fe2013-08-27 10:40:50 +0200437 old_tree_sha1 = commit2->tree->object.sha1;
438 } else {
439 old_tree_sha1 = NULL;
Lars Hjemli6a8749d2007-05-13 23:13:12 +0200440 }
Ragnar Ouchterlonyc358aa32009-09-14 20:19:02 +0200441
Lukas Fleischer9003cc12013-08-14 10:50:32 +0200442 if (raw) {
Lukas Fleischer2da46fe2013-08-27 10:40:50 +0200443 struct diff_options diffopt;
444
445 diff_setup(&diffopt);
446 diffopt.output_format = DIFF_FORMAT_PATCH;
447 DIFF_OPT_SET(&diffopt, RECURSIVE);
448 diff_setup_done(&diffopt);
449
Lukas Fleischer9003cc12013-08-14 10:50:32 +0200450 ctx.page.mimetype = "text/plain";
Lukas Fleischerf60ffa12014-01-15 21:53:15 +0100451 cgit_print_http_headers();
Lukas Fleischer2da46fe2013-08-27 10:40:50 +0200452 if (old_tree_sha1) {
453 diff_tree_sha1(old_tree_sha1, new_tree_sha1, "",
454 &diffopt);
455 } else {
456 diff_root_tree_sha1(new_tree_sha1, "", &diffopt);
457 }
458 diffcore_std(&diffopt);
459 diff_flush(&diffopt);
460
Lukas Fleischer9003cc12013-08-14 10:50:32 +0200461 return;
462 }
463
John Keeping18302712014-10-05 10:59:04 +0100464 difftype = ctx.qry.has_difftype ? ctx.qry.difftype : ctx.cfg.difftype;
465 use_ssdiff = difftype == DIFF_SSDIFF;
Ragnar Ouchterlonyc358aa32009-09-14 20:19:02 +0200466
John Keeping3b220eb2015-08-14 12:47:14 +0100467 if (show_ctrls) {
468 cgit_print_layout_start();
Lars Hjemli962a2482011-03-06 23:59:56 +0100469 cgit_print_diff_ctrls();
John Keeping3b220eb2015-08-14 12:47:14 +0100470 }
Lars Hjemli962a2482011-03-06 23:59:56 +0100471
John Keepingd6c40502014-12-29 22:27:55 +0000472 /*
473 * Clicking on a link to a file in the diff stat should show a diff
474 * of the file, showing the diff stat limited to a single file is
475 * pretty useless. All links from this point on will be to
476 * individual files, so we simply reset the difftype in the query
477 * here to avoid propagating DIFF_STATONLY to the individual files.
478 */
479 if (difftype == DIFF_STATONLY)
480 ctx.qry.difftype = ctx.cfg.difftype;
481
Johan Herlandc46e4682010-06-10 01:09:31 +0200482 cgit_print_diffstat(old_rev_sha1, new_rev_sha1, prefix);
Lars Hjemlife1230d2008-04-24 23:32:02 +0200483
John Keepingddfaef62014-10-05 10:59:05 +0100484 if (difftype == DIFF_STATONLY)
485 return;
486
Ragnar Ouchterlony207cc342009-09-15 19:44:37 +0200487 if (use_ssdiff) {
488 html("<table summary='ssdiff' class='ssdiff'>");
489 } else {
490 html("<table summary='diff' class='diff'>");
491 html("<tr><td>");
492 }
Johan Herland2cc8b992010-06-24 17:52:57 +0200493 cgit_diff_tree(old_rev_sha1, new_rev_sha1, filepair_cb, prefix,
494 ctx.qry.ignorews);
Ragnar Ouchterlony207cc342009-09-15 19:44:37 +0200495 if (!use_ssdiff)
496 html("</td></tr>");
Ondrej Jirman0928d882007-05-26 01:14:25 +0200497 html("</table>");
John Keeping3b220eb2015-08-14 12:47:14 +0100498
499 if (show_ctrls)
500 cgit_print_layout_end();
Lars Hjemli36aba002006-12-20 22:48:27 +0100501}