summaryrefslogtreecommitdiffabout
authorLars Hjemli <hjemli@gmail.com>2011-06-02 10:30:26 (UTC)
committer Lars Hjemli <hjemli@gmail.com>2011-06-02 10:30:26 (UTC)
commitd885158f6ac29e04bd14dd132331c7e3a93e7490 (patch) (unidiff)
tree15dee6a8e4f3cfd2737a50725e480d09220ee0dd
parent2aabeaf834a47c2fd64e045a28cd2e5b90658939 (diff)
downloadcgit-d885158f6ac29e04bd14dd132331c7e3a93e7490.zip
cgit-d885158f6ac29e04bd14dd132331c7e3a93e7490.tar.gz
cgit-d885158f6ac29e04bd14dd132331c7e3a93e7490.tar.bz2
ui-log.c: do not link from age column
The link url wasn't properly escaped, and since the link was identical to the one used on the commit message it didn't serve any special purpose. Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Diffstat (more/less context) (ignore whitespace changes)
-rwxr-xr-xtests/t0103-log.sh2
-rw-r--r--ui-log.c9
2 files changed, 1 insertions, 10 deletions
diff --git a/tests/t0103-log.sh b/tests/t0103-log.sh
index def5c18..75dd761 100755
--- a/tests/t0103-log.sh
+++ b/tests/t0103-log.sh
@@ -1,25 +1,25 @@
1#!/bin/sh 1#!/bin/sh
2 2
3. ./setup.sh 3. ./setup.sh
4 4
5prepare_tests "Check content on log page" 5prepare_tests "Check content on log page"
6 6
7run_test 'generate foo/log' 'cgit_url "foo/log" >trash/tmp' 7run_test 'generate foo/log' 'cgit_url "foo/log" >trash/tmp'
8run_test 'find commit 1' 'grep -e "commit 1" trash/tmp' 8run_test 'find commit 1' 'grep -e "commit 1" trash/tmp'
9run_test 'find commit 5' 'grep -e "commit 5" trash/tmp' 9run_test 'find commit 5' 'grep -e "commit 5" trash/tmp'
10 10
11run_test 'generate bar/log' 'cgit_url "bar/log" >trash/tmp' 11run_test 'generate bar/log' 'cgit_url "bar/log" >trash/tmp'
12run_test 'find commit 1' 'grep -e "commit 1" trash/tmp' 12run_test 'find commit 1' 'grep -e "commit 1" trash/tmp'
13run_test 'find commit 50' 'grep -e "commit 50" trash/tmp' 13run_test 'find commit 50' 'grep -e "commit 50" trash/tmp'
14 14
15run_test 'generate "with%20space/log?qt=grep&q=commit+1"' ' 15run_test 'generate "with%20space/log?qt=grep&q=commit+1"' '
16 cgit_url "with+space/log&qt=grep&q=commit+1" >trash/tmp 16 cgit_url "with+space/log&qt=grep&q=commit+1" >trash/tmp
17' 17'
18run_test 'find commit 1' 'grep -e "commit 1" trash/tmp' 18run_test 'find commit 1' 'grep -e "commit 1" trash/tmp'
19run_test 'find link with %20 in path' 'grep -e "/with%20space/log/?qt=grep" trash/tmp' 19run_test 'find link with %20 in path' 'grep -e "/with%20space/log/?qt=grep" trash/tmp'
20run_test 'find link with + in arg' 'grep -e "/log/?qt=grep&q=commit+1" trash/tmp' 20run_test 'find link with + in arg' 'grep -e "/log/?qt=grep&q=commit+1" trash/tmp'
21run_test BUG 'no links with space in path' '! grep -e "href=./with space/" trash/tmp' 21run_test 'no links with space in path' '! grep -e "href=./with space/" trash/tmp'
22run_test 'no links with space in arg' '! grep -e "q=commit 1" trash/tmp' 22run_test 'no links with space in arg' '! grep -e "q=commit 1" trash/tmp'
23run_test 'commit 2 is not visible' '! grep -e "commit 2" trash/tmp' 23run_test 'commit 2 is not visible' '! grep -e "commit 2" trash/tmp'
24 24
25tests_done 25tests_done
diff --git a/ui-log.c b/ui-log.c
index 8add66a..15ed6a3 100644
--- a/ui-log.c
+++ b/ui-log.c
@@ -1,428 +1,419 @@
1/* ui-log.c: functions for log output 1/* ui-log.c: functions for log 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#include "vector.h" 12#include "vector.h"
13 13
14int files, add_lines, rem_lines; 14int files, add_lines, rem_lines;
15 15
16/* 16/*
17 * The list of available column colors in the commit graph. 17 * The list of available column colors in the commit graph.
18 */ 18 */
19static const char *column_colors_html[] = { 19static const char *column_colors_html[] = {
20 "<span class='column1'>", 20 "<span class='column1'>",
21 "<span class='column2'>", 21 "<span class='column2'>",
22 "<span class='column3'>", 22 "<span class='column3'>",
23 "<span class='column4'>", 23 "<span class='column4'>",
24 "<span class='column5'>", 24 "<span class='column5'>",
25 "<span class='column6'>", 25 "<span class='column6'>",
26 "</span>", 26 "</span>",
27}; 27};
28 28
29#define COLUMN_COLORS_HTML_MAX (ARRAY_SIZE(column_colors_html) - 1) 29#define COLUMN_COLORS_HTML_MAX (ARRAY_SIZE(column_colors_html) - 1)
30 30
31void count_lines(char *line, int size) 31void count_lines(char *line, int size)
32{ 32{
33 if (size <= 0) 33 if (size <= 0)
34 return; 34 return;
35 35
36 if (line[0] == '+') 36 if (line[0] == '+')
37 add_lines++; 37 add_lines++;
38 38
39 else if (line[0] == '-') 39 else if (line[0] == '-')
40 rem_lines++; 40 rem_lines++;
41} 41}
42 42
43void inspect_files(struct diff_filepair *pair) 43void inspect_files(struct diff_filepair *pair)
44{ 44{
45 unsigned long old_size = 0; 45 unsigned long old_size = 0;
46 unsigned long new_size = 0; 46 unsigned long new_size = 0;
47 int binary = 0; 47 int binary = 0;
48 48
49 files++; 49 files++;
50 if (ctx.repo->enable_log_linecount) 50 if (ctx.repo->enable_log_linecount)
51 cgit_diff_files(pair->one->sha1, pair->two->sha1, &old_size, 51 cgit_diff_files(pair->one->sha1, pair->two->sha1, &old_size,
52 &new_size, &binary, 0, ctx.qry.ignorews, 52 &new_size, &binary, 0, ctx.qry.ignorews,
53 count_lines); 53 count_lines);
54} 54}
55 55
56void show_commit_decorations(struct commit *commit) 56void show_commit_decorations(struct commit *commit)
57{ 57{
58 struct name_decoration *deco; 58 struct name_decoration *deco;
59 static char buf[1024]; 59 static char buf[1024];
60 60
61 buf[sizeof(buf) - 1] = 0; 61 buf[sizeof(buf) - 1] = 0;
62 deco = lookup_decoration(&name_decoration, &commit->object); 62 deco = lookup_decoration(&name_decoration, &commit->object);
63 while (deco) { 63 while (deco) {
64 if (!prefixcmp(deco->name, "refs/heads/")) { 64 if (!prefixcmp(deco->name, "refs/heads/")) {
65 strncpy(buf, deco->name + 11, sizeof(buf) - 1); 65 strncpy(buf, deco->name + 11, sizeof(buf) - 1);
66 cgit_log_link(buf, NULL, "branch-deco", buf, NULL, 66 cgit_log_link(buf, NULL, "branch-deco", buf, NULL,
67 ctx.qry.vpath, 0, NULL, NULL, 67 ctx.qry.vpath, 0, NULL, NULL,
68 ctx.qry.showmsg); 68 ctx.qry.showmsg);
69 } 69 }
70 else if (!prefixcmp(deco->name, "tag: refs/tags/")) { 70 else if (!prefixcmp(deco->name, "tag: refs/tags/")) {
71 strncpy(buf, deco->name + 15, sizeof(buf) - 1); 71 strncpy(buf, deco->name + 15, sizeof(buf) - 1);
72 cgit_tag_link(buf, NULL, "tag-deco", ctx.qry.head, buf); 72 cgit_tag_link(buf, NULL, "tag-deco", ctx.qry.head, buf);
73 } 73 }
74 else if (!prefixcmp(deco->name, "refs/tags/")) { 74 else if (!prefixcmp(deco->name, "refs/tags/")) {
75 strncpy(buf, deco->name + 10, sizeof(buf) - 1); 75 strncpy(buf, deco->name + 10, sizeof(buf) - 1);
76 cgit_tag_link(buf, NULL, "tag-deco", ctx.qry.head, buf); 76 cgit_tag_link(buf, NULL, "tag-deco", ctx.qry.head, buf);
77 } 77 }
78 else if (!prefixcmp(deco->name, "refs/remotes/")) { 78 else if (!prefixcmp(deco->name, "refs/remotes/")) {
79 strncpy(buf, deco->name + 13, sizeof(buf) - 1); 79 strncpy(buf, deco->name + 13, sizeof(buf) - 1);
80 cgit_log_link(buf, NULL, "remote-deco", NULL, 80 cgit_log_link(buf, NULL, "remote-deco", NULL,
81 sha1_to_hex(commit->object.sha1), 81 sha1_to_hex(commit->object.sha1),
82 ctx.qry.vpath, 0, NULL, NULL, 82 ctx.qry.vpath, 0, NULL, NULL,
83 ctx.qry.showmsg); 83 ctx.qry.showmsg);
84 } 84 }
85 else { 85 else {
86 strncpy(buf, deco->name, sizeof(buf) - 1); 86 strncpy(buf, deco->name, sizeof(buf) - 1);
87 cgit_commit_link(buf, NULL, "deco", ctx.qry.head, 87 cgit_commit_link(buf, NULL, "deco", ctx.qry.head,
88 sha1_to_hex(commit->object.sha1), 88 sha1_to_hex(commit->object.sha1),
89 ctx.qry.vpath, 0); 89 ctx.qry.vpath, 0);
90 } 90 }
91 deco = deco->next; 91 deco = deco->next;
92 } 92 }
93} 93}
94 94
95void print_commit(struct commit *commit, struct rev_info *revs) 95void print_commit(struct commit *commit, struct rev_info *revs)
96{ 96{
97 struct commitinfo *info; 97 struct commitinfo *info;
98 char *tmp;
99 int cols = revs->graph ? 3 : 2; 98 int cols = revs->graph ? 3 : 2;
100 struct strbuf graphbuf = STRBUF_INIT; 99 struct strbuf graphbuf = STRBUF_INIT;
101 struct strbuf msgbuf = STRBUF_INIT; 100 struct strbuf msgbuf = STRBUF_INIT;
102 101
103 if (ctx.repo->enable_log_filecount) { 102 if (ctx.repo->enable_log_filecount) {
104 cols++; 103 cols++;
105 if (ctx.repo->enable_log_linecount) 104 if (ctx.repo->enable_log_linecount)
106 cols++; 105 cols++;
107 } 106 }
108 107
109 if (revs->graph) { 108 if (revs->graph) {
110 /* Advance graph until current commit */ 109 /* Advance graph until current commit */
111 while (!graph_next_line(revs->graph, &graphbuf)) { 110 while (!graph_next_line(revs->graph, &graphbuf)) {
112 /* Print graph segment in otherwise empty table row */ 111 /* Print graph segment in otherwise empty table row */
113 html("<tr class='nohover'><td class='commitgraph'>"); 112 html("<tr class='nohover'><td class='commitgraph'>");
114 html(graphbuf.buf); 113 html(graphbuf.buf);
115 htmlf("</td><td colspan='%d' /></tr>\n", cols); 114 htmlf("</td><td colspan='%d' /></tr>\n", cols);
116 strbuf_setlen(&graphbuf, 0); 115 strbuf_setlen(&graphbuf, 0);
117 } 116 }
118 /* Current commit's graph segment is now ready in graphbuf */ 117 /* Current commit's graph segment is now ready in graphbuf */
119 } 118 }
120 119
121 info = cgit_parse_commit(commit); 120 info = cgit_parse_commit(commit);
122 htmlf("<tr%s>", ctx.qry.showmsg ? " class='logheader'" : ""); 121 htmlf("<tr%s>", ctx.qry.showmsg ? " class='logheader'" : "");
123 122
124 if (revs->graph) { 123 if (revs->graph) {
125 /* Print graph segment for current commit */ 124 /* Print graph segment for current commit */
126 html("<td class='commitgraph'>"); 125 html("<td class='commitgraph'>");
127 html(graphbuf.buf); 126 html(graphbuf.buf);
128 html("</td>"); 127 html("</td>");
129 strbuf_setlen(&graphbuf, 0); 128 strbuf_setlen(&graphbuf, 0);
130 } 129 }
131 else { 130 else {
132 html("<td>"); 131 html("<td>");
133 tmp = fmt("id=%s", sha1_to_hex(commit->object.sha1));
134 tmp = cgit_fileurl(ctx.repo->url, "commit", ctx.qry.vpath, tmp);
135 html_link_open(tmp, NULL, NULL);
136 cgit_print_age(commit->date, TM_WEEK * 2, FMT_SHORTDATE); 132 cgit_print_age(commit->date, TM_WEEK * 2, FMT_SHORTDATE);
137 html_link_close();
138 html("</td>"); 133 html("</td>");
139 } 134 }
140 135
141 htmlf("<td%s>", ctx.qry.showmsg ? " class='logsubject'" : ""); 136 htmlf("<td%s>", ctx.qry.showmsg ? " class='logsubject'" : "");
142 if (ctx.qry.showmsg) { 137 if (ctx.qry.showmsg) {
143 /* line-wrap long commit subjects instead of truncating them */ 138 /* line-wrap long commit subjects instead of truncating them */
144 size_t subject_len = strlen(info->subject); 139 size_t subject_len = strlen(info->subject);
145 140
146 if (subject_len > ctx.cfg.max_msg_len && 141 if (subject_len > ctx.cfg.max_msg_len &&
147 ctx.cfg.max_msg_len >= 15) { 142 ctx.cfg.max_msg_len >= 15) {
148 /* symbol for signaling line-wrap (in PAGE_ENCODING) */ 143 /* symbol for signaling line-wrap (in PAGE_ENCODING) */
149 const char wrap_symbol[] = { ' ', 0xE2, 0x86, 0xB5, 0 }; 144 const char wrap_symbol[] = { ' ', 0xE2, 0x86, 0xB5, 0 };
150 int i = ctx.cfg.max_msg_len - strlen(wrap_symbol); 145 int i = ctx.cfg.max_msg_len - strlen(wrap_symbol);
151 146
152 /* Rewind i to preceding space character */ 147 /* Rewind i to preceding space character */
153 while (i > 0 && !isspace(info->subject[i])) 148 while (i > 0 && !isspace(info->subject[i]))
154 --i; 149 --i;
155 if (!i) /* Oops, zero spaces. Reset i */ 150 if (!i) /* Oops, zero spaces. Reset i */
156 i = ctx.cfg.max_msg_len - strlen(wrap_symbol); 151 i = ctx.cfg.max_msg_len - strlen(wrap_symbol);
157 152
158 /* add remainder starting at i to msgbuf */ 153 /* add remainder starting at i to msgbuf */
159 strbuf_add(&msgbuf, info->subject + i, subject_len - i); 154 strbuf_add(&msgbuf, info->subject + i, subject_len - i);
160 strbuf_trim(&msgbuf); 155 strbuf_trim(&msgbuf);
161 strbuf_add(&msgbuf, "\n\n", 2); 156 strbuf_add(&msgbuf, "\n\n", 2);
162 157
163 /* Place wrap_symbol at position i in info->subject */ 158 /* Place wrap_symbol at position i in info->subject */
164 strcpy(info->subject + i, wrap_symbol); 159 strcpy(info->subject + i, wrap_symbol);
165 } 160 }
166 } 161 }
167 cgit_commit_link(info->subject, NULL, NULL, ctx.qry.head, 162 cgit_commit_link(info->subject, NULL, NULL, ctx.qry.head,
168 sha1_to_hex(commit->object.sha1), ctx.qry.vpath, 0); 163 sha1_to_hex(commit->object.sha1), ctx.qry.vpath, 0);
169 show_commit_decorations(commit); 164 show_commit_decorations(commit);
170 html("</td><td>"); 165 html("</td><td>");
171 html_txt(info->author); 166 html_txt(info->author);
172 167
173 if (revs->graph) { 168 if (revs->graph) {
174 html("</td><td>"); 169 html("</td><td>");
175 tmp = fmt("id=%s", sha1_to_hex(commit->object.sha1));
176 tmp = cgit_fileurl(ctx.repo->url, "commit", ctx.qry.vpath, tmp);
177 html_link_open(tmp, NULL, NULL);
178 cgit_print_age(commit->date, TM_WEEK * 2, FMT_SHORTDATE); 170 cgit_print_age(commit->date, TM_WEEK * 2, FMT_SHORTDATE);
179 html_link_close();
180 } 171 }
181 172
182 if (ctx.repo->enable_log_filecount) { 173 if (ctx.repo->enable_log_filecount) {
183 files = 0; 174 files = 0;
184 add_lines = 0; 175 add_lines = 0;
185 rem_lines = 0; 176 rem_lines = 0;
186 cgit_diff_commit(commit, inspect_files, ctx.qry.vpath); 177 cgit_diff_commit(commit, inspect_files, ctx.qry.vpath);
187 html("</td><td>"); 178 html("</td><td>");
188 htmlf("%d", files); 179 htmlf("%d", files);
189 if (ctx.repo->enable_log_linecount) { 180 if (ctx.repo->enable_log_linecount) {
190 html("</td><td>"); 181 html("</td><td>");
191 htmlf("-%d/+%d", rem_lines, add_lines); 182 htmlf("-%d/+%d", rem_lines, add_lines);
192 } 183 }
193 } 184 }
194 html("</td></tr>\n"); 185 html("</td></tr>\n");
195 186
196 if (revs->graph || ctx.qry.showmsg) { /* Print a second table row */ 187 if (revs->graph || ctx.qry.showmsg) { /* Print a second table row */
197 html("<tr class='nohover'>"); 188 html("<tr class='nohover'>");
198 189
199 if (ctx.qry.showmsg) { 190 if (ctx.qry.showmsg) {
200 /* Concatenate commit message + notes in msgbuf */ 191 /* Concatenate commit message + notes in msgbuf */
201 if (info->msg && *(info->msg)) { 192 if (info->msg && *(info->msg)) {
202 strbuf_addstr(&msgbuf, info->msg); 193 strbuf_addstr(&msgbuf, info->msg);
203 strbuf_addch(&msgbuf, '\n'); 194 strbuf_addch(&msgbuf, '\n');
204 } 195 }
205 format_note(NULL, commit->object.sha1, &msgbuf, 196 format_note(NULL, commit->object.sha1, &msgbuf,
206 PAGE_ENCODING, 197 PAGE_ENCODING,
207 NOTES_SHOW_HEADER | NOTES_INDENT); 198 NOTES_SHOW_HEADER | NOTES_INDENT);
208 strbuf_addch(&msgbuf, '\n'); 199 strbuf_addch(&msgbuf, '\n');
209 strbuf_ltrim(&msgbuf); 200 strbuf_ltrim(&msgbuf);
210 } 201 }
211 202
212 if (revs->graph) { 203 if (revs->graph) {
213 int lines = 0; 204 int lines = 0;
214 205
215 /* Calculate graph padding */ 206 /* Calculate graph padding */
216 if (ctx.qry.showmsg) { 207 if (ctx.qry.showmsg) {
217 /* Count #lines in commit message + notes */ 208 /* Count #lines in commit message + notes */
218 const char *p = msgbuf.buf; 209 const char *p = msgbuf.buf;
219 lines = 1; 210 lines = 1;
220 while ((p = strchr(p, '\n'))) { 211 while ((p = strchr(p, '\n'))) {
221 p++; 212 p++;
222 lines++; 213 lines++;
223 } 214 }
224 } 215 }
225 216
226 /* Print graph padding */ 217 /* Print graph padding */
227 html("<td class='commitgraph'>"); 218 html("<td class='commitgraph'>");
228 while (lines > 0 || !graph_is_commit_finished(revs->graph)) { 219 while (lines > 0 || !graph_is_commit_finished(revs->graph)) {
229 if (graphbuf.len) 220 if (graphbuf.len)
230 html("\n"); 221 html("\n");
231 strbuf_setlen(&graphbuf, 0); 222 strbuf_setlen(&graphbuf, 0);
232 graph_next_line(revs->graph, &graphbuf); 223 graph_next_line(revs->graph, &graphbuf);
233 html(graphbuf.buf); 224 html(graphbuf.buf);
234 lines--; 225 lines--;
235 } 226 }
236 html("</td>\n"); 227 html("</td>\n");
237 } 228 }
238 else 229 else
239 html("<td/>"); /* Empty 'Age' column */ 230 html("<td/>"); /* Empty 'Age' column */
240 231
241 /* Print msgbuf into remainder of table row */ 232 /* Print msgbuf into remainder of table row */
242 htmlf("<td colspan='%d'%s>\n", cols, 233 htmlf("<td colspan='%d'%s>\n", cols,
243 ctx.qry.showmsg ? " class='logmsg'" : ""); 234 ctx.qry.showmsg ? " class='logmsg'" : "");
244 html_txt(msgbuf.buf); 235 html_txt(msgbuf.buf);
245 html("</td></tr>\n"); 236 html("</td></tr>\n");
246 } 237 }
247 238
248 strbuf_release(&msgbuf); 239 strbuf_release(&msgbuf);
249 strbuf_release(&graphbuf); 240 strbuf_release(&graphbuf);
250 cgit_free_commitinfo(info); 241 cgit_free_commitinfo(info);
251} 242}
252 243
253static const char *disambiguate_ref(const char *ref) 244static const char *disambiguate_ref(const char *ref)
254{ 245{
255 unsigned char sha1[20]; 246 unsigned char sha1[20];
256 const char *longref; 247 const char *longref;
257 248
258 longref = fmt("refs/heads/%s", ref); 249 longref = fmt("refs/heads/%s", ref);
259 if (get_sha1(longref, sha1) == 0) 250 if (get_sha1(longref, sha1) == 0)
260 return longref; 251 return longref;
261 252
262 return ref; 253 return ref;
263} 254}
264 255
265static char *next_token(char **src) 256static char *next_token(char **src)
266{ 257{
267 char *result; 258 char *result;
268 259
269 if (!src || !*src) 260 if (!src || !*src)
270 return NULL; 261 return NULL;
271 while (isspace(**src)) 262 while (isspace(**src))
272 (*src)++; 263 (*src)++;
273 if (!**src) 264 if (!**src)
274 return NULL; 265 return NULL;
275 result = *src; 266 result = *src;
276 while (**src) { 267 while (**src) {
277 if (isspace(**src)) { 268 if (isspace(**src)) {
278 **src = '\0'; 269 **src = '\0';
279 (*src)++; 270 (*src)++;
280 break; 271 break;
281 } 272 }
282 (*src)++; 273 (*src)++;
283 } 274 }
284 return result; 275 return result;
285} 276}
286 277
287void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern, 278void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern,
288 char *path, int pager, int commit_graph) 279 char *path, int pager, int commit_graph)
289{ 280{
290 struct rev_info rev; 281 struct rev_info rev;
291 struct commit *commit; 282 struct commit *commit;
292 struct vector vec = VECTOR_INIT(char *); 283 struct vector vec = VECTOR_INIT(char *);
293 int i, columns = 3; 284 int i, columns = 3;
294 char *arg; 285 char *arg;
295 286
296 /* First argv is NULL */ 287 /* First argv is NULL */
297 vector_push(&vec, NULL, 0); 288 vector_push(&vec, NULL, 0);
298 289
299 if (!tip) 290 if (!tip)
300 tip = ctx.qry.head; 291 tip = ctx.qry.head;
301 tip = disambiguate_ref(tip); 292 tip = disambiguate_ref(tip);
302 vector_push(&vec, &tip, 0); 293 vector_push(&vec, &tip, 0);
303 294
304 if (grep && pattern && *pattern) { 295 if (grep && pattern && *pattern) {
305 pattern = xstrdup(pattern); 296 pattern = xstrdup(pattern);
306 if (!strcmp(grep, "grep") || !strcmp(grep, "author") || 297 if (!strcmp(grep, "grep") || !strcmp(grep, "author") ||
307 !strcmp(grep, "committer")) { 298 !strcmp(grep, "committer")) {
308 arg = fmt("--%s=%s", grep, pattern); 299 arg = fmt("--%s=%s", grep, pattern);
309 vector_push(&vec, &arg, 0); 300 vector_push(&vec, &arg, 0);
310 } 301 }
311 if (!strcmp(grep, "range")) { 302 if (!strcmp(grep, "range")) {
312 /* Split the pattern at whitespace and add each token 303 /* Split the pattern at whitespace and add each token
313 * as a revision expression. Do not accept other 304 * as a revision expression. Do not accept other
314 * rev-list options. Also, replace the previously 305 * rev-list options. Also, replace the previously
315 * pushed tip (it's no longer relevant). 306 * pushed tip (it's no longer relevant).
316 */ 307 */
317 vec.count--; 308 vec.count--;
318 while ((arg = next_token(&pattern))) { 309 while ((arg = next_token(&pattern))) {
319 if (*arg == '-') { 310 if (*arg == '-') {
320 fprintf(stderr, "Bad range expr: %s\n", 311 fprintf(stderr, "Bad range expr: %s\n",
321 arg); 312 arg);
322 break; 313 break;
323 } 314 }
324 vector_push(&vec, &arg, 0); 315 vector_push(&vec, &arg, 0);
325 } 316 }
326 } 317 }
327 } 318 }
328 if (commit_graph) { 319 if (commit_graph) {
329 static const char *graph_arg = "--graph"; 320 static const char *graph_arg = "--graph";
330 static const char *color_arg = "--color"; 321 static const char *color_arg = "--color";
331 vector_push(&vec, &graph_arg, 0); 322 vector_push(&vec, &graph_arg, 0);
332 vector_push(&vec, &color_arg, 0); 323 vector_push(&vec, &color_arg, 0);
333 graph_set_column_colors(column_colors_html, 324 graph_set_column_colors(column_colors_html,
334 COLUMN_COLORS_HTML_MAX); 325 COLUMN_COLORS_HTML_MAX);
335 } 326 }
336 327
337 if (path) { 328 if (path) {
338 arg = "--"; 329 arg = "--";
339 vector_push(&vec, &arg, 0); 330 vector_push(&vec, &arg, 0);
340 vector_push(&vec, &path, 0); 331 vector_push(&vec, &path, 0);
341 } 332 }
342 333
343 /* Make sure the vector is NULL-terminated */ 334 /* Make sure the vector is NULL-terminated */
344 vector_push(&vec, NULL, 0); 335 vector_push(&vec, NULL, 0);
345 vec.count--; 336 vec.count--;
346 337
347 init_revisions(&rev, NULL); 338 init_revisions(&rev, NULL);
348 rev.abbrev = DEFAULT_ABBREV; 339 rev.abbrev = DEFAULT_ABBREV;
349 rev.commit_format = CMIT_FMT_DEFAULT; 340 rev.commit_format = CMIT_FMT_DEFAULT;
350 rev.verbose_header = 1; 341 rev.verbose_header = 1;
351 rev.show_root_diff = 0; 342 rev.show_root_diff = 0;
352 setup_revisions(vec.count, vec.data, &rev, NULL); 343 setup_revisions(vec.count, vec.data, &rev, NULL);
353 load_ref_decorations(DECORATE_FULL_REFS); 344 load_ref_decorations(DECORATE_FULL_REFS);
354 rev.show_decorations = 1; 345 rev.show_decorations = 1;
355 rev.grep_filter.regflags |= REG_ICASE; 346 rev.grep_filter.regflags |= REG_ICASE;
356 compile_grep_patterns(&rev.grep_filter); 347 compile_grep_patterns(&rev.grep_filter);
357 prepare_revision_walk(&rev); 348 prepare_revision_walk(&rev);
358 349
359 if (pager) 350 if (pager)
360 html("<table class='list nowrap'>"); 351 html("<table class='list nowrap'>");
361 352
362 html("<tr class='nohover'>"); 353 html("<tr class='nohover'>");
363 if (commit_graph) 354 if (commit_graph)
364 html("<th></th>"); 355 html("<th></th>");
365 else 356 else
366 html("<th class='left'>Age</th>"); 357 html("<th class='left'>Age</th>");
367 html("<th class='left'>Commit message"); 358 html("<th class='left'>Commit message");
368 if (pager) { 359 if (pager) {
369 html(" ("); 360 html(" (");
370 cgit_log_link(ctx.qry.showmsg ? "Collapse" : "Expand", NULL, 361 cgit_log_link(ctx.qry.showmsg ? "Collapse" : "Expand", NULL,
371 NULL, ctx.qry.head, ctx.qry.sha1, 362 NULL, ctx.qry.head, ctx.qry.sha1,
372 ctx.qry.vpath, ctx.qry.ofs, ctx.qry.grep, 363 ctx.qry.vpath, ctx.qry.ofs, ctx.qry.grep,
373 ctx.qry.search, ctx.qry.showmsg ? 0 : 1); 364 ctx.qry.search, ctx.qry.showmsg ? 0 : 1);
374 html(")"); 365 html(")");
375 } 366 }
376 html("</th><th class='left'>Author</th>"); 367 html("</th><th class='left'>Author</th>");
377 if (commit_graph) 368 if (commit_graph)
378 html("<th class='left'>Age</th>"); 369 html("<th class='left'>Age</th>");
379 if (ctx.repo->enable_log_filecount) { 370 if (ctx.repo->enable_log_filecount) {
380 html("<th class='left'>Files</th>"); 371 html("<th class='left'>Files</th>");
381 columns++; 372 columns++;
382 if (ctx.repo->enable_log_linecount) { 373 if (ctx.repo->enable_log_linecount) {
383 html("<th class='left'>Lines</th>"); 374 html("<th class='left'>Lines</th>");
384 columns++; 375 columns++;
385 } 376 }
386 } 377 }
387 html("</tr>\n"); 378 html("</tr>\n");
388 379
389 if (ofs<0) 380 if (ofs<0)
390 ofs = 0; 381 ofs = 0;
391 382
392 for (i = 0; i < ofs && (commit = get_revision(&rev)) != NULL; i++) { 383 for (i = 0; i < ofs && (commit = get_revision(&rev)) != NULL; i++) {
393 free(commit->buffer); 384 free(commit->buffer);
394 commit->buffer = NULL; 385 commit->buffer = NULL;
395 free_commit_list(commit->parents); 386 free_commit_list(commit->parents);
396 commit->parents = NULL; 387 commit->parents = NULL;
397 } 388 }
398 389
399 for (i = 0; i < cnt && (commit = get_revision(&rev)) != NULL; i++) { 390 for (i = 0; i < cnt && (commit = get_revision(&rev)) != NULL; i++) {
400 print_commit(commit, &rev); 391 print_commit(commit, &rev);
401 free(commit->buffer); 392 free(commit->buffer);
402 commit->buffer = NULL; 393 commit->buffer = NULL;
403 free_commit_list(commit->parents); 394 free_commit_list(commit->parents);
404 commit->parents = NULL; 395 commit->parents = NULL;
405 } 396 }
406 if (pager) { 397 if (pager) {
407 html("</table><div class='pager'>"); 398 html("</table><div class='pager'>");
408 if (ofs > 0) { 399 if (ofs > 0) {
409 cgit_log_link("[prev]", NULL, NULL, ctx.qry.head, 400 cgit_log_link("[prev]", NULL, NULL, ctx.qry.head,
410 ctx.qry.sha1, ctx.qry.vpath, 401 ctx.qry.sha1, ctx.qry.vpath,
411 ofs - cnt, ctx.qry.grep, 402 ofs - cnt, ctx.qry.grep,
412 ctx.qry.search, ctx.qry.showmsg); 403 ctx.qry.search, ctx.qry.showmsg);
413 html("&nbsp;"); 404 html("&nbsp;");
414 } 405 }
415 if ((commit = get_revision(&rev)) != NULL) { 406 if ((commit = get_revision(&rev)) != NULL) {
416 cgit_log_link("[next]", NULL, NULL, ctx.qry.head, 407 cgit_log_link("[next]", NULL, NULL, ctx.qry.head,
417 ctx.qry.sha1, ctx.qry.vpath, 408 ctx.qry.sha1, ctx.qry.vpath,
418 ofs + cnt, ctx.qry.grep, 409 ofs + cnt, ctx.qry.grep,
419 ctx.qry.search, ctx.qry.showmsg); 410 ctx.qry.search, ctx.qry.showmsg);
420 } 411 }
421 html("</div>"); 412 html("</div>");
422 } else if ((commit = get_revision(&rev)) != NULL) { 413 } else if ((commit = get_revision(&rev)) != NULL) {
423 html("<tr class='nohover'><td colspan='3'>"); 414 html("<tr class='nohover'><td colspan='3'>");
424 cgit_log_link("[...]", NULL, NULL, ctx.qry.head, NULL, 415 cgit_log_link("[...]", NULL, NULL, ctx.qry.head, NULL,
425 ctx.qry.vpath, 0, NULL, NULL, ctx.qry.showmsg); 416 ctx.qry.vpath, 0, NULL, NULL, ctx.qry.showmsg);
426 html("</td></tr>\n"); 417 html("</td></tr>\n");
427 } 418 }
428} 419}