diff options
-rw-r--r-- | cache.c | 7 | ||||
-rw-r--r-- | cgit.c | 2 | ||||
-rw-r--r-- | cgit.css | 28 | ||||
-rw-r--r-- | filter.c | 22 | ||||
-rw-r--r-- | html.c | 2 | ||||
-rw-r--r-- | robots.txt | 1 | ||||
-rwxr-xr-x | tests/t0105-commit.sh | 6 | ||||
-rwxr-xr-x | tests/t0106-diff.sh | 4 | ||||
-rw-r--r-- | ui-blame.c | 4 | ||||
-rw-r--r-- | ui-commit.c | 7 | ||||
-rw-r--r-- | ui-diff.c | 30 | ||||
-rw-r--r-- | ui-log.c | 4 | ||||
-rw-r--r-- | ui-repolist.c | 4 | ||||
-rw-r--r-- | ui-shared.c | 44 | ||||
-rw-r--r-- | ui-snapshot.c | 3 | ||||
-rw-r--r-- | ui-tag.c | 4 | ||||
-rw-r--r-- | ui-tree.c | 40 |
17 files changed, 148 insertions, 64 deletions
diff --git a/cache.c b/cache.c index 55199e8..578b73b 100644 --- a/cache.c +++ b/cache.c | |||
@@ -265,6 +265,13 @@ static int process_slot(struct cache_slot *slot) | |||
265 | { | 265 | { |
266 | int err; | 266 | int err; |
267 | 267 | ||
268 | /* | ||
269 | * Make sure any buffered data is flushed before we redirect, | ||
270 | * do sendfile(2) or write(2) | ||
271 | */ | ||
272 | if (fflush(stdout)) | ||
273 | return errno; | ||
274 | |||
268 | err = open_slot(slot); | 275 | err = open_slot(slot); |
269 | if (!err && slot->match) { | 276 | if (!err && slot->match) { |
270 | if (is_expired(slot)) { | 277 | if (is_expired(slot)) { |
diff --git a/cgit.c b/cgit.c index 08d81a1..40825cb 100644 --- a/cgit.c +++ b/cgit.c | |||
@@ -674,7 +674,7 @@ static inline void authenticate_post(void) | |||
674 | len = MAX_AUTHENTICATION_POST_BYTES; | 674 | len = MAX_AUTHENTICATION_POST_BYTES; |
675 | if ((len = read(STDIN_FILENO, buffer, len)) < 0) | 675 | if ((len = read(STDIN_FILENO, buffer, len)) < 0) |
676 | die_errno("Could not read POST from stdin"); | 676 | die_errno("Could not read POST from stdin"); |
677 | if (write(STDOUT_FILENO, buffer, len) < 0) | 677 | if (fwrite(buffer, 1, len, stdout) < len) |
678 | die_errno("Could not write POST to stdout"); | 678 | die_errno("Could not write POST to stdout"); |
679 | cgit_close_filter(ctx.cfg.auth_filter); | 679 | cgit_close_filter(ctx.cfg.auth_filter); |
680 | exit(0); | 680 | exit(0); |
diff --git a/cgit.css b/cgit.css index dfa144d..f3dbb7a 100644 --- a/cgit.css +++ b/cgit.css | |||
@@ -75,7 +75,7 @@ div#cgit table.tabs td { | |||
75 | } | 75 | } |
76 | 76 | ||
77 | div#cgit table.tabs td a { | 77 | div#cgit table.tabs td a { |
78 | padding: 2px 0.75em; | 78 | padding: 2px 0.25em; |
79 | color: #777; | 79 | color: #777; |
80 | font-size: 110%; | 80 | font-size: 110%; |
81 | } | 81 | } |
@@ -437,11 +437,6 @@ div#cgit div.commit-subject { | |||
437 | padding: 0em; | 437 | padding: 0em; |
438 | } | 438 | } |
439 | 439 | ||
440 | div#cgit div.commit-msg { | ||
441 | white-space: pre; | ||
442 | font-family: monospace; | ||
443 | } | ||
444 | |||
445 | div#cgit div.notes-header { | 440 | div#cgit div.notes-header { |
446 | font-weight: bold; | 441 | font-weight: bold; |
447 | padding-top: 1.5em; | 442 | padding-top: 1.5em; |
@@ -538,26 +533,20 @@ div#cgit table.diff { | |||
538 | width: 100%; | 533 | width: 100%; |
539 | } | 534 | } |
540 | 535 | ||
541 | div#cgit table.diff td { | 536 | div#cgit table.diff td span.head { |
542 | font-family: monospace; | ||
543 | white-space: pre; | ||
544 | } | ||
545 | |||
546 | div#cgit table.diff td div.head { | ||
547 | font-weight: bold; | 537 | font-weight: bold; |
548 | margin-top: 1em; | ||
549 | color: black; | 538 | color: black; |
550 | } | 539 | } |
551 | 540 | ||
552 | div#cgit table.diff td div.hunk { | 541 | div#cgit table.diff td span.hunk { |
553 | color: #009; | 542 | color: #009; |
554 | } | 543 | } |
555 | 544 | ||
556 | div#cgit table.diff td div.add { | 545 | div#cgit table.diff td span.add { |
557 | color: green; | 546 | color: green; |
558 | } | 547 | } |
559 | 548 | ||
560 | div#cgit table.diff td div.del { | 549 | div#cgit table.diff td span.del { |
561 | color: red; | 550 | color: red; |
562 | } | 551 | } |
563 | 552 | ||
@@ -581,7 +570,6 @@ div#cgit table.list td.reposection { | |||
581 | 570 | ||
582 | div#cgit a.button { | 571 | div#cgit a.button { |
583 | font-size: 80%; | 572 | font-size: 80%; |
584 | padding: 0em 0.5em; | ||
585 | } | 573 | } |
586 | 574 | ||
587 | div#cgit a.primary { | 575 | div#cgit a.primary { |
@@ -671,7 +659,6 @@ div#cgit div.footer a:hover { | |||
671 | 659 | ||
672 | div#cgit a.branch-deco { | 660 | div#cgit a.branch-deco { |
673 | color: #000; | 661 | color: #000; |
674 | margin: 0px 0.5em; | ||
675 | padding: 0px 0.25em; | 662 | padding: 0px 0.25em; |
676 | background-color: #88ff88; | 663 | background-color: #88ff88; |
677 | border: solid 1px #007700; | 664 | border: solid 1px #007700; |
@@ -679,7 +666,6 @@ div#cgit a.branch-deco { | |||
679 | 666 | ||
680 | div#cgit a.tag-deco { | 667 | div#cgit a.tag-deco { |
681 | color: #000; | 668 | color: #000; |
682 | margin: 0px 0.5em; | ||
683 | padding: 0px 0.25em; | 669 | padding: 0px 0.25em; |
684 | background-color: #ffff88; | 670 | background-color: #ffff88; |
685 | border: solid 1px #777700; | 671 | border: solid 1px #777700; |
@@ -687,7 +673,6 @@ div#cgit a.tag-deco { | |||
687 | 673 | ||
688 | div#cgit a.tag-annotated-deco { | 674 | div#cgit a.tag-annotated-deco { |
689 | color: #000; | 675 | color: #000; |
690 | margin: 0px 0.5em; | ||
691 | padding: 0px 0.25em; | 676 | padding: 0px 0.25em; |
692 | background-color: #ffcc88; | 677 | background-color: #ffcc88; |
693 | border: solid 1px #777700; | 678 | border: solid 1px #777700; |
@@ -695,7 +680,6 @@ div#cgit a.tag-annotated-deco { | |||
695 | 680 | ||
696 | div#cgit a.remote-deco { | 681 | div#cgit a.remote-deco { |
697 | color: #000; | 682 | color: #000; |
698 | margin: 0px 0.5em; | ||
699 | padding: 0px 0.25em; | 683 | padding: 0px 0.25em; |
700 | background-color: #ccccff; | 684 | background-color: #ccccff; |
701 | border: solid 1px #000077; | 685 | border: solid 1px #000077; |
@@ -703,7 +687,6 @@ div#cgit a.remote-deco { | |||
703 | 687 | ||
704 | div#cgit a.deco { | 688 | div#cgit a.deco { |
705 | color: #000; | 689 | color: #000; |
706 | margin: 0px 0.5em; | ||
707 | padding: 0px 0.25em; | 690 | padding: 0px 0.25em; |
708 | background-color: #ff8888; | 691 | background-color: #ff8888; |
709 | border: solid 1px #770000; | 692 | border: solid 1px #770000; |
@@ -714,7 +697,6 @@ div#cgit div.commit-subject a.tag-deco, | |||
714 | div#cgit div.commit-subject a.tag-annotated-deco, | 697 | div#cgit div.commit-subject a.tag-annotated-deco, |
715 | div#cgit div.commit-subject a.remote-deco, | 698 | div#cgit div.commit-subject a.remote-deco, |
716 | div#cgit div.commit-subject a.deco { | 699 | div#cgit div.commit-subject a.deco { |
717 | margin-left: 1em; | ||
718 | font-size: 75%; | 700 | font-size: 75%; |
719 | } | 701 | } |
720 | 702 | ||
diff --git a/filter.c b/filter.c index 70f5b74..fba26aa 100644 --- a/filter.c +++ b/filter.c | |||
@@ -48,6 +48,7 @@ static int open_exec_filter(struct cgit_filter *base, va_list ap) | |||
48 | for (i = 0; i < filter->base.argument_count; i++) | 48 | for (i = 0; i < filter->base.argument_count; i++) |
49 | filter->argv[i + 1] = va_arg(ap, char *); | 49 | filter->argv[i + 1] = va_arg(ap, char *); |
50 | 50 | ||
51 | chk_zero(fflush(stdout), "unable to flush STDOUT"); | ||
51 | filter->old_stdout = chk_positive(dup(STDOUT_FILENO), | 52 | filter->old_stdout = chk_positive(dup(STDOUT_FILENO), |
52 | "Unable to duplicate STDOUT"); | 53 | "Unable to duplicate STDOUT"); |
53 | chk_zero(pipe(pipe_fh), "Unable to create pipe to subprocess"); | 54 | chk_zero(pipe(pipe_fh), "Unable to create pipe to subprocess"); |
@@ -71,6 +72,7 @@ static int close_exec_filter(struct cgit_filter *base) | |||
71 | struct cgit_exec_filter *filter = (struct cgit_exec_filter *)base; | 72 | struct cgit_exec_filter *filter = (struct cgit_exec_filter *)base; |
72 | int i, exit_status = 0; | 73 | int i, exit_status = 0; |
73 | 74 | ||
75 | chk_zero(fflush(stdout), "unable to flush STDOUT"); | ||
74 | chk_non_negative(dup2(filter->old_stdout, STDOUT_FILENO), | 76 | chk_non_negative(dup2(filter->old_stdout, STDOUT_FILENO), |
75 | "Unable to restore STDOUT"); | 77 | "Unable to restore STDOUT"); |
76 | close(filter->old_stdout); | 78 | close(filter->old_stdout); |
@@ -143,17 +145,32 @@ void cgit_init_filters(void) | |||
143 | #endif | 145 | #endif |
144 | 146 | ||
145 | #ifndef NO_LUA | 147 | #ifndef NO_LUA |
146 | static ssize_t (*libc_write)(int fd, const void *buf, size_t count); | 148 | static size_t (*libc_fwrite)(const void *buf, size_t size, size_t n, FILE *); |
149 | static ssize_t (*libc_write)(int fd, const void *buf, size_t size); | ||
147 | static ssize_t (*filter_write)(struct cgit_filter *base, const void *buf, size_t count) = NULL; | 150 | static ssize_t (*filter_write)(struct cgit_filter *base, const void *buf, size_t count) = NULL; |
148 | static struct cgit_filter *current_write_filter = NULL; | 151 | static struct cgit_filter *current_write_filter = NULL; |
149 | 152 | ||
150 | void cgit_init_filters(void) | 153 | void cgit_init_filters(void) |
151 | { | 154 | { |
155 | /* | ||
156 | * we need to wrap both functions since the Lua filter may | ||
157 | * have code which calls write(2) directly, bypassing fwrite(3) | ||
158 | */ | ||
159 | libc_fwrite = dlsym(RTLD_NEXT, "fwrite"); | ||
160 | if (!libc_fwrite) | ||
161 | die("Could not locate libc's write function"); | ||
152 | libc_write = dlsym(RTLD_NEXT, "write"); | 162 | libc_write = dlsym(RTLD_NEXT, "write"); |
153 | if (!libc_write) | 163 | if (!libc_write) |
154 | die("Could not locate libc's write function"); | 164 | die("Could not locate libc's write function"); |
155 | } | 165 | } |
156 | 166 | ||
167 | size_t fwrite(const void *buf, size_t size, size_t n, FILE *f) | ||
168 | { | ||
169 | if (f != stdout || !filter_write) | ||
170 | return libc_fwrite(buf, size, n, f); | ||
171 | return filter_write(current_write_filter, buf, size * n); | ||
172 | } | ||
173 | |||
157 | ssize_t write(int fd, const void *buf, size_t count) | 174 | ssize_t write(int fd, const void *buf, size_t count) |
158 | { | 175 | { |
159 | if (fd != STDOUT_FILENO || !filter_write) | 176 | if (fd != STDOUT_FILENO || !filter_write) |
@@ -305,6 +322,9 @@ static int open_lua_filter(struct cgit_filter *base, va_list ap) | |||
305 | struct lua_filter *filter = (struct lua_filter *)base; | 322 | struct lua_filter *filter = (struct lua_filter *)base; |
306 | int i; | 323 | int i; |
307 | 324 | ||
325 | if (fflush(stdout)) | ||
326 | return 1; | ||
327 | |||
308 | if (init_lua_filter(filter)) | 328 | if (init_lua_filter(filter)) |
309 | return 1; | 329 | return 1; |
310 | 330 | ||
diff --git a/html.c b/html.c index 7f81965..cefcf5e 100644 --- a/html.c +++ b/html.c | |||
@@ -80,7 +80,7 @@ char *fmtalloc(const char *format, ...) | |||
80 | 80 | ||
81 | void html_raw(const char *data, size_t size) | 81 | void html_raw(const char *data, size_t size) |
82 | { | 82 | { |
83 | if (write(STDOUT_FILENO, data, size) != size) | 83 | if (fwrite(data, 1, size, stdout) != size) |
84 | die_errno("write error on html output"); | 84 | die_errno("write error on html output"); |
85 | } | 85 | } |
86 | 86 | ||
diff --git a/robots.txt b/robots.txt index 4ce948f..1b33266 100644 --- a/robots.txt +++ b/robots.txt | |||
@@ -1,3 +1,4 @@ | |||
1 | User-agent: * | 1 | User-agent: * |
2 | Disallow: /*/snapshot/* | 2 | Disallow: /*/snapshot/* |
3 | Disallow: /*/blame/* | ||
3 | Allow: / | 4 | Allow: / |
diff --git a/tests/t0105-commit.sh b/tests/t0105-commit.sh index 1a12ee3..cfed1e7 100755 --- a/tests/t0105-commit.sh +++ b/tests/t0105-commit.sh | |||
@@ -11,7 +11,7 @@ test_expect_success 'find commit subject' ' | |||
11 | grep "<div class=.commit-subject.>commit 5<" tmp | 11 | grep "<div class=.commit-subject.>commit 5<" tmp |
12 | ' | 12 | ' |
13 | 13 | ||
14 | test_expect_success 'find commit msg' 'grep "<div class=.commit-msg.></div>" tmp' | 14 | test_expect_success 'find commit msg' 'grep "<pre class=.commit-msg.></pre>" tmp' |
15 | test_expect_success 'find diffstat' 'grep "<table summary=.diffstat. class=.diffstat.>" tmp' | 15 | test_expect_success 'find diffstat' 'grep "<table summary=.diffstat. class=.diffstat.>" tmp' |
16 | 16 | ||
17 | test_expect_success 'find diff summary' ' | 17 | test_expect_success 'find diff summary' ' |
@@ -29,8 +29,8 @@ test_expect_success 'root commit contains diffstat' ' | |||
29 | ' | 29 | ' |
30 | 30 | ||
31 | test_expect_success 'root commit contains diff' ' | 31 | test_expect_success 'root commit contains diff' ' |
32 | grep ">diff --git a/file-1 b/file-1<" tmp && | 32 | grep ">diff --git a/file-1 b/file-1" tmp && |
33 | grep "<div class=.add.>+1</div>" tmp | 33 | grep "<span class=.add.>+1</span>" tmp |
34 | ' | 34 | ' |
35 | 35 | ||
36 | test_done | 36 | test_done |
diff --git a/tests/t0106-diff.sh b/tests/t0106-diff.sh index 82b645e..62a0a74 100755 --- a/tests/t0106-diff.sh +++ b/tests/t0106-diff.sh | |||
@@ -9,11 +9,11 @@ test_expect_success 'find blob link' 'grep "<a href=./foo/tree/file-5?id=" tmp' | |||
9 | test_expect_success 'find added file' 'grep "new file mode 100644" tmp' | 9 | test_expect_success 'find added file' 'grep "new file mode 100644" tmp' |
10 | 10 | ||
11 | test_expect_success 'find hunk header' ' | 11 | test_expect_success 'find hunk header' ' |
12 | grep "<div class=.hunk.>@@ -0,0 +1 @@</div>" tmp | 12 | grep "<span class=.hunk.>@@ -0,0 +1 @@</span>" tmp |
13 | ' | 13 | ' |
14 | 14 | ||
15 | test_expect_success 'find added line' ' | 15 | test_expect_success 'find added line' ' |
16 | grep "<div class=.add.>+5</div>" tmp | 16 | grep "<span class=.add.>+5</span>" tmp |
17 | ' | 17 | ' |
18 | 18 | ||
19 | test_done | 19 | test_done |
diff --git a/ui-blame.c b/ui-blame.c index 03136f7..4adec2b 100644 --- a/ui-blame.c +++ b/ui-blame.c | |||
@@ -152,6 +152,10 @@ static void print_object(const struct object_id *oid, const char *path, | |||
152 | cgit_tree_link("tree", NULL, NULL, ctx.qry.head, rev, path); | 152 | cgit_tree_link("tree", NULL, NULL, ctx.qry.head, rev, path); |
153 | html(")\n"); | 153 | html(")\n"); |
154 | 154 | ||
155 | if (buffer_is_binary(buf, size)) { | ||
156 | html("<div class='error'>blob is binary.</div>"); | ||
157 | goto cleanup; | ||
158 | } | ||
155 | if (ctx.cfg.max_blob_size && size / 1024 > ctx.cfg.max_blob_size) { | 159 | if (ctx.cfg.max_blob_size && size / 1024 > ctx.cfg.max_blob_size) { |
156 | htmlf("<div class='error'>blob size (%ldKB)" | 160 | htmlf("<div class='error'>blob size (%ldKB)" |
157 | " exceeds display size limit (%dKB).</div>", | 161 | " exceeds display size limit (%dKB).</div>", |
diff --git a/ui-commit.c b/ui-commit.c index 948118c..b49259e 100644 --- a/ui-commit.c +++ b/ui-commit.c | |||
@@ -39,10 +39,11 @@ void cgit_print_commit(char *hex, const char *prefix) | |||
39 | } | 39 | } |
40 | info = cgit_parse_commit(commit); | 40 | info = cgit_parse_commit(commit); |
41 | 41 | ||
42 | format_display_notes(&oid, ¬es, PAGE_ENCODING, 0); | 42 | format_display_notes(&oid, ¬es, PAGE_ENCODING, 1); |
43 | 43 | ||
44 | load_ref_decorations(NULL, DECORATE_FULL_REFS); | 44 | load_ref_decorations(NULL, DECORATE_FULL_REFS); |
45 | 45 | ||
46 | ctx.page.title = fmtalloc("%s - %s", info->subject, ctx.page.title); | ||
46 | cgit_print_layout_start(); | 47 | cgit_print_layout_start(); |
47 | cgit_print_diff_ctrls(); | 48 | cgit_print_diff_ctrls(); |
48 | html("<table summary='commit info' class='commit-info'>\n"); | 49 | html("<table summary='commit info' class='commit-info'>\n"); |
@@ -120,11 +121,11 @@ void cgit_print_commit(char *hex, const char *prefix) | |||
120 | cgit_close_filter(ctx.repo->commit_filter); | 121 | cgit_close_filter(ctx.repo->commit_filter); |
121 | show_commit_decorations(commit); | 122 | show_commit_decorations(commit); |
122 | html("</div>"); | 123 | html("</div>"); |
123 | html("<div class='commit-msg'>"); | 124 | html("<pre class='commit-msg'>"); |
124 | cgit_open_filter(ctx.repo->commit_filter); | 125 | cgit_open_filter(ctx.repo->commit_filter); |
125 | html_txt(info->msg); | 126 | html_txt(info->msg); |
126 | cgit_close_filter(ctx.repo->commit_filter); | 127 | cgit_close_filter(ctx.repo->commit_filter); |
127 | html("</div>"); | 128 | html("</pre>"); |
128 | if (notes.len != 0) { | 129 | if (notes.len != 0) { |
129 | html("<div class='notes-header'>Notes</div>"); | 130 | html("<div class='notes-header'>Notes</div>"); |
130 | html("<div class='notes'>"); | 131 | html("<div class='notes'>"); |
diff --git a/ui-diff.c b/ui-diff.c index 5ed5990..2a64ae8 100644 --- a/ui-diff.c +++ b/ui-diff.c | |||
@@ -231,11 +231,11 @@ static void print_line(char *line, int len) | |||
231 | else if (line[0] == '@') | 231 | else if (line[0] == '@') |
232 | class = "hunk"; | 232 | class = "hunk"; |
233 | 233 | ||
234 | htmlf("<div class='%s'>", class); | 234 | htmlf("<span class='%s'>", class); |
235 | line[len-1] = '\0'; | 235 | line[len-1] = '\0'; |
236 | html_txt(line); | 236 | html_txt(line); |
237 | html("</div>"); | ||
238 | line[len-1] = c; | 237 | line[len-1] = c; |
238 | html("</span>\n"); | ||
239 | } | 239 | } |
240 | 240 | ||
241 | static void header(const struct object_id *oid1, char *path1, int mode1, | 241 | static void header(const struct object_id *oid1, char *path1, int mode1, |
@@ -245,22 +245,23 @@ static void header(const struct object_id *oid1, char *path1, int mode1, | |||
245 | int subproject; | 245 | int subproject; |
246 | 246 | ||
247 | subproject = (S_ISGITLINK(mode1) || S_ISGITLINK(mode2)); | 247 | subproject = (S_ISGITLINK(mode1) || S_ISGITLINK(mode2)); |
248 | html("<div class='head'>"); | 248 | html("<span class='head'>"); |
249 | html("diff --git a/"); | 249 | html("diff --git a/"); |
250 | html_txt(path1); | 250 | html_txt(path1); |
251 | html(" b/"); | 251 | html(" b/"); |
252 | html_txt(path2); | 252 | html_txt(path2); |
253 | html("\n"); | ||
253 | 254 | ||
254 | if (mode1 == 0) | 255 | if (mode1 == 0) |
255 | htmlf("<br/>new file mode %.6o", mode2); | 256 | htmlf("new file mode %.6o\n", mode2); |
256 | 257 | ||
257 | if (mode2 == 0) | 258 | if (mode2 == 0) |
258 | htmlf("<br/>deleted file mode %.6o", mode1); | 259 | htmlf("deleted file mode %.6o\n", mode1); |
259 | 260 | ||
260 | if (!subproject) { | 261 | if (!subproject) { |
261 | abbrev1 = xstrdup(find_unique_abbrev(oid1, DEFAULT_ABBREV)); | 262 | abbrev1 = xstrdup(find_unique_abbrev(oid1, DEFAULT_ABBREV)); |
262 | abbrev2 = xstrdup(find_unique_abbrev(oid2, DEFAULT_ABBREV)); | 263 | abbrev2 = xstrdup(find_unique_abbrev(oid2, DEFAULT_ABBREV)); |
263 | htmlf("<br/>index %s..%s", abbrev1, abbrev2); | 264 | htmlf("index %s..%s", abbrev1, abbrev2); |
264 | free(abbrev1); | 265 | free(abbrev1); |
265 | free(abbrev2); | 266 | free(abbrev2); |
266 | if (mode1 != 0 && mode2 != 0) { | 267 | if (mode1 != 0 && mode2 != 0) { |
@@ -268,28 +269,31 @@ static void header(const struct object_id *oid1, char *path1, int mode1, | |||
268 | if (mode2 != mode1) | 269 | if (mode2 != mode1) |
269 | htmlf("..%.6o", mode2); | 270 | htmlf("..%.6o", mode2); |
270 | } | 271 | } |
272 | html("\n"); | ||
271 | if (is_null_oid(oid1)) { | 273 | if (is_null_oid(oid1)) { |
272 | path1 = "dev/null"; | 274 | path1 = "dev/null"; |
273 | html("<br/>--- /"); | 275 | html("--- /"); |
274 | } else | 276 | } else |
275 | html("<br/>--- a/"); | 277 | html("--- a/"); |
276 | if (mode1 != 0) | 278 | if (mode1 != 0) |
277 | cgit_tree_link(path1, NULL, NULL, ctx.qry.head, | 279 | cgit_tree_link(path1, NULL, NULL, ctx.qry.head, |
278 | oid_to_hex(old_rev_oid), path1); | 280 | oid_to_hex(old_rev_oid), path1); |
279 | else | 281 | else |
280 | html_txt(path1); | 282 | html_txt(path1); |
283 | html("\n"); | ||
281 | if (is_null_oid(oid2)) { | 284 | if (is_null_oid(oid2)) { |
282 | path2 = "dev/null"; | 285 | path2 = "dev/null"; |
283 | html("<br/>+++ /"); | 286 | html("+++ /"); |
284 | } else | 287 | } else |
285 | html("<br/>+++ b/"); | 288 | html("+++ b/"); |
286 | if (mode2 != 0) | 289 | if (mode2 != 0) |
287 | cgit_tree_link(path2, NULL, NULL, ctx.qry.head, | 290 | cgit_tree_link(path2, NULL, NULL, ctx.qry.head, |
288 | oid_to_hex(new_rev_oid), path2); | 291 | oid_to_hex(new_rev_oid), path2); |
289 | else | 292 | else |
290 | html_txt(path2); | 293 | html_txt(path2); |
294 | html("\n"); | ||
291 | } | 295 | } |
292 | html("</div>"); | 296 | html("</span>"); |
293 | } | 297 | } |
294 | 298 | ||
295 | static void filepair_cb(struct diff_filepair *pair) | 299 | static void filepair_cb(struct diff_filepair *pair) |
@@ -488,12 +492,12 @@ void cgit_print_diff(const char *new_rev, const char *old_rev, | |||
488 | html("<table summary='ssdiff' class='ssdiff'>"); | 492 | html("<table summary='ssdiff' class='ssdiff'>"); |
489 | } else { | 493 | } else { |
490 | html("<table summary='diff' class='diff'>"); | 494 | html("<table summary='diff' class='diff'>"); |
491 | html("<tr><td>"); | 495 | html("<tr><td><pre>"); |
492 | } | 496 | } |
493 | cgit_diff_tree(old_rev_oid, new_rev_oid, filepair_cb, prefix, | 497 | cgit_diff_tree(old_rev_oid, new_rev_oid, filepair_cb, prefix, |
494 | ctx.qry.ignorews); | 498 | ctx.qry.ignorews); |
495 | if (!use_ssdiff) | 499 | if (!use_ssdiff) |
496 | html("</td></tr>"); | 500 | html("</pre></td></tr>"); |
497 | html("</table>"); | 501 | html("</table>"); |
498 | 502 | ||
499 | if (show_ctrls) | 503 | if (show_ctrls) |
diff --git a/ui-log.c b/ui-log.c index 20774bf..b443ca7 100644 --- a/ui-log.c +++ b/ui-log.c | |||
@@ -75,11 +75,13 @@ void show_commit_decorations(struct commit *commit) | |||
75 | * don't display anything. */ | 75 | * don't display anything. */ |
76 | break; | 76 | break; |
77 | case DECORATION_REF_LOCAL: | 77 | case DECORATION_REF_LOCAL: |
78 | html(" "); | ||
78 | cgit_log_link(buf, NULL, "branch-deco", buf, NULL, | 79 | cgit_log_link(buf, NULL, "branch-deco", buf, NULL, |
79 | ctx.qry.vpath, 0, NULL, NULL, | 80 | ctx.qry.vpath, 0, NULL, NULL, |
80 | ctx.qry.showmsg, 0); | 81 | ctx.qry.showmsg, 0); |
81 | break; | 82 | break; |
82 | case DECORATION_REF_TAG: | 83 | case DECORATION_REF_TAG: |
84 | html(" "); | ||
83 | if (!read_ref(deco->name, &oid_tag) && !peel_iterated_oid(&oid_tag, &peeled)) | 85 | if (!read_ref(deco->name, &oid_tag) && !peel_iterated_oid(&oid_tag, &peeled)) |
84 | is_annotated = !oideq(&oid_tag, &peeled); | 86 | is_annotated = !oideq(&oid_tag, &peeled); |
85 | cgit_tag_link(buf, NULL, is_annotated ? "tag-annotated-deco" : "tag-deco", buf); | 87 | cgit_tag_link(buf, NULL, is_annotated ? "tag-annotated-deco" : "tag-deco", buf); |
@@ -87,12 +89,14 @@ void show_commit_decorations(struct commit *commit) | |||
87 | case DECORATION_REF_REMOTE: | 89 | case DECORATION_REF_REMOTE: |
88 | if (!ctx.repo->enable_remote_branches) | 90 | if (!ctx.repo->enable_remote_branches) |
89 | break; | 91 | break; |
92 | html(" "); | ||
90 | cgit_log_link(buf, NULL, "remote-deco", NULL, | 93 | cgit_log_link(buf, NULL, "remote-deco", NULL, |
91 | oid_to_hex(&commit->object.oid), | 94 | oid_to_hex(&commit->object.oid), |
92 | ctx.qry.vpath, 0, NULL, NULL, | 95 | ctx.qry.vpath, 0, NULL, NULL, |
93 | ctx.qry.showmsg, 0); | 96 | ctx.qry.showmsg, 0); |
94 | break; | 97 | break; |
95 | default: | 98 | default: |
99 | html(" "); | ||
96 | cgit_commit_link(buf, NULL, "deco", ctx.qry.head, | 100 | cgit_commit_link(buf, NULL, "deco", ctx.qry.head, |
97 | oid_to_hex(&commit->object.oid), | 101 | oid_to_hex(&commit->object.oid), |
98 | ctx.qry.vpath); | 102 | ctx.qry.vpath); |
diff --git a/ui-repolist.c b/ui-repolist.c index 529a203..97b11c5 100644 --- a/ui-repolist.c +++ b/ui-repolist.c | |||
@@ -321,7 +321,7 @@ void cgit_print_repolist(void) | |||
321 | } | 321 | } |
322 | htmlf("<tr><td class='%s'>", | 322 | htmlf("<tr><td class='%s'>", |
323 | !sorted && section ? "sublevel-repo" : "toplevel-repo"); | 323 | !sorted && section ? "sublevel-repo" : "toplevel-repo"); |
324 | cgit_summary_link(ctx.repo->name, ctx.repo->name, NULL, NULL); | 324 | cgit_summary_link(ctx.repo->name, NULL, NULL, NULL); |
325 | html("</td><td>"); | 325 | html("</td><td>"); |
326 | repourl = cgit_repourl(ctx.repo->url); | 326 | repourl = cgit_repourl(ctx.repo->url); |
327 | html_link_open(repourl, NULL, NULL); | 327 | html_link_open(repourl, NULL, NULL); |
@@ -353,8 +353,10 @@ void cgit_print_repolist(void) | |||
353 | if (ctx.cfg.enable_index_links) { | 353 | if (ctx.cfg.enable_index_links) { |
354 | html("<td>"); | 354 | html("<td>"); |
355 | cgit_summary_link("summary", NULL, "button", NULL); | 355 | cgit_summary_link("summary", NULL, "button", NULL); |
356 | html(" "); | ||
356 | cgit_log_link("log", NULL, "button", NULL, NULL, NULL, | 357 | cgit_log_link("log", NULL, "button", NULL, NULL, NULL, |
357 | 0, NULL, NULL, ctx.qry.showmsg, 0); | 358 | 0, NULL, NULL, ctx.qry.showmsg, 0); |
359 | html(" "); | ||
358 | cgit_tree_link("tree", NULL, "button", NULL, NULL, NULL); | 360 | cgit_tree_link("tree", NULL, "button", NULL, NULL, NULL); |
359 | html("</td>"); | 361 | html("</td>"); |
360 | } | 362 | } |
diff --git a/ui-shared.c b/ui-shared.c index acd8ab5..225a363 100644 --- a/ui-shared.c +++ b/ui-shared.c | |||
@@ -894,6 +894,15 @@ void cgit_add_clone_urls(void (*fn)(const char *)) | |||
894 | add_clone_urls(fn, ctx.cfg.clone_prefix, ctx.repo->url); | 894 | add_clone_urls(fn, ctx.cfg.clone_prefix, ctx.repo->url); |
895 | } | 895 | } |
896 | 896 | ||
897 | static int print_this_commit_option(void) | ||
898 | { | ||
899 | struct object_id oid; | ||
900 | if (!ctx.qry.head || get_oid(ctx.qry.head, &oid)) | ||
901 | return 1; | ||
902 | html_option(oid_to_hex(&oid), "this commit", ctx.qry.head); | ||
903 | return 0; | ||
904 | } | ||
905 | |||
897 | static int print_branch_option(const char *refname, const struct object_id *oid, | 906 | static int print_branch_option(const char *refname, const struct object_id *oid, |
898 | int flags, void *cb_data) | 907 | int flags, void *cb_data) |
899 | { | 908 | { |
@@ -995,15 +1004,18 @@ static void print_header(void) | |||
995 | if (ctx.repo) { | 1004 | if (ctx.repo) { |
996 | cgit_index_link("index", NULL, NULL, NULL, NULL, 0, 1); | 1005 | cgit_index_link("index", NULL, NULL, NULL, NULL, 0, 1); |
997 | html(" : "); | 1006 | html(" : "); |
998 | cgit_summary_link(ctx.repo->name, ctx.repo->name, NULL, NULL); | 1007 | cgit_summary_link(ctx.repo->name, NULL, NULL, NULL); |
999 | if (ctx.env.authenticated) { | 1008 | if (ctx.env.authenticated) { |
1000 | html("</td><td class='form'>"); | 1009 | html("</td><td class='form'>"); |
1001 | html("<form method='get'>\n"); | 1010 | html("<form method='get'>\n"); |
1002 | cgit_add_hidden_formfields(0, 1, ctx.qry.page); | 1011 | cgit_add_hidden_formfields(0, 1, ctx.qry.page); |
1003 | html("<select name='h' onchange='this.form.submit();'>\n"); | 1012 | html("<select name='h' onchange='this.form.submit();'>\n"); |
1013 | print_this_commit_option(); | ||
1014 | html("<optgroup label='branches'>"); | ||
1004 | for_each_branch_ref(print_branch_option, ctx.qry.head); | 1015 | for_each_branch_ref(print_branch_option, ctx.qry.head); |
1005 | if (ctx.repo->enable_remote_branches) | 1016 | if (ctx.repo->enable_remote_branches) |
1006 | for_each_remote_ref(print_branch_option, ctx.qry.head); | 1017 | for_each_remote_ref(print_branch_option, ctx.qry.head); |
1018 | html("</optgroup>"); | ||
1007 | html("</select> "); | 1019 | html("</select> "); |
1008 | html("<input type='submit' value='switch'/>"); | 1020 | html("<input type='submit' value='switch'/>"); |
1009 | html("</form>"); | 1021 | html("</form>"); |
@@ -1016,7 +1028,13 @@ static void print_header(void) | |||
1016 | if (ctx.repo) { | 1028 | if (ctx.repo) { |
1017 | html_txt(ctx.repo->desc); | 1029 | html_txt(ctx.repo->desc); |
1018 | html("</td><td class='sub right'>"); | 1030 | html("</td><td class='sub right'>"); |
1019 | html_txt(ctx.repo->owner); | 1031 | if (ctx.repo->owner_filter) { |
1032 | cgit_open_filter(ctx.repo->owner_filter); | ||
1033 | html_txt(ctx.repo->owner); | ||
1034 | cgit_close_filter(ctx.repo->owner_filter); | ||
1035 | } else { | ||
1036 | html_txt(ctx.repo->owner); | ||
1037 | } | ||
1020 | } else { | 1038 | } else { |
1021 | if (ctx.cfg.root_desc) | 1039 | if (ctx.cfg.root_desc) |
1022 | html_txt(ctx.cfg.root_desc); | 1040 | html_txt(ctx.cfg.root_desc); |
@@ -1032,32 +1050,41 @@ void cgit_print_pageheader(void) | |||
1032 | 1050 | ||
1033 | html("<table class='tabs'><tr><td>\n"); | 1051 | html("<table class='tabs'><tr><td>\n"); |
1034 | if (ctx.env.authenticated && ctx.repo) { | 1052 | if (ctx.env.authenticated && ctx.repo) { |
1035 | if (ctx.repo->readme.nr) | 1053 | if (ctx.repo->readme.nr) { |
1036 | reporevlink("about", "about", NULL, | 1054 | reporevlink("about", "about", NULL, |
1037 | hc("about"), ctx.qry.head, NULL, | 1055 | hc("about"), ctx.qry.head, NULL, |
1038 | NULL); | 1056 | NULL); |
1057 | html(" "); | ||
1058 | } | ||
1039 | cgit_summary_link("summary", NULL, hc("summary"), | 1059 | cgit_summary_link("summary", NULL, hc("summary"), |
1040 | ctx.qry.head); | 1060 | ctx.qry.head); |
1061 | html(" "); | ||
1041 | cgit_refs_link("refs", NULL, hc("refs"), ctx.qry.head, | 1062 | cgit_refs_link("refs", NULL, hc("refs"), ctx.qry.head, |
1042 | ctx.qry.oid, NULL); | 1063 | ctx.qry.oid, NULL); |
1064 | html(" "); | ||
1043 | cgit_log_link("log", NULL, hc("log"), ctx.qry.head, | 1065 | cgit_log_link("log", NULL, hc("log"), ctx.qry.head, |
1044 | NULL, ctx.qry.vpath, 0, NULL, NULL, | 1066 | NULL, ctx.qry.vpath, 0, NULL, NULL, |
1045 | ctx.qry.showmsg, ctx.qry.follow); | 1067 | ctx.qry.showmsg, ctx.qry.follow); |
1068 | html(" "); | ||
1046 | if (ctx.qry.page && !strcmp(ctx.qry.page, "blame")) | 1069 | if (ctx.qry.page && !strcmp(ctx.qry.page, "blame")) |
1047 | cgit_blame_link("blame", NULL, hc("blame"), ctx.qry.head, | 1070 | cgit_blame_link("blame", NULL, hc("blame"), ctx.qry.head, |
1048 | ctx.qry.oid, ctx.qry.vpath); | 1071 | ctx.qry.oid, ctx.qry.vpath); |
1049 | else | 1072 | else |
1050 | cgit_tree_link("tree", NULL, hc("tree"), ctx.qry.head, | 1073 | cgit_tree_link("tree", NULL, hc("tree"), ctx.qry.head, |
1051 | ctx.qry.oid, ctx.qry.vpath); | 1074 | ctx.qry.oid, ctx.qry.vpath); |
1075 | html(" "); | ||
1052 | cgit_commit_link("commit", NULL, hc("commit"), | 1076 | cgit_commit_link("commit", NULL, hc("commit"), |
1053 | ctx.qry.head, ctx.qry.oid, ctx.qry.vpath); | 1077 | ctx.qry.head, ctx.qry.oid, ctx.qry.vpath); |
1078 | html(" "); | ||
1054 | cgit_diff_link("diff", NULL, hc("diff"), ctx.qry.head, | 1079 | cgit_diff_link("diff", NULL, hc("diff"), ctx.qry.head, |
1055 | ctx.qry.oid, ctx.qry.oid2, ctx.qry.vpath); | 1080 | ctx.qry.oid, ctx.qry.oid2, ctx.qry.vpath); |
1056 | if (ctx.repo->max_stats) | 1081 | if (ctx.repo->max_stats) { |
1082 | html(" "); | ||
1057 | cgit_stats_link("stats", NULL, hc("stats"), | 1083 | cgit_stats_link("stats", NULL, hc("stats"), |
1058 | ctx.qry.head, ctx.qry.vpath); | 1084 | ctx.qry.head, ctx.qry.vpath); |
1085 | } | ||
1059 | if (ctx.repo->homepage) { | 1086 | if (ctx.repo->homepage) { |
1060 | html("<a href='"); | 1087 | html(" <a href='"); |
1061 | html_attr(ctx.repo->homepage); | 1088 | html_attr(ctx.repo->homepage); |
1062 | html("'>homepage</a>"); | 1089 | html("'>homepage</a>"); |
1063 | } | 1090 | } |
@@ -1201,9 +1228,12 @@ void cgit_set_title_from_path(const char *path) | |||
1201 | if (!path) | 1228 | if (!path) |
1202 | return; | 1229 | return; |
1203 | 1230 | ||
1204 | for (last_slash = path + strlen(path); (slash = memrchr(path, '/', last_slash - path)) != NULL; last_slash = slash) { | 1231 | last_slash = path + strlen(path); |
1232 | for (slash = last_slash; slash > path; --slash) { | ||
1233 | if (*slash != '/') continue; | ||
1205 | strbuf_add(&sb, slash + 1, last_slash - slash - 1); | 1234 | strbuf_add(&sb, slash + 1, last_slash - slash - 1); |
1206 | strbuf_addstr(&sb, " \xc2\xab "); | 1235 | strbuf_addstr(&sb, " \xc2\xab "); |
1236 | last_slash = slash; | ||
1207 | } | 1237 | } |
1208 | strbuf_add(&sb, path, last_slash - path); | 1238 | strbuf_add(&sb, path, last_slash - path); |
1209 | strbuf_addf(&sb, " - %s", ctx.page.title); | 1239 | strbuf_addf(&sb, " - %s", ctx.page.title); |
diff --git a/ui-snapshot.c b/ui-snapshot.c index 18361a6..2801393 100644 --- a/ui-snapshot.c +++ b/ui-snapshot.c | |||
@@ -37,6 +37,9 @@ static int write_archive_type(const char *format, const char *hex, const char *p | |||
37 | /* strvec guarantees a trailing NULL entry. */ | 37 | /* strvec guarantees a trailing NULL entry. */ |
38 | memcpy(nargv, argv.v, sizeof(char *) * (argv.nr + 1)); | 38 | memcpy(nargv, argv.v, sizeof(char *) * (argv.nr + 1)); |
39 | 39 | ||
40 | if (fflush(stdout)) | ||
41 | return errno; | ||
42 | |||
40 | result = write_archive(argv.nr, nargv, NULL, the_repository, NULL, 0); | 43 | result = write_archive(argv.nr, nargv, NULL, the_repository, NULL, 0); |
41 | strvec_clear(&argv); | 44 | strvec_clear(&argv); |
42 | free(nargv); | 45 | free(nargv); |
diff --git a/ui-tag.c b/ui-tag.c index 424bbcc..0595242 100644 --- a/ui-tag.c +++ b/ui-tag.c | |||
@@ -25,9 +25,9 @@ static void print_tag_content(char *buf) | |||
25 | html_txt(buf); | 25 | html_txt(buf); |
26 | html("</div>"); | 26 | html("</div>"); |
27 | if (p) { | 27 | if (p) { |
28 | html("<div class='commit-msg'>"); | 28 | html("<pre class='commit-msg'>"); |
29 | html_txt(++p); | 29 | html_txt(++p); |
30 | html("</div>"); | 30 | html("</pre>"); |
31 | } | 31 | } |
32 | } | 32 | } |
33 | 33 | ||
diff --git a/ui-tree.c b/ui-tree.c index b61f6f5..21e0b88 100644 --- a/ui-tree.c +++ b/ui-tree.c | |||
@@ -89,6 +89,7 @@ static void print_object(const struct object_id *oid, const char *path, const ch | |||
89 | enum object_type type; | 89 | enum object_type type; |
90 | char *buf; | 90 | char *buf; |
91 | unsigned long size; | 91 | unsigned long size; |
92 | int is_binary; | ||
92 | 93 | ||
93 | type = oid_object_info(the_repository, oid, &size); | 94 | type = oid_object_info(the_repository, oid, &size); |
94 | if (type == OBJ_BAD) { | 95 | if (type == OBJ_BAD) { |
@@ -103,6 +104,7 @@ static void print_object(const struct object_id *oid, const char *path, const ch | |||
103 | "Error reading object %s", oid_to_hex(oid)); | 104 | "Error reading object %s", oid_to_hex(oid)); |
104 | return; | 105 | return; |
105 | } | 106 | } |
107 | is_binary = buffer_is_binary(buf, size); | ||
106 | 108 | ||
107 | cgit_set_title_from_path(path); | 109 | cgit_set_title_from_path(path); |
108 | 110 | ||
@@ -110,7 +112,7 @@ static void print_object(const struct object_id *oid, const char *path, const ch | |||
110 | htmlf("blob: %s (", oid_to_hex(oid)); | 112 | htmlf("blob: %s (", oid_to_hex(oid)); |
111 | cgit_plain_link("plain", NULL, NULL, ctx.qry.head, | 113 | cgit_plain_link("plain", NULL, NULL, ctx.qry.head, |
112 | rev, path); | 114 | rev, path); |
113 | if (ctx.repo->enable_blame) { | 115 | if (ctx.repo->enable_blame && !is_binary) { |
114 | html(") ("); | 116 | html(") ("); |
115 | cgit_blame_link("blame", NULL, NULL, ctx.qry.head, | 117 | cgit_blame_link("blame", NULL, NULL, ctx.qry.head, |
116 | rev, path); | 118 | rev, path); |
@@ -123,7 +125,7 @@ static void print_object(const struct object_id *oid, const char *path, const ch | |||
123 | return; | 125 | return; |
124 | } | 126 | } |
125 | 127 | ||
126 | if (buffer_is_binary(buf, size)) | 128 | if (is_binary) |
127 | print_binary_buffer(buf, size); | 129 | print_binary_buffer(buf, size); |
128 | else | 130 | else |
129 | print_text_buffer(basename, buf, size); | 131 | print_text_buffer(basename, buf, size); |
@@ -202,9 +204,11 @@ static int ls_item(const struct object_id *oid, struct strbuf *base, | |||
202 | struct walk_tree_context *walk_tree_ctx = cbdata; | 204 | struct walk_tree_context *walk_tree_ctx = cbdata; |
203 | char *name; | 205 | char *name; |
204 | struct strbuf fullpath = STRBUF_INIT; | 206 | struct strbuf fullpath = STRBUF_INIT; |
207 | struct strbuf linkpath = STRBUF_INIT; | ||
205 | struct strbuf class = STRBUF_INIT; | 208 | struct strbuf class = STRBUF_INIT; |
206 | enum object_type type; | 209 | enum object_type type; |
207 | unsigned long size = 0; | 210 | unsigned long size = 0; |
211 | char *buf; | ||
208 | 212 | ||
209 | name = xstrdup(pathname); | 213 | name = xstrdup(pathname); |
210 | strbuf_addf(&fullpath, "%s%s%s", ctx.qry.path ? ctx.qry.path : "", | 214 | strbuf_addf(&fullpath, "%s%s%s", ctx.qry.path ? ctx.qry.path : "", |
@@ -216,8 +220,7 @@ static int ls_item(const struct object_id *oid, struct strbuf *base, | |||
216 | htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>", | 220 | htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>", |
217 | name, | 221 | name, |
218 | oid_to_hex(oid)); | 222 | oid_to_hex(oid)); |
219 | free(name); | 223 | goto cleanup; |
220 | return 0; | ||
221 | } | 224 | } |
222 | } | 225 | } |
223 | 226 | ||
@@ -237,22 +240,45 @@ static int ls_item(const struct object_id *oid, struct strbuf *base, | |||
237 | cgit_tree_link(name, NULL, class.buf, ctx.qry.head, | 240 | cgit_tree_link(name, NULL, class.buf, ctx.qry.head, |
238 | walk_tree_ctx->curr_rev, fullpath.buf); | 241 | walk_tree_ctx->curr_rev, fullpath.buf); |
239 | } | 242 | } |
243 | if (S_ISLNK(mode)) { | ||
244 | html(" -> "); | ||
245 | buf = read_object_file(oid, &type, &size); | ||
246 | if (!buf) { | ||
247 | htmlf("Error reading object: %s", oid_to_hex(oid)); | ||
248 | goto cleanup; | ||
249 | } | ||
250 | strbuf_addbuf(&linkpath, &fullpath); | ||
251 | strbuf_addf(&linkpath, "/../%s", buf); | ||
252 | strbuf_normalize_path(&linkpath); | ||
253 | cgit_tree_link(buf, NULL, class.buf, ctx.qry.head, | ||
254 | walk_tree_ctx->curr_rev, linkpath.buf); | ||
255 | free(buf); | ||
256 | strbuf_release(&linkpath); | ||
257 | } | ||
240 | htmlf("</td><td class='ls-size'>%li</td>", size); | 258 | htmlf("</td><td class='ls-size'>%li</td>", size); |
241 | 259 | ||
242 | html("<td>"); | 260 | html("<td>"); |
243 | cgit_log_link("log", NULL, "button", ctx.qry.head, | 261 | cgit_log_link("log", NULL, "button", ctx.qry.head, |
244 | walk_tree_ctx->curr_rev, fullpath.buf, 0, NULL, NULL, | 262 | walk_tree_ctx->curr_rev, fullpath.buf, 0, NULL, NULL, |
245 | ctx.qry.showmsg, 0); | 263 | ctx.qry.showmsg, 0); |
246 | if (ctx.repo->max_stats) | 264 | if (ctx.repo->max_stats) { |
265 | html(" "); | ||
247 | cgit_stats_link("stats", NULL, "button", ctx.qry.head, | 266 | cgit_stats_link("stats", NULL, "button", ctx.qry.head, |
248 | fullpath.buf); | 267 | fullpath.buf); |
249 | if (!S_ISGITLINK(mode)) | 268 | } |
269 | if (!S_ISGITLINK(mode)) { | ||
270 | html(" "); | ||
250 | cgit_plain_link("plain", NULL, "button", ctx.qry.head, | 271 | cgit_plain_link("plain", NULL, "button", ctx.qry.head, |
251 | walk_tree_ctx->curr_rev, fullpath.buf); | 272 | walk_tree_ctx->curr_rev, fullpath.buf); |
252 | if (!S_ISDIR(mode) && ctx.repo->enable_blame) | 273 | } |
274 | if (!S_ISDIR(mode) && ctx.repo->enable_blame) { | ||
275 | html(" "); | ||
253 | cgit_blame_link("blame", NULL, "button", ctx.qry.head, | 276 | cgit_blame_link("blame", NULL, "button", ctx.qry.head, |
254 | walk_tree_ctx->curr_rev, fullpath.buf); | 277 | walk_tree_ctx->curr_rev, fullpath.buf); |
278 | } | ||
255 | html("</td></tr>\n"); | 279 | html("</td></tr>\n"); |
280 | |||
281 | cleanup: | ||
256 | free(name); | 282 | free(name); |
257 | strbuf_release(&fullpath); | 283 | strbuf_release(&fullpath); |
258 | strbuf_release(&class); | 284 | strbuf_release(&class); |