aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile10
-rw-r--r--cgit.c7
-rw-r--r--cgit.css347
-rw-r--r--cgit.h1
-rw-r--r--cgitrc.5.txt2
-rwxr-xr-xfilters/commit-links.sh7
-rwxr-xr-xfilters/syntax-highlighting.sh28
-rw-r--r--html.c4
-rw-r--r--parsing.c2
-rw-r--r--shared.c3
-rwxr-xr-xtests/setup.sh5
-rwxr-xr-xtests/t0108-patch.sh2
-rw-r--r--ui-diff.c17
-rw-r--r--ui-log.c3
-rw-r--r--ui-repolist.c6
-rw-r--r--ui-shared.c30
-rw-r--r--ui-shared.h2
-rw-r--r--ui-ssdiff.c29
-rw-r--r--ui-ssdiff.h12
19 files changed, 303 insertions, 214 deletions
diff --git a/Makefile b/Makefile
index f6d6968..eac24ad 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
1CGIT_VERSION = v0.9.0.1 1CGIT_VERSION = v0.9.0.3
2CGIT_SCRIPT_NAME = cgit.cgi 2CGIT_SCRIPT_NAME = cgit.cgi
3CGIT_SCRIPT_PATH = /var/www/htdocs/cgit 3CGIT_SCRIPT_PATH = /var/www/htdocs/cgit
4CGIT_DATA_PATH = $(CGIT_SCRIPT_PATH) 4CGIT_DATA_PATH = $(CGIT_SCRIPT_PATH)
@@ -13,7 +13,7 @@ pdfdir = $(docdir)
13mandir = $(prefix)/share/man 13mandir = $(prefix)/share/man
14SHA1_HEADER = <openssl/sha.h> 14SHA1_HEADER = <openssl/sha.h>
15GIT_VER = 1.7.4 15GIT_VER = 1.7.4
16GIT_URL = http://www.kernel.org/pub/software/scm/git/git-$(GIT_VER).tar.bz2 16GIT_URL = http://hjemli.net/git/git/snapshot/git-$(GIT_VER).tar.bz2
17INSTALL = install 17INSTALL = install
18MAN5_TXT = $(wildcard *.5.txt) 18MAN5_TXT = $(wildcard *.5.txt)
19MAN_TXT = $(MAN5_TXT) 19MAN_TXT = $(MAN5_TXT)
@@ -198,9 +198,9 @@ install-pdf: doc-pdf
198 $(INSTALL) -m 0644 $(DOC_PDF) $(DESTDIR)$(pdfdir) 198 $(INSTALL) -m 0644 $(DOC_PDF) $(DESTDIR)$(pdfdir)
199 199
200uninstall: 200uninstall:
201 rm -f $(CGIT_SCRIPT_PATH)/$(CGIT_SCRIPT_NAME) 201 rm -f $(DESTDIR)$(CGIT_SCRIPT_PATH)/$(CGIT_SCRIPT_NAME)
202 rm -f $(CGIT_DATA_PATH)/cgit.css 202 rm -f $(DESTDIR)$(CGIT_DATA_PATH)/cgit.css
203 rm -f $(CGIT_DATA_PATH)/cgit.png 203 rm -f $(DESTDIR)$(CGIT_DATA_PATH)/cgit.png
204 204
205uninstall-doc: uninstall-man uninstall-html uninstall-pdf 205uninstall-doc: uninstall-man uninstall-html uninstall-pdf
206 206
diff --git a/cgit.c b/cgit.c
index 9eb2535..7e3d349 100644
--- a/cgit.c
+++ b/cgit.c
@@ -303,6 +303,7 @@ static void querystring_cb(const char *name, const char *value)
303 ctx.qry.period = xstrdup(value); 303 ctx.qry.period = xstrdup(value);
304 } else if (!strcmp(name, "ss")) { 304 } else if (!strcmp(name, "ss")) {
305 ctx.qry.ssdiff = atoi(value); 305 ctx.qry.ssdiff = atoi(value);
306 ctx.qry.has_ssdiff = 1;
306 } else if (!strcmp(name, "all")) { 307 } else if (!strcmp(name, "all")) {
307 ctx.qry.show_all = atoi(value); 308 ctx.qry.show_all = atoi(value);
308 } else if (!strcmp(name, "context")) { 309 } else if (!strcmp(name, "context")) {
@@ -425,13 +426,17 @@ static int prepare_repo_cmd(struct cgit_context *ctx)
425 char *tmp; 426 char *tmp;
426 unsigned char sha1[20]; 427 unsigned char sha1[20];
427 int nongit = 0; 428 int nongit = 0;
429 int rc;
428 430
429 setenv("GIT_DIR", ctx->repo->path, 1); 431 setenv("GIT_DIR", ctx->repo->path, 1);
430 setup_git_directory_gently(&nongit); 432 setup_git_directory_gently(&nongit);
431 if (nongit) { 433 if (nongit) {
434 rc = errno;
432 ctx->page.title = fmt("%s - %s", ctx->cfg.root_title, 435 ctx->page.title = fmt("%s - %s", ctx->cfg.root_title,
433 "config error"); 436 "config error");
434 tmp = fmt("Not a git repository: '%s'", ctx->repo->path); 437 tmp = fmt("Failed to open %s: %s",
438 ctx->repo->name,
439 rc ? strerror(rc) : "Not a valid git repository");
435 ctx->repo = NULL; 440 ctx->repo = NULL;
436 cgit_print_http_headers(ctx); 441 cgit_print_http_headers(ctx);
437 cgit_print_docstart(ctx); 442 cgit_print_docstart(ctx);
diff --git a/cgit.css b/cgit.css
index 55afa94..e06c261 100644
--- a/cgit.css
+++ b/cgit.css
@@ -1,4 +1,4 @@
1body, table, form { 1body, div#cgit table, div#cgit form {
2 padding: 0em; 2 padding: 0em;
3 margin: 0em; 3 margin: 0em;
4} 4}
@@ -11,39 +11,40 @@ body {
11 padding: 4px; 11 padding: 4px;
12} 12}
13 13
14a { 14div#cgit a {
15 color: blue; 15 color: blue;
16 text-decoration: none; 16 text-decoration: none;
17} 17}
18 18
19a:hover { 19div#cgit a:hover {
20 text-decoration: underline; 20 text-decoration: underline;
21} 21}
22 22
23table { 23div#cgit table {
24 border-collapse: collapse; 24 border-collapse: collapse;
25} 25}
26 26
27table#header { 27div#cgit table#header {
28 width: 100%; 28 width: 100%;
29 margin-bottom: 1em; 29 margin-bottom: 1em;
30} 30}
31 31
32table#header td.logo { 32div#cgit table#header td.logo {
33 width: 96px; 33 width: 96px;
34 vertical-align: top;
34} 35}
35 36
36table#header td.main { 37div#cgit table#header td.main {
37 font-size: 250%; 38 font-size: 250%;
38 padding-left: 10px; 39 padding-left: 10px;
39 white-space: nowrap; 40 white-space: nowrap;
40} 41}
41 42
42table#header td.main a { 43div#cgit table#header td.main a {
43 color: #000; 44 color: #000;
44} 45}
45 46
46table#header td.form { 47div#cgit table#header td.form {
47 text-align: right; 48 text-align: right;
48 vertical-align: bottom; 49 vertical-align: bottom;
49 padding-right: 1em; 50 padding-right: 1em;
@@ -51,19 +52,19 @@ table#header td.form {
51 white-space: nowrap; 52 white-space: nowrap;
52} 53}
53 54
54table#header td.form form, 55div#cgit table#header td.form form,
55table#header td.form input, 56div#cgit table#header td.form input,
56table#header td.form select { 57div#cgit table#header td.form select {
57 font-size: 90%; 58 font-size: 90%;
58} 59}
59 60
60table#header td.sub { 61div#cgit table#header td.sub {
61 color: #777; 62 color: #777;
62 border-top: solid 1px #ccc; 63 border-top: solid 1px #ccc;
63 padding-left: 10px; 64 padding-left: 10px;
64} 65}
65 66
66table.tabs { 67div#cgit table.tabs {
67 border-bottom: solid 3px #ccc; 68 border-bottom: solid 3px #ccc;
68 border-collapse: collapse; 69 border-collapse: collapse;
69 margin-top: 2em; 70 margin-top: 2em;
@@ -71,74 +72,74 @@ table.tabs {
71 width: 100%; 72 width: 100%;
72} 73}
73 74
74table.tabs td { 75div#cgit table.tabs td {
75 padding: 0px 1em; 76 padding: 0px 1em;
76 vertical-align: bottom; 77 vertical-align: bottom;
77} 78}
78 79
79table.tabs td a { 80div#cgit table.tabs td a {
80 padding: 2px 0.75em; 81 padding: 2px 0.75em;
81 color: #777; 82 color: #777;
82 font-size: 110%; 83 font-size: 110%;
83} 84}
84 85
85table.tabs td a.active { 86div#cgit table.tabs td a.active {
86 color: #000; 87 color: #000;
87 background-color: #ccc; 88 background-color: #ccc;
88} 89}
89 90
90table.tabs td.form { 91div#cgit table.tabs td.form {
91 text-align: right; 92 text-align: right;
92} 93}
93 94
94table.tabs td.form form { 95div#cgit table.tabs td.form form {
95 padding-bottom: 2px; 96 padding-bottom: 2px;
96 font-size: 90%; 97 font-size: 90%;
97 white-space: nowrap; 98 white-space: nowrap;
98} 99}
99 100
100table.tabs td.form input, 101div#cgit table.tabs td.form input,
101table.tabs td.form select { 102div#cgit table.tabs td.form select {
102 font-size: 90%; 103 font-size: 90%;
103} 104}
104 105
105div.path { 106div#cgit div.path {
106 margin: 0px; 107 margin: 0px;
107 padding: 5px 2em 2px 2em; 108 padding: 5px 2em 2px 2em;
108 color: #000; 109 color: #000;
109 background-color: #eee; 110 background-color: #eee;
110} 111}
111 112
112div.content { 113div#cgit div.content {
113 margin: 0px; 114 margin: 0px;
114 padding: 2em; 115 padding: 2em;
115 border-bottom: solid 3px #ccc; 116 border-bottom: solid 3px #ccc;
116} 117}
117 118
118 119
119table.list { 120div#cgit table.list {
120 width: 100%; 121 width: 100%;
121 border: none; 122 border: none;
122 border-collapse: collapse; 123 border-collapse: collapse;
123} 124}
124 125
125table.list tr { 126div#cgit table.list tr {
126 background: white; 127 background: white;
127} 128}
128 129
129table.list tr.logheader { 130div#cgit table.list tr.logheader {
130 background: #eee; 131 background: #eee;
131} 132}
132 133
133table.list tr:hover { 134div#cgit table.list tr:hover {
134 background: #eee; 135 background: #eee;
135} 136}
136 137
137table.list tr.nohover:hover { 138div#cgit table.list tr.nohover:hover {
138 background: white; 139 background: white;
139} 140}
140 141
141table.list th { 142div#cgit table.list th {
142 font-weight: bold; 143 font-weight: bold;
143 /* color: #888; 144 /* color: #888;
144 border-top: dashed 1px #888; 145 border-top: dashed 1px #888;
@@ -148,93 +149,93 @@ table.list th {
148 vertical-align: baseline; 149 vertical-align: baseline;
149} 150}
150 151
151table.list td { 152div#cgit table.list td {
152 border: none; 153 border: none;
153 padding: 0.1em 0.5em 0.1em 0.5em; 154 padding: 0.1em 0.5em 0.1em 0.5em;
154} 155}
155 156
156table.list td.commitgraph { 157div#cgit table.list td.commitgraph {
157 font-family: monospace; 158 font-family: monospace;
158 white-space: pre; 159 white-space: pre;
159} 160}
160 161
161table.list td.commitgraph .column1 { 162div#cgit table.list td.commitgraph .column1 {
162 color: #a00; 163 color: #a00;
163} 164}
164 165
165table.list td.commitgraph .column2 { 166div#cgit table.list td.commitgraph .column2 {
166 color: #0a0; 167 color: #0a0;
167} 168}
168 169
169table.list td.commitgraph .column3 { 170div#cgit table.list td.commitgraph .column3 {
170 color: #aa0; 171 color: #aa0;
171} 172}
172 173
173table.list td.commitgraph .column4 { 174div#cgit table.list td.commitgraph .column4 {
174 color: #00a; 175 color: #00a;
175} 176}
176 177
177table.list td.commitgraph .column5 { 178div#cgit table.list td.commitgraph .column5 {
178 color: #a0a; 179 color: #a0a;
179} 180}
180 181
181table.list td.commitgraph .column6 { 182div#cgit table.list td.commitgraph .column6 {
182 color: #0aa; 183 color: #0aa;
183} 184}
184 185
185table.list td.logsubject { 186div#cgit table.list td.logsubject {
186 font-family: monospace; 187 font-family: monospace;
187 font-weight: bold; 188 font-weight: bold;
188} 189}
189 190
190table.list td.logmsg { 191div#cgit table.list td.logmsg {
191 font-family: monospace; 192 font-family: monospace;
192 white-space: pre; 193 white-space: pre;
193 padding: 0 0.5em; 194 padding: 0 0.5em;
194} 195}
195 196
196table.list td a { 197div#cgit table.list td a {
197 color: black; 198 color: black;
198} 199}
199 200
200table.list td a.ls-dir { 201div#cgit table.list td a.ls-dir {
201 font-weight: bold; 202 font-weight: bold;
202 color: #00f; 203 color: #00f;
203} 204}
204 205
205table.list td a:hover { 206div#cgit table.list td a:hover {
206 color: #00f; 207 color: #00f;
207} 208}
208 209
209img { 210div#cgit img {
210 border: none; 211 border: none;
211} 212}
212 213
213input#switch-btn { 214div#cgit input#switch-btn {
214 margin: 2px 0px 0px 0px; 215 margin: 2px 0px 0px 0px;
215} 216}
216 217
217td#sidebar input.txt { 218div#cgit td#sidebar input.txt {
218 width: 100%; 219 width: 100%;
219 margin: 2px 0px 0px 0px; 220 margin: 2px 0px 0px 0px;
220} 221}
221 222
222table#grid { 223div#cgit table#grid {
223 margin: 0px; 224 margin: 0px;
224} 225}
225 226
226td#content { 227div#cgit td#content {
227 vertical-align: top; 228 vertical-align: top;
228 padding: 1em 2em 1em 1em; 229 padding: 1em 2em 1em 1em;
229 border: none; 230 border: none;
230} 231}
231 232
232div#summary { 233div#cgit div#summary {
233 vertical-align: top; 234 vertical-align: top;
234 margin-bottom: 1em; 235 margin-bottom: 1em;
235} 236}
236 237
237table#downloads { 238div#cgit table#downloads {
238 float: right; 239 float: right;
239 border-collapse: collapse; 240 border-collapse: collapse;
240 border: solid 1px #777; 241 border: solid 1px #777;
@@ -242,152 +243,152 @@ table#downloads {
242 margin-bottom: 0.5em; 243 margin-bottom: 0.5em;
243} 244}
244 245
245table#downloads th { 246div#cgit table#downloads th {
246 background-color: #ccc; 247 background-color: #ccc;
247} 248}
248 249
249div#blob { 250div#cgit div#blob {
250 border: solid 1px black; 251 border: solid 1px black;
251} 252}
252 253
253div.error { 254div#cgit div.error {
254 color: red; 255 color: red;
255 font-weight: bold; 256 font-weight: bold;
256 margin: 1em 2em; 257 margin: 1em 2em;
257} 258}
258 259
259a.ls-blob, a.ls-dir, a.ls-mod { 260div#cgit a.ls-blob, div#cgit a.ls-dir, div#cgit a.ls-mod {
260 font-family: monospace; 261 font-family: monospace;
261} 262}
262 263
263td.ls-size { 264div#cgit td.ls-size {
264 text-align: right; 265 text-align: right;
265 font-family: monospace; 266 font-family: monospace;
266 width: 10em; 267 width: 10em;
267} 268}
268 269
269td.ls-mode { 270div#cgit td.ls-mode {
270 font-family: monospace; 271 font-family: monospace;
271 width: 10em; 272 width: 10em;
272} 273}
273 274
274table.blob { 275div#cgit table.blob {
275 margin-top: 0.5em; 276 margin-top: 0.5em;
276 border-top: solid 1px black; 277 border-top: solid 1px black;
277} 278}
278 279
279table.blob td.lines { 280div#cgit table.blob td.lines {
280 margin: 0; padding: 0 0 0 0.5em; 281 margin: 0; padding: 0 0 0 0.5em;
281 vertical-align: top; 282 vertical-align: top;
282 color: black; 283 color: black;
283} 284}
284 285
285table.blob td.linenumbers { 286div#cgit table.blob td.linenumbers {
286 margin: 0; padding: 0 0.5em 0 0.5em; 287 margin: 0; padding: 0 0.5em 0 0.5em;
287 vertical-align: top; 288 vertical-align: top;
288 text-align: right; 289 text-align: right;
289 border-right: 1px solid gray; 290 border-right: 1px solid gray;
290} 291}
291 292
292table.blob pre { 293div#cgit table.blob pre {
293 padding: 0; margin: 0; 294 padding: 0; margin: 0;
294} 295}
295 296
296table.blob a.no, table.ssdiff a.no { 297div#cgit table.blob a.no, div#cgit table.ssdiff a.no {
297 color: gray; 298 color: gray;
298 text-align: right; 299 text-align: right;
299 text-decoration: none; 300 text-decoration: none;
300} 301}
301 302
302table.blob a.no a:hover { 303div#cgit table.blob a.no a:hover {
303 color: black; 304 color: black;
304} 305}
305 306
306table.bin-blob { 307div#cgit table.bin-blob {
307 margin-top: 0.5em; 308 margin-top: 0.5em;
308 border: solid 1px black; 309 border: solid 1px black;
309} 310}
310 311
311table.bin-blob th { 312div#cgit table.bin-blob th {
312 font-family: monospace; 313 font-family: monospace;
313 white-space: pre; 314 white-space: pre;
314 border: solid 1px #777; 315 border: solid 1px #777;
315 padding: 0.5em 1em; 316 padding: 0.5em 1em;
316} 317}
317 318
318table.bin-blob td { 319div#cgit table.bin-blob td {
319 font-family: monospace; 320 font-family: monospace;
320 white-space: pre; 321 white-space: pre;
321 border-left: solid 1px #777; 322 border-left: solid 1px #777;
322 padding: 0em 1em; 323 padding: 0em 1em;
323} 324}
324 325
325table.nowrap td { 326div#cgit table.nowrap td {
326 white-space: nowrap; 327 white-space: nowrap;
327} 328}
328 329
329table.commit-info { 330div#cgit table.commit-info {
330 border-collapse: collapse; 331 border-collapse: collapse;
331 margin-top: 1.5em; 332 margin-top: 1.5em;
332} 333}
333 334
334div.cgit-panel { 335div#cgit div.cgit-panel {
335 float: right; 336 float: right;
336 margin-top: 1.5em; 337 margin-top: 1.5em;
337} 338}
338 339
339div.cgit-panel table { 340div#cgit div.cgit-panel table {
340 border-collapse: collapse; 341 border-collapse: collapse;
341 border: solid 1px #aaa; 342 border: solid 1px #aaa;
342 background-color: #eee; 343 background-color: #eee;
343} 344}
344 345
345div.cgit-panel th { 346div#cgit div.cgit-panel th {
346 text-align: center; 347 text-align: center;
347} 348}
348 349
349div.cgit-panel td { 350div#cgit div.cgit-panel td {
350 padding: 0.25em 0.5em; 351 padding: 0.25em 0.5em;
351} 352}
352 353
353div.cgit-panel td.label { 354div#cgit div.cgit-panel td.label {
354 padding-right: 0.5em; 355 padding-right: 0.5em;
355} 356}
356 357
357div.cgit-panel td.ctrl { 358div#cgit div.cgit-panel td.ctrl {
358 padding-left: 0.5em; 359 padding-left: 0.5em;
359} 360}
360 361
361table.commit-info th { 362div#cgit table.commit-info th {
362 text-align: left; 363 text-align: left;
363 font-weight: normal; 364 font-weight: normal;
364 padding: 0.1em 1em 0.1em 0.1em; 365 padding: 0.1em 1em 0.1em 0.1em;
365 vertical-align: top; 366 vertical-align: top;
366} 367}
367 368
368table.commit-info td { 369div#cgit table.commit-info td {
369 font-weight: normal; 370 font-weight: normal;
370 padding: 0.1em 1em 0.1em 0.1em; 371 padding: 0.1em 1em 0.1em 0.1em;
371} 372}
372 373
373div.commit-subject { 374div#cgit div.commit-subject {
374 font-weight: bold; 375 font-weight: bold;
375 font-size: 125%; 376 font-size: 125%;
376 margin: 1.5em 0em 0.5em 0em; 377 margin: 1.5em 0em 0.5em 0em;
377 padding: 0em; 378 padding: 0em;
378} 379}
379 380
380div.commit-msg { 381div#cgit div.commit-msg {
381 white-space: pre; 382 white-space: pre;
382 font-family: monospace; 383 font-family: monospace;
383} 384}
384 385
385div.notes-header { 386div#cgit div.notes-header {
386 font-weight: bold; 387 font-weight: bold;
387 padding-top: 1.5em; 388 padding-top: 1.5em;
388} 389}
389 390
390div.notes { 391div#cgit div.notes {
391 white-space: pre; 392 white-space: pre;
392 font-family: monospace; 393 font-family: monospace;
393 border: solid 1px #ee9; 394 border: solid 1px #ee9;
@@ -396,22 +397,22 @@ div.notes {
396 float: left; 397 float: left;
397} 398}
398 399
399div.notes-footer { 400div#cgit div.notes-footer {
400 clear: left; 401 clear: left;
401} 402}
402 403
403div.diffstat-header { 404div#cgit div.diffstat-header {
404 font-weight: bold; 405 font-weight: bold;
405 padding-top: 1.5em; 406 padding-top: 1.5em;
406} 407}
407 408
408table.diffstat { 409div#cgit table.diffstat {
409 border-collapse: collapse; 410 border-collapse: collapse;
410 border: solid 1px #aaa; 411 border: solid 1px #aaa;
411 background-color: #eee; 412 background-color: #eee;
412} 413}
413 414
414table.diffstat th { 415div#cgit table.diffstat th {
415 font-weight: normal; 416 font-weight: normal;
416 text-align: left; 417 text-align: left;
417 text-decoration: underline; 418 text-decoration: underline;
@@ -419,282 +420,286 @@ table.diffstat th {
419 font-size: 100%; 420 font-size: 100%;
420} 421}
421 422
422table.diffstat td { 423div#cgit table.diffstat td {
423 padding: 0.2em 0.2em 0.1em 0.1em; 424 padding: 0.2em 0.2em 0.1em 0.1em;
424 font-size: 100%; 425 font-size: 100%;
425 border: none; 426 border: none;
426} 427}
427 428
428table.diffstat td.mode { 429div#cgit table.diffstat td.mode {
429 white-space: nowrap; 430 white-space: nowrap;
430} 431}
431 432
432table.diffstat td span.modechange { 433div#cgit table.diffstat td span.modechange {
433 padding-left: 1em; 434 padding-left: 1em;
434 color: red; 435 color: red;
435} 436}
436 437
437table.diffstat td.add a { 438div#cgit table.diffstat td.add a {
438 color: green; 439 color: green;
439} 440}
440 441
441table.diffstat td.del a { 442div#cgit table.diffstat td.del a {
442 color: red; 443 color: red;
443} 444}
444 445
445table.diffstat td.upd a { 446div#cgit table.diffstat td.upd a {
446 color: blue; 447 color: blue;
447} 448}
448 449
449table.diffstat td.graph { 450div#cgit table.diffstat td.graph {
450 width: 500px; 451 width: 500px;
451 vertical-align: middle; 452 vertical-align: middle;
452} 453}
453 454
454table.diffstat td.graph table { 455div#cgit table.diffstat td.graph table {
455 border: none; 456 border: none;
456} 457}
457 458
458table.diffstat td.graph td { 459div#cgit table.diffstat td.graph td {
459 padding: 0px; 460 padding: 0px;
460 border: 0px; 461 border: 0px;
461 height: 7pt; 462 height: 7pt;
462} 463}
463 464
464table.diffstat td.graph td.add { 465div#cgit table.diffstat td.graph td.add {
465 background-color: #5c5; 466 background-color: #5c5;
466} 467}
467 468
468table.diffstat td.graph td.rem { 469div#cgit table.diffstat td.graph td.rem {
469 background-color: #c55; 470 background-color: #c55;
470} 471}
471 472
472div.diffstat-summary { 473div#cgit div.diffstat-summary {
473 color: #888; 474 color: #888;
474 padding-top: 0.5em; 475 padding-top: 0.5em;
475} 476}
476 477
477table.diff { 478div#cgit table.diff {
478 width: 100%; 479 width: 100%;
479} 480}
480 481
481table.diff td { 482div#cgit table.diff td {
482 font-family: monospace; 483 font-family: monospace;
483 white-space: pre; 484 white-space: pre;
484} 485}
485 486
486table.diff td div.head { 487div#cgit table.diff td div.head {
487 font-weight: bold; 488 font-weight: bold;
488 margin-top: 1em; 489 margin-top: 1em;
489 color: black; 490 color: black;
490} 491}
491 492
492table.diff td div.hunk { 493div#cgit table.diff td div.hunk {
493 color: #009; 494 color: #009;
494} 495}
495 496
496table.diff td div.add { 497div#cgit table.diff td div.add {
497 color: green; 498 color: green;
498} 499}
499 500
500table.diff td div.del { 501div#cgit table.diff td div.del {
501 color: red; 502 color: red;
502} 503}
503 504
504.sha1 { 505div#cgit .sha1 {
505 font-family: monospace; 506 font-family: monospace;
506 font-size: 90%; 507 font-size: 90%;
507} 508}
508 509
509.left { 510div#cgit .left {
510 text-align: left; 511 text-align: left;
511} 512}
512 513
513.right { 514div#cgit .right {
514 text-align: right; 515 text-align: right;
515} 516}
516 517
517table.list td.reposection { 518div#cgit table.list td.reposection {
518 font-style: italic; 519 font-style: italic;
519 color: #888; 520 color: #888;
520} 521}
521 522
522a.button { 523div#cgit a.button {
523 font-size: 80%; 524 font-size: 80%;
524 padding: 0em 0.5em; 525 padding: 0em 0.5em;
525} 526}
526 527
527a.primary { 528div#cgit a.primary {
528 font-size: 100%; 529 font-size: 100%;
529} 530}
530 531
531a.secondary { 532div#cgit a.secondary {
532 font-size: 90%; 533 font-size: 90%;
533} 534}
534 535
535td.toplevel-repo { 536div#cgit td.toplevel-repo {
536 537
537} 538}
538 539
539table.list td.sublevel-repo { 540div#cgit table.list td.sublevel-repo {
540 padding-left: 1.5em; 541 padding-left: 1.5em;
541} 542}
542 543
543div.pager { 544div#cgit div.pager {
544 text-align: center; 545 text-align: center;
545 margin: 1em 0em 0em 0em; 546 margin: 1em 0em 0em 0em;
546} 547}
547 548
548div.pager a { 549div#cgit div.pager a {
549 color: #777; 550 color: #777;
550 margin: 0em 0.5em; 551 margin: 0em 0.5em;
551} 552}
552 553
553span.age-mins { 554div#cgit span.age-mins {
554 font-weight: bold; 555 font-weight: bold;
555 color: #080; 556 color: #080;
556} 557}
557 558
558span.age-hours { 559div#cgit span.age-hours {
559 color: #080; 560 color: #080;
560} 561}
561 562
562span.age-days { 563div#cgit span.age-days {
563 color: #040; 564 color: #040;
564} 565}
565 566
566span.age-weeks { 567div#cgit span.age-weeks {
567 color: #444; 568 color: #444;
568} 569}
569 570
570span.age-months { 571div#cgit span.age-months {
571 color: #888; 572 color: #888;
572} 573}
573 574
574span.age-years { 575div#cgit span.age-years {
575 color: #bbb; 576 color: #bbb;
576} 577}
577div.footer { 578div#cgit div.footer {
578 margin-top: 0.5em; 579 margin-top: 0.5em;
579 text-align: center; 580 text-align: center;
580 font-size: 80%; 581 font-size: 80%;
581 color: #ccc; 582 color: #ccc;
582} 583}
583a.branch-deco { 584div#cgit a.branch-deco {
585 color: #000;
584 margin: 0px 0.5em; 586 margin: 0px 0.5em;
585 padding: 0px 0.25em; 587 padding: 0px 0.25em;
586 background-color: #88ff88; 588 background-color: #88ff88;
587 border: solid 1px #007700; 589 border: solid 1px #007700;
588} 590}
589a.tag-deco { 591div#cgit a.tag-deco {
592 color: #000;
590 margin: 0px 0.5em; 593 margin: 0px 0.5em;
591 padding: 0px 0.25em; 594 padding: 0px 0.25em;
592 background-color: #ffff88; 595 background-color: #ffff88;
593 border: solid 1px #777700; 596 border: solid 1px #777700;
594} 597}
595a.remote-deco { 598div#cgit a.remote-deco {
599 color: #000;
596 margin: 0px 0.5em; 600 margin: 0px 0.5em;
597 padding: 0px 0.25em; 601 padding: 0px 0.25em;
598 background-color: #ccccff; 602 background-color: #ccccff;
599 border: solid 1px #000077; 603 border: solid 1px #000077;
600} 604}
601a.deco { 605div#cgit a.deco {
606 color: #000;
602 margin: 0px 0.5em; 607 margin: 0px 0.5em;
603 padding: 0px 0.25em; 608 padding: 0px 0.25em;
604 background-color: #ff8888; 609 background-color: #ff8888;
605 border: solid 1px #770000; 610 border: solid 1px #770000;
606} 611}
607 612
608div.commit-subject a.branch-deco, 613div#cgit div.commit-subject a.branch-deco,
609div.commit-subject a.tag-deco, 614div#cgit div.commit-subject a.tag-deco,
610div.commit-subject a.remote-deco, 615div#cgit div.commit-subject a.remote-deco,
611div.commit-subject a.deco { 616div#cgit div.commit-subject a.deco {
612 margin-left: 1em; 617 margin-left: 1em;
613 font-size: 75%; 618 font-size: 75%;
614} 619}
615 620
616table.stats { 621div#cgit table.stats {
617 border: solid 1px black; 622 border: solid 1px black;
618 border-collapse: collapse; 623 border-collapse: collapse;
619} 624}
620 625
621table.stats th { 626div#cgit table.stats th {
622 text-align: left; 627 text-align: left;
623 padding: 1px 0.5em; 628 padding: 1px 0.5em;
624 background-color: #eee; 629 background-color: #eee;
625 border: solid 1px black; 630 border: solid 1px black;
626} 631}
627 632
628table.stats td { 633div#cgit table.stats td {
629 text-align: right; 634 text-align: right;
630 padding: 1px 0.5em; 635 padding: 1px 0.5em;
631 border: solid 1px black; 636 border: solid 1px black;
632} 637}
633 638
634table.stats td.total { 639div#cgit table.stats td.total {
635 font-weight: bold; 640 font-weight: bold;
636 text-align: left; 641 text-align: left;
637} 642}
638 643
639table.stats td.sum { 644div#cgit table.stats td.sum {
640 color: #c00; 645 color: #c00;
641 font-weight: bold; 646 font-weight: bold;
642/* background-color: #eee; */ 647/* background-color: #eee; */
643} 648}
644 649
645table.stats td.left { 650div#cgit table.stats td.left {
646 text-align: left; 651 text-align: left;
647} 652}
648 653
649table.vgraph { 654div#cgit table.vgraph {
650 border-collapse: separate; 655 border-collapse: separate;
651 border: solid 1px black; 656 border: solid 1px black;
652 height: 200px; 657 height: 200px;
653} 658}
654 659
655table.vgraph th { 660div#cgit table.vgraph th {
656 background-color: #eee; 661 background-color: #eee;
657 font-weight: bold; 662 font-weight: bold;
658 border: solid 1px white; 663 border: solid 1px white;
659 padding: 1px 0.5em; 664 padding: 1px 0.5em;
660} 665}
661 666
662table.vgraph td { 667div#cgit table.vgraph td {
663 vertical-align: bottom; 668 vertical-align: bottom;
664 padding: 0px 10px; 669 padding: 0px 10px;
665} 670}
666 671
667table.vgraph div.bar { 672div#cgit table.vgraph div.bar {
668 background-color: #eee; 673 background-color: #eee;
669} 674}
670 675
671table.hgraph { 676div#cgit table.hgraph {
672 border: solid 1px black; 677 border: solid 1px black;
673 width: 800px; 678 width: 800px;
674} 679}
675 680
676table.hgraph th { 681div#cgit table.hgraph th {
677 background-color: #eee; 682 background-color: #eee;
678 font-weight: bold; 683 font-weight: bold;
679 border: solid 1px black; 684 border: solid 1px black;
680 padding: 1px 0.5em; 685 padding: 1px 0.5em;
681} 686}
682 687
683table.hgraph td { 688div#cgit table.hgraph td {
684 vertical-align: center; 689 vertical-align: middle;
685 padding: 2px 2px; 690 padding: 2px 2px;
686} 691}
687 692
688table.hgraph div.bar { 693div#cgit table.hgraph div.bar {
689 background-color: #eee; 694 background-color: #eee;
690 height: 1em; 695 height: 1em;
691} 696}
692 697
693table.ssdiff { 698div#cgit table.ssdiff {
694 width: 100%; 699 width: 100%;
695} 700}
696 701
697table.ssdiff td { 702div#cgit table.ssdiff td {
698 font-size: 75%; 703 font-size: 75%;
699 font-family: monospace; 704 font-family: monospace;
700 white-space: pre; 705 white-space: pre;
@@ -703,53 +708,53 @@ table.ssdiff td {
703 border-right: solid 1px #aaa; 708 border-right: solid 1px #aaa;
704} 709}
705 710
706table.ssdiff td.add { 711div#cgit table.ssdiff td.add {
707 color: black; 712 color: black;
708 background: #cfc; 713 background: #cfc;
709 min-width: 50%; 714 min-width: 50%;
710} 715}
711 716
712table.ssdiff td.add_dark { 717div#cgit table.ssdiff td.add_dark {
713 color: black; 718 color: black;
714 background: #aca; 719 background: #aca;
715 min-width: 50%; 720 min-width: 50%;
716} 721}
717 722
718table.ssdiff span.add { 723div#cgit table.ssdiff span.add {
719 background: #cfc; 724 background: #cfc;
720 font-weight: bold; 725 font-weight: bold;
721} 726}
722 727
723table.ssdiff td.del { 728div#cgit table.ssdiff td.del {
724 color: black; 729 color: black;
725 background: #fcc; 730 background: #fcc;
726 min-width: 50%; 731 min-width: 50%;
727} 732}
728 733
729table.ssdiff td.del_dark { 734div#cgit table.ssdiff td.del_dark {
730 color: black; 735 color: black;
731 background: #caa; 736 background: #caa;
732 min-width: 50%; 737 min-width: 50%;
733} 738}
734 739
735table.ssdiff span.del { 740div#cgit table.ssdiff span.del {
736 background: #fcc; 741 background: #fcc;
737 font-weight: bold; 742 font-weight: bold;
738} 743}
739 744
740table.ssdiff td.changed { 745div#cgit table.ssdiff td.changed {
741 color: black; 746 color: black;
742 background: #ffc; 747 background: #ffc;
743 min-width: 50%; 748 min-width: 50%;
744} 749}
745 750
746table.ssdiff td.changed_dark { 751div#cgit table.ssdiff td.changed_dark {
747 color: black; 752 color: black;
748 background: #cca; 753 background: #cca;
749 min-width: 50%; 754 min-width: 50%;
750} 755}
751 756
752table.ssdiff td.lineno { 757div#cgit table.ssdiff td.lineno {
753 color: black; 758 color: black;
754 background: #eee; 759 background: #eee;
755 text-align: right; 760 text-align: right;
@@ -757,48 +762,48 @@ table.ssdiff td.lineno {
757 min-width: 3em; 762 min-width: 3em;
758} 763}
759 764
760table.ssdiff td.hunk { 765div#cgit table.ssdiff td.hunk {
761 color: #black; 766 color: black;
762 background: #ccf; 767 background: #ccf;
763 border-top: solid 1px #aaa; 768 border-top: solid 1px #aaa;
764 border-bottom: solid 1px #aaa; 769 border-bottom: solid 1px #aaa;
765} 770}
766 771
767table.ssdiff td.head { 772div#cgit table.ssdiff td.head {
768 border-top: solid 1px #aaa; 773 border-top: solid 1px #aaa;
769 border-bottom: solid 1px #aaa; 774 border-bottom: solid 1px #aaa;
770} 775}
771 776
772table.ssdiff td.head div.head { 777div#cgit table.ssdiff td.head div.head {
773 font-weight: bold; 778 font-weight: bold;
774 color: black; 779 color: black;
775} 780}
776 781
777table.ssdiff td.foot { 782div#cgit table.ssdiff td.foot {
778 border-top: solid 1px #aaa; 783 border-top: solid 1px #aaa;
779 border-left: none; 784 border-left: none;
780 border-right: none; 785 border-right: none;
781 border-bottom: none; 786 border-bottom: none;
782} 787}
783 788
784table.ssdiff td.space { 789div#cgit table.ssdiff td.space {
785 border: none; 790 border: none;
786} 791}
787 792
788table.ssdiff td.space div { 793div#cgit table.ssdiff td.space div {
789 min-height: 3em; 794 min-height: 3em;
790} 795}
791 796
792/* Syntax highlighting */ 797/* Syntax highlighting */
793table.blob .num { color:#2928ff; } 798div#cgit table.blob .num { color:#2928ff; }
794table.blob .esc { color:#ff00ff; } 799div#cgit table.blob .esc { color:#ff00ff; }
795table.blob .str { color:#ff0000; } 800div#cgit table.blob .str { color:#ff0000; }
796table.blob .dstr { color:#818100; } 801div#cgit table.blob .dstr { color:#818100; }
797table.blob .slc { color:#838183; font-style:italic; } 802div#cgit table.blob .slc { color:#838183; font-style:italic; }
798table.blob .com { color:#838183; font-style:italic; } 803div#cgit table.blob .com { color:#838183; font-style:italic; }
799table.blob .dir { color:#008200; } 804div#cgit table.blob .dir { color:#008200; }
800table.blob .sym { color:#000000; } 805div#cgit table.blob .sym { color:#000000; }
801table.blob .kwa { color:#000000; font-weight:bold; } 806div#cgit table.blob .kwa { color:#000000; font-weight:bold; }
802table.blob .kwb { color:#830000; } 807div#cgit table.blob .kwb { color:#830000; }
803table.blob .kwc { color:#000000; font-weight:bold; } 808div#cgit table.blob .kwc { color:#000000; font-weight:bold; }
804table.blob .kwd { color:#010181; } 809div#cgit table.blob .kwd { color:#010181; }
diff --git a/cgit.h b/cgit.h
index 9d0b3d0..b7c7ac9 100644
--- a/cgit.h
+++ b/cgit.h
@@ -138,6 +138,7 @@ struct reflist {
138struct cgit_query { 138struct cgit_query {
139 int has_symref; 139 int has_symref;
140 int has_sha1; 140 int has_sha1;
141 int has_ssdiff;
141 char *raw; 142 char *raw;
142 char *repo; 143 char *repo;
143 char *page; 144 char *page;
diff --git a/cgitrc.5.txt b/cgitrc.5.txt
index c8198c1..b4ad2ac 100644
--- a/cgitrc.5.txt
+++ b/cgitrc.5.txt
@@ -506,7 +506,7 @@ Also, all filters are handed the following environment variables:
506 506
507If a setting is not defined for a repository and the corresponding global 507If a setting is not defined for a repository and the corresponding global
508setting is also not defined (if applicable), then the corresponding 508setting is also not defined (if applicable), then the corresponding
509environment variable will be an empty string. 509environment variable will be unset.
510 510
511 511
512MACRO EXPANSION 512MACRO EXPANSION
diff --git a/filters/commit-links.sh b/filters/commit-links.sh
index d2cd2b3..5881952 100755
--- a/filters/commit-links.sh
+++ b/filters/commit-links.sh
@@ -15,11 +15,14 @@
15# CGIT_REPO_CLONE_URL ( = repo.clone-url setting ) 15# CGIT_REPO_CLONE_URL ( = repo.clone-url setting )
16# 16#
17 17
18regex=''
19
18# This expression generates links to commits referenced by their SHA1. 20# This expression generates links to commits referenced by their SHA1.
19regex=$regex' 21regex=$regex'
20s|\b([0-9a-fA-F]{8,40})\b|<a href="./?id=\1">\1</a>|g' 22s|\b([0-9a-fA-F]{7,40})\b|<a href="./?id=\1">\1</a>|g'
23
21# This expression generates links to a fictional bugtracker. 24# This expression generates links to a fictional bugtracker.
22regex=$regex' 25regex=$regex'
23s| #([0-9]+)\b|<a href="http://bugs.example.com/?bug=\1">#\1</a>|g' 26s|#([0-9]+)\b|<a href="http://bugs.example.com/?bug=\1">#\1</a>|g'
24 27
25sed -re "$regex" 28sed -re "$regex"
diff --git a/filters/syntax-highlighting.sh b/filters/syntax-highlighting.sh
index 6283ce9..5fcc9c9 100755
--- a/filters/syntax-highlighting.sh
+++ b/filters/syntax-highlighting.sh
@@ -42,4 +42,32 @@ EXTENSION="${BASENAME##*.}"
42# map Makefile and Makefile.* to .mk 42# map Makefile and Makefile.* to .mk
43[ "${BASENAME%%.*}" == "Makefile" ] && EXTENSION=mk 43[ "${BASENAME%%.*}" == "Makefile" ] && EXTENSION=mk
44 44
45# highlight versions 2 and 3 have different commandline options. Specifically,
46# the -X option that is used for version 2 is replaced by the -O xhtml option
47# for version 3.
48#
49# Version 2 can be found (for example) on EPEL 5, while version 3 can be
50# found (for example) on EPEL 6.
51#
52# This is for version 2
45exec highlight --force -f -I -X -S $EXTENSION 2>/dev/null 53exec highlight --force -f -I -X -S $EXTENSION 2>/dev/null
54
55# This is for version 3
56#
57# On CentOS 6.2 (using highlight from EPEL), when highlight doesn't know about
58# an EXTENSION, it outputs a lua error and _no_ text, even when the --force
59# option is used.
60#
61# Also see the bug reports at:
62# http://sourceforge.net/tracker/?func=detail&aid=3490017&group_id=215618&atid=1034391
63# https://bugzilla.redhat.com/show_bug.cgi?id=795567
64#
65# This workaround can be removed when the bug is fixed upstream and the new
66# version is packaged in most distributions.
67#
68# The workaround is to set the extension to 'txt' (plain text) when highlight
69# exits with an error (doesn't know the format).
70#
71#echo "test" | highlight -f -I -O xhtml -S $EXTENSION &>/dev/null
72#[ ${?} -ne 0 ] && EXTENSION="txt"
73#exec highlight --force -f -I -O xhtml -S $EXTENSION 2>/dev/null
diff --git a/html.c b/html.c
index eb1c25d..8f6e4f6 100644
--- a/html.c
+++ b/html.c
@@ -162,7 +162,7 @@ void html_url_path(const char *txt)
162{ 162{
163 const char *t = txt; 163 const char *t = txt;
164 while(t && *t){ 164 while(t && *t){
165 int c = *t; 165 unsigned char c = *t;
166 const char *e = url_escape_table[c]; 166 const char *e = url_escape_table[c];
167 if (e && c!='+' && c!='&') { 167 if (e && c!='+' && c!='&') {
168 html_raw(txt, t - txt); 168 html_raw(txt, t - txt);
@@ -179,7 +179,7 @@ void html_url_arg(const char *txt)
179{ 179{
180 const char *t = txt; 180 const char *t = txt;
181 while(t && *t){ 181 while(t && *t){
182 int c = *t; 182 unsigned char c = *t;
183 const char *e = url_escape_table[c]; 183 const char *e = url_escape_table[c];
184 if (c == ' ') 184 if (c == ' ')
185 e = "+"; 185 e = "+";
diff --git a/parsing.c b/parsing.c
index 151c0fe..602e3de 100644
--- a/parsing.c
+++ b/parsing.c
@@ -125,7 +125,7 @@ const char *reencode(char **txt, const char *src_enc, const char *dst_enc)
125struct commitinfo *cgit_parse_commit(struct commit *commit) 125struct commitinfo *cgit_parse_commit(struct commit *commit)
126{ 126{
127 struct commitinfo *ret; 127 struct commitinfo *ret;
128 char *p = commit->buffer, *t = commit->buffer; 128 char *p = commit->buffer, *t;
129 129
130 ret = xmalloc(sizeof(*ret)); 130 ret = xmalloc(sizeof(*ret));
131 ret->commit = commit; 131 ret->commit = commit;
diff --git a/shared.c b/shared.c
index 0add2e5..cb52380 100644
--- a/shared.c
+++ b/shared.c
@@ -8,7 +8,6 @@
8 8
9#include "cgit.h" 9#include "cgit.h"
10#include <stdio.h> 10#include <stdio.h>
11#include <linux/limits.h>
12 11
13struct cgit_repolist cgit_repolist; 12struct cgit_repolist cgit_repolist;
14struct cgit_context ctx; 13struct cgit_context ctx;
@@ -394,7 +393,7 @@ void cgit_prepare_repo_env(struct cgit_repo * repo)
394 p = env_vars; 393 p = env_vars;
395 q = p + env_var_count; 394 q = p + env_var_count;
396 for (; p < q; p++) 395 for (; p < q; p++)
397 if (setenv(p->name, p->value, 1)) 396 if (p->value && setenv(p->name, p->value, 1))
398 fprintf(stderr, warn, p->name, p->value); 397 fprintf(stderr, warn, p->name, p->value);
399} 398}
400 399
diff --git a/tests/setup.sh b/tests/setup.sh
index 1e06107..e3c6c17 100755
--- a/tests/setup.sh
+++ b/tests/setup.sh
@@ -15,13 +15,14 @@
15# run_test 'repo index' 'cgit_url "/" | tidy -e' 15# run_test 'repo index' 'cgit_url "/" | tidy -e'
16# run_test 'repo summary' 'cgit_url "/foo" | tidy -e' 16# run_test 'repo summary' 'cgit_url "/foo" | tidy -e'
17 17
18unset CDPATH
18 19
19mkrepo() { 20mkrepo() {
20 name=$1 21 name=$1
21 count=$2 22 count=$2
22 dir=$PWD 23 dir=$PWD
23 test -d "$name" && return 24 test -d "$name" && return
24 printf "Creating testrepo %s\n" $name 25 printf "Creating testrepo %s\n" "$name"
25 mkdir -p "$name" 26 mkdir -p "$name"
26 cd "$name" 27 cd "$name"
27 git init 28 git init
@@ -40,7 +41,7 @@ mkrepo() {
40 git commit -m "add a+b" 41 git commit -m "add a+b"
41 git branch "1+2" 42 git branch "1+2"
42 fi 43 fi
43 cd $dir 44 cd "$dir"
44} 45}
45 46
46setup_repos() 47setup_repos()
diff --git a/tests/t0108-patch.sh b/tests/t0108-patch.sh
index e608104..6ee70b3 100755
--- a/tests/t0108-patch.sh
+++ b/tests/t0108-patch.sh
@@ -25,7 +25,7 @@ run_test 'find `cgit` signature' '
25' 25'
26 26
27run_test 'find initial commit' ' 27run_test 'find initial commit' '
28 root=$(git --git-dir=$PWD/trash/repos/foo/.git rev-list HEAD | tail -1) 28 root=$(git --git-dir="$PWD/trash/repos/foo/.git" rev-list HEAD | tail -1)
29' 29'
30 30
31run_test 'generate patch for initial commit' ' 31run_test 'generate patch for initial commit' '
diff --git a/ui-diff.c b/ui-diff.c
index 868ceec..c6bad63 100644
--- a/ui-diff.c
+++ b/ui-diff.c
@@ -97,10 +97,12 @@ static void print_fileinfo(struct fileinfo *info)
97 htmlf("</td><td class='%s'>", class); 97 htmlf("</td><td class='%s'>", class);
98 cgit_diff_link(info->new_path, NULL, NULL, ctx.qry.head, ctx.qry.sha1, 98 cgit_diff_link(info->new_path, NULL, NULL, ctx.qry.head, ctx.qry.sha1,
99 ctx.qry.sha2, info->new_path, 0); 99 ctx.qry.sha2, info->new_path, 0);
100 if (info->status == DIFF_STATUS_COPIED || info->status == DIFF_STATUS_RENAMED) 100 if (info->status == DIFF_STATUS_COPIED || info->status == DIFF_STATUS_RENAMED) {
101 htmlf(" (%s from %s)", 101 htmlf(" (%s from ",
102 info->status == DIFF_STATUS_COPIED ? "copied" : "renamed", 102 info->status == DIFF_STATUS_COPIED ? "copied" : "renamed");
103 info->old_path); 103 html_txt(info->old_path);
104 html(")");
105 }
104 html("</td><td class='right'>"); 106 html("</td><td class='right'>");
105 if (info->binary) { 107 if (info->binary) {
106 htmlf("bin</td><td class='graph'>%ld -> %ld bytes", 108 htmlf("bin</td><td class='graph'>%ld -> %ld bytes",
@@ -339,9 +341,7 @@ void cgit_print_diff_ctrls()
339 html("<td class='label'>mode:</td>"); 341 html("<td class='label'>mode:</td>");
340 html("<td class='ctrl'>"); 342 html("<td class='ctrl'>");
341 html("<select name='ss' onchange='this.form.submit();'>"); 343 html("<select name='ss' onchange='this.form.submit();'>");
342 curr = ctx.qry.ssdiff; 344 curr = ctx.qry.has_ssdiff ? ctx.qry.ssdiff : ctx.cfg.ssdiff;
343 if (!curr && ctx.cfg.ssdiff)
344 curr = 1;
345 html_intoption(0, "unified", curr); 345 html_intoption(0, "unified", curr);
346 html_intoption(1, "ssdiff", curr); 346 html_intoption(1, "ssdiff", curr);
347 html("</select></td></tr>"); 347 html("</select></td></tr>");
@@ -393,8 +393,7 @@ void cgit_print_diff(const char *new_rev, const char *old_rev,
393 } 393 }
394 } 394 }
395 395
396 if ((ctx.qry.ssdiff && !ctx.cfg.ssdiff) || (!ctx.qry.ssdiff && ctx.cfg.ssdiff)) 396 use_ssdiff = ctx.qry.has_ssdiff ? ctx.qry.ssdiff : ctx.cfg.ssdiff;
397 use_ssdiff = 1;
398 397
399 if (show_ctrls) 398 if (show_ctrls)
400 cgit_print_diff_ctrls(); 399 cgit_print_diff_ctrls();
diff --git a/ui-log.c b/ui-log.c
index 4a295bd..6b12ca2 100644
--- a/ui-log.c
+++ b/ui-log.c
@@ -76,6 +76,8 @@ void show_commit_decorations(struct commit *commit)
76 cgit_tag_link(buf, NULL, "tag-deco", ctx.qry.head, buf); 76 cgit_tag_link(buf, NULL, "tag-deco", ctx.qry.head, buf);
77 } 77 }
78 else if (!prefixcmp(deco->name, "refs/remotes/")) { 78 else if (!prefixcmp(deco->name, "refs/remotes/")) {
79 if (!ctx.repo->enable_remote_branches)
80 goto next;
79 strncpy(buf, deco->name + 13, sizeof(buf) - 1); 81 strncpy(buf, deco->name + 13, sizeof(buf) - 1);
80 cgit_log_link(buf, NULL, "remote-deco", NULL, 82 cgit_log_link(buf, NULL, "remote-deco", NULL,
81 sha1_to_hex(commit->object.sha1), 83 sha1_to_hex(commit->object.sha1),
@@ -88,6 +90,7 @@ void show_commit_decorations(struct commit *commit)
88 sha1_to_hex(commit->object.sha1), 90 sha1_to_hex(commit->object.sha1),
89 ctx.qry.vpath, 0); 91 ctx.qry.vpath, 0);
90 } 92 }
93next:
91 deco = deco->next; 94 deco = deco->next;
92 } 95 }
93} 96}
diff --git a/ui-repolist.c b/ui-repolist.c
index 25c36ce..a09a689 100644
--- a/ui-repolist.c
+++ b/ui-repolist.c
@@ -118,13 +118,13 @@ void print_header(int columns)
118} 118}
119 119
120 120
121void print_pager(int items, int pagelen, char *search) 121void print_pager(int items, int pagelen, char *search, char *sort)
122{ 122{
123 int i; 123 int i;
124 html("<div class='pager'>"); 124 html("<div class='pager'>");
125 for(i = 0; i * pagelen < items; i++) 125 for(i = 0; i * pagelen < items; i++)
126 cgit_index_link(fmt("[%d]", i+1), fmt("Page %d", i+1), NULL, 126 cgit_index_link(fmt("[%d]", i+1), fmt("Page %d", i+1), NULL,
127 search, i * pagelen); 127 search, sort, i * pagelen);
128 html("</div>"); 128 html("</div>");
129} 129}
130 130
@@ -291,7 +291,7 @@ void cgit_print_repolist()
291 if (!hits) 291 if (!hits)
292 cgit_print_error("No repositories found"); 292 cgit_print_error("No repositories found");
293 else if (hits > ctx.cfg.max_repo_count) 293 else if (hits > ctx.cfg.max_repo_count)
294 print_pager(hits, ctx.cfg.max_repo_count, ctx.qry.search); 294 print_pager(hits, ctx.cfg.max_repo_count, ctx.qry.search, ctx.qry.sort);
295 cgit_print_docend(); 295 cgit_print_docend();
296} 296}
297 297
diff --git a/ui-shared.c b/ui-shared.c
index b736fca..43166af 100644
--- a/ui-shared.c
+++ b/ui-shared.c
@@ -133,7 +133,7 @@ char *cgit_currurl()
133 return fmt("%s/", ctx.cfg.virtual_root); 133 return fmt("%s/", ctx.cfg.virtual_root);
134} 134}
135 135
136static void site_url(const char *page, const char *search, int ofs) 136static void site_url(const char *page, const char *search, const char *sort, int ofs)
137{ 137{
138 char *delim = "?"; 138 char *delim = "?";
139 139
@@ -154,6 +154,12 @@ static void site_url(const char *page, const char *search, int ofs)
154 html_attr(search); 154 html_attr(search);
155 delim = "&"; 155 delim = "&";
156 } 156 }
157 if (sort) {
158 html(delim);
159 html("s=");
160 html_attr(sort);
161 delim = "&";
162 }
157 if (ofs) { 163 if (ofs) {
158 html(delim); 164 html(delim);
159 htmlf("ofs=%d", ofs); 165 htmlf("ofs=%d", ofs);
@@ -161,7 +167,7 @@ static void site_url(const char *page, const char *search, int ofs)
161} 167}
162 168
163static void site_link(const char *page, const char *name, const char *title, 169static void site_link(const char *page, const char *name, const char *title,
164 const char *class, const char *search, int ofs) 170 const char *class, const char *search, const char *sort, int ofs)
165{ 171{
166 html("<a"); 172 html("<a");
167 if (title) { 173 if (title) {
@@ -175,16 +181,16 @@ static void site_link(const char *page, const char *name, const char *title,
175 html("'"); 181 html("'");
176 } 182 }
177 html(" href='"); 183 html(" href='");
178 site_url(page, search, ofs); 184 site_url(page, search, sort, ofs);
179 html("'>"); 185 html("'>");
180 html_txt(name); 186 html_txt(name);
181 html("</a>"); 187 html("</a>");
182} 188}
183 189
184void cgit_index_link(const char *name, const char *title, const char *class, 190void cgit_index_link(const char *name, const char *title, const char *class,
185 const char *pattern, int ofs) 191 const char *pattern, const char *sort, int ofs)
186{ 192{
187 site_link(NULL, name, title, class, pattern, ofs); 193 site_link(NULL, name, title, class, pattern, sort, ofs);
188} 194}
189 195
190static char *repolink(const char *title, const char *class, const char *page, 196static char *repolink(const char *title, const char *class, const char *page,
@@ -288,7 +294,7 @@ void cgit_log_link(const char *name, const char *title, const char *class,
288 char *delim; 294 char *delim;
289 295
290 delim = repolink(title, class, "log", head, path); 296 delim = repolink(title, class, "log", head, path);
291 if (rev && strcmp(rev, ctx.qry.head)) { 297 if (rev && ctx.qry.head && strcmp(rev, ctx.qry.head)) {
292 html(delim); 298 html(delim);
293 html("id="); 299 html("id=");
294 html_url_arg(rev); 300 html_url_arg(rev);
@@ -332,7 +338,7 @@ void cgit_commit_link(char *name, const char *title, const char *class,
332 char *delim; 338 char *delim;
333 339
334 delim = repolink(title, class, "commit", head, path); 340 delim = repolink(title, class, "commit", head, path);
335 if (rev && strcmp(rev, ctx.qry.head)) { 341 if (rev && ctx.qry.head && strcmp(rev, ctx.qry.head)) {
336 html(delim); 342 html(delim);
337 html("id="); 343 html("id=");
338 html_url_arg(rev); 344 html_url_arg(rev);
@@ -428,7 +434,7 @@ void cgit_self_link(char *name, const char *title, const char *class,
428 struct cgit_context *ctx) 434 struct cgit_context *ctx)
429{ 435{
430 if (!strcmp(ctx->qry.page, "repolist")) 436 if (!strcmp(ctx->qry.page, "repolist"))
431 return cgit_index_link(name, title, class, ctx->qry.search, 437 return cgit_index_link(name, title, class, ctx->qry.search, ctx->qry.sort,
432 ctx->qry.ofs); 438 ctx->qry.ofs);
433 else if (!strcmp(ctx->qry.page, "summary")) 439 else if (!strcmp(ctx->qry.page, "summary"))
434 return cgit_summary_link(name, title, class, ctx->qry.head); 440 return cgit_summary_link(name, title, class, ctx->qry.head);
@@ -669,7 +675,7 @@ void cgit_print_docstart(struct cgit_context *ctx)
669 html_attr(ctx->cfg.favicon); 675 html_attr(ctx->cfg.favicon);
670 html("'/>\n"); 676 html("'/>\n");
671 } 677 }
672 if (host && ctx->repo) { 678 if (host && ctx->repo && ctx->qry.head) {
673 html("<link rel='alternate' title='Atom feed' href='"); 679 html("<link rel='alternate' title='Atom feed' href='");
674 html(cgit_httpscheme()); 680 html(cgit_httpscheme());
675 html_attr(cgit_hosturl()); 681 html_attr(cgit_hosturl());
@@ -838,7 +844,7 @@ static void print_header(struct cgit_context *ctx)
838 844
839 html("<td class='main'>"); 845 html("<td class='main'>");
840 if (ctx->repo) { 846 if (ctx->repo) {
841 cgit_index_link("index", NULL, NULL, NULL, 0); 847 cgit_index_link("index", NULL, NULL, NULL, NULL, 0);
842 html(" : "); 848 html(" : ");
843 cgit_summary_link(ctx->repo->name, ctx->repo->name, NULL, NULL); 849 cgit_summary_link(ctx->repo->name, ctx->repo->name, NULL, NULL);
844 html("</td><td class='form'>"); 850 html("</td><td class='form'>");
@@ -914,10 +920,10 @@ void cgit_print_pageheader(struct cgit_context *ctx)
914 html("<input type='submit' value='search'/>\n"); 920 html("<input type='submit' value='search'/>\n");
915 html("</form>\n"); 921 html("</form>\n");
916 } else { 922 } else {
917 site_link(NULL, "index", NULL, hc(ctx, "repolist"), NULL, 0); 923 site_link(NULL, "index", NULL, hc(ctx, "repolist"), NULL, NULL, 0);
918 if (ctx->cfg.root_readme) 924 if (ctx->cfg.root_readme)
919 site_link("about", "about", NULL, hc(ctx, "about"), 925 site_link("about", "about", NULL, hc(ctx, "about"),
920 NULL, 0); 926 NULL, NULL, 0);
921 html("</td><td class='form'>"); 927 html("</td><td class='form'>");
922 html("<form method='get' action='"); 928 html("<form method='get' action='");
923 html_attr(cgit_rooturl()); 929 html_attr(cgit_rooturl());
diff --git a/ui-shared.h b/ui-shared.h
index e80b975..87a7dac 100644
--- a/ui-shared.h
+++ b/ui-shared.h
@@ -11,7 +11,7 @@ extern char *cgit_pageurl(const char *reponame, const char *pagename,
11 const char *query); 11 const char *query);
12 12
13extern void cgit_index_link(const char *name, const char *title, 13extern void cgit_index_link(const char *name, const char *title,
14 const char *class, const char *pattern, int ofs); 14 const char *class, const char *pattern, const char *sort, int ofs);
15extern void cgit_summary_link(const char *name, const char *title, 15extern void cgit_summary_link(const char *name, const char *title,
16 const char *class, const char *head); 16 const char *class, const char *head);
17extern void cgit_tag_link(const char *name, const char *title, 17extern void cgit_tag_link(const char *name, const char *title,
diff --git a/ui-ssdiff.c b/ui-ssdiff.c
index 2481585..0cff4b8 100644
--- a/ui-ssdiff.c
+++ b/ui-ssdiff.c
@@ -2,10 +2,12 @@
2#include "html.h" 2#include "html.h"
3#include "ui-shared.h" 3#include "ui-shared.h"
4#include "ui-diff.h" 4#include "ui-diff.h"
5#include "ui-ssdiff.h"
5 6
6extern int use_ssdiff; 7extern int use_ssdiff;
7 8
8static int current_old_line, current_new_line; 9static int current_old_line, current_new_line;
10static int **L = NULL;
9 11
10struct deferred_lines { 12struct deferred_lines {
11 int line_no; 13 int line_no;
@@ -16,16 +18,40 @@ struct deferred_lines {
16static struct deferred_lines *deferred_old, *deferred_old_last; 18static struct deferred_lines *deferred_old, *deferred_old_last;
17static struct deferred_lines *deferred_new, *deferred_new_last; 19static struct deferred_lines *deferred_new, *deferred_new_last;
18 20
21static void create_or_reset_lcs_table()
22{
23 int i;
24
25 if (L != NULL) {
26 memset(*L, 0, sizeof(int) * MAX_SSDIFF_SIZE);
27 return;
28 }
29
30 // xcalloc will die if we ran out of memory;
31 // not very helpful for debugging
32 L = (int**)xcalloc(MAX_SSDIFF_M, sizeof(int *));
33 *L = (int*)xcalloc(MAX_SSDIFF_SIZE, sizeof(int));
34
35 for (i = 1; i < MAX_SSDIFF_M; i++) {
36 L[i] = *L + i * MAX_SSDIFF_N;
37 }
38}
39
19static char *longest_common_subsequence(char *A, char *B) 40static char *longest_common_subsequence(char *A, char *B)
20{ 41{
21 int i, j, ri; 42 int i, j, ri;
22 int m = strlen(A); 43 int m = strlen(A);
23 int n = strlen(B); 44 int n = strlen(B);
24 int L[m + 1][n + 1];
25 int tmp1, tmp2; 45 int tmp1, tmp2;
26 int lcs_length; 46 int lcs_length;
27 char *result; 47 char *result;
28 48
49 // We bail if the lines are too long
50 if (m >= MAX_SSDIFF_M || n >= MAX_SSDIFF_N)
51 return NULL;
52
53 create_or_reset_lcs_table();
54
29 for (i = m; i >= 0; i--) { 55 for (i = m; i >= 0; i--) {
30 for (j = n; j >= 0; j--) { 56 for (j = n; j >= 0; j--) {
31 if (A[i] == '\0' || B[j] == '\0') { 57 if (A[i] == '\0' || B[j] == '\0') {
@@ -59,6 +85,7 @@ static char *longest_common_subsequence(char *A, char *B)
59 j += 1; 85 j += 1;
60 } 86 }
61 } 87 }
88
62 return result; 89 return result;
63} 90}
64 91
diff --git a/ui-ssdiff.h b/ui-ssdiff.h
index 64b4b12..88627e2 100644
--- a/ui-ssdiff.h
+++ b/ui-ssdiff.h
@@ -1,6 +1,18 @@
1#ifndef UI_SSDIFF_H 1#ifndef UI_SSDIFF_H
2#define UI_SSDIFF_H 2#define UI_SSDIFF_H
3 3
4/*
5 * ssdiff line limits
6 */
7#ifndef MAX_SSDIFF_M
8#define MAX_SSDIFF_M 128
9#endif
10
11#ifndef MAX_SSDIFF_N
12#define MAX_SSDIFF_N 128
13#endif
14#define MAX_SSDIFF_SIZE ((MAX_SSDIFF_M) * (MAX_SSDIFF_N))
15
4extern void cgit_ssdiff_print_deferred_lines(); 16extern void cgit_ssdiff_print_deferred_lines();
5 17
6extern void cgit_ssdiff_line_cb(char *line, int len); 18extern void cgit_ssdiff_line_cb(char *line, int len);