author | Ragnar Ouchterlony <ragnar@lysator.liu.se> | 2009-09-15 17:44:37 (UTC) |
---|---|---|
committer | Lars Hjemli <hjemli@gmail.com> | 2009-09-16 18:17:56 (UTC) |
commit | 207cc34711039329b41345f716bf421a88a6fd0a (patch) (unidiff) | |
tree | 5fb56c7e5c105c9045e52abd971013270db23368 /ui-diff.c | |
parent | c358aa3dfebf4fc1f3005dd960aa5c1c020eed76 (diff) | |
download | cgit-207cc34711039329b41345f716bf421a88a6fd0a.zip cgit-207cc34711039329b41345f716bf421a88a6fd0a.tar.gz cgit-207cc34711039329b41345f716bf421a88a6fd0a.tar.bz2 |
Polishing of how the side-by-side diff looks.
Aligned all different files, so that all side-by-side tables look
the same. Also made sure that the tables take up the whole browser
width.
Also various changes to the css to make things easier on the eye.
Signed-off-by: Ragnar Ouchterlony <ragnar@lysator.liu.se>
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
-rw-r--r-- | ui-diff.c | 27 |
1 files changed, 16 insertions, 11 deletions
@@ -1,342 +1,347 @@ | |||
1 | /* ui-diff.c: show diff between two blobs | 1 | /* ui-diff.c: show diff between two blobs |
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 | #include "html.h" | 10 | #include "html.h" |
11 | #include "ui-shared.h" | 11 | #include "ui-shared.h" |
12 | #include "ui-ssdiff.h" | 12 | #include "ui-ssdiff.h" |
13 | 13 | ||
14 | unsigned char old_rev_sha1[20]; | 14 | unsigned char old_rev_sha1[20]; |
15 | unsigned char new_rev_sha1[20]; | 15 | unsigned char new_rev_sha1[20]; |
16 | 16 | ||
17 | static int files, slots; | 17 | static int files, slots; |
18 | static int total_adds, total_rems, max_changes; | 18 | static int total_adds, total_rems, max_changes; |
19 | static int lines_added, lines_removed; | 19 | static int lines_added, lines_removed; |
20 | 20 | ||
21 | static struct fileinfo { | 21 | static struct fileinfo { |
22 | char status; | 22 | char status; |
23 | unsigned char old_sha1[20]; | 23 | unsigned char old_sha1[20]; |
24 | unsigned char new_sha1[20]; | 24 | unsigned char new_sha1[20]; |
25 | unsigned short old_mode; | 25 | unsigned short old_mode; |
26 | unsigned short new_mode; | 26 | unsigned short new_mode; |
27 | char *old_path; | 27 | char *old_path; |
28 | char *new_path; | 28 | char *new_path; |
29 | unsigned int added; | 29 | unsigned int added; |
30 | unsigned int removed; | 30 | unsigned int removed; |
31 | unsigned long old_size; | 31 | unsigned long old_size; |
32 | unsigned long new_size; | 32 | unsigned long new_size; |
33 | int binary:1; | 33 | int binary:1; |
34 | } *items; | 34 | } *items; |
35 | 35 | ||
36 | static int use_ssdiff = 0; | 36 | static int use_ssdiff = 0; |
37 | 37 | ||
38 | static void print_fileinfo(struct fileinfo *info) | 38 | static void print_fileinfo(struct fileinfo *info) |
39 | { | 39 | { |
40 | char *class; | 40 | char *class; |
41 | 41 | ||
42 | switch (info->status) { | 42 | switch (info->status) { |
43 | case DIFF_STATUS_ADDED: | 43 | case DIFF_STATUS_ADDED: |
44 | class = "add"; | 44 | class = "add"; |
45 | break; | 45 | break; |
46 | case DIFF_STATUS_COPIED: | 46 | case DIFF_STATUS_COPIED: |
47 | class = "cpy"; | 47 | class = "cpy"; |
48 | break; | 48 | break; |
49 | case DIFF_STATUS_DELETED: | 49 | case DIFF_STATUS_DELETED: |
50 | class = "del"; | 50 | class = "del"; |
51 | break; | 51 | break; |
52 | case DIFF_STATUS_MODIFIED: | 52 | case DIFF_STATUS_MODIFIED: |
53 | class = "upd"; | 53 | class = "upd"; |
54 | break; | 54 | break; |
55 | case DIFF_STATUS_RENAMED: | 55 | case DIFF_STATUS_RENAMED: |
56 | class = "mov"; | 56 | class = "mov"; |
57 | break; | 57 | break; |
58 | case DIFF_STATUS_TYPE_CHANGED: | 58 | case DIFF_STATUS_TYPE_CHANGED: |
59 | class = "typ"; | 59 | class = "typ"; |
60 | break; | 60 | break; |
61 | case DIFF_STATUS_UNKNOWN: | 61 | case DIFF_STATUS_UNKNOWN: |
62 | class = "unk"; | 62 | class = "unk"; |
63 | break; | 63 | break; |
64 | case DIFF_STATUS_UNMERGED: | 64 | case DIFF_STATUS_UNMERGED: |
65 | class = "stg"; | 65 | class = "stg"; |
66 | break; | 66 | break; |
67 | default: | 67 | default: |
68 | die("bug: unhandled diff status %c", info->status); | 68 | die("bug: unhandled diff status %c", info->status); |
69 | } | 69 | } |
70 | 70 | ||
71 | html("<tr>"); | 71 | html("<tr>"); |
72 | htmlf("<td class='mode'>"); | 72 | htmlf("<td class='mode'>"); |
73 | if (is_null_sha1(info->new_sha1)) { | 73 | if (is_null_sha1(info->new_sha1)) { |
74 | cgit_print_filemode(info->old_mode); | 74 | cgit_print_filemode(info->old_mode); |
75 | } else { | 75 | } else { |
76 | cgit_print_filemode(info->new_mode); | 76 | cgit_print_filemode(info->new_mode); |
77 | } | 77 | } |
78 | 78 | ||
79 | if (info->old_mode != info->new_mode && | 79 | if (info->old_mode != info->new_mode && |
80 | !is_null_sha1(info->old_sha1) && | 80 | !is_null_sha1(info->old_sha1) && |
81 | !is_null_sha1(info->new_sha1)) { | 81 | !is_null_sha1(info->new_sha1)) { |
82 | html("<span class='modechange'>["); | 82 | html("<span class='modechange'>["); |
83 | cgit_print_filemode(info->old_mode); | 83 | cgit_print_filemode(info->old_mode); |
84 | html("]</span>"); | 84 | html("]</span>"); |
85 | } | 85 | } |
86 | htmlf("</td><td class='%s'>", class); | 86 | htmlf("</td><td class='%s'>", class); |
87 | cgit_diff_link(info->new_path, NULL, NULL, ctx.qry.head, ctx.qry.sha1, | 87 | cgit_diff_link(info->new_path, NULL, NULL, ctx.qry.head, ctx.qry.sha1, |
88 | ctx.qry.sha2, info->new_path, 0); | 88 | ctx.qry.sha2, info->new_path, 0); |
89 | if (info->status == DIFF_STATUS_COPIED || info->status == DIFF_STATUS_RENAMED) | 89 | if (info->status == DIFF_STATUS_COPIED || info->status == DIFF_STATUS_RENAMED) |
90 | htmlf(" (%s from %s)", | 90 | htmlf(" (%s from %s)", |
91 | info->status == DIFF_STATUS_COPIED ? "copied" : "renamed", | 91 | info->status == DIFF_STATUS_COPIED ? "copied" : "renamed", |
92 | info->old_path); | 92 | info->old_path); |
93 | html("</td><td class='right'>"); | 93 | html("</td><td class='right'>"); |
94 | if (info->binary) { | 94 | if (info->binary) { |
95 | htmlf("bin</td><td class='graph'>%d -> %d bytes", | 95 | htmlf("bin</td><td class='graph'>%d -> %d bytes", |
96 | info->old_size, info->new_size); | 96 | info->old_size, info->new_size); |
97 | return; | 97 | return; |
98 | } | 98 | } |
99 | htmlf("%d", info->added + info->removed); | 99 | htmlf("%d", info->added + info->removed); |
100 | html("</td><td class='graph'>"); | 100 | html("</td><td class='graph'>"); |
101 | htmlf("<table summary='file diffstat' width='%d%%'><tr>", (max_changes > 100 ? 100 : max_changes)); | 101 | htmlf("<table summary='file diffstat' width='%d%%'><tr>", (max_changes > 100 ? 100 : max_changes)); |
102 | htmlf("<td class='add' style='width: %.1f%%;'/>", | 102 | htmlf("<td class='add' style='width: %.1f%%;'/>", |
103 | info->added * 100.0 / max_changes); | 103 | info->added * 100.0 / max_changes); |
104 | htmlf("<td class='rem' style='width: %.1f%%;'/>", | 104 | htmlf("<td class='rem' style='width: %.1f%%;'/>", |
105 | info->removed * 100.0 / max_changes); | 105 | info->removed * 100.0 / max_changes); |
106 | htmlf("<td class='none' style='width: %.1f%%;'/>", | 106 | htmlf("<td class='none' style='width: %.1f%%;'/>", |
107 | (max_changes - info->removed - info->added) * 100.0 / max_changes); | 107 | (max_changes - info->removed - info->added) * 100.0 / max_changes); |
108 | html("</tr></table></td></tr>\n"); | 108 | html("</tr></table></td></tr>\n"); |
109 | } | 109 | } |
110 | 110 | ||
111 | static void count_diff_lines(char *line, int len) | 111 | static void count_diff_lines(char *line, int len) |
112 | { | 112 | { |
113 | if (line && (len > 0)) { | 113 | if (line && (len > 0)) { |
114 | if (line[0] == '+') | 114 | if (line[0] == '+') |
115 | lines_added++; | 115 | lines_added++; |
116 | else if (line[0] == '-') | 116 | else if (line[0] == '-') |
117 | lines_removed++; | 117 | lines_removed++; |
118 | } | 118 | } |
119 | } | 119 | } |
120 | 120 | ||
121 | static void inspect_filepair(struct diff_filepair *pair) | 121 | static void inspect_filepair(struct diff_filepair *pair) |
122 | { | 122 | { |
123 | int binary = 0; | 123 | int binary = 0; |
124 | unsigned long old_size = 0; | 124 | unsigned long old_size = 0; |
125 | unsigned long new_size = 0; | 125 | unsigned long new_size = 0; |
126 | files++; | 126 | files++; |
127 | lines_added = 0; | 127 | lines_added = 0; |
128 | lines_removed = 0; | 128 | lines_removed = 0; |
129 | cgit_diff_files(pair->one->sha1, pair->two->sha1, &old_size, &new_size, | 129 | cgit_diff_files(pair->one->sha1, pair->two->sha1, &old_size, &new_size, |
130 | &binary, count_diff_lines); | 130 | &binary, count_diff_lines); |
131 | if (files >= slots) { | 131 | if (files >= slots) { |
132 | if (slots == 0) | 132 | if (slots == 0) |
133 | slots = 4; | 133 | slots = 4; |
134 | else | 134 | else |
135 | slots = slots * 2; | 135 | slots = slots * 2; |
136 | items = xrealloc(items, slots * sizeof(struct fileinfo)); | 136 | items = xrealloc(items, slots * sizeof(struct fileinfo)); |
137 | } | 137 | } |
138 | items[files-1].status = pair->status; | 138 | items[files-1].status = pair->status; |
139 | hashcpy(items[files-1].old_sha1, pair->one->sha1); | 139 | hashcpy(items[files-1].old_sha1, pair->one->sha1); |
140 | hashcpy(items[files-1].new_sha1, pair->two->sha1); | 140 | hashcpy(items[files-1].new_sha1, pair->two->sha1); |
141 | items[files-1].old_mode = pair->one->mode; | 141 | items[files-1].old_mode = pair->one->mode; |
142 | items[files-1].new_mode = pair->two->mode; | 142 | items[files-1].new_mode = pair->two->mode; |
143 | items[files-1].old_path = xstrdup(pair->one->path); | 143 | items[files-1].old_path = xstrdup(pair->one->path); |
144 | items[files-1].new_path = xstrdup(pair->two->path); | 144 | items[files-1].new_path = xstrdup(pair->two->path); |
145 | items[files-1].added = lines_added; | 145 | items[files-1].added = lines_added; |
146 | items[files-1].removed = lines_removed; | 146 | items[files-1].removed = lines_removed; |
147 | items[files-1].old_size = old_size; | 147 | items[files-1].old_size = old_size; |
148 | items[files-1].new_size = new_size; | 148 | items[files-1].new_size = new_size; |
149 | items[files-1].binary = binary; | 149 | items[files-1].binary = binary; |
150 | if (lines_added + lines_removed > max_changes) | 150 | if (lines_added + lines_removed > max_changes) |
151 | max_changes = lines_added + lines_removed; | 151 | max_changes = lines_added + lines_removed; |
152 | total_adds += lines_added; | 152 | total_adds += lines_added; |
153 | total_rems += lines_removed; | 153 | total_rems += lines_removed; |
154 | } | 154 | } |
155 | 155 | ||
156 | void cgit_print_diffstat(const unsigned char *old_sha1, | 156 | void cgit_print_diffstat(const unsigned char *old_sha1, |
157 | const unsigned char *new_sha1) | 157 | const unsigned char *new_sha1) |
158 | { | 158 | { |
159 | int i; | 159 | int i; |
160 | 160 | ||
161 | html("<div class='diffstat-header'>"); | 161 | html("<div class='diffstat-header'>"); |
162 | cgit_diff_link("Diffstat", NULL, NULL, ctx.qry.head, ctx.qry.sha1, | 162 | cgit_diff_link("Diffstat", NULL, NULL, ctx.qry.head, ctx.qry.sha1, |
163 | ctx.qry.sha2, NULL, 0); | 163 | ctx.qry.sha2, NULL, 0); |
164 | html("</div>"); | 164 | html("</div>"); |
165 | html("<table summary='diffstat' class='diffstat'>"); | 165 | html("<table summary='diffstat' class='diffstat'>"); |
166 | max_changes = 0; | 166 | max_changes = 0; |
167 | cgit_diff_tree(old_sha1, new_sha1, inspect_filepair, NULL); | 167 | cgit_diff_tree(old_sha1, new_sha1, inspect_filepair, NULL); |
168 | for(i = 0; i<files; i++) | 168 | for(i = 0; i<files; i++) |
169 | print_fileinfo(&items[i]); | 169 | print_fileinfo(&items[i]); |
170 | html("</table>"); | 170 | html("</table>"); |
171 | html("<div class='diffstat-summary'>"); | 171 | html("<div class='diffstat-summary'>"); |
172 | htmlf("%d files changed, %d insertions, %d deletions", | 172 | htmlf("%d files changed, %d insertions, %d deletions", |
173 | files, total_adds, total_rems); | 173 | files, total_adds, total_rems); |
174 | html("</div>"); | 174 | html("</div>"); |
175 | } | 175 | } |
176 | 176 | ||
177 | 177 | ||
178 | /* | 178 | /* |
179 | * print a single line returned from xdiff | 179 | * print a single line returned from xdiff |
180 | */ | 180 | */ |
181 | static void print_line(char *line, int len) | 181 | static void print_line(char *line, int len) |
182 | { | 182 | { |
183 | char *class = "ctx"; | 183 | char *class = "ctx"; |
184 | char c = line[len-1]; | 184 | char c = line[len-1]; |
185 | 185 | ||
186 | if (line[0] == '+') | 186 | if (line[0] == '+') |
187 | class = "add"; | 187 | class = "add"; |
188 | else if (line[0] == '-') | 188 | else if (line[0] == '-') |
189 | class = "del"; | 189 | class = "del"; |
190 | else if (line[0] == '@') | 190 | else if (line[0] == '@') |
191 | class = "hunk"; | 191 | class = "hunk"; |
192 | 192 | ||
193 | htmlf("<div class='%s'>", class); | 193 | htmlf("<div class='%s'>", class); |
194 | line[len-1] = '\0'; | 194 | line[len-1] = '\0'; |
195 | html_txt(line); | 195 | html_txt(line); |
196 | html("</div>"); | 196 | html("</div>"); |
197 | line[len-1] = c; | 197 | line[len-1] = c; |
198 | } | 198 | } |
199 | 199 | ||
200 | static void header(unsigned char *sha1, char *path1, int mode1, | 200 | static void header(unsigned char *sha1, char *path1, int mode1, |
201 | unsigned char *sha2, char *path2, int mode2) | 201 | unsigned char *sha2, char *path2, int mode2) |
202 | { | 202 | { |
203 | char *abbrev1, *abbrev2; | 203 | char *abbrev1, *abbrev2; |
204 | int subproject; | 204 | int subproject; |
205 | 205 | ||
206 | subproject = (S_ISGITLINK(mode1) || S_ISGITLINK(mode2)); | 206 | subproject = (S_ISGITLINK(mode1) || S_ISGITLINK(mode2)); |
207 | html("<div class='head'>"); | 207 | html("<div class='head'>"); |
208 | html("diff --git a/"); | 208 | html("diff --git a/"); |
209 | html_txt(path1); | 209 | html_txt(path1); |
210 | html(" b/"); | 210 | html(" b/"); |
211 | html_txt(path2); | 211 | html_txt(path2); |
212 | 212 | ||
213 | if (is_null_sha1(sha1)) | 213 | if (is_null_sha1(sha1)) |
214 | path1 = "dev/null"; | 214 | path1 = "dev/null"; |
215 | if (is_null_sha1(sha2)) | 215 | if (is_null_sha1(sha2)) |
216 | path2 = "dev/null"; | 216 | path2 = "dev/null"; |
217 | 217 | ||
218 | if (mode1 == 0) | 218 | if (mode1 == 0) |
219 | htmlf("<br/>new file mode %.6o", mode2); | 219 | htmlf("<br/>new file mode %.6o", mode2); |
220 | 220 | ||
221 | if (mode2 == 0) | 221 | if (mode2 == 0) |
222 | htmlf("<br/>deleted file mode %.6o", mode1); | 222 | htmlf("<br/>deleted file mode %.6o", mode1); |
223 | 223 | ||
224 | if (!subproject) { | 224 | if (!subproject) { |
225 | abbrev1 = xstrdup(find_unique_abbrev(sha1, DEFAULT_ABBREV)); | 225 | abbrev1 = xstrdup(find_unique_abbrev(sha1, DEFAULT_ABBREV)); |
226 | abbrev2 = xstrdup(find_unique_abbrev(sha2, DEFAULT_ABBREV)); | 226 | abbrev2 = xstrdup(find_unique_abbrev(sha2, DEFAULT_ABBREV)); |
227 | htmlf("<br/>index %s..%s", abbrev1, abbrev2); | 227 | htmlf("<br/>index %s..%s", abbrev1, abbrev2); |
228 | free(abbrev1); | 228 | free(abbrev1); |
229 | free(abbrev2); | 229 | free(abbrev2); |
230 | if (mode1 != 0 && mode2 != 0) { | 230 | if (mode1 != 0 && mode2 != 0) { |
231 | htmlf(" %.6o", mode1); | 231 | htmlf(" %.6o", mode1); |
232 | if (mode2 != mode1) | 232 | if (mode2 != mode1) |
233 | htmlf("..%.6o", mode2); | 233 | htmlf("..%.6o", mode2); |
234 | } | 234 | } |
235 | html("<br/>--- a/"); | 235 | html("<br/>--- a/"); |
236 | if (mode1 != 0) | 236 | if (mode1 != 0) |
237 | cgit_tree_link(path1, NULL, NULL, ctx.qry.head, | 237 | cgit_tree_link(path1, NULL, NULL, ctx.qry.head, |
238 | sha1_to_hex(old_rev_sha1), path1); | 238 | sha1_to_hex(old_rev_sha1), path1); |
239 | else | 239 | else |
240 | html_txt(path1); | 240 | html_txt(path1); |
241 | html("<br/>+++ b/"); | 241 | html("<br/>+++ b/"); |
242 | if (mode2 != 0) | 242 | if (mode2 != 0) |
243 | cgit_tree_link(path2, NULL, NULL, ctx.qry.head, | 243 | cgit_tree_link(path2, NULL, NULL, ctx.qry.head, |
244 | sha1_to_hex(new_rev_sha1), path2); | 244 | sha1_to_hex(new_rev_sha1), path2); |
245 | else | 245 | else |
246 | html_txt(path2); | 246 | html_txt(path2); |
247 | } | 247 | } |
248 | html("</div>"); | 248 | html("</div>"); |
249 | if (use_ssdiff) | ||
250 | cgit_ssdiff_header(); | ||
251 | } | 249 | } |
252 | 250 | ||
253 | static void print_ssdiff_link() | 251 | static void print_ssdiff_link() |
254 | { | 252 | { |
255 | if (!strcmp(ctx.qry.page, "diff")) { | 253 | if (!strcmp(ctx.qry.page, "diff")) { |
256 | if (use_ssdiff) | 254 | if (use_ssdiff) |
257 | cgit_diff_link("Unidiff", NULL, NULL, ctx.qry.head, | 255 | cgit_diff_link("Unidiff", NULL, NULL, ctx.qry.head, |
258 | ctx.qry.sha1, ctx.qry.sha2, NULL, 1); | 256 | ctx.qry.sha1, ctx.qry.sha2, NULL, 1); |
259 | else | 257 | else |
260 | cgit_diff_link("Side-by-side diff", NULL, NULL, | 258 | cgit_diff_link("Side-by-side diff", NULL, NULL, |
261 | ctx.qry.head, ctx.qry.sha1, | 259 | ctx.qry.head, ctx.qry.sha1, |
262 | ctx.qry.sha2, NULL, 1); | 260 | ctx.qry.sha2, NULL, 1); |
263 | } | 261 | } |
264 | } | 262 | } |
265 | 263 | ||
266 | static void filepair_cb(struct diff_filepair *pair) | 264 | static void filepair_cb(struct diff_filepair *pair) |
267 | { | 265 | { |
268 | unsigned long old_size = 0; | 266 | unsigned long old_size = 0; |
269 | unsigned long new_size = 0; | 267 | unsigned long new_size = 0; |
270 | int binary = 0; | 268 | int binary = 0; |
271 | linediff_fn print_line_fn = print_line; | 269 | linediff_fn print_line_fn = print_line; |
272 | 270 | ||
273 | header(pair->one->sha1, pair->one->path, pair->one->mode, | ||
274 | pair->two->sha1, pair->two->path, pair->two->mode); | ||
275 | if (use_ssdiff) { | 271 | if (use_ssdiff) { |
276 | cgit_ssdiff_header(); | 272 | cgit_ssdiff_header_begin(); |
277 | print_line_fn = cgit_ssdiff_line_cb; | 273 | print_line_fn = cgit_ssdiff_line_cb; |
278 | } | 274 | } |
275 | header(pair->one->sha1, pair->one->path, pair->one->mode, | ||
276 | pair->two->sha1, pair->two->path, pair->two->mode); | ||
277 | if (use_ssdiff) | ||
278 | cgit_ssdiff_header_end(); | ||
279 | if (S_ISGITLINK(pair->one->mode) || S_ISGITLINK(pair->two->mode)) { | 279 | if (S_ISGITLINK(pair->one->mode) || S_ISGITLINK(pair->two->mode)) { |
280 | if (S_ISGITLINK(pair->one->mode)) | 280 | if (S_ISGITLINK(pair->one->mode)) |
281 | print_line(fmt("-Subproject %s", sha1_to_hex(pair->one->sha1)), 52); | 281 | print_line_fn(fmt("-Subproject %s", sha1_to_hex(pair->one->sha1)), 52); |
282 | if (S_ISGITLINK(pair->two->mode)) | 282 | if (S_ISGITLINK(pair->two->mode)) |
283 | print_line(fmt("+Subproject %s", sha1_to_hex(pair->two->sha1)), 52); | 283 | print_line_fn(fmt("+Subproject %s", sha1_to_hex(pair->two->sha1)), 52); |
284 | return; | 284 | return; |
285 | } | 285 | } |
286 | if (cgit_diff_files(pair->one->sha1, pair->two->sha1, &old_size, | 286 | if (cgit_diff_files(pair->one->sha1, pair->two->sha1, &old_size, |
287 | &new_size, &binary, print_line_fn)) | 287 | &new_size, &binary, print_line_fn)) |
288 | cgit_print_error("Error running diff"); | 288 | cgit_print_error("Error running diff"); |
289 | if (binary) | 289 | if (binary) |
290 | html("Binary files differ"); | 290 | print_line_fn(" Binary files differ", 20); |
291 | if (use_ssdiff) | 291 | if (use_ssdiff) |
292 | cgit_ssdiff_footer(); | 292 | cgit_ssdiff_footer(); |
293 | } | 293 | } |
294 | 294 | ||
295 | void cgit_print_diff(const char *new_rev, const char *old_rev, const char *prefix) | 295 | void cgit_print_diff(const char *new_rev, const char *old_rev, const char *prefix) |
296 | { | 296 | { |
297 | enum object_type type; | 297 | enum object_type type; |
298 | unsigned long size; | 298 | unsigned long size; |
299 | struct commit *commit, *commit2; | 299 | struct commit *commit, *commit2; |
300 | 300 | ||
301 | if (!new_rev) | 301 | if (!new_rev) |
302 | new_rev = ctx.qry.head; | 302 | new_rev = ctx.qry.head; |
303 | get_sha1(new_rev, new_rev_sha1); | 303 | get_sha1(new_rev, new_rev_sha1); |
304 | type = sha1_object_info(new_rev_sha1, &size); | 304 | type = sha1_object_info(new_rev_sha1, &size); |
305 | if (type == OBJ_BAD) { | 305 | if (type == OBJ_BAD) { |
306 | cgit_print_error(fmt("Bad object name: %s", new_rev)); | 306 | cgit_print_error(fmt("Bad object name: %s", new_rev)); |
307 | return; | 307 | return; |
308 | } | 308 | } |
309 | commit = lookup_commit_reference(new_rev_sha1); | 309 | commit = lookup_commit_reference(new_rev_sha1); |
310 | if (!commit || parse_commit(commit)) | 310 | if (!commit || parse_commit(commit)) |
311 | cgit_print_error(fmt("Bad commit: %s", sha1_to_hex(new_rev_sha1))); | 311 | cgit_print_error(fmt("Bad commit: %s", sha1_to_hex(new_rev_sha1))); |
312 | 312 | ||
313 | if (old_rev) | 313 | if (old_rev) |
314 | get_sha1(old_rev, old_rev_sha1); | 314 | get_sha1(old_rev, old_rev_sha1); |
315 | else if (commit->parents && commit->parents->item) | 315 | else if (commit->parents && commit->parents->item) |
316 | hashcpy(old_rev_sha1, commit->parents->item->object.sha1); | 316 | hashcpy(old_rev_sha1, commit->parents->item->object.sha1); |
317 | else | 317 | else |
318 | hashclr(old_rev_sha1); | 318 | hashclr(old_rev_sha1); |
319 | 319 | ||
320 | if (!is_null_sha1(old_rev_sha1)) { | 320 | if (!is_null_sha1(old_rev_sha1)) { |
321 | type = sha1_object_info(old_rev_sha1, &size); | 321 | type = sha1_object_info(old_rev_sha1, &size); |
322 | if (type == OBJ_BAD) { | 322 | if (type == OBJ_BAD) { |
323 | cgit_print_error(fmt("Bad object name: %s", sha1_to_hex(old_rev_sha1))); | 323 | cgit_print_error(fmt("Bad object name: %s", sha1_to_hex(old_rev_sha1))); |
324 | return; | 324 | return; |
325 | } | 325 | } |
326 | commit2 = lookup_commit_reference(old_rev_sha1); | 326 | commit2 = lookup_commit_reference(old_rev_sha1); |
327 | if (!commit2 || parse_commit(commit2)) | 327 | if (!commit2 || parse_commit(commit2)) |
328 | cgit_print_error(fmt("Bad commit: %s", sha1_to_hex(old_rev_sha1))); | 328 | cgit_print_error(fmt("Bad commit: %s", sha1_to_hex(old_rev_sha1))); |
329 | } | 329 | } |
330 | 330 | ||
331 | if ((ctx.qry.ssdiff && !ctx.cfg.ssdiff) || (!ctx.qry.ssdiff && ctx.cfg.ssdiff)) | 331 | if ((ctx.qry.ssdiff && !ctx.cfg.ssdiff) || (!ctx.qry.ssdiff && ctx.cfg.ssdiff)) |
332 | use_ssdiff = 1; | 332 | use_ssdiff = 1; |
333 | 333 | ||
334 | print_ssdiff_link(); | 334 | print_ssdiff_link(); |
335 | cgit_print_diffstat(old_rev_sha1, new_rev_sha1); | 335 | cgit_print_diffstat(old_rev_sha1, new_rev_sha1); |
336 | 336 | ||
337 | html("<table summary='diff' class='diff'>"); | 337 | if (use_ssdiff) { |
338 | html("<tr><td>"); | 338 | html("<table summary='ssdiff' class='ssdiff'>"); |
339 | } else { | ||
340 | html("<table summary='diff' class='diff'>"); | ||
341 | html("<tr><td>"); | ||
342 | } | ||
339 | cgit_diff_tree(old_rev_sha1, new_rev_sha1, filepair_cb, prefix); | 343 | cgit_diff_tree(old_rev_sha1, new_rev_sha1, filepair_cb, prefix); |
340 | html("</td></tr>"); | 344 | if (!use_ssdiff) |
345 | html("</td></tr>"); | ||
341 | html("</table>"); | 346 | html("</table>"); |
342 | } | 347 | } |