author | Johan Herland <johan@herland.net> | 2010-11-15 17:39:51 (UTC) |
---|---|---|
committer | Lars Hjemli <hjemli@gmail.com> | 2010-11-16 07:18:37 (UTC) |
commit | 268b34af23cdcac87aed3300bfe6154cbc65753e (patch) (unidiff) | |
tree | fccbebc21c004f5967947275ba5086589086ec36 | |
parent | 9a8d39c668b98464bac97d4e5442966de63f97b2 (diff) | |
download | cgit-268b34af23cdcac87aed3300bfe6154cbc65753e.zip cgit-268b34af23cdcac87aed3300bfe6154cbc65753e.tar.gz cgit-268b34af23cdcac87aed3300bfe6154cbc65753e.tar.bz2 |
ui-log: Colorize commit graph
Use the existing coloring logic in Git's graph code to color the lines
between commits in the commit graph.
Whereas Git normally uses ANSI color escapes to produce colors, we here
use graph_set_column_colors() to replace those with HTML color escapes,
that embed the graph lines in <span> tags that apply the desired color
using CSS.
Signed-off-by: Johan Herland <johan@herland.net>
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
-rw-r--r-- | cgit.css | 24 | ||||
-rw-r--r-- | ui-log.c | 19 |
2 files changed, 43 insertions, 0 deletions
@@ -65,192 +65,216 @@ table#header td.sub { | |||
65 | 65 | ||
66 | table.tabs { | 66 | table.tabs { |
67 | border-bottom: solid 3px #ccc; | 67 | border-bottom: solid 3px #ccc; |
68 | border-collapse: collapse; | 68 | border-collapse: collapse; |
69 | margin-top: 2em; | 69 | margin-top: 2em; |
70 | margin-bottom: 0px; | 70 | margin-bottom: 0px; |
71 | width: 100%; | 71 | width: 100%; |
72 | } | 72 | } |
73 | 73 | ||
74 | table.tabs td { | 74 | table.tabs td { |
75 | padding: 0px 1em; | 75 | padding: 0px 1em; |
76 | vertical-align: bottom; | 76 | vertical-align: bottom; |
77 | } | 77 | } |
78 | 78 | ||
79 | table.tabs td a { | 79 | table.tabs td a { |
80 | padding: 2px 0.75em; | 80 | padding: 2px 0.75em; |
81 | color: #777; | 81 | color: #777; |
82 | font-size: 110%; | 82 | font-size: 110%; |
83 | } | 83 | } |
84 | 84 | ||
85 | table.tabs td a.active { | 85 | table.tabs td a.active { |
86 | color: #000; | 86 | color: #000; |
87 | background-color: #ccc; | 87 | background-color: #ccc; |
88 | } | 88 | } |
89 | 89 | ||
90 | table.tabs td.form { | 90 | table.tabs td.form { |
91 | text-align: right; | 91 | text-align: right; |
92 | } | 92 | } |
93 | 93 | ||
94 | table.tabs td.form form { | 94 | table.tabs td.form form { |
95 | padding-bottom: 2px; | 95 | padding-bottom: 2px; |
96 | font-size: 90%; | 96 | font-size: 90%; |
97 | white-space: nowrap; | 97 | white-space: nowrap; |
98 | } | 98 | } |
99 | 99 | ||
100 | table.tabs td.form input, | 100 | table.tabs td.form input, |
101 | table.tabs td.form select { | 101 | table.tabs td.form select { |
102 | font-size: 90%; | 102 | font-size: 90%; |
103 | } | 103 | } |
104 | 104 | ||
105 | div.path { | 105 | div.path { |
106 | margin: 0px; | 106 | margin: 0px; |
107 | padding: 5px 2em 2px 2em; | 107 | padding: 5px 2em 2px 2em; |
108 | color: #000; | 108 | color: #000; |
109 | background-color: #eee; | 109 | background-color: #eee; |
110 | } | 110 | } |
111 | 111 | ||
112 | div.content { | 112 | div.content { |
113 | margin: 0px; | 113 | margin: 0px; |
114 | padding: 2em; | 114 | padding: 2em; |
115 | border-bottom: solid 3px #ccc; | 115 | border-bottom: solid 3px #ccc; |
116 | } | 116 | } |
117 | 117 | ||
118 | 118 | ||
119 | table.list { | 119 | table.list { |
120 | width: 100%; | 120 | width: 100%; |
121 | border: none; | 121 | border: none; |
122 | border-collapse: collapse; | 122 | border-collapse: collapse; |
123 | } | 123 | } |
124 | 124 | ||
125 | table.list tr { | 125 | table.list tr { |
126 | background: white; | 126 | background: white; |
127 | } | 127 | } |
128 | 128 | ||
129 | table.list tr.logheader { | 129 | table.list tr.logheader { |
130 | background: #eee; | 130 | background: #eee; |
131 | } | 131 | } |
132 | 132 | ||
133 | table.list tr:hover { | 133 | table.list tr:hover { |
134 | background: #eee; | 134 | background: #eee; |
135 | } | 135 | } |
136 | 136 | ||
137 | table.list tr.nohover:hover { | 137 | table.list tr.nohover:hover { |
138 | background: white; | 138 | background: white; |
139 | } | 139 | } |
140 | 140 | ||
141 | table.list th { | 141 | table.list th { |
142 | font-weight: bold; | 142 | font-weight: bold; |
143 | /* color: #888; | 143 | /* color: #888; |
144 | border-top: dashed 1px #888; | 144 | border-top: dashed 1px #888; |
145 | border-bottom: dashed 1px #888; | 145 | border-bottom: dashed 1px #888; |
146 | */ | 146 | */ |
147 | padding: 0.1em 0.5em 0.05em 0.5em; | 147 | padding: 0.1em 0.5em 0.05em 0.5em; |
148 | vertical-align: baseline; | 148 | vertical-align: baseline; |
149 | } | 149 | } |
150 | 150 | ||
151 | table.list td { | 151 | table.list td { |
152 | border: none; | 152 | border: none; |
153 | padding: 0.1em 0.5em 0.1em 0.5em; | 153 | padding: 0.1em 0.5em 0.1em 0.5em; |
154 | } | 154 | } |
155 | 155 | ||
156 | table.list td.commitgraph { | 156 | table.list td.commitgraph { |
157 | font-family: monospace; | 157 | font-family: monospace; |
158 | white-space: pre; | 158 | white-space: pre; |
159 | } | 159 | } |
160 | 160 | ||
161 | table.list td.commitgraph .column1 { | ||
162 | color: #a00; | ||
163 | } | ||
164 | |||
165 | table.list td.commitgraph .column2 { | ||
166 | color: #0a0; | ||
167 | } | ||
168 | |||
169 | table.list td.commitgraph .column3 { | ||
170 | color: #aa0; | ||
171 | } | ||
172 | |||
173 | table.list td.commitgraph .column4 { | ||
174 | color: #00a; | ||
175 | } | ||
176 | |||
177 | table.list td.commitgraph .column5 { | ||
178 | color: #a0a; | ||
179 | } | ||
180 | |||
181 | table.list td.commitgraph .column6 { | ||
182 | color: #0aa; | ||
183 | } | ||
184 | |||
161 | table.list td.logsubject { | 185 | table.list td.logsubject { |
162 | font-family: monospace; | 186 | font-family: monospace; |
163 | font-weight: bold; | 187 | font-weight: bold; |
164 | } | 188 | } |
165 | 189 | ||
166 | table.list td.logmsg { | 190 | table.list td.logmsg { |
167 | font-family: monospace; | 191 | font-family: monospace; |
168 | white-space: pre; | 192 | white-space: pre; |
169 | padding: 0 0.5em; | 193 | padding: 0 0.5em; |
170 | } | 194 | } |
171 | 195 | ||
172 | table.list td a { | 196 | table.list td a { |
173 | color: black; | 197 | color: black; |
174 | } | 198 | } |
175 | 199 | ||
176 | table.list td a.ls-dir { | 200 | table.list td a.ls-dir { |
177 | font-weight: bold; | 201 | font-weight: bold; |
178 | color: #00f; | 202 | color: #00f; |
179 | } | 203 | } |
180 | 204 | ||
181 | table.list td a:hover { | 205 | table.list td a:hover { |
182 | color: #00f; | 206 | color: #00f; |
183 | } | 207 | } |
184 | 208 | ||
185 | img { | 209 | img { |
186 | border: none; | 210 | border: none; |
187 | } | 211 | } |
188 | 212 | ||
189 | input#switch-btn { | 213 | input#switch-btn { |
190 | margin: 2px 0px 0px 0px; | 214 | margin: 2px 0px 0px 0px; |
191 | } | 215 | } |
192 | 216 | ||
193 | td#sidebar input.txt { | 217 | td#sidebar input.txt { |
194 | width: 100%; | 218 | width: 100%; |
195 | margin: 2px 0px 0px 0px; | 219 | margin: 2px 0px 0px 0px; |
196 | } | 220 | } |
197 | 221 | ||
198 | table#grid { | 222 | table#grid { |
199 | margin: 0px; | 223 | margin: 0px; |
200 | } | 224 | } |
201 | 225 | ||
202 | td#content { | 226 | td#content { |
203 | vertical-align: top; | 227 | vertical-align: top; |
204 | padding: 1em 2em 1em 1em; | 228 | padding: 1em 2em 1em 1em; |
205 | border: none; | 229 | border: none; |
206 | } | 230 | } |
207 | 231 | ||
208 | div#summary { | 232 | div#summary { |
209 | vertical-align: top; | 233 | vertical-align: top; |
210 | margin-bottom: 1em; | 234 | margin-bottom: 1em; |
211 | } | 235 | } |
212 | 236 | ||
213 | table#downloads { | 237 | table#downloads { |
214 | float: right; | 238 | float: right; |
215 | border-collapse: collapse; | 239 | border-collapse: collapse; |
216 | border: solid 1px #777; | 240 | border: solid 1px #777; |
217 | margin-left: 0.5em; | 241 | margin-left: 0.5em; |
218 | margin-bottom: 0.5em; | 242 | margin-bottom: 0.5em; |
219 | } | 243 | } |
220 | 244 | ||
221 | table#downloads th { | 245 | table#downloads th { |
222 | background-color: #ccc; | 246 | background-color: #ccc; |
223 | } | 247 | } |
224 | 248 | ||
225 | div#blob { | 249 | div#blob { |
226 | border: solid 1px black; | 250 | border: solid 1px black; |
227 | } | 251 | } |
228 | 252 | ||
229 | div.error { | 253 | div.error { |
230 | color: red; | 254 | color: red; |
231 | font-weight: bold; | 255 | font-weight: bold; |
232 | margin: 1em 2em; | 256 | margin: 1em 2em; |
233 | } | 257 | } |
234 | 258 | ||
235 | a.ls-blob, a.ls-dir, a.ls-mod { | 259 | a.ls-blob, a.ls-dir, a.ls-mod { |
236 | font-family: monospace; | 260 | font-family: monospace; |
237 | } | 261 | } |
238 | 262 | ||
239 | td.ls-size { | 263 | td.ls-size { |
240 | text-align: right; | 264 | text-align: right; |
241 | font-family: monospace; | 265 | font-family: monospace; |
242 | width: 10em; | 266 | width: 10em; |
243 | } | 267 | } |
244 | 268 | ||
245 | td.ls-mode { | 269 | td.ls-mode { |
246 | font-family: monospace; | 270 | font-family: monospace; |
247 | width: 10em; | 271 | width: 10em; |
248 | } | 272 | } |
249 | 273 | ||
250 | table.blob { | 274 | table.blob { |
251 | margin-top: 0.5em; | 275 | margin-top: 0.5em; |
252 | border-top: solid 1px black; | 276 | border-top: solid 1px black; |
253 | } | 277 | } |
254 | 278 | ||
255 | table.blob td.lines { | 279 | table.blob td.lines { |
256 | margin: 0; padding: 0 0 0 0.5em; | 280 | margin: 0; padding: 0 0 0 0.5em; |
@@ -1,111 +1,126 @@ | |||
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 | ||
14 | int files, add_lines, rem_lines; | 14 | int files, add_lines, rem_lines; |
15 | 15 | ||
16 | /* | ||
17 | * The list of available column colors in the commit graph. | ||
18 | */ | ||
19 | static const char *column_colors_html[] = { | ||
20 | "<span class='column1'>", | ||
21 | "<span class='column2'>", | ||
22 | "<span class='column3'>", | ||
23 | "<span class='column4'>", | ||
24 | "<span class='column5'>", | ||
25 | "<span class='column6'>", | ||
26 | "</span>", | ||
27 | }; | ||
28 | |||
29 | #define COLUMN_COLORS_HTML_MAX (ARRAY_SIZE(column_colors_html) - 1) | ||
30 | |||
16 | void count_lines(char *line, int size) | 31 | void count_lines(char *line, int size) |
17 | { | 32 | { |
18 | if (size <= 0) | 33 | if (size <= 0) |
19 | return; | 34 | return; |
20 | 35 | ||
21 | if (line[0] == '+') | 36 | if (line[0] == '+') |
22 | add_lines++; | 37 | add_lines++; |
23 | 38 | ||
24 | else if (line[0] == '-') | 39 | else if (line[0] == '-') |
25 | rem_lines++; | 40 | rem_lines++; |
26 | } | 41 | } |
27 | 42 | ||
28 | void inspect_files(struct diff_filepair *pair) | 43 | void inspect_files(struct diff_filepair *pair) |
29 | { | 44 | { |
30 | unsigned long old_size = 0; | 45 | unsigned long old_size = 0; |
31 | unsigned long new_size = 0; | 46 | unsigned long new_size = 0; |
32 | int binary = 0; | 47 | int binary = 0; |
33 | 48 | ||
34 | files++; | 49 | files++; |
35 | if (ctx.repo->enable_log_linecount) | 50 | if (ctx.repo->enable_log_linecount) |
36 | cgit_diff_files(pair->one->sha1, pair->two->sha1, &old_size, | 51 | cgit_diff_files(pair->one->sha1, pair->two->sha1, &old_size, |
37 | &new_size, &binary, 0, ctx.qry.ignorews, | 52 | &new_size, &binary, 0, ctx.qry.ignorews, |
38 | count_lines); | 53 | count_lines); |
39 | } | 54 | } |
40 | 55 | ||
41 | void show_commit_decorations(struct commit *commit) | 56 | void show_commit_decorations(struct commit *commit) |
42 | { | 57 | { |
43 | struct name_decoration *deco; | 58 | struct name_decoration *deco; |
44 | static char buf[1024]; | 59 | static char buf[1024]; |
45 | 60 | ||
46 | buf[sizeof(buf) - 1] = 0; | 61 | buf[sizeof(buf) - 1] = 0; |
47 | deco = lookup_decoration(&name_decoration, &commit->object); | 62 | deco = lookup_decoration(&name_decoration, &commit->object); |
48 | while (deco) { | 63 | while (deco) { |
49 | if (!prefixcmp(deco->name, "refs/heads/")) { | 64 | if (!prefixcmp(deco->name, "refs/heads/")) { |
50 | strncpy(buf, deco->name + 11, sizeof(buf) - 1); | 65 | strncpy(buf, deco->name + 11, sizeof(buf) - 1); |
51 | cgit_log_link(buf, NULL, "branch-deco", buf, NULL, | 66 | cgit_log_link(buf, NULL, "branch-deco", buf, NULL, |
52 | ctx.qry.vpath, 0, NULL, NULL, | 67 | ctx.qry.vpath, 0, NULL, NULL, |
53 | ctx.qry.showmsg); | 68 | ctx.qry.showmsg); |
54 | } | 69 | } |
55 | else if (!prefixcmp(deco->name, "tag: refs/tags/")) { | 70 | else if (!prefixcmp(deco->name, "tag: refs/tags/")) { |
56 | strncpy(buf, deco->name + 15, sizeof(buf) - 1); | 71 | strncpy(buf, deco->name + 15, sizeof(buf) - 1); |
57 | cgit_tag_link(buf, NULL, "tag-deco", ctx.qry.head, buf); | 72 | cgit_tag_link(buf, NULL, "tag-deco", ctx.qry.head, buf); |
58 | } | 73 | } |
59 | else if (!prefixcmp(deco->name, "refs/tags/")) { | 74 | else if (!prefixcmp(deco->name, "refs/tags/")) { |
60 | strncpy(buf, deco->name + 10, sizeof(buf) - 1); | 75 | strncpy(buf, deco->name + 10, sizeof(buf) - 1); |
61 | cgit_tag_link(buf, NULL, "tag-deco", ctx.qry.head, buf); | 76 | cgit_tag_link(buf, NULL, "tag-deco", ctx.qry.head, buf); |
62 | } | 77 | } |
63 | else if (!prefixcmp(deco->name, "refs/remotes/")) { | 78 | else if (!prefixcmp(deco->name, "refs/remotes/")) { |
64 | strncpy(buf, deco->name + 13, sizeof(buf) - 1); | 79 | strncpy(buf, deco->name + 13, sizeof(buf) - 1); |
65 | cgit_log_link(buf, NULL, "remote-deco", NULL, | 80 | cgit_log_link(buf, NULL, "remote-deco", NULL, |
66 | sha1_to_hex(commit->object.sha1), | 81 | sha1_to_hex(commit->object.sha1), |
67 | ctx.qry.vpath, 0, NULL, NULL, | 82 | ctx.qry.vpath, 0, NULL, NULL, |
68 | ctx.qry.showmsg); | 83 | ctx.qry.showmsg); |
69 | } | 84 | } |
70 | else { | 85 | else { |
71 | strncpy(buf, deco->name, sizeof(buf) - 1); | 86 | strncpy(buf, deco->name, sizeof(buf) - 1); |
72 | cgit_commit_link(buf, NULL, "deco", ctx.qry.head, | 87 | cgit_commit_link(buf, NULL, "deco", ctx.qry.head, |
73 | sha1_to_hex(commit->object.sha1), | 88 | sha1_to_hex(commit->object.sha1), |
74 | ctx.qry.vpath, 0); | 89 | ctx.qry.vpath, 0); |
75 | } | 90 | } |
76 | deco = deco->next; | 91 | deco = deco->next; |
77 | } | 92 | } |
78 | } | 93 | } |
79 | 94 | ||
80 | void print_commit(struct commit *commit, struct rev_info *revs) | 95 | void print_commit(struct commit *commit, struct rev_info *revs) |
81 | { | 96 | { |
82 | struct commitinfo *info; | 97 | struct commitinfo *info; |
83 | char *tmp; | 98 | char *tmp; |
84 | int cols = 2; | 99 | int cols = 2; |
85 | struct strbuf graphbuf = STRBUF_INIT; | 100 | struct strbuf graphbuf = STRBUF_INIT; |
86 | 101 | ||
87 | if (ctx.repo->enable_log_filecount) { | 102 | if (ctx.repo->enable_log_filecount) { |
88 | cols++; | 103 | cols++; |
89 | if (ctx.repo->enable_log_linecount) | 104 | if (ctx.repo->enable_log_linecount) |
90 | cols++; | 105 | cols++; |
91 | } | 106 | } |
92 | 107 | ||
93 | if (revs->graph) { | 108 | if (revs->graph) { |
94 | /* Advance graph until current commit */ | 109 | /* Advance graph until current commit */ |
95 | while (!graph_next_line(revs->graph, &graphbuf)) { | 110 | while (!graph_next_line(revs->graph, &graphbuf)) { |
96 | /* Print graph segment in otherwise empty table row */ | 111 | /* Print graph segment in otherwise empty table row */ |
97 | html("<tr class='nohover'><td/><td class='commitgraph'>"); | 112 | html("<tr class='nohover'><td/><td class='commitgraph'>"); |
98 | html(graphbuf.buf); | 113 | html(graphbuf.buf); |
99 | htmlf("</td><td colspan='%d' /></tr>\n", cols); | 114 | htmlf("</td><td colspan='%d' /></tr>\n", cols); |
100 | strbuf_setlen(&graphbuf, 0); | 115 | strbuf_setlen(&graphbuf, 0); |
101 | } | 116 | } |
102 | /* Current commit's graph segment is now ready in graphbuf */ | 117 | /* Current commit's graph segment is now ready in graphbuf */ |
103 | } | 118 | } |
104 | 119 | ||
105 | info = cgit_parse_commit(commit); | 120 | info = cgit_parse_commit(commit); |
106 | htmlf("<tr%s><td>", | 121 | htmlf("<tr%s><td>", |
107 | ctx.qry.showmsg ? " class='logheader'" : ""); | 122 | ctx.qry.showmsg ? " class='logheader'" : ""); |
108 | tmp = fmt("id=%s", sha1_to_hex(commit->object.sha1)); | 123 | tmp = fmt("id=%s", sha1_to_hex(commit->object.sha1)); |
109 | tmp = cgit_fileurl(ctx.repo->url, "commit", ctx.qry.vpath, tmp); | 124 | tmp = cgit_fileurl(ctx.repo->url, "commit", ctx.qry.vpath, tmp); |
110 | html_link_open(tmp, NULL, NULL); | 125 | html_link_open(tmp, NULL, NULL); |
111 | cgit_print_age(commit->date, TM_WEEK * 2, FMT_SHORTDATE); | 126 | cgit_print_age(commit->date, TM_WEEK * 2, FMT_SHORTDATE); |
@@ -180,187 +195,191 @@ void print_commit(struct commit *commit, struct rev_info *revs) | |||
180 | graph_next_line(revs->graph, &graphbuf); | 195 | graph_next_line(revs->graph, &graphbuf); |
181 | html(graphbuf.buf); | 196 | html(graphbuf.buf); |
182 | lines--; | 197 | lines--; |
183 | } | 198 | } |
184 | html("</td>\n"); | 199 | html("</td>\n"); |
185 | } | 200 | } |
186 | 201 | ||
187 | /* Print msgbuf into remainder of table row */ | 202 | /* Print msgbuf into remainder of table row */ |
188 | htmlf("<td colspan='%d'%s>\n", cols, | 203 | htmlf("<td colspan='%d'%s>\n", cols, |
189 | ctx.qry.showmsg ? " class='logmsg'" : ""); | 204 | ctx.qry.showmsg ? " class='logmsg'" : ""); |
190 | html_txt(msgbuf.buf); | 205 | html_txt(msgbuf.buf); |
191 | html("</td></tr>\n"); | 206 | html("</td></tr>\n"); |
192 | strbuf_release(&msgbuf); | 207 | strbuf_release(&msgbuf); |
193 | } | 208 | } |
194 | 209 | ||
195 | strbuf_release(&graphbuf); | 210 | strbuf_release(&graphbuf); |
196 | cgit_free_commitinfo(info); | 211 | cgit_free_commitinfo(info); |
197 | } | 212 | } |
198 | 213 | ||
199 | static const char *disambiguate_ref(const char *ref) | 214 | static const char *disambiguate_ref(const char *ref) |
200 | { | 215 | { |
201 | unsigned char sha1[20]; | 216 | unsigned char sha1[20]; |
202 | const char *longref; | 217 | const char *longref; |
203 | 218 | ||
204 | longref = fmt("refs/heads/%s", ref); | 219 | longref = fmt("refs/heads/%s", ref); |
205 | if (get_sha1(longref, sha1) == 0) | 220 | if (get_sha1(longref, sha1) == 0) |
206 | return longref; | 221 | return longref; |
207 | 222 | ||
208 | return ref; | 223 | return ref; |
209 | } | 224 | } |
210 | 225 | ||
211 | static char *next_token(char **src) | 226 | static char *next_token(char **src) |
212 | { | 227 | { |
213 | char *result; | 228 | char *result; |
214 | 229 | ||
215 | if (!src || !*src) | 230 | if (!src || !*src) |
216 | return NULL; | 231 | return NULL; |
217 | while (isspace(**src)) | 232 | while (isspace(**src)) |
218 | (*src)++; | 233 | (*src)++; |
219 | if (!**src) | 234 | if (!**src) |
220 | return NULL; | 235 | return NULL; |
221 | result = *src; | 236 | result = *src; |
222 | while (**src) { | 237 | while (**src) { |
223 | if (isspace(**src)) { | 238 | if (isspace(**src)) { |
224 | **src = '\0'; | 239 | **src = '\0'; |
225 | (*src)++; | 240 | (*src)++; |
226 | break; | 241 | break; |
227 | } | 242 | } |
228 | (*src)++; | 243 | (*src)++; |
229 | } | 244 | } |
230 | return result; | 245 | return result; |
231 | } | 246 | } |
232 | 247 | ||
233 | void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern, | 248 | void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern, |
234 | char *path, int pager) | 249 | char *path, int pager) |
235 | { | 250 | { |
236 | struct rev_info rev; | 251 | struct rev_info rev; |
237 | struct commit *commit; | 252 | struct commit *commit; |
238 | struct vector vec = VECTOR_INIT(char *); | 253 | struct vector vec = VECTOR_INIT(char *); |
239 | int i, columns = 3; | 254 | int i, columns = 3; |
240 | char *arg; | 255 | char *arg; |
241 | 256 | ||
242 | /* First argv is NULL */ | 257 | /* First argv is NULL */ |
243 | vector_push(&vec, NULL, 0); | 258 | vector_push(&vec, NULL, 0); |
244 | 259 | ||
245 | if (!tip) | 260 | if (!tip) |
246 | tip = ctx.qry.head; | 261 | tip = ctx.qry.head; |
247 | tip = disambiguate_ref(tip); | 262 | tip = disambiguate_ref(tip); |
248 | vector_push(&vec, &tip, 0); | 263 | vector_push(&vec, &tip, 0); |
249 | 264 | ||
250 | if (grep && pattern && *pattern) { | 265 | if (grep && pattern && *pattern) { |
251 | pattern = xstrdup(pattern); | 266 | pattern = xstrdup(pattern); |
252 | if (!strcmp(grep, "grep") || !strcmp(grep, "author") || | 267 | if (!strcmp(grep, "grep") || !strcmp(grep, "author") || |
253 | !strcmp(grep, "committer")) { | 268 | !strcmp(grep, "committer")) { |
254 | arg = fmt("--%s=%s", grep, pattern); | 269 | arg = fmt("--%s=%s", grep, pattern); |
255 | vector_push(&vec, &arg, 0); | 270 | vector_push(&vec, &arg, 0); |
256 | } | 271 | } |
257 | if (!strcmp(grep, "range")) { | 272 | if (!strcmp(grep, "range")) { |
258 | /* Split the pattern at whitespace and add each token | 273 | /* Split the pattern at whitespace and add each token |
259 | * as a revision expression. Do not accept other | 274 | * as a revision expression. Do not accept other |
260 | * rev-list options. Also, replace the previously | 275 | * rev-list options. Also, replace the previously |
261 | * pushed tip (it's no longer relevant). | 276 | * pushed tip (it's no longer relevant). |
262 | */ | 277 | */ |
263 | vec.count--; | 278 | vec.count--; |
264 | while ((arg = next_token(&pattern))) { | 279 | while ((arg = next_token(&pattern))) { |
265 | if (*arg == '-') { | 280 | if (*arg == '-') { |
266 | fprintf(stderr, "Bad range expr: %s\n", | 281 | fprintf(stderr, "Bad range expr: %s\n", |
267 | arg); | 282 | arg); |
268 | break; | 283 | break; |
269 | } | 284 | } |
270 | vector_push(&vec, &arg, 0); | 285 | vector_push(&vec, &arg, 0); |
271 | } | 286 | } |
272 | } | 287 | } |
273 | } | 288 | } |
274 | if (ctx.repo->enable_commit_graph) { | 289 | if (ctx.repo->enable_commit_graph) { |
275 | static const char *graph_arg = "--graph"; | 290 | static const char *graph_arg = "--graph"; |
291 | static const char *color_arg = "--color"; | ||
276 | vector_push(&vec, &graph_arg, 0); | 292 | vector_push(&vec, &graph_arg, 0); |
293 | vector_push(&vec, &color_arg, 0); | ||
294 | graph_set_column_colors(column_colors_html, | ||
295 | COLUMN_COLORS_HTML_MAX); | ||
277 | } | 296 | } |
278 | 297 | ||
279 | if (path) { | 298 | if (path) { |
280 | arg = "--"; | 299 | arg = "--"; |
281 | vector_push(&vec, &arg, 0); | 300 | vector_push(&vec, &arg, 0); |
282 | vector_push(&vec, &path, 0); | 301 | vector_push(&vec, &path, 0); |
283 | } | 302 | } |
284 | 303 | ||
285 | /* Make sure the vector is NULL-terminated */ | 304 | /* Make sure the vector is NULL-terminated */ |
286 | vector_push(&vec, NULL, 0); | 305 | vector_push(&vec, NULL, 0); |
287 | vec.count--; | 306 | vec.count--; |
288 | 307 | ||
289 | init_revisions(&rev, NULL); | 308 | init_revisions(&rev, NULL); |
290 | rev.abbrev = DEFAULT_ABBREV; | 309 | rev.abbrev = DEFAULT_ABBREV; |
291 | rev.commit_format = CMIT_FMT_DEFAULT; | 310 | rev.commit_format = CMIT_FMT_DEFAULT; |
292 | rev.verbose_header = 1; | 311 | rev.verbose_header = 1; |
293 | rev.show_root_diff = 0; | 312 | rev.show_root_diff = 0; |
294 | setup_revisions(vec.count, vec.data, &rev, NULL); | 313 | setup_revisions(vec.count, vec.data, &rev, NULL); |
295 | load_ref_decorations(DECORATE_FULL_REFS); | 314 | load_ref_decorations(DECORATE_FULL_REFS); |
296 | rev.show_decorations = 1; | 315 | rev.show_decorations = 1; |
297 | rev.grep_filter.regflags |= REG_ICASE; | 316 | rev.grep_filter.regflags |= REG_ICASE; |
298 | compile_grep_patterns(&rev.grep_filter); | 317 | compile_grep_patterns(&rev.grep_filter); |
299 | prepare_revision_walk(&rev); | 318 | prepare_revision_walk(&rev); |
300 | 319 | ||
301 | if (pager) | 320 | if (pager) |
302 | html("<table class='list nowrap'>"); | 321 | html("<table class='list nowrap'>"); |
303 | 322 | ||
304 | html("<tr class='nohover'><th class='left'>Age</th>"); | 323 | html("<tr class='nohover'><th class='left'>Age</th>"); |
305 | if (ctx.repo->enable_commit_graph) | 324 | if (ctx.repo->enable_commit_graph) |
306 | html("<th></th>"); | 325 | html("<th></th>"); |
307 | html("<th class='left'>Commit message"); | 326 | html("<th class='left'>Commit message"); |
308 | if (pager) { | 327 | if (pager) { |
309 | html(" ("); | 328 | html(" ("); |
310 | cgit_log_link(ctx.qry.showmsg ? "Collapse" : "Expand", NULL, | 329 | cgit_log_link(ctx.qry.showmsg ? "Collapse" : "Expand", NULL, |
311 | NULL, ctx.qry.head, ctx.qry.sha1, | 330 | NULL, ctx.qry.head, ctx.qry.sha1, |
312 | ctx.qry.vpath, ctx.qry.ofs, ctx.qry.grep, | 331 | ctx.qry.vpath, ctx.qry.ofs, ctx.qry.grep, |
313 | ctx.qry.search, ctx.qry.showmsg ? 0 : 1); | 332 | ctx.qry.search, ctx.qry.showmsg ? 0 : 1); |
314 | html(")"); | 333 | html(")"); |
315 | } | 334 | } |
316 | html("</th><th class='left'>Author</th>"); | 335 | html("</th><th class='left'>Author</th>"); |
317 | if (ctx.repo->enable_log_filecount) { | 336 | if (ctx.repo->enable_log_filecount) { |
318 | html("<th class='left'>Files</th>"); | 337 | html("<th class='left'>Files</th>"); |
319 | columns++; | 338 | columns++; |
320 | if (ctx.repo->enable_log_linecount) { | 339 | if (ctx.repo->enable_log_linecount) { |
321 | html("<th class='left'>Lines</th>"); | 340 | html("<th class='left'>Lines</th>"); |
322 | columns++; | 341 | columns++; |
323 | } | 342 | } |
324 | } | 343 | } |
325 | html("</tr>\n"); | 344 | html("</tr>\n"); |
326 | 345 | ||
327 | if (ofs<0) | 346 | if (ofs<0) |
328 | ofs = 0; | 347 | ofs = 0; |
329 | 348 | ||
330 | for (i = 0; i < ofs && (commit = get_revision(&rev)) != NULL; i++) { | 349 | for (i = 0; i < ofs && (commit = get_revision(&rev)) != NULL; i++) { |
331 | free(commit->buffer); | 350 | free(commit->buffer); |
332 | commit->buffer = NULL; | 351 | commit->buffer = NULL; |
333 | free_commit_list(commit->parents); | 352 | free_commit_list(commit->parents); |
334 | commit->parents = NULL; | 353 | commit->parents = NULL; |
335 | } | 354 | } |
336 | 355 | ||
337 | for (i = 0; i < cnt && (commit = get_revision(&rev)) != NULL; i++) { | 356 | for (i = 0; i < cnt && (commit = get_revision(&rev)) != NULL; i++) { |
338 | print_commit(commit, &rev); | 357 | print_commit(commit, &rev); |
339 | free(commit->buffer); | 358 | free(commit->buffer); |
340 | commit->buffer = NULL; | 359 | commit->buffer = NULL; |
341 | free_commit_list(commit->parents); | 360 | free_commit_list(commit->parents); |
342 | commit->parents = NULL; | 361 | commit->parents = NULL; |
343 | } | 362 | } |
344 | if (pager) { | 363 | if (pager) { |
345 | html("</table><div class='pager'>"); | 364 | html("</table><div class='pager'>"); |
346 | if (ofs > 0) { | 365 | if (ofs > 0) { |
347 | cgit_log_link("[prev]", NULL, NULL, ctx.qry.head, | 366 | cgit_log_link("[prev]", NULL, NULL, ctx.qry.head, |
348 | ctx.qry.sha1, ctx.qry.vpath, | 367 | ctx.qry.sha1, ctx.qry.vpath, |
349 | ofs - cnt, ctx.qry.grep, | 368 | ofs - cnt, ctx.qry.grep, |
350 | ctx.qry.search, ctx.qry.showmsg); | 369 | ctx.qry.search, ctx.qry.showmsg); |
351 | html(" "); | 370 | html(" "); |
352 | } | 371 | } |
353 | if ((commit = get_revision(&rev)) != NULL) { | 372 | if ((commit = get_revision(&rev)) != NULL) { |
354 | cgit_log_link("[next]", NULL, NULL, ctx.qry.head, | 373 | cgit_log_link("[next]", NULL, NULL, ctx.qry.head, |
355 | ctx.qry.sha1, ctx.qry.vpath, | 374 | ctx.qry.sha1, ctx.qry.vpath, |
356 | ofs + cnt, ctx.qry.grep, | 375 | ofs + cnt, ctx.qry.grep, |
357 | ctx.qry.search, ctx.qry.showmsg); | 376 | ctx.qry.search, ctx.qry.showmsg); |
358 | } | 377 | } |
359 | html("</div>"); | 378 | html("</div>"); |
360 | } else if ((commit = get_revision(&rev)) != NULL) { | 379 | } else if ((commit = get_revision(&rev)) != NULL) { |
361 | html("<tr class='nohover'><td colspan='3'>"); | 380 | html("<tr class='nohover'><td colspan='3'>"); |
362 | cgit_log_link("[...]", NULL, NULL, ctx.qry.head, NULL, | 381 | cgit_log_link("[...]", NULL, NULL, ctx.qry.head, NULL, |
363 | ctx.qry.vpath, 0, NULL, NULL, ctx.qry.showmsg); | 382 | ctx.qry.vpath, 0, NULL, NULL, ctx.qry.showmsg); |
364 | html("</td></tr>\n"); | 383 | html("</td></tr>\n"); |
365 | } | 384 | } |
366 | } | 385 | } |