summaryrefslogtreecommitdiffabout
authorLars Hjemli <hjemli@gmail.com>2008-08-06 09:07:13 (UTC)
committer Lars Hjemli <hjemli@gmail.com>2008-08-06 09:21:30 (UTC)
commit65b7b876aaaf50fc15060533359d6561f4f1819a (patch) (unidiff)
treec5cfe73456cf31afb13bcb12c5331fa711f89d71
parente5da4bca54574522b28f88cab0dc8ebad9e35a73 (diff)
downloadcgit-65b7b876aaaf50fc15060533359d6561f4f1819a.zip
cgit-65b7b876aaaf50fc15060533359d6561f4f1819a.tar.gz
cgit-65b7b876aaaf50fc15060533359d6561f4f1819a.tar.bz2
ui-tree: link to plain view instead of blob view
The urls for plain view makes it possible to download blobs without knowing their SHA1, but the function needs to be promoted and the link from tree view seems like a perfect fit. PS: Although hidden, the blob view still is nice for direct blob access so there's no point in removing it. Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--ui-shared.c6
-rw-r--r--ui-shared.h2
-rw-r--r--ui-tree.c8
3 files changed, 12 insertions, 4 deletions
diff --git a/ui-shared.c b/ui-shared.c
index 4408969..a2e0dd2 100644
--- a/ui-shared.c
+++ b/ui-shared.c
@@ -118,256 +118,262 @@ static void site_url(char *page, char *search, int ofs)
118{ 118{
119 char *delim = "?"; 119 char *delim = "?";
120 120
121 if (ctx.cfg.virtual_root) { 121 if (ctx.cfg.virtual_root) {
122 html_attr(ctx.cfg.virtual_root); 122 html_attr(ctx.cfg.virtual_root);
123 if (ctx.cfg.virtual_root[strlen(ctx.cfg.virtual_root) - 1] != '/') 123 if (ctx.cfg.virtual_root[strlen(ctx.cfg.virtual_root) - 1] != '/')
124 html("/"); 124 html("/");
125 } else 125 } else
126 html(ctx.cfg.script_name); 126 html(ctx.cfg.script_name);
127 127
128 if (page) { 128 if (page) {
129 htmlf("?p=%s", page); 129 htmlf("?p=%s", page);
130 delim = "&"; 130 delim = "&";
131 } 131 }
132 if (search) { 132 if (search) {
133 html(delim); 133 html(delim);
134 html("q="); 134 html("q=");
135 html_attr(search); 135 html_attr(search);
136 delim = "&"; 136 delim = "&";
137 } 137 }
138 if (ofs) { 138 if (ofs) {
139 html(delim); 139 html(delim);
140 htmlf("ofs=%d", ofs); 140 htmlf("ofs=%d", ofs);
141 } 141 }
142} 142}
143 143
144static void site_link(char *page, char *name, char *title, char *class, 144static void site_link(char *page, char *name, char *title, char *class,
145 char *search, int ofs) 145 char *search, int ofs)
146{ 146{
147 html("<a"); 147 html("<a");
148 if (title) { 148 if (title) {
149 html(" title='"); 149 html(" title='");
150 html_attr(title); 150 html_attr(title);
151 html("'"); 151 html("'");
152 } 152 }
153 if (class) { 153 if (class) {
154 html(" class='"); 154 html(" class='");
155 html_attr(class); 155 html_attr(class);
156 html("'"); 156 html("'");
157 } 157 }
158 html(" href='"); 158 html(" href='");
159 site_url(page, search, ofs); 159 site_url(page, search, ofs);
160 html("'>"); 160 html("'>");
161 html_txt(name); 161 html_txt(name);
162 html("</a>"); 162 html("</a>");
163} 163}
164 164
165void cgit_index_link(char *name, char *title, char *class, char *pattern, 165void cgit_index_link(char *name, char *title, char *class, char *pattern,
166 int ofs) 166 int ofs)
167{ 167{
168 site_link(NULL, name, title, class, pattern, ofs); 168 site_link(NULL, name, title, class, pattern, ofs);
169} 169}
170 170
171static char *repolink(char *title, char *class, char *page, char *head, 171static char *repolink(char *title, char *class, char *page, char *head,
172 char *path) 172 char *path)
173{ 173{
174 char *delim = "?"; 174 char *delim = "?";
175 175
176 html("<a"); 176 html("<a");
177 if (title) { 177 if (title) {
178 html(" title='"); 178 html(" title='");
179 html_attr(title); 179 html_attr(title);
180 html("'"); 180 html("'");
181 } 181 }
182 if (class) { 182 if (class) {
183 html(" class='"); 183 html(" class='");
184 html_attr(class); 184 html_attr(class);
185 html("'"); 185 html("'");
186 } 186 }
187 html(" href='"); 187 html(" href='");
188 if (ctx.cfg.virtual_root) { 188 if (ctx.cfg.virtual_root) {
189 html_attr(ctx.cfg.virtual_root); 189 html_attr(ctx.cfg.virtual_root);
190 if (ctx.cfg.virtual_root[strlen(ctx.cfg.virtual_root) - 1] != '/') 190 if (ctx.cfg.virtual_root[strlen(ctx.cfg.virtual_root) - 1] != '/')
191 html("/"); 191 html("/");
192 html_attr(ctx.repo->url); 192 html_attr(ctx.repo->url);
193 if (ctx.repo->url[strlen(ctx.repo->url) - 1] != '/') 193 if (ctx.repo->url[strlen(ctx.repo->url) - 1] != '/')
194 html("/"); 194 html("/");
195 if (page) { 195 if (page) {
196 html(page); 196 html(page);
197 html("/"); 197 html("/");
198 if (path) 198 if (path)
199 html_attr(path); 199 html_attr(path);
200 } 200 }
201 } else { 201 } else {
202 html(ctx.cfg.script_name); 202 html(ctx.cfg.script_name);
203 html("?url="); 203 html("?url=");
204 html_attr(ctx.repo->url); 204 html_attr(ctx.repo->url);
205 if (ctx.repo->url[strlen(ctx.repo->url) - 1] != '/') 205 if (ctx.repo->url[strlen(ctx.repo->url) - 1] != '/')
206 html("/"); 206 html("/");
207 if (page) { 207 if (page) {
208 html(page); 208 html(page);
209 html("/"); 209 html("/");
210 if (path) 210 if (path)
211 html_attr(path); 211 html_attr(path);
212 } 212 }
213 delim = "&amp;"; 213 delim = "&amp;";
214 } 214 }
215 if (head && strcmp(head, ctx.repo->defbranch)) { 215 if (head && strcmp(head, ctx.repo->defbranch)) {
216 html(delim); 216 html(delim);
217 html("h="); 217 html("h=");
218 html_attr(head); 218 html_attr(head);
219 delim = "&amp;"; 219 delim = "&amp;";
220 } 220 }
221 return fmt("%s", delim); 221 return fmt("%s", delim);
222} 222}
223 223
224static void reporevlink(char *page, char *name, char *title, char *class, 224static void reporevlink(char *page, char *name, char *title, char *class,
225 char *head, char *rev, char *path) 225 char *head, char *rev, char *path)
226{ 226{
227 char *delim; 227 char *delim;
228 228
229 delim = repolink(title, class, page, head, path); 229 delim = repolink(title, class, page, head, path);
230 if (rev && strcmp(rev, ctx.qry.head)) { 230 if (rev && strcmp(rev, ctx.qry.head)) {
231 html(delim); 231 html(delim);
232 html("id="); 232 html("id=");
233 html_attr(rev); 233 html_attr(rev);
234 } 234 }
235 html("'>"); 235 html("'>");
236 html_txt(name); 236 html_txt(name);
237 html("</a>"); 237 html("</a>");
238} 238}
239 239
240void cgit_tree_link(char *name, char *title, char *class, char *head, 240void cgit_tree_link(char *name, char *title, char *class, char *head,
241 char *rev, char *path) 241 char *rev, char *path)
242{ 242{
243 reporevlink("tree", name, title, class, head, rev, path); 243 reporevlink("tree", name, title, class, head, rev, path);
244} 244}
245 245
246void cgit_plain_link(char *name, char *title, char *class, char *head,
247 char *rev, char *path)
248{
249 reporevlink("plain", name, title, class, head, rev, path);
250}
251
246void cgit_log_link(char *name, char *title, char *class, char *head, 252void cgit_log_link(char *name, char *title, char *class, char *head,
247 char *rev, char *path, int ofs, char *grep, char *pattern) 253 char *rev, char *path, int ofs, char *grep, char *pattern)
248{ 254{
249 char *delim; 255 char *delim;
250 256
251 delim = repolink(title, class, "log", head, path); 257 delim = repolink(title, class, "log", head, path);
252 if (rev && strcmp(rev, ctx.qry.head)) { 258 if (rev && strcmp(rev, ctx.qry.head)) {
253 html(delim); 259 html(delim);
254 html("id="); 260 html("id=");
255 html_attr(rev); 261 html_attr(rev);
256 delim = "&"; 262 delim = "&";
257 } 263 }
258 if (grep && pattern) { 264 if (grep && pattern) {
259 html(delim); 265 html(delim);
260 html("qt="); 266 html("qt=");
261 html_attr(grep); 267 html_attr(grep);
262 delim = "&"; 268 delim = "&";
263 html(delim); 269 html(delim);
264 html("q="); 270 html("q=");
265 html_attr(pattern); 271 html_attr(pattern);
266 } 272 }
267 if (ofs > 0) { 273 if (ofs > 0) {
268 html(delim); 274 html(delim);
269 html("ofs="); 275 html("ofs=");
270 htmlf("%d", ofs); 276 htmlf("%d", ofs);
271 } 277 }
272 html("'>"); 278 html("'>");
273 html_txt(name); 279 html_txt(name);
274 html("</a>"); 280 html("</a>");
275} 281}
276 282
277void cgit_commit_link(char *name, char *title, char *class, char *head, 283void cgit_commit_link(char *name, char *title, char *class, char *head,
278 char *rev) 284 char *rev)
279{ 285{
280 if (strlen(name) > ctx.cfg.max_msg_len && ctx.cfg.max_msg_len >= 15) { 286 if (strlen(name) > ctx.cfg.max_msg_len && ctx.cfg.max_msg_len >= 15) {
281 name[ctx.cfg.max_msg_len] = '\0'; 287 name[ctx.cfg.max_msg_len] = '\0';
282 name[ctx.cfg.max_msg_len - 1] = '.'; 288 name[ctx.cfg.max_msg_len - 1] = '.';
283 name[ctx.cfg.max_msg_len - 2] = '.'; 289 name[ctx.cfg.max_msg_len - 2] = '.';
284 name[ctx.cfg.max_msg_len - 3] = '.'; 290 name[ctx.cfg.max_msg_len - 3] = '.';
285 } 291 }
286 reporevlink("commit", name, title, class, head, rev, NULL); 292 reporevlink("commit", name, title, class, head, rev, NULL);
287} 293}
288 294
289void cgit_refs_link(char *name, char *title, char *class, char *head, 295void cgit_refs_link(char *name, char *title, char *class, char *head,
290 char *rev, char *path) 296 char *rev, char *path)
291{ 297{
292 reporevlink("refs", name, title, class, head, rev, path); 298 reporevlink("refs", name, title, class, head, rev, path);
293} 299}
294 300
295void cgit_snapshot_link(char *name, char *title, char *class, char *head, 301void cgit_snapshot_link(char *name, char *title, char *class, char *head,
296 char *rev, char *archivename) 302 char *rev, char *archivename)
297{ 303{
298 reporevlink("snapshot", name, title, class, head, rev, archivename); 304 reporevlink("snapshot", name, title, class, head, rev, archivename);
299} 305}
300 306
301void cgit_diff_link(char *name, char *title, char *class, char *head, 307void cgit_diff_link(char *name, char *title, char *class, char *head,
302 char *new_rev, char *old_rev, char *path) 308 char *new_rev, char *old_rev, char *path)
303{ 309{
304 char *delim; 310 char *delim;
305 311
306 delim = repolink(title, class, "diff", head, path); 312 delim = repolink(title, class, "diff", head, path);
307 if (new_rev && strcmp(new_rev, ctx.qry.head)) { 313 if (new_rev && strcmp(new_rev, ctx.qry.head)) {
308 html(delim); 314 html(delim);
309 html("id="); 315 html("id=");
310 html_attr(new_rev); 316 html_attr(new_rev);
311 delim = "&amp;"; 317 delim = "&amp;";
312 } 318 }
313 if (old_rev) { 319 if (old_rev) {
314 html(delim); 320 html(delim);
315 html("id2="); 321 html("id2=");
316 html_attr(old_rev); 322 html_attr(old_rev);
317 } 323 }
318 html("'>"); 324 html("'>");
319 html_txt(name); 325 html_txt(name);
320 html("</a>"); 326 html("</a>");
321} 327}
322 328
323void cgit_patch_link(char *name, char *title, char *class, char *head, 329void cgit_patch_link(char *name, char *title, char *class, char *head,
324 char *rev) 330 char *rev)
325{ 331{
326 reporevlink("patch", name, title, class, head, rev, NULL); 332 reporevlink("patch", name, title, class, head, rev, NULL);
327} 333}
328 334
329void cgit_object_link(struct object *obj) 335void cgit_object_link(struct object *obj)
330{ 336{
331 char *page, *arg, *url; 337 char *page, *arg, *url;
332 338
333 if (obj->type == OBJ_COMMIT) { 339 if (obj->type == OBJ_COMMIT) {
334 cgit_commit_link(fmt("commit %s", sha1_to_hex(obj->sha1)), NULL, NULL, 340 cgit_commit_link(fmt("commit %s", sha1_to_hex(obj->sha1)), NULL, NULL,
335 ctx.qry.head, sha1_to_hex(obj->sha1)); 341 ctx.qry.head, sha1_to_hex(obj->sha1));
336 return; 342 return;
337 } else if (obj->type == OBJ_TREE) { 343 } else if (obj->type == OBJ_TREE) {
338 page = "tree"; 344 page = "tree";
339 arg = "id"; 345 arg = "id";
340 } else if (obj->type == OBJ_TAG) { 346 } else if (obj->type == OBJ_TAG) {
341 page = "tag"; 347 page = "tag";
342 arg = "id"; 348 arg = "id";
343 } else { 349 } else {
344 page = "blob"; 350 page = "blob";
345 arg = "id"; 351 arg = "id";
346 } 352 }
347 353
348 url = cgit_pageurl(ctx.qry.repo, page, 354 url = cgit_pageurl(ctx.qry.repo, page,
349 fmt("%s=%s", arg, sha1_to_hex(obj->sha1))); 355 fmt("%s=%s", arg, sha1_to_hex(obj->sha1)));
350 html_link_open(url, NULL, NULL); 356 html_link_open(url, NULL, NULL);
351 htmlf("%s %s", typename(obj->type), 357 htmlf("%s %s", typename(obj->type),
352 sha1_to_hex(obj->sha1)); 358 sha1_to_hex(obj->sha1));
353 html_link_close(); 359 html_link_close();
354} 360}
355 361
356void cgit_print_date(time_t secs, char *format, int local_time) 362void cgit_print_date(time_t secs, char *format, int local_time)
357{ 363{
358 char buf[64]; 364 char buf[64];
359 struct tm *time; 365 struct tm *time;
360 366
361 if (!secs) 367 if (!secs)
362 return; 368 return;
363 if(local_time) 369 if(local_time)
364 time = localtime(&secs); 370 time = localtime(&secs);
365 else 371 else
366 time = gmtime(&secs); 372 time = gmtime(&secs);
367 strftime(buf, sizeof(buf)-1, format, time); 373 strftime(buf, sizeof(buf)-1, format, time);
368 html_txt(buf); 374 html_txt(buf);
369} 375}
370 376
371void cgit_print_age(time_t t, time_t max_relative, char *format) 377void cgit_print_age(time_t t, time_t max_relative, char *format)
372{ 378{
373 time_t now, secs; 379 time_t now, secs;
diff --git a/ui-shared.h b/ui-shared.h
index 07da4b4..c5ce056 100644
--- a/ui-shared.h
+++ b/ui-shared.h
@@ -1,40 +1,42 @@
1#ifndef UI_SHARED_H 1#ifndef UI_SHARED_H
2#define UI_SHARED_H 2#define UI_SHARED_H
3 3
4extern char *cgit_repourl(const char *reponame); 4extern char *cgit_repourl(const char *reponame);
5extern char *cgit_fileurl(const char *reponame, const char *pagename, 5extern char *cgit_fileurl(const char *reponame, const char *pagename,
6 const char *filename, const char *query); 6 const char *filename, const char *query);
7extern char *cgit_pageurl(const char *reponame, const char *pagename, 7extern char *cgit_pageurl(const char *reponame, const char *pagename,
8 const char *query); 8 const char *query);
9 9
10extern void cgit_index_link(char *name, char *title, char *class, 10extern void cgit_index_link(char *name, char *title, char *class,
11 char *pattern, int ofs); 11 char *pattern, int ofs);
12extern void cgit_tree_link(char *name, char *title, char *class, char *head, 12extern void cgit_tree_link(char *name, char *title, char *class, char *head,
13 char *rev, char *path); 13 char *rev, char *path);
14extern void cgit_plain_link(char *name, char *title, char *class, char *head,
15 char *rev, char *path);
14extern void cgit_log_link(char *name, char *title, char *class, char *head, 16extern void cgit_log_link(char *name, char *title, char *class, char *head,
15 char *rev, char *path, int ofs, char *grep, 17 char *rev, char *path, int ofs, char *grep,
16 char *pattern); 18 char *pattern);
17extern void cgit_commit_link(char *name, char *title, char *class, char *head, 19extern void cgit_commit_link(char *name, char *title, char *class, char *head,
18 char *rev); 20 char *rev);
19extern void cgit_patch_link(char *name, char *title, char *class, char *head, 21extern void cgit_patch_link(char *name, char *title, char *class, char *head,
20 char *rev); 22 char *rev);
21extern void cgit_refs_link(char *name, char *title, char *class, char *head, 23extern void cgit_refs_link(char *name, char *title, char *class, char *head,
22 char *rev, char *path); 24 char *rev, char *path);
23extern void cgit_snapshot_link(char *name, char *title, char *class, 25extern void cgit_snapshot_link(char *name, char *title, char *class,
24 char *head, char *rev, char *archivename); 26 char *head, char *rev, char *archivename);
25extern void cgit_diff_link(char *name, char *title, char *class, char *head, 27extern void cgit_diff_link(char *name, char *title, char *class, char *head,
26 char *new_rev, char *old_rev, char *path); 28 char *new_rev, char *old_rev, char *path);
27extern void cgit_object_link(struct object *obj); 29extern void cgit_object_link(struct object *obj);
28 30
29extern void cgit_print_error(char *msg); 31extern void cgit_print_error(char *msg);
30extern void cgit_print_date(time_t secs, char *format, int local_time); 32extern void cgit_print_date(time_t secs, char *format, int local_time);
31extern void cgit_print_age(time_t t, time_t max_relative, char *format); 33extern void cgit_print_age(time_t t, time_t max_relative, char *format);
32extern void cgit_print_http_headers(struct cgit_context *ctx); 34extern void cgit_print_http_headers(struct cgit_context *ctx);
33extern void cgit_print_docstart(struct cgit_context *ctx); 35extern void cgit_print_docstart(struct cgit_context *ctx);
34extern void cgit_print_docend(); 36extern void cgit_print_docend();
35extern void cgit_print_pageheader(struct cgit_context *ctx); 37extern void cgit_print_pageheader(struct cgit_context *ctx);
36extern void cgit_print_filemode(unsigned short mode); 38extern void cgit_print_filemode(unsigned short mode);
37extern void cgit_print_snapshot_links(const char *repo, const char *head, 39extern void cgit_print_snapshot_links(const char *repo, const char *head,
38 const char *hex, int snapshots); 40 const char *hex, int snapshots);
39 41
40#endif /* UI_SHARED_H */ 42#endif /* UI_SHARED_H */
diff --git a/ui-tree.c b/ui-tree.c
index 9a837e2..79332fc 100644
--- a/ui-tree.c
+++ b/ui-tree.c
@@ -1,169 +1,169 @@
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#include "html.h" 10#include "html.h"
11#include "ui-shared.h" 11#include "ui-shared.h"
12 12
13char *curr_rev; 13char *curr_rev;
14char *match_path; 14char *match_path;
15int header = 0; 15int header = 0;
16 16
17static void print_object(const unsigned char *sha1, char *path) 17static void print_object(const unsigned char *sha1, char *path)
18{ 18{
19 enum object_type type; 19 enum object_type type;
20 char *buf; 20 char *buf;
21 unsigned long size, lineno, start, idx; 21 unsigned long size, lineno, start, idx;
22 const char *linefmt = "<tr><td class='no'><a id='n%1$d' name='n%1$d' href='#n%1$d'>%1$d</a></td><td class='txt'>"; 22 const char *linefmt = "<tr><td class='no'><a id='n%1$d' name='n%1$d' href='#n%1$d'>%1$d</a></td><td class='txt'>";
23 23
24 type = sha1_object_info(sha1, &size); 24 type = sha1_object_info(sha1, &size);
25 if (type == OBJ_BAD) { 25 if (type == OBJ_BAD) {
26 cgit_print_error(fmt("Bad object name: %s", 26 cgit_print_error(fmt("Bad object name: %s",
27 sha1_to_hex(sha1))); 27 sha1_to_hex(sha1)));
28 return; 28 return;
29 } 29 }
30 30
31 buf = read_sha1_file(sha1, &type, &size); 31 buf = read_sha1_file(sha1, &type, &size);
32 if (!buf) { 32 if (!buf) {
33 cgit_print_error(fmt("Error reading object %s", 33 cgit_print_error(fmt("Error reading object %s",
34 sha1_to_hex(sha1))); 34 sha1_to_hex(sha1)));
35 return; 35 return;
36 } 36 }
37 37
38 html(" blob: <a href='"); 38 html(" (");
39 html_attr(cgit_pageurl(ctx.qry.repo, "blob", 39 cgit_plain_link("plain", NULL, NULL, ctx.qry.head,
40 fmt("id=%s&path=%s", sha1_to_hex(sha1), path))); 40 curr_rev, path);
41 htmlf("'>%s</a>",sha1_to_hex(sha1)); 41 htmlf(")<br/>blob: %s", sha1_to_hex(sha1));
42 42
43 html("<table summary='blob content' class='blob'>\n"); 43 html("<table summary='blob content' class='blob'>\n");
44 idx = 0; 44 idx = 0;
45 start = 0; 45 start = 0;
46 lineno = 0; 46 lineno = 0;
47 while(idx < size) { 47 while(idx < size) {
48 if (buf[idx] == '\n') { 48 if (buf[idx] == '\n') {
49 buf[idx] = '\0'; 49 buf[idx] = '\0';
50 htmlf(linefmt, ++lineno); 50 htmlf(linefmt, ++lineno);
51 html_txt(buf + start); 51 html_txt(buf + start);
52 html("</td></tr>\n"); 52 html("</td></tr>\n");
53 start = idx + 1; 53 start = idx + 1;
54 } 54 }
55 idx++; 55 idx++;
56 } 56 }
57 htmlf(linefmt, ++lineno); 57 htmlf(linefmt, ++lineno);
58 html_txt(buf + start); 58 html_txt(buf + start);
59 html("</td></tr>\n"); 59 html("</td></tr>\n");
60 html("</table>\n"); 60 html("</table>\n");
61} 61}
62 62
63 63
64static int ls_item(const unsigned char *sha1, const char *base, int baselen, 64static int ls_item(const unsigned char *sha1, const char *base, int baselen,
65 const char *pathname, unsigned int mode, int stage, 65 const char *pathname, unsigned int mode, int stage,
66 void *cbdata) 66 void *cbdata)
67{ 67{
68 char *name; 68 char *name;
69 char *fullpath; 69 char *fullpath;
70 enum object_type type; 70 enum object_type type;
71 unsigned long size = 0; 71 unsigned long size = 0;
72 72
73 name = xstrdup(pathname); 73 name = xstrdup(pathname);
74 fullpath = fmt("%s%s%s", ctx.qry.path ? ctx.qry.path : "", 74 fullpath = fmt("%s%s%s", ctx.qry.path ? ctx.qry.path : "",
75 ctx.qry.path ? "/" : "", name); 75 ctx.qry.path ? "/" : "", name);
76 76
77 if (!S_ISGITLINK(mode)) { 77 if (!S_ISGITLINK(mode)) {
78 type = sha1_object_info(sha1, &size); 78 type = sha1_object_info(sha1, &size);
79 if (type == OBJ_BAD) { 79 if (type == OBJ_BAD) {
80 htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>", 80 htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>",
81 name, 81 name,
82 sha1_to_hex(sha1)); 82 sha1_to_hex(sha1));
83 return 0; 83 return 0;
84 } 84 }
85 } 85 }
86 86
87 html("<tr><td class='ls-mode'>"); 87 html("<tr><td class='ls-mode'>");
88 cgit_print_filemode(mode); 88 cgit_print_filemode(mode);
89 html("</td><td>"); 89 html("</td><td>");
90 if (S_ISGITLINK(mode)) { 90 if (S_ISGITLINK(mode)) {
91 htmlf("<a class='ls-mod' href='"); 91 htmlf("<a class='ls-mod' href='");
92 html_attr(fmt(ctx.repo->module_link, 92 html_attr(fmt(ctx.repo->module_link,
93 name, 93 name,
94 sha1_to_hex(sha1))); 94 sha1_to_hex(sha1)));
95 html("'>"); 95 html("'>");
96 html_txt(name); 96 html_txt(name);
97 html("</a>"); 97 html("</a>");
98 } else if (S_ISDIR(mode)) { 98 } else if (S_ISDIR(mode)) {
99 cgit_tree_link(name, NULL, "ls-dir", ctx.qry.head, 99 cgit_tree_link(name, NULL, "ls-dir", ctx.qry.head,
100 curr_rev, fullpath); 100 curr_rev, fullpath);
101 } else { 101 } else {
102 cgit_tree_link(name, NULL, "ls-blob", ctx.qry.head, 102 cgit_tree_link(name, NULL, "ls-blob", ctx.qry.head,
103 curr_rev, fullpath); 103 curr_rev, fullpath);
104 } 104 }
105 htmlf("</td><td class='ls-size'>%li</td>", size); 105 htmlf("</td><td class='ls-size'>%li</td>", size);
106 106
107 html("<td>"); 107 html("<td>");
108 cgit_log_link("log", NULL, "button", ctx.qry.head, curr_rev, 108 cgit_log_link("log", NULL, "button", ctx.qry.head, curr_rev,
109 fullpath, 0, NULL, NULL); 109 fullpath, 0, NULL, NULL);
110 html("</td></tr>\n"); 110 html("</td></tr>\n");
111 free(name); 111 free(name);
112 return 0; 112 return 0;
113} 113}
114 114
115static void ls_head() 115static void ls_head()
116{ 116{
117 html("<table summary='tree listing' class='list'>\n"); 117 html("<table summary='tree listing' class='list'>\n");
118 html("<tr class='nohover'>"); 118 html("<tr class='nohover'>");
119 html("<th class='left'>Mode</th>"); 119 html("<th class='left'>Mode</th>");
120 html("<th class='left'>Name</th>"); 120 html("<th class='left'>Name</th>");
121 html("<th class='right'>Size</th>"); 121 html("<th class='right'>Size</th>");
122 html("<th/>"); 122 html("<th/>");
123 html("</tr>\n"); 123 html("</tr>\n");
124 header = 1; 124 header = 1;
125} 125}
126 126
127static void ls_tail() 127static void ls_tail()
128{ 128{
129 if (!header) 129 if (!header)
130 return; 130 return;
131 html("</table>\n"); 131 html("</table>\n");
132 header = 0; 132 header = 0;
133} 133}
134 134
135static void ls_tree(const unsigned char *sha1, char *path) 135static void ls_tree(const unsigned char *sha1, char *path)
136{ 136{
137 struct tree *tree; 137 struct tree *tree;
138 138
139 tree = parse_tree_indirect(sha1); 139 tree = parse_tree_indirect(sha1);
140 if (!tree) { 140 if (!tree) {
141 cgit_print_error(fmt("Not a tree object: %s", 141 cgit_print_error(fmt("Not a tree object: %s",
142 sha1_to_hex(sha1))); 142 sha1_to_hex(sha1)));
143 return; 143 return;
144 } 144 }
145 145
146 ls_head(); 146 ls_head();
147 read_tree_recursive(tree, "", 0, 1, NULL, ls_item, NULL); 147 read_tree_recursive(tree, "", 0, 1, NULL, ls_item, NULL);
148 ls_tail(); 148 ls_tail();
149} 149}
150 150
151 151
152static int walk_tree(const unsigned char *sha1, const char *base, int baselen, 152static int walk_tree(const unsigned char *sha1, const char *base, int baselen,
153 const char *pathname, unsigned mode, int stage, 153 const char *pathname, unsigned mode, int stage,
154 void *cbdata) 154 void *cbdata)
155{ 155{
156 static int state; 156 static int state;
157 static char buffer[PATH_MAX]; 157 static char buffer[PATH_MAX];
158 char *url; 158 char *url;
159 159
160 if (state == 0) { 160 if (state == 0) {
161 memcpy(buffer, base, baselen); 161 memcpy(buffer, base, baselen);
162 strcpy(buffer+baselen, pathname); 162 strcpy(buffer+baselen, pathname);
163 url = cgit_pageurl(ctx.qry.repo, "tree", 163 url = cgit_pageurl(ctx.qry.repo, "tree",
164 fmt("h=%s&amp;path=%s", curr_rev, buffer)); 164 fmt("h=%s&amp;path=%s", curr_rev, buffer));
165 html("/"); 165 html("/");
166 cgit_tree_link(xstrdup(pathname), NULL, NULL, ctx.qry.head, 166 cgit_tree_link(xstrdup(pathname), NULL, NULL, ctx.qry.head,
167 curr_rev, buffer); 167 curr_rev, buffer);
168 168
169 if (strcmp(match_path, buffer)) 169 if (strcmp(match_path, buffer))