summaryrefslogtreecommitdiffabout
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--cgit.css27
-rwxr-xr-xtests/t0104-tree.sh4
-rw-r--r--ui-tree.c31
3 files changed, 34 insertions, 28 deletions
diff --git a/cgit.css b/cgit.css
index e8214de..f844efa 100644
--- a/cgit.css
+++ b/cgit.css
@@ -175,148 +175,153 @@ input#switch-btn {
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.no { 239table.blob td.lines {
240 border-right: solid 1px black; 240 margin: 0; padding: 0;
241 vertical-align: top;
241 color: black; 242 color: black;
243}
244
245table.blob td.linenumbers {
246 margin: 0; padding: 0;
247 vertical-align: top;
248 border-right: 1px solid gray;
242 background-color: #eee; 249 background-color: #eee;
243 text-align: right;
244} 250}
245 251
246table.blob td.no a { 252table.blob pre {
247 color: black; 253 padding: 0; margin: 0;
248} 254}
249 255
250table.blob td.no a:hover { 256table.blob a.no {
251 color: black; 257 color: gray;
258 text-align: right;
252 text-decoration: none; 259 text-decoration: none;
253} 260}
254 261
255table.blob td.txt { 262table.blob a.no a:hover {
256 white-space: pre; 263 color: black;
257 font-family: monospace;
258 padding-left: 0.5em;
259} 264}
260 265
261table.nowrap td { 266table.nowrap td {
262 white-space: nowrap; 267 white-space: nowrap;
263} 268}
264 269
265table.commit-info { 270table.commit-info {
266 border-collapse: collapse; 271 border-collapse: collapse;
267 margin-top: 1.5em; 272 margin-top: 1.5em;
268} 273}
269 274
270table.commit-info th { 275table.commit-info th {
271 text-align: left; 276 text-align: left;
272 font-weight: normal; 277 font-weight: normal;
273 padding: 0.1em 1em 0.1em 0.1em; 278 padding: 0.1em 1em 0.1em 0.1em;
274 vertical-align: top; 279 vertical-align: top;
275} 280}
276 281
277table.commit-info td { 282table.commit-info td {
278 font-weight: normal; 283 font-weight: normal;
279 padding: 0.1em 1em 0.1em 0.1em; 284 padding: 0.1em 1em 0.1em 0.1em;
280} 285}
281 286
282div.commit-subject { 287div.commit-subject {
283 font-weight: bold; 288 font-weight: bold;
284 font-size: 125%; 289 font-size: 125%;
285 margin: 1.5em 0em 0.5em 0em; 290 margin: 1.5em 0em 0.5em 0em;
286 padding: 0em; 291 padding: 0em;
287} 292}
288 293
289div.commit-msg { 294div.commit-msg {
290 white-space: pre; 295 white-space: pre;
291 font-family: monospace; 296 font-family: monospace;
292} 297}
293 298
294div.diffstat-header { 299div.diffstat-header {
295 font-weight: bold; 300 font-weight: bold;
296 padding-top: 1.5em; 301 padding-top: 1.5em;
297} 302}
298 303
299table.diffstat { 304table.diffstat {
300 border-collapse: collapse; 305 border-collapse: collapse;
301 border: solid 1px #aaa; 306 border: solid 1px #aaa;
302 background-color: #eee; 307 background-color: #eee;
303} 308}
304 309
305table.diffstat th { 310table.diffstat th {
306 font-weight: normal; 311 font-weight: normal;
307 text-align: left; 312 text-align: left;
308 text-decoration: underline; 313 text-decoration: underline;
309 padding: 0.1em 1em 0.1em 0.1em; 314 padding: 0.1em 1em 0.1em 0.1em;
310 font-size: 100%; 315 font-size: 100%;
311} 316}
312 317
313table.diffstat td { 318table.diffstat td {
314 padding: 0.2em 0.2em 0.1em 0.1em; 319 padding: 0.2em 0.2em 0.1em 0.1em;
315 font-size: 100%; 320 font-size: 100%;
316 border: none; 321 border: none;
317} 322}
318 323
319table.diffstat td.mode { 324table.diffstat td.mode {
320 white-space: nowrap; 325 white-space: nowrap;
321} 326}
322 327
diff --git a/tests/t0104-tree.sh b/tests/t0104-tree.sh
index 33f4eb0..2ce1251 100755
--- a/tests/t0104-tree.sh
+++ b/tests/t0104-tree.sh
@@ -1,33 +1,33 @@
1#!/bin/sh 1#!/bin/sh
2 2
3. ./setup.sh 3. ./setup.sh
4 4
5prepare_tests "Check content on tree page" 5prepare_tests "Check content on tree page"
6 6
7run_test 'generate bar/tree' 'cgit_url "bar/tree" >trash/tmp' 7run_test 'generate bar/tree' 'cgit_url "bar/tree" >trash/tmp'
8run_test 'find file-1' 'grep -e "file-1" trash/tmp' 8run_test 'find file-1' 'grep -e "file-1" trash/tmp'
9run_test 'find file-50' 'grep -e "file-50" trash/tmp' 9run_test 'find file-50' 'grep -e "file-50" trash/tmp'
10 10
11run_test 'generate bar/tree/file-50' 'cgit_url "bar/tree/file-50" >trash/tmp' 11run_test 'generate bar/tree/file-50' 'cgit_url "bar/tree/file-50" >trash/tmp'
12 12
13run_test 'find line 1' ' 13run_test 'find line 1' '
14 grep -e "<a id=.n1. name=.n1. href=.#n1.>1</a>" trash/tmp 14 grep -e "<a class=.no. id=.n1. name=.n1. href=.#n1.>1</a>" trash/tmp
15' 15'
16 16
17run_test 'no line 2' ' 17run_test 'no line 2' '
18 ! grep -e "<a id=.n2. name=.n2. href=.#n2.>2</a>" trash/tmp 18 ! grep -e "<a class=.no. id=.n2. name=.n2. href=.#n2.>2</a>" trash/tmp
19' 19'
20 20
21run_test 'generate foo+bar/tree' 'cgit_url "foo%2bbar/tree" >trash/tmp' 21run_test 'generate foo+bar/tree' 'cgit_url "foo%2bbar/tree" >trash/tmp'
22 22
23run_test 'verify a+b link' ' 23run_test 'verify a+b link' '
24 grep -e "/foo+bar/tree/a+b" trash/tmp 24 grep -e "/foo+bar/tree/a+b" trash/tmp
25' 25'
26 26
27run_test 'generate foo+bar/tree?h=1+2' 'cgit_url "foo%2bbar/tree&h=1%2b2" >trash/tmp' 27run_test 'generate foo+bar/tree?h=1+2' 'cgit_url "foo%2bbar/tree&h=1%2b2" >trash/tmp'
28 28
29run_test 'verify a+b?h=1+2 link' ' 29run_test 'verify a+b?h=1+2 link' '
30 grep -e "/foo+bar/tree/a+b?h=1%2b2" trash/tmp 30 grep -e "/foo+bar/tree/a+b?h=1%2b2" trash/tmp
31' 31'
32 32
33tests_done 33tests_done
diff --git a/ui-tree.c b/ui-tree.c
index 4b8e7a0..c26ba4c 100644
--- a/ui-tree.c
+++ b/ui-tree.c
@@ -1,125 +1,126 @@
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, 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 *numberfmt = "<a class='no' id='n%1$d' name='n%1$d' href='#n%1$d'>%1$d</a>\n";
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(" ("); 38 html(" (");
39 cgit_plain_link("plain", NULL, NULL, ctx.qry.head, 39 cgit_plain_link("plain", NULL, NULL, ctx.qry.head,
40 curr_rev, path); 40 curr_rev, path);
41 htmlf(")<br/>blob: %s", sha1_to_hex(sha1)); 41 htmlf(")<br/>blob: %s\n", 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 html("<tr>\n");
45
46 html("<td class='linenumbers'><pre>");
44 idx = 0; 47 idx = 0;
45 start = 0;
46 lineno = 0; 48 lineno = 0;
47 while(idx < size) { 49 htmlf(numberfmt, ++lineno);
50 while(idx < size - 1) { // skip absolute last newline
48 if (buf[idx] == '\n') { 51 if (buf[idx] == '\n') {
49 buf[idx] = '\0'; 52 htmlf(numberfmt, ++lineno);
50 htmlf(linefmt, ++lineno);
51 html_txt(buf + start);
52 html("</td></tr>\n");
53 start = idx + 1;
54 } 53 }
55 idx++; 54 idx++;
56 } 55 }
57 if (start < idx) { 56 html("</pre></td>\n");
58 htmlf(linefmt, ++lineno); 57
59 html_txt(buf + start); 58 html("<td class='lines'><pre><code>");
60 } 59 html_txt(buf);
61 html("</td></tr>\n"); 60 html("</code></pre></td>\n");
61
62 html("</tr>\n");
62 html("</table>\n"); 63 html("</table>\n");
63} 64}
64 65
65 66
66static int ls_item(const unsigned char *sha1, const char *base, int baselen, 67static int ls_item(const unsigned char *sha1, const char *base, int baselen,
67 const char *pathname, unsigned int mode, int stage, 68 const char *pathname, unsigned int mode, int stage,
68 void *cbdata) 69 void *cbdata)
69{ 70{
70 char *name; 71 char *name;
71 char *fullpath; 72 char *fullpath;
72 enum object_type type; 73 enum object_type type;
73 unsigned long size = 0; 74 unsigned long size = 0;
74 75
75 name = xstrdup(pathname); 76 name = xstrdup(pathname);
76 fullpath = fmt("%s%s%s", ctx.qry.path ? ctx.qry.path : "", 77 fullpath = fmt("%s%s%s", ctx.qry.path ? ctx.qry.path : "",
77 ctx.qry.path ? "/" : "", name); 78 ctx.qry.path ? "/" : "", name);
78 79
79 if (!S_ISGITLINK(mode)) { 80 if (!S_ISGITLINK(mode)) {
80 type = sha1_object_info(sha1, &size); 81 type = sha1_object_info(sha1, &size);
81 if (type == OBJ_BAD) { 82 if (type == OBJ_BAD) {
82 htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>", 83 htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>",
83 name, 84 name,
84 sha1_to_hex(sha1)); 85 sha1_to_hex(sha1));
85 return 0; 86 return 0;
86 } 87 }
87 } 88 }
88 89
89 html("<tr><td class='ls-mode'>"); 90 html("<tr><td class='ls-mode'>");
90 cgit_print_filemode(mode); 91 cgit_print_filemode(mode);
91 html("</td><td>"); 92 html("</td><td>");
92 if (S_ISGITLINK(mode)) { 93 if (S_ISGITLINK(mode)) {
93 htmlf("<a class='ls-mod' href='"); 94 htmlf("<a class='ls-mod' href='");
94 html_attr(fmt(ctx.repo->module_link, 95 html_attr(fmt(ctx.repo->module_link,
95 name, 96 name,
96 sha1_to_hex(sha1))); 97 sha1_to_hex(sha1)));
97 html("'>"); 98 html("'>");
98 html_txt(name); 99 html_txt(name);
99 html("</a>"); 100 html("</a>");
100 } else if (S_ISDIR(mode)) { 101 } else if (S_ISDIR(mode)) {
101 cgit_tree_link(name, NULL, "ls-dir", ctx.qry.head, 102 cgit_tree_link(name, NULL, "ls-dir", ctx.qry.head,
102 curr_rev, fullpath); 103 curr_rev, fullpath);
103 } else { 104 } else {
104 cgit_tree_link(name, NULL, "ls-blob", ctx.qry.head, 105 cgit_tree_link(name, NULL, "ls-blob", ctx.qry.head,
105 curr_rev, fullpath); 106 curr_rev, fullpath);
106 } 107 }
107 htmlf("</td><td class='ls-size'>%li</td>", size); 108 htmlf("</td><td class='ls-size'>%li</td>", size);
108 109
109 html("<td>"); 110 html("<td>");
110 cgit_log_link("log", NULL, "button", ctx.qry.head, curr_rev, 111 cgit_log_link("log", NULL, "button", ctx.qry.head, curr_rev,
111 fullpath, 0, NULL, NULL, ctx.qry.showmsg); 112 fullpath, 0, NULL, NULL, ctx.qry.showmsg);
112 if (ctx.repo->max_stats) 113 if (ctx.repo->max_stats)
113 cgit_stats_link("stats", NULL, "button", ctx.qry.head, 114 cgit_stats_link("stats", NULL, "button", ctx.qry.head,
114 fullpath); 115 fullpath);
115 html("</td></tr>\n"); 116 html("</td></tr>\n");
116 free(name); 117 free(name);
117 return 0; 118 return 0;
118} 119}
119 120
120static void ls_head() 121static void ls_head()
121{ 122{
122 html("<table summary='tree listing' class='list'>\n"); 123 html("<table summary='tree listing' class='list'>\n");
123 html("<tr class='nohover'>"); 124 html("<tr class='nohover'>");
124 html("<th class='left'>Mode</th>"); 125 html("<th class='left'>Mode</th>");
125 html("<th class='left'>Name</th>"); 126 html("<th class='left'>Name</th>");