summaryrefslogtreecommitdiffabout
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--cgit.css19
-rw-r--r--ui-tree.c71
2 files changed, 67 insertions, 23 deletions
diff --git a/cgit.css b/cgit.css
index 957d5aa..adfc8ae 100644
--- a/cgit.css
+++ b/cgit.css
@@ -74,384 +74,403 @@ table.tabs {
74table.tabs td { 74table.tabs td {
75 padding: 0px 1em; 75 padding: 0px 1em;
76 vertical-align: bottom; 76 vertical-align: bottom;
77} 77}
78 78
79table.tabs td a { 79table.tabs td a {
80 padding: 2px 0.75em; 80 padding: 2px 0.75em;
81 color: #777; 81 color: #777;
82 font-size: 110%; 82 font-size: 110%;
83} 83}
84 84
85table.tabs td a.active { 85table.tabs td a.active {
86 color: #000; 86 color: #000;
87 background-color: #ccc; 87 background-color: #ccc;
88} 88}
89 89
90table.tabs td.form { 90table.tabs td.form {
91 text-align: right; 91 text-align: right;
92} 92}
93 93
94table.tabs td.form form { 94table.tabs td.form form {
95 padding-bottom: 2px; 95 padding-bottom: 2px;
96 font-size: 90%; 96 font-size: 90%;
97 white-space: nowrap; 97 white-space: nowrap;
98} 98}
99 99
100table.tabs td.form input, 100table.tabs td.form input,
101table.tabs td.form select { 101table.tabs td.form select {
102 font-size: 90%; 102 font-size: 90%;
103} 103}
104 104
105div.content { 105div.content {
106 margin: 0px; 106 margin: 0px;
107 padding: 2em; 107 padding: 2em;
108 border-top: solid 3px #ccc; 108 border-top: solid 3px #ccc;
109 border-bottom: solid 3px #ccc; 109 border-bottom: solid 3px #ccc;
110} 110}
111 111
112 112
113table.list { 113table.list {
114 width: 100%; 114 width: 100%;
115 border: none; 115 border: none;
116 border-collapse: collapse; 116 border-collapse: collapse;
117} 117}
118 118
119table.list tr { 119table.list tr {
120 background: white; 120 background: white;
121} 121}
122 122
123table.list tr.logheader { 123table.list tr.logheader {
124 background: #eee; 124 background: #eee;
125} 125}
126 126
127table.list tr:hover { 127table.list tr:hover {
128 background: #eee; 128 background: #eee;
129} 129}
130 130
131table.list tr.nohover:hover { 131table.list tr.nohover:hover {
132 background: white; 132 background: white;
133} 133}
134 134
135table.list th { 135table.list th {
136 font-weight: bold; 136 font-weight: bold;
137 /* color: #888; 137 /* color: #888;
138 border-top: dashed 1px #888; 138 border-top: dashed 1px #888;
139 border-bottom: dashed 1px #888; 139 border-bottom: dashed 1px #888;
140 */ 140 */
141 padding: 0.1em 0.5em 0.05em 0.5em; 141 padding: 0.1em 0.5em 0.05em 0.5em;
142 vertical-align: baseline; 142 vertical-align: baseline;
143} 143}
144 144
145table.list td { 145table.list td {
146 border: none; 146 border: none;
147 padding: 0.1em 0.5em 0.1em 0.5em; 147 padding: 0.1em 0.5em 0.1em 0.5em;
148} 148}
149 149
150table.list td.logsubject { 150table.list td.logsubject {
151 font-family: monospace; 151 font-family: monospace;
152 font-weight: bold; 152 font-weight: bold;
153} 153}
154 154
155table.list td.logmsg { 155table.list td.logmsg {
156 font-family: monospace; 156 font-family: monospace;
157 white-space: pre; 157 white-space: pre;
158 padding: 1em 0em 2em 0em; 158 padding: 1em 0em 2em 0em;
159} 159}
160 160
161table.list td a { 161table.list td a {
162 color: black; 162 color: black;
163} 163}
164 164
165table.list td a:hover { 165table.list td a:hover {
166 color: #00f; 166 color: #00f;
167} 167}
168 168
169img { 169img {
170 border: none; 170 border: none;
171} 171}
172 172
173input#switch-btn { 173input#switch-btn {
174 margin: 2px 0px 0px 0px; 174 margin: 2px 0px 0px 0px;
175} 175}
176 176
177td#sidebar input.txt { 177td#sidebar input.txt {
178 width: 100%; 178 width: 100%;
179 margin: 2px 0px 0px 0px; 179 margin: 2px 0px 0px 0px;
180} 180}
181 181
182table#grid { 182table#grid {
183 margin: 0px; 183 margin: 0px;
184} 184}
185 185
186td#content { 186td#content {
187 vertical-align: top; 187 vertical-align: top;
188 padding: 1em 2em 1em 1em; 188 padding: 1em 2em 1em 1em;
189 border: none; 189 border: none;
190} 190}
191 191
192div#summary { 192div#summary {
193 vertical-align: top; 193 vertical-align: top;
194 margin-bottom: 1em; 194 margin-bottom: 1em;
195} 195}
196 196
197table#downloads { 197table#downloads {
198 float: right; 198 float: right;
199 border-collapse: collapse; 199 border-collapse: collapse;
200 border: solid 1px #777; 200 border: solid 1px #777;
201 margin-left: 0.5em; 201 margin-left: 0.5em;
202 margin-bottom: 0.5em; 202 margin-bottom: 0.5em;
203} 203}
204 204
205table#downloads th { 205table#downloads th {
206 background-color: #ccc; 206 background-color: #ccc;
207} 207}
208 208
209div#blob { 209div#blob {
210 border: solid 1px black; 210 border: solid 1px black;
211} 211}
212 212
213div.error { 213div.error {
214 color: red; 214 color: red;
215 font-weight: bold; 215 font-weight: bold;
216 margin: 1em 2em; 216 margin: 1em 2em;
217} 217}
218 218
219a.ls-blob, a.ls-dir, a.ls-mod { 219a.ls-blob, a.ls-dir, a.ls-mod {
220 font-family: monospace; 220 font-family: monospace;
221} 221}
222 222
223td.ls-size { 223td.ls-size {
224 text-align: right; 224 text-align: right;
225 font-family: monospace; 225 font-family: monospace;
226 width: 10em; 226 width: 10em;
227} 227}
228 228
229td.ls-mode { 229td.ls-mode {
230 font-family: monospace; 230 font-family: monospace;
231 width: 10em; 231 width: 10em;
232} 232}
233 233
234table.blob { 234table.blob {
235 margin-top: 0.5em; 235 margin-top: 0.5em;
236 border-top: solid 1px black; 236 border-top: solid 1px black;
237} 237}
238 238
239table.blob td.lines { 239table.blob td.lines {
240 margin: 0; padding: 0; 240 margin: 0; padding: 0;
241 vertical-align: top; 241 vertical-align: top;
242 color: black; 242 color: black;
243} 243}
244 244
245table.blob td.linenumbers { 245table.blob td.linenumbers {
246 margin: 0; padding: 0; 246 margin: 0; padding: 0;
247 vertical-align: top; 247 vertical-align: top;
248 border-right: 1px solid gray; 248 border-right: 1px solid gray;
249 background-color: #eee; 249 background-color: #eee;
250} 250}
251 251
252table.blob pre { 252table.blob pre {
253 padding: 0; margin: 0; 253 padding: 0; margin: 0;
254} 254}
255 255
256table.blob a.no { 256table.blob a.no {
257 color: gray; 257 color: gray;
258 text-align: right; 258 text-align: right;
259 text-decoration: none; 259 text-decoration: none;
260} 260}
261 261
262table.blob a.no a:hover { 262table.blob a.no a:hover {
263 color: black; 263 color: black;
264} 264}
265 265
266table.bin-blob {
267 margin-top: 0.5em;
268 border: solid 1px black;
269}
270
271table.bin-blob th {
272 font-family: monospace;
273 white-space: pre;
274 border: solid 1px #777;
275 padding: 0.5em 1em;
276}
277
278table.bin-blob td {
279 font-family: monospace;
280 white-space: pre;
281 border-left: solid 1px #777;
282 padding: 0em 1em;
283}
284
266table.nowrap td { 285table.nowrap td {
267 white-space: nowrap; 286 white-space: nowrap;
268} 287}
269 288
270table.commit-info { 289table.commit-info {
271 border-collapse: collapse; 290 border-collapse: collapse;
272 margin-top: 1.5em; 291 margin-top: 1.5em;
273} 292}
274 293
275table.commit-info th { 294table.commit-info th {
276 text-align: left; 295 text-align: left;
277 font-weight: normal; 296 font-weight: normal;
278 padding: 0.1em 1em 0.1em 0.1em; 297 padding: 0.1em 1em 0.1em 0.1em;
279 vertical-align: top; 298 vertical-align: top;
280} 299}
281 300
282table.commit-info td { 301table.commit-info td {
283 font-weight: normal; 302 font-weight: normal;
284 padding: 0.1em 1em 0.1em 0.1em; 303 padding: 0.1em 1em 0.1em 0.1em;
285} 304}
286 305
287div.commit-subject { 306div.commit-subject {
288 font-weight: bold; 307 font-weight: bold;
289 font-size: 125%; 308 font-size: 125%;
290 margin: 1.5em 0em 0.5em 0em; 309 margin: 1.5em 0em 0.5em 0em;
291 padding: 0em; 310 padding: 0em;
292} 311}
293 312
294div.commit-msg { 313div.commit-msg {
295 white-space: pre; 314 white-space: pre;
296 font-family: monospace; 315 font-family: monospace;
297} 316}
298 317
299div.diffstat-header { 318div.diffstat-header {
300 font-weight: bold; 319 font-weight: bold;
301 padding-top: 1.5em; 320 padding-top: 1.5em;
302} 321}
303 322
304table.diffstat { 323table.diffstat {
305 border-collapse: collapse; 324 border-collapse: collapse;
306 border: solid 1px #aaa; 325 border: solid 1px #aaa;
307 background-color: #eee; 326 background-color: #eee;
308} 327}
309 328
310table.diffstat th { 329table.diffstat th {
311 font-weight: normal; 330 font-weight: normal;
312 text-align: left; 331 text-align: left;
313 text-decoration: underline; 332 text-decoration: underline;
314 padding: 0.1em 1em 0.1em 0.1em; 333 padding: 0.1em 1em 0.1em 0.1em;
315 font-size: 100%; 334 font-size: 100%;
316} 335}
317 336
318table.diffstat td { 337table.diffstat td {
319 padding: 0.2em 0.2em 0.1em 0.1em; 338 padding: 0.2em 0.2em 0.1em 0.1em;
320 font-size: 100%; 339 font-size: 100%;
321 border: none; 340 border: none;
322} 341}
323 342
324table.diffstat td.mode { 343table.diffstat td.mode {
325 white-space: nowrap; 344 white-space: nowrap;
326} 345}
327 346
328table.diffstat td span.modechange { 347table.diffstat td span.modechange {
329 padding-left: 1em; 348 padding-left: 1em;
330 color: red; 349 color: red;
331} 350}
332 351
333table.diffstat td.add a { 352table.diffstat td.add a {
334 color: green; 353 color: green;
335} 354}
336 355
337table.diffstat td.del a { 356table.diffstat td.del a {
338 color: red; 357 color: red;
339} 358}
340 359
341table.diffstat td.upd a { 360table.diffstat td.upd a {
342 color: blue; 361 color: blue;
343} 362}
344 363
345table.diffstat td.graph { 364table.diffstat td.graph {
346 width: 500px; 365 width: 500px;
347 vertical-align: middle; 366 vertical-align: middle;
348} 367}
349 368
350table.diffstat td.graph table { 369table.diffstat td.graph table {
351 border: none; 370 border: none;
352} 371}
353 372
354table.diffstat td.graph td { 373table.diffstat td.graph td {
355 padding: 0px; 374 padding: 0px;
356 border: 0px; 375 border: 0px;
357 height: 7pt; 376 height: 7pt;
358} 377}
359 378
360table.diffstat td.graph td.add { 379table.diffstat td.graph td.add {
361 background-color: #5c5; 380 background-color: #5c5;
362} 381}
363 382
364table.diffstat td.graph td.rem { 383table.diffstat td.graph td.rem {
365 background-color: #c55; 384 background-color: #c55;
366} 385}
367 386
368div.diffstat-summary { 387div.diffstat-summary {
369 color: #888; 388 color: #888;
370 padding-top: 0.5em; 389 padding-top: 0.5em;
371} 390}
372 391
373table.diff { 392table.diff {
374 width: 100%; 393 width: 100%;
375} 394}
376 395
377table.diff td { 396table.diff td {
378 font-family: monospace; 397 font-family: monospace;
379 white-space: pre; 398 white-space: pre;
380} 399}
381 400
382table.diff td div.head { 401table.diff td div.head {
383 font-weight: bold; 402 font-weight: bold;
384 margin-top: 1em; 403 margin-top: 1em;
385 color: black; 404 color: black;
386} 405}
387 406
388table.diff td div.hunk { 407table.diff td div.hunk {
389 color: #009; 408 color: #009;
390} 409}
391 410
392table.diff td div.add { 411table.diff td div.add {
393 color: green; 412 color: green;
394} 413}
395 414
396table.diff td div.del { 415table.diff td div.del {
397 color: red; 416 color: red;
398} 417}
399 418
400.sha1 { 419.sha1 {
401 font-family: monospace; 420 font-family: monospace;
402 font-size: 90%; 421 font-size: 90%;
403} 422}
404 423
405.left { 424.left {
406 text-align: left; 425 text-align: left;
407} 426}
408 427
409.right { 428.right {
410 text-align: right; 429 text-align: right;
411} 430}
412 431
413table.list td.repogroup { 432table.list td.repogroup {
414 font-style: italic; 433 font-style: italic;
415 color: #888; 434 color: #888;
416} 435}
417 436
418a.button { 437a.button {
419 font-size: 80%; 438 font-size: 80%;
420 padding: 0em 0.5em; 439 padding: 0em 0.5em;
421} 440}
422 441
423a.primary { 442a.primary {
424 font-size: 100%; 443 font-size: 100%;
425} 444}
426 445
427a.secondary { 446a.secondary {
428 font-size: 90%; 447 font-size: 90%;
429} 448}
430 449
431td.toplevel-repo { 450td.toplevel-repo {
432 451
433} 452}
434 453
435table.list td.sublevel-repo { 454table.list td.sublevel-repo {
436 padding-left: 1.5em; 455 padding-left: 1.5em;
437} 456}
438 457
439div.pager { 458div.pager {
440 text-align: center; 459 text-align: center;
441 margin: 1em 0em 0em 0em; 460 margin: 1em 0em 0em 0em;
442} 461}
443 462
444div.pager a { 463div.pager a {
445 color: #777; 464 color: #777;
446 margin: 0em 0.5em; 465 margin: 0em 0.5em;
447} 466}
448 467
449span.age-mins { 468span.age-mins {
450 font-weight: bold; 469 font-weight: bold;
451 color: #080; 470 color: #080;
452} 471}
453 472
454span.age-hours { 473span.age-hours {
455 color: #080; 474 color: #080;
456} 475}
457 476
diff --git a/ui-tree.c b/ui-tree.c
index c26ba4c..a37a4e5 100644
--- a/ui-tree.c
+++ b/ui-tree.c
@@ -1,229 +1,254 @@
1/* ui-tree.c: functions for tree output 1/* ui-tree.c: functions for tree output
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 <ctype.h>
9#include "cgit.h" 10#include "cgit.h"
10#include "html.h" 11#include "html.h"
11#include "ui-shared.h" 12#include "ui-shared.h"
12 13
13char *curr_rev; 14char *curr_rev;
14char *match_path; 15char *match_path;
15int header = 0; 16int header = 0;
16 17
18static void print_text_buffer(char *buf, unsigned long size)
19{
20 unsigned long lineno, idx;
21 const char *numberfmt =
22 "<a class='no' id='n%1$d' name='n%1$d' href='#n%1$d'>%1$d</a>\n";
23
24 html("<table summary='blob content' class='blob'>\n");
25 html("<tr><td class='linenumbers'><pre>");
26 idx = 0;
27 lineno = 0;
28 htmlf(numberfmt, ++lineno);
29 while(idx < size - 1) { // skip absolute last newline
30 if (buf[idx] == '\n')
31 htmlf(numberfmt, ++lineno);
32 idx++;
33 }
34 html("</pre></td>\n");
35 html("<td class='lines'><pre><code>");
36 html_txt(buf);
37 html("</code></pre></td></tr></table>\n");
38}
39
40static void print_binary_buffer(char *buf, unsigned long size)
41{
42 unsigned long ofs, idx;
43
44 html("<table summary='blob content' class='bin-blob'>\n");
45 html("<tr><th>ofs</th><th>hex dump</th><th>ascii</th></tr>");
46 for (ofs = 0; ofs < size; ofs += 32, buf += 32) {
47 htmlf("<tr><td class='right'>%04x</td><td class='hex'>", ofs);
48 for (idx = 0; idx < 32 && ofs + idx < size; idx++)
49 htmlf("%*s%02x",
50 idx == 16 ? 4 : 1, "",
51 buf[idx] & 0xff);
52 html(" </td><td class='hex'>");
53 for (idx = 0; idx < 32 && ofs + idx < size; idx++)
54 htmlf("%c", isgraph(buf[idx]) ? buf[idx] : '.');
55 html("</td></tr>\n");
56 }
57 html("</table>\n");
58}
59
17static void print_object(const unsigned char *sha1, char *path) 60static void print_object(const unsigned char *sha1, char *path)
18{ 61{
19 enum object_type type; 62 enum object_type type;
20 char *buf; 63 char *buf;
21 unsigned long size, lineno, idx; 64 unsigned long size;
22 const char *numberfmt = "<a class='no' id='n%1$d' name='n%1$d' href='#n%1$d'>%1$d</a>\n";
23 65
24 type = sha1_object_info(sha1, &size); 66 type = sha1_object_info(sha1, &size);
25 if (type == OBJ_BAD) { 67 if (type == OBJ_BAD) {
26 cgit_print_error(fmt("Bad object name: %s", 68 cgit_print_error(fmt("Bad object name: %s",
27 sha1_to_hex(sha1))); 69 sha1_to_hex(sha1)));
28 return; 70 return;
29 } 71 }
30 72
31 buf = read_sha1_file(sha1, &type, &size); 73 buf = read_sha1_file(sha1, &type, &size);
32 if (!buf) { 74 if (!buf) {
33 cgit_print_error(fmt("Error reading object %s", 75 cgit_print_error(fmt("Error reading object %s",
34 sha1_to_hex(sha1))); 76 sha1_to_hex(sha1)));
35 return; 77 return;
36 } 78 }
37 79
38 html(" ("); 80 html(" (");
39 cgit_plain_link("plain", NULL, NULL, ctx.qry.head, 81 cgit_plain_link("plain", NULL, NULL, ctx.qry.head,
40 curr_rev, path); 82 curr_rev, path);
41 htmlf(")<br/>blob: %s\n", sha1_to_hex(sha1)); 83 htmlf(")<br/>blob: %s\n", sha1_to_hex(sha1));
42 84
43 html("<table summary='blob content' class='blob'>\n"); 85 if (buffer_is_binary(buf, size))
44 html("<tr>\n"); 86 print_binary_buffer(buf, size);
45 87 else
46 html("<td class='linenumbers'><pre>"); 88 print_text_buffer(buf, size);
47 idx = 0;
48 lineno = 0;
49 htmlf(numberfmt, ++lineno);
50 while(idx < size - 1) { // skip absolute last newline
51 if (buf[idx] == '\n') {
52 htmlf(numberfmt, ++lineno);
53 }
54 idx++;
55 }
56 html("</pre></td>\n");
57
58 html("<td class='lines'><pre><code>");
59 html_txt(buf);
60 html("</code></pre></td>\n");
61
62 html("</tr>\n");
63 html("</table>\n");
64} 89}
65 90
66 91
67static int ls_item(const unsigned char *sha1, const char *base, int baselen, 92static int ls_item(const unsigned char *sha1, const char *base, int baselen,
68 const char *pathname, unsigned int mode, int stage, 93 const char *pathname, unsigned int mode, int stage,
69 void *cbdata) 94 void *cbdata)
70{ 95{
71 char *name; 96 char *name;
72 char *fullpath; 97 char *fullpath;
73 enum object_type type; 98 enum object_type type;
74 unsigned long size = 0; 99 unsigned long size = 0;
75 100
76 name = xstrdup(pathname); 101 name = xstrdup(pathname);
77 fullpath = fmt("%s%s%s", ctx.qry.path ? ctx.qry.path : "", 102 fullpath = fmt("%s%s%s", ctx.qry.path ? ctx.qry.path : "",
78 ctx.qry.path ? "/" : "", name); 103 ctx.qry.path ? "/" : "", name);
79 104
80 if (!S_ISGITLINK(mode)) { 105 if (!S_ISGITLINK(mode)) {
81 type = sha1_object_info(sha1, &size); 106 type = sha1_object_info(sha1, &size);
82 if (type == OBJ_BAD) { 107 if (type == OBJ_BAD) {
83 htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>", 108 htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>",
84 name, 109 name,
85 sha1_to_hex(sha1)); 110 sha1_to_hex(sha1));
86 return 0; 111 return 0;
87 } 112 }
88 } 113 }
89 114
90 html("<tr><td class='ls-mode'>"); 115 html("<tr><td class='ls-mode'>");
91 cgit_print_filemode(mode); 116 cgit_print_filemode(mode);
92 html("</td><td>"); 117 html("</td><td>");
93 if (S_ISGITLINK(mode)) { 118 if (S_ISGITLINK(mode)) {
94 htmlf("<a class='ls-mod' href='"); 119 htmlf("<a class='ls-mod' href='");
95 html_attr(fmt(ctx.repo->module_link, 120 html_attr(fmt(ctx.repo->module_link,
96 name, 121 name,
97 sha1_to_hex(sha1))); 122 sha1_to_hex(sha1)));
98 html("'>"); 123 html("'>");
99 html_txt(name); 124 html_txt(name);
100 html("</a>"); 125 html("</a>");
101 } else if (S_ISDIR(mode)) { 126 } else if (S_ISDIR(mode)) {
102 cgit_tree_link(name, NULL, "ls-dir", ctx.qry.head, 127 cgit_tree_link(name, NULL, "ls-dir", ctx.qry.head,
103 curr_rev, fullpath); 128 curr_rev, fullpath);
104 } else { 129 } else {
105 cgit_tree_link(name, NULL, "ls-blob", ctx.qry.head, 130 cgit_tree_link(name, NULL, "ls-blob", ctx.qry.head,
106 curr_rev, fullpath); 131 curr_rev, fullpath);
107 } 132 }
108 htmlf("</td><td class='ls-size'>%li</td>", size); 133 htmlf("</td><td class='ls-size'>%li</td>", size);
109 134
110 html("<td>"); 135 html("<td>");
111 cgit_log_link("log", NULL, "button", ctx.qry.head, curr_rev, 136 cgit_log_link("log", NULL, "button", ctx.qry.head, curr_rev,
112 fullpath, 0, NULL, NULL, ctx.qry.showmsg); 137 fullpath, 0, NULL, NULL, ctx.qry.showmsg);
113 if (ctx.repo->max_stats) 138 if (ctx.repo->max_stats)
114 cgit_stats_link("stats", NULL, "button", ctx.qry.head, 139 cgit_stats_link("stats", NULL, "button", ctx.qry.head,
115 fullpath); 140 fullpath);
116 html("</td></tr>\n"); 141 html("</td></tr>\n");
117 free(name); 142 free(name);
118 return 0; 143 return 0;
119} 144}
120 145
121static void ls_head() 146static void ls_head()
122{ 147{
123 html("<table summary='tree listing' class='list'>\n"); 148 html("<table summary='tree listing' class='list'>\n");
124 html("<tr class='nohover'>"); 149 html("<tr class='nohover'>");
125 html("<th class='left'>Mode</th>"); 150 html("<th class='left'>Mode</th>");
126 html("<th class='left'>Name</th>"); 151 html("<th class='left'>Name</th>");
127 html("<th class='right'>Size</th>"); 152 html("<th class='right'>Size</th>");
128 html("<th/>"); 153 html("<th/>");
129 html("</tr>\n"); 154 html("</tr>\n");
130 header = 1; 155 header = 1;
131} 156}
132 157
133static void ls_tail() 158static void ls_tail()
134{ 159{
135 if (!header) 160 if (!header)
136 return; 161 return;
137 html("</table>\n"); 162 html("</table>\n");
138 header = 0; 163 header = 0;
139} 164}
140 165
141static void ls_tree(const unsigned char *sha1, char *path) 166static void ls_tree(const unsigned char *sha1, char *path)
142{ 167{
143 struct tree *tree; 168 struct tree *tree;
144 169
145 tree = parse_tree_indirect(sha1); 170 tree = parse_tree_indirect(sha1);
146 if (!tree) { 171 if (!tree) {
147 cgit_print_error(fmt("Not a tree object: %s", 172 cgit_print_error(fmt("Not a tree object: %s",
148 sha1_to_hex(sha1))); 173 sha1_to_hex(sha1)));
149 return; 174 return;
150 } 175 }
151 176
152 ls_head(); 177 ls_head();
153 read_tree_recursive(tree, "", 0, 1, NULL, ls_item, NULL); 178 read_tree_recursive(tree, "", 0, 1, NULL, ls_item, NULL);
154 ls_tail(); 179 ls_tail();
155} 180}
156 181
157 182
158static int walk_tree(const unsigned char *sha1, const char *base, int baselen, 183static int walk_tree(const unsigned char *sha1, const char *base, int baselen,
159 const char *pathname, unsigned mode, int stage, 184 const char *pathname, unsigned mode, int stage,
160 void *cbdata) 185 void *cbdata)
161{ 186{
162 static int state; 187 static int state;
163 static char buffer[PATH_MAX]; 188 static char buffer[PATH_MAX];
164 char *url; 189 char *url;
165 190
166 if (state == 0) { 191 if (state == 0) {
167 memcpy(buffer, base, baselen); 192 memcpy(buffer, base, baselen);
168 strcpy(buffer+baselen, pathname); 193 strcpy(buffer+baselen, pathname);
169 url = cgit_pageurl(ctx.qry.repo, "tree", 194 url = cgit_pageurl(ctx.qry.repo, "tree",
170 fmt("h=%s&amp;path=%s", curr_rev, buffer)); 195 fmt("h=%s&amp;path=%s", curr_rev, buffer));
171 html("/"); 196 html("/");
172 cgit_tree_link(xstrdup(pathname), NULL, NULL, ctx.qry.head, 197 cgit_tree_link(xstrdup(pathname), NULL, NULL, ctx.qry.head,
173 curr_rev, buffer); 198 curr_rev, buffer);
174 199
175 if (strcmp(match_path, buffer)) 200 if (strcmp(match_path, buffer))
176 return READ_TREE_RECURSIVE; 201 return READ_TREE_RECURSIVE;
177 202
178 if (S_ISDIR(mode)) { 203 if (S_ISDIR(mode)) {
179 state = 1; 204 state = 1;
180 ls_head(); 205 ls_head();
181 return READ_TREE_RECURSIVE; 206 return READ_TREE_RECURSIVE;
182 } else { 207 } else {
183 print_object(sha1, buffer); 208 print_object(sha1, buffer);
184 return 0; 209 return 0;
185 } 210 }
186 } 211 }
187 ls_item(sha1, base, baselen, pathname, mode, stage, NULL); 212 ls_item(sha1, base, baselen, pathname, mode, stage, NULL);
188 return 0; 213 return 0;
189} 214}
190 215
191 216
192/* 217/*
193 * Show a tree or a blob 218 * Show a tree or a blob
194 * rev: the commit pointing at the root tree object 219 * rev: the commit pointing at the root tree object
195 * path: path to tree or blob 220 * path: path to tree or blob
196 */ 221 */
197void cgit_print_tree(const char *rev, char *path) 222void cgit_print_tree(const char *rev, char *path)
198{ 223{
199 unsigned char sha1[20]; 224 unsigned char sha1[20];
200 struct commit *commit; 225 struct commit *commit;
201 const char *paths[] = {path, NULL}; 226 const char *paths[] = {path, NULL};
202 227
203 if (!rev) 228 if (!rev)
204 rev = ctx.qry.head; 229 rev = ctx.qry.head;
205 230
206 curr_rev = xstrdup(rev); 231 curr_rev = xstrdup(rev);
207 if (get_sha1(rev, sha1)) { 232 if (get_sha1(rev, sha1)) {
208 cgit_print_error(fmt("Invalid revision name: %s", rev)); 233 cgit_print_error(fmt("Invalid revision name: %s", rev));
209 return; 234 return;
210 } 235 }
211 commit = lookup_commit_reference(sha1); 236 commit = lookup_commit_reference(sha1);
212 if (!commit || parse_commit(commit)) { 237 if (!commit || parse_commit(commit)) {
213 cgit_print_error(fmt("Invalid commit reference: %s", rev)); 238 cgit_print_error(fmt("Invalid commit reference: %s", rev));
214 return; 239 return;
215 } 240 }
216 241
217 html("path: <a href='"); 242 html("path: <a href='");
218 html_attr(cgit_pageurl(ctx.qry.repo, "tree", fmt("h=%s", rev))); 243 html_attr(cgit_pageurl(ctx.qry.repo, "tree", fmt("h=%s", rev)));
219 html("'>root</a>"); 244 html("'>root</a>");
220 245
221 if (path == NULL) { 246 if (path == NULL) {
222 ls_tree(commit->tree->object.sha1, NULL); 247 ls_tree(commit->tree->object.sha1, NULL);
223 return; 248 return;
224 } 249 }
225 250
226 match_path = path; 251 match_path = path;
227 read_tree_recursive(commit->tree, NULL, 0, 0, paths, walk_tree, NULL); 252 read_tree_recursive(commit->tree, NULL, 0, 0, paths, walk_tree, NULL);
228 ls_tail(); 253 ls_tail();
229} 254}