summaryrefslogtreecommitdiffabout
authorLars Hjemli <hjemli@gmail.com>2007-06-18 20:12:09 (UTC)
committer Lars Hjemli <hjemli@gmail.com>2007-06-18 20:14:17 (UTC)
commita215bf4620113fcefb8dd3442bf3501bd648c463 (patch) (unidiff)
tree22e156c5b67605d7174c73efcd132696b335e8a0
parent1f34fb9d4f0bf82706ed8912c37a4b320a14813b (diff)
downloadcgit-a215bf4620113fcefb8dd3442bf3501bd648c463.zip
cgit-a215bf4620113fcefb8dd3442bf3501bd648c463.tar.gz
cgit-a215bf4620113fcefb8dd3442bf3501bd648c463.tar.bz2
Change S/L/T to summary/log/tree
In yet another attempt at better usability, the cryptic S/L/T links are changed to show their full name. Suggested-by: Kristian Høgsberg <krh@bitplanet.net> Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--cgit.css9
-rw-r--r--ui-repolist.c8
-rw-r--r--ui-tree.c2
3 files changed, 10 insertions, 9 deletions
diff --git a/cgit.css b/cgit.css
index 9c79c32..112dac1 100644
--- a/cgit.css
+++ b/cgit.css
@@ -118,308 +118,309 @@ td#crumb, td#search {
118} 118}
119 119
120td#crumb { 120td#crumb {
121 font-weight: bold; 121 font-weight: bold;
122} 122}
123 123
124td#crumb a { 124td#crumb a {
125 color: #ccc; 125 color: #ccc;
126 background-color: #666; 126 background-color: #666;
127 padding: 0em 0.5em 0em 0.5em; 127 padding: 0em 0.5em 0em 0.5em;
128} 128}
129 129
130td#crumb a:hover { 130td#crumb a:hover {
131 color: #666; 131 color: #666;
132 background-color: #ccc; 132 background-color: #ccc;
133 text-decoration: none; 133 text-decoration: none;
134} 134}
135 135
136td#search { 136td#search {
137 text-align: right; 137 text-align: right;
138 vertical-align: middle; 138 vertical-align: middle;
139 padding-right: 0.5em; 139 padding-right: 0.5em;
140} 140}
141 141
142td#search form { 142td#search form {
143 margin: 0px; 143 margin: 0px;
144 padding: 0px; 144 padding: 0px;
145} 145}
146 146
147td#search input { 147td#search input {
148 font-size: 9pt; 148 font-size: 9pt;
149 padding: 0px; 149 padding: 0px;
150 width: 10em; 150 width: 10em;
151 border: solid 1px #333; 151 border: solid 1px #333;
152 color: #333; 152 color: #333;
153 background-color: #fff; 153 background-color: #fff;
154} 154}
155 155
156div#summary { 156div#summary {
157 vertical-align: top; 157 vertical-align: top;
158 margin-bottom: 1em; 158 margin-bottom: 1em;
159} 159}
160 160
161table#downloads { 161table#downloads {
162 float: right; 162 float: right;
163 border-collapse: collapse; 163 border-collapse: collapse;
164 border: solid 1px #777; 164 border: solid 1px #777;
165 margin-left: 0.5em; 165 margin-left: 0.5em;
166 margin-bottom: 0.5em; 166 margin-bottom: 0.5em;
167} 167}
168 168
169table#downloads th { 169table#downloads th {
170 background-color: #ccc; 170 background-color: #ccc;
171} 171}
172 172
173td#content { 173td#content {
174 padding: 1em 0.5em; 174 padding: 1em 0.5em;
175} 175}
176 176
177div#blob { 177div#blob {
178 border: solid 1px black; 178 border: solid 1px black;
179} 179}
180 180
181div.error { 181div.error {
182 color: red; 182 color: red;
183 font-weight: bold; 183 font-weight: bold;
184 margin: 1em 2em; 184 margin: 1em 2em;
185} 185}
186 186
187a.ls-blob, a.ls-dir, a.ls-mod { 187a.ls-blob, a.ls-dir, a.ls-mod {
188 font-family: monospace; 188 font-family: monospace;
189} 189}
190 190
191td.ls-size { 191td.ls-size {
192 text-align: right; 192 text-align: right;
193} 193}
194 194
195td.ls-size { 195td.ls-size {
196 font-family: monospace; 196 font-family: monospace;
197} 197}
198 198
199td.ls-mode { 199td.ls-mode {
200 font-family: monospace; 200 font-family: monospace;
201} 201}
202 202
203table.blob { 203table.blob {
204 margin-top: 0.5em; 204 margin-top: 0.5em;
205 border-top: solid 1px black; 205 border-top: solid 1px black;
206} 206}
207 207
208table.blob td.no { 208table.blob td.no {
209 border-right: solid 1px black; 209 border-right: solid 1px black;
210 color: black; 210 color: black;
211 background-color: #eee; 211 background-color: #eee;
212 text-align: right; 212 text-align: right;
213} 213}
214 214
215table.blob td.txt { 215table.blob td.txt {
216 white-space: pre; 216 white-space: pre;
217 font-family: monospace; 217 font-family: monospace;
218 padding-left: 0.5em; 218 padding-left: 0.5em;
219} 219}
220 220
221table.nowrap td { 221table.nowrap td {
222 white-space: nowrap; 222 white-space: nowrap;
223} 223}
224 224
225table.commit-info { 225table.commit-info {
226 border-collapse: collapse; 226 border-collapse: collapse;
227 margin-top: 1.5em; 227 margin-top: 1.5em;
228} 228}
229 229
230table.commit-info th { 230table.commit-info th {
231 text-align: left; 231 text-align: left;
232 font-weight: normal; 232 font-weight: normal;
233 padding: 0.1em 1em 0.1em 0.1em; 233 padding: 0.1em 1em 0.1em 0.1em;
234} 234}
235 235
236table.commit-info td { 236table.commit-info td {
237 font-weight: normal; 237 font-weight: normal;
238 padding: 0.1em 1em 0.1em 0.1em; 238 padding: 0.1em 1em 0.1em 0.1em;
239} 239}
240 240
241div.commit-subject { 241div.commit-subject {
242 font-weight: bold; 242 font-weight: bold;
243 font-size: 125%; 243 font-size: 125%;
244 margin: 1.5em 0em 0.5em 0em; 244 margin: 1.5em 0em 0.5em 0em;
245 padding: 0em; 245 padding: 0em;
246} 246}
247 247
248div.commit-msg { 248div.commit-msg {
249 white-space: pre; 249 white-space: pre;
250 font-family: monospace; 250 font-family: monospace;
251} 251}
252 252
253div.diffstat-header { 253div.diffstat-header {
254 font-weight: bold; 254 font-weight: bold;
255 padding-top: 1.5em; 255 padding-top: 1.5em;
256} 256}
257 257
258table.diffstat { 258table.diffstat {
259 border-collapse: collapse; 259 border-collapse: collapse;
260 width: 100%; 260 width: 100%;
261 border: solid 1px #aaa; 261 border: solid 1px #aaa;
262 background-color: #eee; 262 background-color: #eee;
263} 263}
264 264
265table.diffstat tr:hover { 265table.diffstat tr:hover {
266 background-color: #ccc; 266 background-color: #ccc;
267} 267}
268 268
269table.diffstat th { 269table.diffstat th {
270 font-weight: normal; 270 font-weight: normal;
271 text-align: left; 271 text-align: left;
272 text-decoration: underline; 272 text-decoration: underline;
273 padding: 0.1em 1em 0.1em 0.1em; 273 padding: 0.1em 1em 0.1em 0.1em;
274 font-size: 100%; 274 font-size: 100%;
275} 275}
276 276
277table.diffstat td { 277table.diffstat td {
278 padding: 0.2em 0.2em 0.1em 0.1em; 278 padding: 0.2em 0.2em 0.1em 0.1em;
279 font-size: 100%; 279 font-size: 100%;
280 border: none; 280 border: none;
281} 281}
282 282
283table.diffstat td.mode { 283table.diffstat td.mode {
284 white-space: nowrap; 284 white-space: nowrap;
285} 285}
286 286
287table.diffstat td span.modechange { 287table.diffstat td span.modechange {
288 padding-left: 1em; 288 padding-left: 1em;
289 color: red; 289 color: red;
290} 290}
291 291
292table.diffstat td.add a { 292table.diffstat td.add a {
293 color: green; 293 color: green;
294} 294}
295 295
296table.diffstat td.del a { 296table.diffstat td.del a {
297 color: red; 297 color: red;
298} 298}
299 299
300table.diffstat td.upd a { 300table.diffstat td.upd a {
301 color: blue; 301 color: blue;
302} 302}
303 303
304table.diffstat td.graph { 304table.diffstat td.graph {
305 width: 75%; 305 width: 75%;
306 vertical-align: middle; 306 vertical-align: middle;
307} 307}
308 308
309table.diffstat td.graph table { 309table.diffstat td.graph table {
310 border: none; 310 border: none;
311} 311}
312 312
313table.diffstat td.graph td { 313table.diffstat td.graph td {
314 padding: 0px; 314 padding: 0px;
315 border: 0px; 315 border: 0px;
316 height: 7pt; 316 height: 7pt;
317} 317}
318 318
319table.diffstat td.graph td.add { 319table.diffstat td.graph td.add {
320 background-color: #5c5; 320 background-color: #5c5;
321} 321}
322 322
323table.diffstat td.graph td.rem { 323table.diffstat td.graph td.rem {
324 background-color: #c55; 324 background-color: #c55;
325} 325}
326 326
327div.diffstat-summary { 327div.diffstat-summary {
328 color: #888; 328 color: #888;
329 padding-top: 0.5em; 329 padding-top: 0.5em;
330} 330}
331 331
332table.diff td { 332table.diff td {
333 font-family: monospace; 333 font-family: monospace;
334 white-space: pre; 334 white-space: pre;
335} 335}
336 336
337table.diff td div.head { 337table.diff td div.head {
338 font-weight: bold; 338 font-weight: bold;
339 padding-top: 1em; 339 padding-top: 1em;
340} 340}
341 341
342table.diff td div.hunk { 342table.diff td div.hunk {
343 color: #009; 343 color: #009;
344} 344}
345 345
346table.diff td div.add { 346table.diff td div.add {
347 color: green; 347 color: green;
348} 348}
349 349
350table.diff td div.del { 350table.diff td div.del {
351 color: red; 351 color: red;
352} 352}
353 353
354.sha1 { 354.sha1 {
355 font-family: monospace; 355 font-family: monospace;
356 font-size: 90%; 356 font-size: 90%;
357} 357}
358 358
359.left { 359.left {
360 text-align: left; 360 text-align: left;
361} 361}
362 362
363.right { 363.right {
364 text-align: right; 364 text-align: right;
365} 365}
366 366
367table.list td.repogroup { 367table.list td.repogroup {
368 font-style: italic; 368 font-style: italic;
369 color: #888; 369 color: #888;
370} 370}
371 371
372a.button { 372a.button {
373 font-size: 80%; 373 font-size: 80%;
374 color: #333; 374 color: #aaa;
375 background-color: #ccc; 375 background-color: #eee;
376 border: solid 1px #999; 376 border: solid 1px #aaa;
377 padding: 0em 0.5em; 377 padding: 0em 0.5em;
378 margin: 0.1em 0.25em; 378 margin: 0.1em 0.25em;
379} 379}
380 380
381a.button:hover { 381a.button:hover {
382 text-decoration: none; 382 text-decoration: none;
383 background-color: #eee; 383 color: #333;
384 background-color: #ccc;
384} 385}
385 386
386a.primary { 387a.primary {
387 font-size: 100%; 388 font-size: 100%;
388} 389}
389 390
390a.secondary { 391a.secondary {
391 font-size: 90%; 392 font-size: 90%;
392} 393}
393 394
394td.toplevel-repo { 395td.toplevel-repo {
395 396
396} 397}
397 398
398table.list td.sublevel-repo { 399table.list td.sublevel-repo {
399 padding-left: 1.5em; 400 padding-left: 1.5em;
400} 401}
401 402
402span.age-mins { 403span.age-mins {
403 font-weight: bold; 404 font-weight: bold;
404 color: #080; 405 color: #080;
405} 406}
406 407
407span.age-hours { 408span.age-hours {
408 color: #080; 409 color: #080;
409} 410}
410 411
411span.age-days { 412span.age-days {
412 color: #040; 413 color: #040;
413} 414}
414 415
415span.age-weeks { 416span.age-weeks {
416 color: #444; 417 color: #444;
417} 418}
418 419
419span.age-months { 420span.age-months {
420 color: #888; 421 color: #888;
421} 422}
422 423
423span.age-years { 424span.age-years {
424 color: #bbb; 425 color: #bbb;
425} 426}
diff --git a/ui-repolist.c b/ui-repolist.c
index d5c77ea..4f820a8 100644
--- a/ui-repolist.c
+++ b/ui-repolist.c
@@ -1,98 +1,98 @@
1/* ui-repolist.c: functions for generating the repolist page 1/* ui-repolist.c: functions for generating the repolist page
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 <time.h> 10#include <time.h>
11 11
12 12
13time_t read_agefile(char *path) 13time_t read_agefile(char *path)
14{ 14{
15 FILE *f; 15 FILE *f;
16 static char buf[64], buf2[64]; 16 static char buf[64], buf2[64];
17 17
18 if (!(f = fopen(path, "r"))) 18 if (!(f = fopen(path, "r")))
19 return -1; 19 return -1;
20 fgets(buf, sizeof(buf), f); 20 fgets(buf, sizeof(buf), f);
21 fclose(f); 21 fclose(f);
22 if (parse_date(buf, buf2, sizeof(buf2))) 22 if (parse_date(buf, buf2, sizeof(buf2)))
23 return strtoul(buf2, NULL, 10); 23 return strtoul(buf2, NULL, 10);
24 else 24 else
25 return 0; 25 return 0;
26} 26}
27 27
28static void print_modtime(struct repoinfo *repo) 28static void print_modtime(struct repoinfo *repo)
29{ 29{
30 char *path; 30 char *path;
31 struct stat s; 31 struct stat s;
32 32
33 path = fmt("%s/%s", repo->path, cgit_agefile); 33 path = fmt("%s/%s", repo->path, cgit_agefile);
34 if (stat(path, &s) == 0) { 34 if (stat(path, &s) == 0) {
35 cgit_print_age(read_agefile(path), -1, NULL); 35 cgit_print_age(read_agefile(path), -1, NULL);
36 return; 36 return;
37 } 37 }
38 38
39 path = fmt("%s/refs/heads/%s", repo->path, repo->defbranch); 39 path = fmt("%s/refs/heads/%s", repo->path, repo->defbranch);
40 if (stat(path, &s) != 0) 40 if (stat(path, &s) != 0)
41 return; 41 return;
42 cgit_print_age(s.st_mtime, -1, NULL); 42 cgit_print_age(s.st_mtime, -1, NULL);
43} 43}
44 44
45void cgit_print_repolist(struct cacheitem *item) 45void cgit_print_repolist(struct cacheitem *item)
46{ 46{
47 int i; 47 int i;
48 char *last_group = NULL; 48 char *last_group = NULL;
49 49
50 cgit_print_docstart(cgit_root_title, item); 50 cgit_print_docstart(cgit_root_title, item);
51 cgit_print_pageheader(cgit_root_title, 0); 51 cgit_print_pageheader(cgit_root_title, 0);
52 52
53 html("<table class='list nowrap'>"); 53 html("<table class='list nowrap'>");
54 if (cgit_index_header) { 54 if (cgit_index_header) {
55 html("<tr class='nohover'><td colspan='5' class='include-block'>"); 55 html("<tr class='nohover'><td colspan='5' class='include-block'>");
56 html_include(cgit_index_header); 56 html_include(cgit_index_header);
57 html("</td></tr>"); 57 html("</td></tr>");
58 } 58 }
59 html("<tr class='nohover'>" 59 html("<tr class='nohover'>"
60 "<th class='left'>Name</th>" 60 "<th class='left'>Name</th>"
61 "<th class='left'>Description</th>" 61 "<th class='left'>Description</th>"
62 "<th class='left'>Owner</th>" 62 "<th class='left'>Owner</th>"
63 "<th class='left'>Idle</th>" 63 "<th class='left'>Idle</th>"
64 "<th>Links</th></tr>\n"); 64 "<th>Links</th></tr>\n");
65 65
66 for (i=0; i<cgit_repolist.count; i++) { 66 for (i=0; i<cgit_repolist.count; i++) {
67 cgit_repo = &cgit_repolist.repos[i]; 67 cgit_repo = &cgit_repolist.repos[i];
68 if ((last_group == NULL && cgit_repo->group != NULL) || 68 if ((last_group == NULL && cgit_repo->group != NULL) ||
69 (last_group != NULL && cgit_repo->group == NULL) || 69 (last_group != NULL && cgit_repo->group == NULL) ||
70 (last_group != NULL && cgit_repo->group != NULL && 70 (last_group != NULL && cgit_repo->group != NULL &&
71 strcmp(cgit_repo->group, last_group))) { 71 strcmp(cgit_repo->group, last_group))) {
72 html("<tr class='nohover'><td colspan='4' class='repogroup'>"); 72 html("<tr class='nohover'><td colspan='4' class='repogroup'>");
73 html_txt(cgit_repo->group); 73 html_txt(cgit_repo->group);
74 html("</td></tr>"); 74 html("</td></tr>");
75 last_group = cgit_repo->group; 75 last_group = cgit_repo->group;
76 } 76 }
77 htmlf("<tr><td class='%s'>", 77 htmlf("<tr><td class='%s'>",
78 cgit_repo->group ? "sublevel-repo" : "toplevel-repo"); 78 cgit_repo->group ? "sublevel-repo" : "toplevel-repo");
79 html_link_open(cgit_repourl(cgit_repo->url), NULL, NULL); 79 html_link_open(cgit_repourl(cgit_repo->url), NULL, NULL);
80 html_txt(cgit_repo->name); 80 html_txt(cgit_repo->name);
81 html_link_close(); 81 html_link_close();
82 html("</td><td>"); 82 html("</td><td>");
83 html_ntxt(cgit_max_repodesc_len, cgit_repo->desc); 83 html_ntxt(cgit_max_repodesc_len, cgit_repo->desc);
84 html("</td><td>"); 84 html("</td><td>");
85 html_txt(cgit_repo->owner); 85 html_txt(cgit_repo->owner);
86 html("</td><td>"); 86 html("</td><td>");
87 print_modtime(cgit_repo); 87 print_modtime(cgit_repo);
88 html("</td><td>"); 88 html("</td><td>");
89 html_link_open(cgit_repourl(cgit_repo->url), 89 html_link_open(cgit_repourl(cgit_repo->url),
90 "Summary", "button"); 90 NULL, "button");
91 html("S</a>"); 91 html("summary</a>");
92 cgit_log_link("L", "Log", "button", NULL, NULL, NULL); 92 cgit_log_link("log", NULL, "button", NULL, NULL, NULL);
93 cgit_tree_link("T", "Tree", "button", NULL, NULL, NULL); 93 cgit_tree_link("tree", NULL, "button", NULL, NULL, NULL);
94 html("</td></tr>\n"); 94 html("</td></tr>\n");
95 } 95 }
96 html("</table>"); 96 html("</table>");
97 cgit_print_docend(); 97 cgit_print_docend();
98} 98}
diff --git a/ui-tree.c b/ui-tree.c
index 1037c82..b6cb813 100644
--- a/ui-tree.c
+++ b/ui-tree.c
@@ -1,209 +1,209 @@
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 "cgit.h" 9#include "cgit.h"
10 10
11char *curr_rev; 11char *curr_rev;
12char *match_path; 12char *match_path;
13int header = 0; 13int header = 0;
14 14
15static void print_object(const unsigned char *sha1, char *path) 15static void print_object(const unsigned char *sha1, char *path)
16{ 16{
17 enum object_type type; 17 enum object_type type;
18 unsigned char *buf; 18 unsigned char *buf;
19 unsigned long size, lineno, start, idx; 19 unsigned long size, lineno, start, idx;
20 20
21 type = sha1_object_info(sha1, &size); 21 type = sha1_object_info(sha1, &size);
22 if (type == OBJ_BAD) { 22 if (type == OBJ_BAD) {
23 cgit_print_error(fmt("Bad object name: %s", 23 cgit_print_error(fmt("Bad object name: %s",
24 sha1_to_hex(sha1))); 24 sha1_to_hex(sha1)));
25 return; 25 return;
26 } 26 }
27 27
28 buf = read_sha1_file(sha1, &type, &size); 28 buf = read_sha1_file(sha1, &type, &size);
29 if (!buf) { 29 if (!buf) {
30 cgit_print_error(fmt("Error reading object %s", 30 cgit_print_error(fmt("Error reading object %s",
31 sha1_to_hex(sha1))); 31 sha1_to_hex(sha1)));
32 return; 32 return;
33 } 33 }
34 34
35 html("<table class='blob'>\n"); 35 html("<table class='blob'>\n");
36 idx = 0; 36 idx = 0;
37 start = 0; 37 start = 0;
38 lineno = 0; 38 lineno = 0;
39 while(idx < size) { 39 while(idx < size) {
40 if (buf[idx] == '\n') { 40 if (buf[idx] == '\n') {
41 buf[idx] = '\0'; 41 buf[idx] = '\0';
42 htmlf("<tr><td class='no'>%d</td><td class='txt'>", 42 htmlf("<tr><td class='no'>%d</td><td class='txt'>",
43 ++lineno); 43 ++lineno);
44 html_txt(buf + start); 44 html_txt(buf + start);
45 html("</td></tr>\n"); 45 html("</td></tr>\n");
46 start = idx + 1; 46 start = idx + 1;
47 } 47 }
48 idx++; 48 idx++;
49 } 49 }
50 html("</table>\n"); 50 html("</table>\n");
51} 51}
52 52
53 53
54static int ls_item(const unsigned char *sha1, const char *base, int baselen, 54static int ls_item(const unsigned char *sha1, const char *base, int baselen,
55 const char *pathname, unsigned int mode, int stage) 55 const char *pathname, unsigned int mode, int stage)
56{ 56{
57 char *name; 57 char *name;
58 char *fullpath; 58 char *fullpath;
59 enum object_type type; 59 enum object_type type;
60 unsigned long size = 0; 60 unsigned long size = 0;
61 61
62 name = xstrdup(pathname); 62 name = xstrdup(pathname);
63 fullpath = fmt("%s%s%s", cgit_query_path ? cgit_query_path : "", 63 fullpath = fmt("%s%s%s", cgit_query_path ? cgit_query_path : "",
64 cgit_query_path ? "/" : "", name); 64 cgit_query_path ? "/" : "", name);
65 65
66 type = sha1_object_info(sha1, &size); 66 type = sha1_object_info(sha1, &size);
67 if (type == OBJ_BAD && !S_ISDIRLNK(mode)) { 67 if (type == OBJ_BAD && !S_ISDIRLNK(mode)) {
68 htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>", 68 htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>",
69 name, 69 name,
70 sha1_to_hex(sha1)); 70 sha1_to_hex(sha1));
71 return 0; 71 return 0;
72 } 72 }
73 73
74 html("<tr><td class='ls-mode'>"); 74 html("<tr><td class='ls-mode'>");
75 html_filemode(mode); 75 html_filemode(mode);
76 html("</td><td>"); 76 html("</td><td>");
77 if (S_ISDIRLNK(mode)) { 77 if (S_ISDIRLNK(mode)) {
78 htmlf("<a class='ls-mod' href='"); 78 htmlf("<a class='ls-mod' href='");
79 html_attr(fmt(cgit_repo->module_link, 79 html_attr(fmt(cgit_repo->module_link,
80 name, 80 name,
81 sha1_to_hex(sha1))); 81 sha1_to_hex(sha1)));
82 html("'>"); 82 html("'>");
83 html_txt(name); 83 html_txt(name);
84 html("</a>"); 84 html("</a>");
85 } else if (S_ISDIR(mode)) { 85 } else if (S_ISDIR(mode)) {
86 cgit_tree_link(name, NULL, "ls-dir", cgit_query_head, 86 cgit_tree_link(name, NULL, "ls-dir", cgit_query_head,
87 curr_rev, fullpath); 87 curr_rev, fullpath);
88 } else { 88 } else {
89 cgit_tree_link(name, NULL, "ls-blob", cgit_query_head, 89 cgit_tree_link(name, NULL, "ls-blob", cgit_query_head,
90 curr_rev, fullpath); 90 curr_rev, fullpath);
91 } 91 }
92 htmlf("</td><td class='ls-size'>%li</td>", size); 92 htmlf("</td><td class='ls-size'>%li</td>", size);
93 93
94 html("<td>"); 94 html("<td>");
95 cgit_log_link("L", "Log", "button", cgit_query_head, curr_rev, 95 cgit_log_link("log", NULL, "button", cgit_query_head, curr_rev,
96 fullpath); 96 fullpath);
97 html("</td></tr>\n"); 97 html("</td></tr>\n");
98 free(name); 98 free(name);
99 return 0; 99 return 0;
100} 100}
101 101
102static void ls_head() 102static void ls_head()
103{ 103{
104 html("<table class='list'>\n"); 104 html("<table class='list'>\n");
105 html("<tr class='nohover'>"); 105 html("<tr class='nohover'>");
106 html("<th class='left'>Mode</th>"); 106 html("<th class='left'>Mode</th>");
107 html("<th class='left'>Name</th>"); 107 html("<th class='left'>Name</th>");
108 html("<th class='right'>Size</th>"); 108 html("<th class='right'>Size</th>");
109 html("<th/>"); 109 html("<th/>");
110 html("</tr>\n"); 110 html("</tr>\n");
111 header = 1; 111 header = 1;
112} 112}
113 113
114static void ls_tail() 114static void ls_tail()
115{ 115{
116 if (!header) 116 if (!header)
117 return; 117 return;
118 html("</table>\n"); 118 html("</table>\n");
119 header = 0; 119 header = 0;
120} 120}
121 121
122static void ls_tree(const unsigned char *sha1, char *path) 122static void ls_tree(const unsigned char *sha1, char *path)
123{ 123{
124 struct tree *tree; 124 struct tree *tree;
125 125
126 tree = parse_tree_indirect(sha1); 126 tree = parse_tree_indirect(sha1);
127 if (!tree) { 127 if (!tree) {
128 cgit_print_error(fmt("Not a tree object: %s", 128 cgit_print_error(fmt("Not a tree object: %s",
129 sha1_to_hex(sha1))); 129 sha1_to_hex(sha1)));
130 return; 130 return;
131 } 131 }
132 132
133 ls_head(); 133 ls_head();
134 read_tree_recursive(tree, "", 0, 1, NULL, ls_item); 134 read_tree_recursive(tree, "", 0, 1, NULL, ls_item);
135 ls_tail(); 135 ls_tail();
136} 136}
137 137
138 138
139static int walk_tree(const unsigned char *sha1, const char *base, int baselen, 139static int walk_tree(const unsigned char *sha1, const char *base, int baselen,
140 const char *pathname, unsigned mode, int stage) 140 const char *pathname, unsigned mode, int stage)
141{ 141{
142 static int state; 142 static int state;
143 static char buffer[PATH_MAX]; 143 static char buffer[PATH_MAX];
144 char *url; 144 char *url;
145 145
146 if (state == 0) { 146 if (state == 0) {
147 memcpy(buffer, base, baselen); 147 memcpy(buffer, base, baselen);
148 strcpy(buffer+baselen, pathname); 148 strcpy(buffer+baselen, pathname);
149 url = cgit_pageurl(cgit_query_repo, "tree", 149 url = cgit_pageurl(cgit_query_repo, "tree",
150 fmt("h=%s&amp;path=%s", curr_rev, buffer)); 150 fmt("h=%s&amp;path=%s", curr_rev, buffer));
151 html("/"); 151 html("/");
152 cgit_tree_link(xstrdup(pathname), NULL, NULL, cgit_query_head, 152 cgit_tree_link(xstrdup(pathname), NULL, NULL, cgit_query_head,
153 curr_rev, buffer); 153 curr_rev, buffer);
154 154
155 if (strcmp(match_path, buffer)) 155 if (strcmp(match_path, buffer))
156 return READ_TREE_RECURSIVE; 156 return READ_TREE_RECURSIVE;
157 157
158 if (S_ISDIR(mode)) { 158 if (S_ISDIR(mode)) {
159 state = 1; 159 state = 1;
160 ls_head(); 160 ls_head();
161 return READ_TREE_RECURSIVE; 161 return READ_TREE_RECURSIVE;
162 } else { 162 } else {
163 print_object(sha1, buffer); 163 print_object(sha1, buffer);
164 return 0; 164 return 0;
165 } 165 }
166 } 166 }
167 ls_item(sha1, base, baselen, pathname, mode, stage); 167 ls_item(sha1, base, baselen, pathname, mode, stage);
168 return 0; 168 return 0;
169} 169}
170 170
171 171
172/* 172/*
173 * Show a tree or a blob 173 * Show a tree or a blob
174 * rev: the commit pointing at the root tree object 174 * rev: the commit pointing at the root tree object
175 * path: path to tree or blob 175 * path: path to tree or blob
176 */ 176 */
177void cgit_print_tree(const char *rev, char *path) 177void cgit_print_tree(const char *rev, char *path)
178{ 178{
179 unsigned char sha1[20]; 179 unsigned char sha1[20];
180 struct commit *commit; 180 struct commit *commit;
181 const char *paths[] = {path, NULL}; 181 const char *paths[] = {path, NULL};
182 182
183 if (!rev) 183 if (!rev)
184 rev = cgit_query_head; 184 rev = cgit_query_head;
185 185
186 curr_rev = xstrdup(rev); 186 curr_rev = xstrdup(rev);
187 if (get_sha1(rev, sha1)) { 187 if (get_sha1(rev, sha1)) {
188 cgit_print_error(fmt("Invalid revision name: %s", rev)); 188 cgit_print_error(fmt("Invalid revision name: %s", rev));
189 return; 189 return;
190 } 190 }
191 commit = lookup_commit_reference(sha1); 191 commit = lookup_commit_reference(sha1);
192 if (!commit || parse_commit(commit)) { 192 if (!commit || parse_commit(commit)) {
193 cgit_print_error(fmt("Invalid commit reference: %s", rev)); 193 cgit_print_error(fmt("Invalid commit reference: %s", rev));
194 return; 194 return;
195 } 195 }
196 196
197 html("path: <a href='"); 197 html("path: <a href='");
198 html_attr(cgit_pageurl(cgit_query_repo, "tree", fmt("h=%s", rev))); 198 html_attr(cgit_pageurl(cgit_query_repo, "tree", fmt("h=%s", rev)));
199 html("'>root</a>"); 199 html("'>root</a>");
200 200
201 if (path == NULL) { 201 if (path == NULL) {
202 ls_tree(commit->tree->object.sha1, NULL); 202 ls_tree(commit->tree->object.sha1, NULL);
203 return; 203 return;
204 } 204 }
205 205
206 match_path = path; 206 match_path = path;
207 read_tree_recursive(commit->tree, NULL, 0, 0, paths, walk_tree); 207 read_tree_recursive(commit->tree, NULL, 0, 0, paths, walk_tree);
208 ls_tail(); 208 ls_tail();
209} 209}