History

Merge branch 'jh/path-limit'

Lars Hjemli committed 16 years ago

Commit 37a24e42 parents 47187b3 a2cbd3c17 files · +275 −164Browse files

Unified · Split

17 files
  1. cgit.c +6 −0
  2. cgit.css +8 −2
  3. cgit.h +1 −0
  4. cgitrc.5.txt +1 −1
  5. cmd.c +23 −23
  6. cmd.h +2 −1
  7. shared.c +0 −1
  8. ui-commit.c +12 −8
  9. ui-commit.h +1 −1
  10. ui-diff.c +5 −3
  11. ui-log.c +15 −12
  12. ui-patch.c +4 −2
  13. ui-patch.h +1 −1
  14. ui-refs.c +1 −1
  15. ui-shared.c +150 −66
  16. ui-shared.h +43 −29
  17. ui-tree.c +2 −13
cgit.c+6−0
@@ -433,6 +433,12 @@ static void process_request(void *cbdata) · 432 unmodified lines
433433 return;
434434 }
435435
436+ /* If cmd->want_vpath is set, assume ctx->qry.path contains a "virtual"
437+ * in-project path limit to be made available at ctx->qry.vpath.
438+ * Otherwise, no path limit is in effect (ctx->qry.vpath = NULL).
439+ */
440+ ctx->qry.vpath = cmd->want_vpath ? ctx->qry.path : NULL;
441+
436442 if (cmd->want_repo && !ctx->repo) {
437443 cgit_print_http_headers(ctx);
438444 cgit_print_docstart(ctx);
cgit.css+8−2
@@ -64,7 +64,7 @@ table#header td.sub { · 63 unmodified lines
6464 }
6565
6666 table.tabs {
67− /* border-bottom: solid 2px #ccc; */
67+ border-bottom: solid 3px #ccc;
6868 border-collapse: collapse;
6969 margin-top: 2em;
7070 margin-bottom: 0px;
@@ -102,10 +102,16 @@ table.tabs td.form select { · 31 unmodified lines
102102 font-size: 90%;
103103 }
104104
105+div.path {
106+ margin: 0px;
107+ padding: 5px 2em 2px 2em;
108+ color: #000;
109+ background-color: #eee;
110+}
111+
105112 div.content {
106113 margin: 0px;
107114 padding: 2em;
108− border-top: solid 3px #ccc;
109115 border-bottom: solid 3px #ccc;
110116 }
111117
cgit.h+1−0
@@ -147,6 +147,7 @@ struct cgit_query { · 146 unmodified lines
147147 int showmsg;
148148 int ssdiff;
149149 int show_all;
150+ char *vpath;
150151 };
151152
152153 struct cgit_config {
cgitrc.5.txt+1−1
@@ -444,7 +444,7 @@ snapshots=tar.gz tar.bz2 zip · 443 unmodified lines
444444 ## List of common mimetypes
445445 ##
446446
447−mimetype.git=image/git
447+mimetype.gif=image/gif
448448 mimetype.html=text/html
449449 mimetype.jpg=image/jpeg
450450 mimetype.jpeg=image/jpeg
cmd.c+23−23
@@ -51,7 +51,7 @@ static void blob_fn(struct cgit_context *ctx) · 50 unmodified lines
5151
5252 static void commit_fn(struct cgit_context *ctx)
5353 {
54− cgit_print_commit(ctx->qry.sha1);
54+ cgit_print_commit(ctx->qry.sha1, ctx->qry.path);
5555 }
5656
5757 static void diff_fn(struct cgit_context *ctx)
@@ -90,7 +90,7 @@ static void repolist_fn(struct cgit_context *ctx) · 32 unmodified lines
9090
9191 static void patch_fn(struct cgit_context *ctx)
9292 {
93− cgit_print_patch(ctx->qry.sha1);
93+ cgit_print_patch(ctx->qry.sha1, ctx->qry.path);
9494 }
9595
9696 static void plain_fn(struct cgit_context *ctx)
@@ -129,31 +129,31 @@ static void tree_fn(struct cgit_context *ctx) · 32 unmodified lines
129129 cgit_print_tree(ctx->qry.sha1, ctx->qry.path);
130130 }
131131
132−#define def_cmd(name, want_repo, want_layout) \
133− {#name, name##_fn, want_repo, want_layout}
132+#define def_cmd(name, want_repo, want_layout, want_vpath) \
133+ {#name, name##_fn, want_repo, want_layout, want_vpath}
134134
135135 struct cgit_cmd *cgit_get_cmd(struct cgit_context *ctx)
136136 {
137137 static struct cgit_cmd cmds[] = {
138− def_cmd(HEAD, 1, 0),
139− def_cmd(atom, 1, 0),
140− def_cmd(about, 0, 1),
141− def_cmd(blob, 1, 0),
142− def_cmd(commit, 1, 1),
143− def_cmd(diff, 1, 1),
144− def_cmd(info, 1, 0),
145− def_cmd(log, 1, 1),
146− def_cmd(ls_cache, 0, 0),
147− def_cmd(objects, 1, 0),
148− def_cmd(patch, 1, 0),
149− def_cmd(plain, 1, 0),
150− def_cmd(refs, 1, 1),
151− def_cmd(repolist, 0, 0),
152− def_cmd(snapshot, 1, 0),
153− def_cmd(stats, 1, 1),
154− def_cmd(summary, 1, 1),
155− def_cmd(tag, 1, 1),
156− def_cmd(tree, 1, 1),
138+ def_cmd(HEAD, 1, 0, 0),
139+ def_cmd(atom, 1, 0, 0),
140+ def_cmd(about, 0, 1, 0),
141+ def_cmd(blob, 1, 0, 0),
142+ def_cmd(commit, 1, 1, 1),
143+ def_cmd(diff, 1, 1, 1),
144+ def_cmd(info, 1, 0, 0),
145+ def_cmd(log, 1, 1, 1),
146+ def_cmd(ls_cache, 0, 0, 0),
147+ def_cmd(objects, 1, 0, 0),
148+ def_cmd(patch, 1, 0, 1),
149+ def_cmd(plain, 1, 0, 0),
150+ def_cmd(refs, 1, 1, 0),
151+ def_cmd(repolist, 0, 0, 0),
152+ def_cmd(snapshot, 1, 0, 0),
153+ def_cmd(stats, 1, 1, 1),
154+ def_cmd(summary, 1, 1, 0),
155+ def_cmd(tag, 1, 1, 0),
156+ def_cmd(tree, 1, 1, 1),
157157 };
158158 int i;
159159
cmd.h+2−1
@@ -7,7 +7,8 @@ struct cgit_cmd { · 6 unmodified lines
77 const char *name;
88 cgit_cmd_fn fn;
99 unsigned int want_repo:1,
10− want_layout:1;
10+ want_layout:1,
11+ want_vpath:1;
1112 };
1213
1314 extern struct cgit_cmd *cgit_get_cmd(struct cgit_context *ctx);
shared.c+0−1
@@ -10,7 +10,6 @@ · 9 unmodified lines
1010
1111 struct cgit_repolist cgit_repolist;
1212 struct cgit_context ctx;
13−int cgit_cmd;
1413
1514 int chk_zero(int result, char *msg)
1615 {
ui-commit.c+12−8
@@ -12,7 +12,7 @@ · 11 unmodified lines
1212 #include "ui-diff.h"
1313 #include "ui-log.h"
1414
15−void cgit_print_commit(char *hex)
15+void cgit_print_commit(char *hex, const char *prefix)
1616 {
1717 struct commit *commit, *parent;
1818 struct commitinfo *info, *parent_info;
@@ -58,19 +58,23 @@ void cgit_print_commit(char *hex) · 39 unmodified lines
5858 html("</td></tr>\n");
5959 html("<tr><th>commit</th><td colspan='2' class='sha1'>");
6060 tmp = sha1_to_hex(commit->object.sha1);
61− cgit_commit_link(tmp, NULL, NULL, ctx.qry.head, tmp, 0);
61+ cgit_commit_link(tmp, NULL, NULL, ctx.qry.head, tmp, prefix, 0);
6262 html(" (");
63− cgit_patch_link("patch", NULL, NULL, NULL, tmp);
63+ cgit_patch_link("patch", NULL, NULL, NULL, tmp, prefix);
6464 html(") (");
6565 if ((ctx.qry.ssdiff && !ctx.cfg.ssdiff) || (!ctx.qry.ssdiff && ctx.cfg.ssdiff))
66− cgit_commit_link("unidiff", NULL, NULL, ctx.qry.head, tmp, 1);
66+ cgit_commit_link("unidiff", NULL, NULL, ctx.qry.head, tmp, prefix, 1);
6767 else
68− cgit_commit_link("side-by-side diff", NULL, NULL, ctx.qry.head, tmp, 1);
68+ cgit_commit_link("side-by-side diff", NULL, NULL, ctx.qry.head, tmp, prefix, 1);
6969 html(")</td></tr>\n");
7070 html("<tr><th>tree</th><td colspan='2' class='sha1'>");
7171 tmp = xstrdup(hex);
7272 cgit_tree_link(sha1_to_hex(commit->tree->object.sha1), NULL, NULL,
7373 ctx.qry.head, tmp, NULL);
74+ if (prefix) {
75+ html(" /");
76+ cgit_tree_link(prefix, NULL, NULL, ctx.qry.head, tmp, prefix);
77+ }
7478 html("</td></tr>\n");
7579 for (p = commit->parents; p ; p = p->next) {
7680 parent = lookup_commit_reference(p->item->object.sha1);
@@ -87,10 +91,10 @@ void cgit_print_commit(char *hex) · 10 unmodified lines
8791 parent_info = cgit_parse_commit(parent);
8892 tmp2 = parent_info->subject;
8993 }
90− cgit_commit_link(tmp2, NULL, NULL, ctx.qry.head, tmp, 0);
94+ cgit_commit_link(tmp2, NULL, NULL, ctx.qry.head, tmp, prefix, 0);
9195 html(" (");
9296 cgit_diff_link("diff", NULL, NULL, ctx.qry.head, hex,
93− sha1_to_hex(p->item->object.sha1), NULL, 0);
97+ sha1_to_hex(p->item->object.sha1), prefix, 0);
9498 html(")</td></tr>");
9599 parents++;
96100 }
@@ -121,7 +125,7 @@ void cgit_print_commit(char *hex) · 24 unmodified lines
121125 tmp = sha1_to_hex(commit->parents->item->object.sha1);
122126 else
123127 tmp = NULL;
124− cgit_print_diff(ctx.qry.sha1, tmp, NULL);
128+ cgit_print_diff(ctx.qry.sha1, tmp, prefix);
125129 }
126130 cgit_free_commitinfo(info);
127131 }
ui-commit.h+1−1
@@ -1,6 +1,6 @@
11 #ifndef UI_COMMIT_H
22 #define UI_COMMIT_H
33
4−extern void cgit_print_commit(char *hex);
4+extern void cgit_print_commit(char *hex, const char *prefix);
55
66 #endif /* UI_COMMIT_H */
ui-diff.c+5−3
@@ -154,17 +154,19 @@ static void inspect_filepair(struct diff_filepair *pair) · 153 unmodified lines
154154 }
155155
156156 void cgit_print_diffstat(const unsigned char *old_sha1,
157− const unsigned char *new_sha1)
157+ const unsigned char *new_sha1, const char *prefix)
158158 {
159159 int i;
160160
161161 html("<div class='diffstat-header'>");
162162 cgit_diff_link("Diffstat", NULL, NULL, ctx.qry.head, ctx.qry.sha1,
163163 ctx.qry.sha2, NULL, 0);
164+ if (prefix)
165+ htmlf(" (limited to '%s')", prefix);
164166 html("</div>");
165167 html("<table summary='diffstat' class='diffstat'>");
166168 max_changes = 0;
167− cgit_diff_tree(old_sha1, new_sha1, inspect_filepair, NULL);
169+ cgit_diff_tree(old_sha1, new_sha1, inspect_filepair, prefix);
168170 for(i = 0; i<files; i++)
169171 print_fileinfo(&items[i]);
170172 html("</table>");
@@ -338,7 +340,7 @@ void cgit_print_diff(const char *new_rev, const char *old_rev, const char *prefi · 167 unmodified lines
338340 use_ssdiff = 1;
339341
340342 print_ssdiff_link();
341− cgit_print_diffstat(old_rev_sha1, new_rev_sha1);
343+ cgit_print_diffstat(old_rev_sha1, new_rev_sha1, prefix);
342344
343345 if (use_ssdiff) {
344346 html("<table summary='ssdiff' class='ssdiff'>");
ui-log.c+15−12
@@ -46,8 +46,9 @@ void show_commit_decorations(struct commit *commit) · 45 unmodified lines
4646 while (deco) {
4747 if (!prefixcmp(deco->name, "refs/heads/")) {
4848 strncpy(buf, deco->name + 11, sizeof(buf) - 1);
49− cgit_log_link(buf, NULL, "branch-deco", buf, NULL, NULL,
50− 0, NULL, NULL, ctx.qry.showmsg);
49+ cgit_log_link(buf, NULL, "branch-deco", buf, NULL,
50+ ctx.qry.vpath, 0, NULL, NULL,
51+ ctx.qry.showmsg);
5152 }
5253 else if (!prefixcmp(deco->name, "tag: refs/tags/")) {
5354 strncpy(buf, deco->name + 15, sizeof(buf) - 1);
@@ -60,13 +61,15 @@ void show_commit_decorations(struct commit *commit) · 6 unmodified lines
6061 else if (!prefixcmp(deco->name, "refs/remotes/")) {
6162 strncpy(buf, deco->name + 13, sizeof(buf) - 1);
6263 cgit_log_link(buf, NULL, "remote-deco", NULL,
63− sha1_to_hex(commit->object.sha1), NULL,
64− 0, NULL, NULL, ctx.qry.showmsg);
64+ sha1_to_hex(commit->object.sha1),
65+ ctx.qry.vpath, 0, NULL, NULL,
66+ ctx.qry.showmsg);
6567 }
6668 else {
6769 strncpy(buf, deco->name, sizeof(buf) - 1);
6870 cgit_commit_link(buf, NULL, "deco", ctx.qry.head,
69− sha1_to_hex(commit->object.sha1), 0);
71+ sha1_to_hex(commit->object.sha1),
72+ ctx.qry.vpath, 0);
7073 }
7174 deco = deco->next;
7275 }
@@ -82,14 +85,14 @@ void print_commit(struct commit *commit) · 9 unmodified lines
8285 htmlf("<tr%s><td>",
8386 ctx.qry.showmsg ? " class='logheader'" : "");
8487 tmp = fmt("id=%s", sha1_to_hex(commit->object.sha1));
85− tmp = cgit_pageurl(ctx.repo->url, "commit", tmp);
88+ tmp = cgit_fileurl(ctx.repo->url, "commit", ctx.qry.vpath, tmp);
8689 html_link_open(tmp, NULL, NULL);
8790 cgit_print_age(commit->date, TM_WEEK * 2, FMT_SHORTDATE);
8891 html_link_close();
8992 htmlf("</td><td%s>",
9093 ctx.qry.showmsg ? " class='logsubject'" : "");
9194 cgit_commit_link(info->subject, NULL, NULL, ctx.qry.head,
92− sha1_to_hex(commit->object.sha1), 0);
95+ sha1_to_hex(commit->object.sha1), ctx.qry.vpath, 0);
9396 show_commit_decorations(commit);
9497 html("</td><td>");
9598 html_txt(info->author);
@@ -176,7 +179,7 @@ void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern · 80 unmodified lines
176179 html(" (");
177180 cgit_log_link(ctx.qry.showmsg ? "Collapse" : "Expand", NULL,
178181 NULL, ctx.qry.head, ctx.qry.sha1,
179− ctx.qry.path, ctx.qry.ofs, ctx.qry.grep,
182+ ctx.qry.vpath, ctx.qry.ofs, ctx.qry.grep,
180183 ctx.qry.search, ctx.qry.showmsg ? 0 : 1);
181184 html(")");
182185 }
@@ -213,22 +216,22 @@ void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern · 30 unmodified lines
213216 columns);
214217 if (ofs > 0) {
215218 cgit_log_link("[prev]", NULL, NULL, ctx.qry.head,
216− ctx.qry.sha1, ctx.qry.path,
219+ ctx.qry.sha1, ctx.qry.vpath,
217220 ofs - cnt, ctx.qry.grep,
218221 ctx.qry.search, ctx.qry.showmsg);
219222 html("&nbsp;");
220223 }
221224 if ((commit = get_revision(&rev)) != NULL) {
222225 cgit_log_link("[next]", NULL, NULL, ctx.qry.head,
223− ctx.qry.sha1, ctx.qry.path,
226+ ctx.qry.sha1, ctx.qry.vpath,
224227 ofs + cnt, ctx.qry.grep,
225228 ctx.qry.search, ctx.qry.showmsg);
226229 }
227230 html("</div>");
228231 } else if ((commit = get_revision(&rev)) != NULL) {
229232 html("<tr class='nohover'><td colspan='3'>");
230− cgit_log_link("[...]", NULL, NULL, ctx.qry.head, NULL, NULL, 0,
231− NULL, NULL, ctx.qry.showmsg);
233+ cgit_log_link("[...]", NULL, NULL, ctx.qry.head, NULL,
234+ ctx.qry.vpath, 0, NULL, NULL, ctx.qry.showmsg);
232235 html("</td></tr>\n");
233236 }
234237 }
ui-patch.c+4−2
@@ -77,7 +77,7 @@ static void filepair_cb(struct diff_filepair *pair) · 76 unmodified lines
7777 html("Binary files differ\n");
7878 }
7979
80−void cgit_print_patch(char *hex)
80+void cgit_print_patch(char *hex, const char *prefix)
8181 {
8282 struct commit *commit;
8383 struct commitinfo *info;
@@ -122,7 +122,9 @@ void cgit_print_patch(char *hex) · 38 unmodified lines
122122 html("\n");
123123 }
124124 html("---\n");
125− cgit_diff_tree(old_sha1, sha1, filepair_cb, NULL);
125+ if (prefix)
126+ htmlf("(limited to '%s')\n\n", prefix);
127+ cgit_diff_tree(old_sha1, sha1, filepair_cb, prefix);
126128 html("--\n");
127129 htmlf("cgit %s\n", CGIT_VERSION);
128130 cgit_free_commitinfo(info);
ui-patch.h+1−1
@@ -1,6 +1,6 @@
11 #ifndef UI_PATCH_H
22 #define UI_PATCH_H
33
4−extern void cgit_print_patch(char *hex);
4+extern void cgit_print_patch(char *hex, const char *prefix);
55
66 #endif /* UI_PATCH_H */
ui-refs.c+1−1
@@ -74,7 +74,7 @@ static int print_branch(struct refinfo *ref) · 73 unmodified lines
7474 html("</td><td>");
7575
7676 if (ref->object->type == OBJ_COMMIT) {
77− cgit_commit_link(info->subject, NULL, NULL, name, NULL, 0);
77+ cgit_commit_link(info->subject, NULL, NULL, name, NULL, NULL, 0);
7878 html("</td><td>");
7979 html_txt(info->author);
8080 html("</td><td colspan='2'>");
ui-shared.c+150−66
@@ -27,7 +27,7 @@ static char *http_date(time_t t) · 26 unmodified lines
2727 tm->tm_hour, tm->tm_min, tm->tm_sec);
2828 }
2929
30−void cgit_print_error(char *msg)
30+void cgit_print_error(const char *msg)
3131 {
3232 html("<div class='error'>");
3333 html_txt(msg);
@@ -133,7 +133,7 @@ char *cgit_currurl() · 99 unmodified lines
133133 return fmt("%s/", ctx.cfg.virtual_root);
134134 }
135135
136−static void site_url(char *page, char *search, int ofs)
136+static void site_url(const char *page, const char *search, int ofs)
137137 {
138138 char *delim = "?";
139139
@@ -160,8 +160,8 @@ static void site_url(char *page, char *search, int ofs) · 20 unmodified lines
160160 }
161161 }
162162
163−static void site_link(char *page, char *name, char *title, char *class,
164− char *search, int ofs)
163+static void site_link(const char *page, const char *name, const char *title,
164+ const char *class, const char *search, int ofs)
165165 {
166166 html("<a");
167167 if (title) {
@@ -181,14 +181,14 @@ static void site_link(char *page, char *name, char *title, char *class, · 13 unmodified lines
181181 html("</a>");
182182 }
183183
184−void cgit_index_link(char *name, char *title, char *class, char *pattern,
185− int ofs)
184+void cgit_index_link(const char *name, const char *title, const char *class,
185+ const char *pattern, int ofs)
186186 {
187187 site_link(NULL, name, title, class, pattern, ofs);
188188 }
189189
190−static char *repolink(char *title, char *class, char *page, char *head,
191− char *path)
190+static char *repolink(const char *title, const char *class, const char *page,
191+ const char *head, const char *path)
192192 {
193193 char *delim = "?";
194194
@@ -240,8 +240,9 @@ static char *repolink(char *title, char *class, char *page, char *head, · 45 unmodified lines
240240 return fmt("%s", delim);
241241 }
242242
243−static void reporevlink(char *page, char *name, char *title, char *class,
244− char *head, char *rev, char *path)
243+static void reporevlink(const char *page, const char *name, const char *title,
244+ const char *class, const char *head, const char *rev,
245+ const char *path)
245246 {
246247 char *delim;
247248
@@ -256,32 +257,33 @@ static void reporevlink(char *page, char *name, char *title, char *class, · 8 unmodified lines
256257 html("</a>");
257258 }
258259
259−void cgit_summary_link(char *name, char *title, char *class, char *head)
260+void cgit_summary_link(const char *name, const char *title, const char *class,
261+ const char *head)
260262 {
261263 reporevlink(NULL, name, title, class, head, NULL, NULL);
262264 }
263265
264−void cgit_tag_link(char *name, char *title, char *class, char *head,
265− char *rev)
266+void cgit_tag_link(const char *name, const char *title, const char *class,
267+ const char *head, const char *rev)
266268 {
267269 reporevlink("tag", name, title, class, head, rev, NULL);
268270 }
269271
270−void cgit_tree_link(char *name, char *title, char *class, char *head,
271− char *rev, char *path)
272+void cgit_tree_link(const char *name, const char *title, const char *class,
273+ const char *head, const char *rev, const char *path)
272274 {
273275 reporevlink("tree", name, title, class, head, rev, path);
274276 }
275277
276−void cgit_plain_link(char *name, char *title, char *class, char *head,
277− char *rev, char *path)
278+void cgit_plain_link(const char *name, const char *title, const char *class,
279+ const char *head, const char *rev, const char *path)
278280 {
279281 reporevlink("plain", name, title, class, head, rev, path);
280282 }
281283
282−void cgit_log_link(char *name, char *title, char *class, char *head,
283− char *rev, char *path, int ofs, char *grep, char *pattern,
284− int showmsg)
284+void cgit_log_link(const char *name, const char *title, const char *class,
285+ const char *head, const char *rev, const char *path,
286+ int ofs, const char *grep, const char *pattern, int showmsg)
285287 {
286288 char *delim;
287289
@@ -316,8 +318,9 @@ void cgit_log_link(char *name, char *title, char *class, char *head, · 28 unmodified lines
316318 html("</a>");
317319 }
318320
319−void cgit_commit_link(char *name, char *title, char *class, char *head,
320− char *rev, int toggle_ssdiff)
321+void cgit_commit_link(char *name, const char *title, const char *class,
322+ const char *head, const char *rev, const char *path,
323+ int toggle_ssdiff)
321324 {
322325 if (strlen(name) > ctx.cfg.max_msg_len && ctx.cfg.max_msg_len >= 15) {
323326 name[ctx.cfg.max_msg_len] = '\0';
@@ -328,7 +331,7 @@ void cgit_commit_link(char *name, char *title, char *class, char *head, · 4 unmodified lines
328331
329332 char *delim;
330333
331− delim = repolink(title, class, "commit", head, NULL);
334+ delim = repolink(title, class, "commit", head, path);
332335 if (rev && strcmp(rev, ctx.qry.head)) {
333336 html(delim);
334337 html("id=");
@@ -344,21 +347,22 @@ void cgit_commit_link(char *name, char *title, char *class, char *head, · 9 unmodified lines
344347 html("</a>");
345348 }
346349
347−void cgit_refs_link(char *name, char *title, char *class, char *head,
348− char *rev, char *path)
350+void cgit_refs_link(const char *name, const char *title, const char *class,
351+ const char *head, const char *rev, const char *path)
349352 {
350353 reporevlink("refs", name, title, class, head, rev, path);
351354 }
352355
353−void cgit_snapshot_link(char *name, char *title, char *class, char *head,
354− char *rev, char *archivename)
356+void cgit_snapshot_link(const char *name, const char *title, const char *class,
357+ const char *head, const char *rev,
358+ const char *archivename)
355359 {
356360 reporevlink("snapshot", name, title, class, head, rev, archivename);
357361 }
358362
359−void cgit_diff_link(char *name, char *title, char *class, char *head,
360− char *new_rev, char *old_rev, char *path,
361− int toggle_ssdiff)
363+void cgit_diff_link(const char *name, const char *title, const char *class,
364+ const char *head, const char *new_rev, const char *old_rev,
365+ const char *path, int toggle_ssdiff)
362366 {
363367 char *delim;
364368
@@ -384,18 +388,76 @@ void cgit_diff_link(char *name, char *title, char *class, char *head, · 19 unmodified lines
384388 html("</a>");
385389 }
386390
387−void cgit_patch_link(char *name, char *title, char *class, char *head,
388− char *rev)
391+void cgit_patch_link(const char *name, const char *title, const char *class,
392+ const char *head, const char *rev, const char *path)
389393 {
390− reporevlink("patch", name, title, class, head, rev, NULL);
394+ reporevlink("patch", name, title, class, head, rev, path);
391395 }
392396
393−void cgit_stats_link(char *name, char *title, char *class, char *head,
394− char *path)
397+void cgit_stats_link(const char *name, const char *title, const char *class,
398+ const char *head, const char *path)
395399 {
396400 reporevlink("stats", name, title, class, head, NULL, path);
397401 }
398402
403+void cgit_self_link(char *name, const char *title, const char *class,
404+ struct cgit_context *ctx)
405+{
406+ if (!strcmp(ctx->qry.page, "repolist"))
407+ return cgit_index_link(name, title, class, ctx->qry.search,
408+ ctx->qry.ofs);
409+ else if (!strcmp(ctx->qry.page, "summary"))
410+ return cgit_summary_link(name, title, class, ctx->qry.head);
411+ else if (!strcmp(ctx->qry.page, "tag"))
412+ return cgit_tag_link(name, title, class, ctx->qry.head,
413+ ctx->qry.has_sha1 ? ctx->qry.sha1 : NULL);
414+ else if (!strcmp(ctx->qry.page, "tree"))
415+ return cgit_tree_link(name, title, class, ctx->qry.head,
416+ ctx->qry.has_sha1 ? ctx->qry.sha1 : NULL,
417+ ctx->qry.path);
418+ else if (!strcmp(ctx->qry.page, "plain"))
419+ return cgit_plain_link(name, title, class, ctx->qry.head,
420+ ctx->qry.has_sha1 ? ctx->qry.sha1 : NULL,
421+ ctx->qry.path);
422+ else if (!strcmp(ctx->qry.page, "log"))
423+ return cgit_log_link(name, title, class, ctx->qry.head,
424+ ctx->qry.has_sha1 ? ctx->qry.sha1 : NULL,
425+ ctx->qry.path, ctx->qry.ofs,
426+ ctx->qry.grep, ctx->qry.search,
427+ ctx->qry.showmsg);
428+ else if (!strcmp(ctx->qry.page, "commit"))
429+ return cgit_commit_link(name, title, class, ctx->qry.head,
430+ ctx->qry.has_sha1 ? ctx->qry.sha1 : NULL,
431+ ctx->qry.path, 0);
432+ else if (!strcmp(ctx->qry.page, "patch"))
433+ return cgit_patch_link(name, title, class, ctx->qry.head,
434+ ctx->qry.has_sha1 ? ctx->qry.sha1 : NULL,
435+ ctx->qry.path);
436+ else if (!strcmp(ctx->qry.page, "refs"))
437+ return cgit_refs_link(name, title, class, ctx->qry.head,
438+ ctx->qry.has_sha1 ? ctx->qry.sha1 : NULL,
439+ ctx->qry.path);
440+ else if (!strcmp(ctx->qry.page, "snapshot"))
441+ return cgit_snapshot_link(name, title, class, ctx->qry.head,
442+ ctx->qry.has_sha1 ? ctx->qry.sha1 : NULL,
443+ ctx->qry.path);
444+ else if (!strcmp(ctx->qry.page, "diff"))
445+ return cgit_diff_link(name, title, class, ctx->qry.head,
446+ ctx->qry.sha1, ctx->qry.sha2,
447+ ctx->qry.path, 0);
448+ else if (!strcmp(ctx->qry.page, "stats"))
449+ return cgit_stats_link(name, title, class, ctx->qry.head,
450+ ctx->qry.path);
451+
452+ /* Don't known how to make link for this page */
453+ repolink(title, class, ctx->qry.page, ctx->qry.head, ctx->qry.path);
454+ html("><!-- cgit_self_link() doesn't know how to make link for page '");
455+ html_txt(ctx->qry.page);
456+ html("' -->");
457+ html_txt(name);
458+ html("</a>");
459+}
460+
399461 void cgit_object_link(struct object *obj)
400462 {
401463 char *page, *shortrev, *fullrev, *name;
@@ -405,7 +467,7 @@ void cgit_object_link(struct object *obj) · 3 unmodified lines
405467 shortrev[10] = '\0';
406468 if (obj->type == OBJ_COMMIT) {
407469 cgit_commit_link(fmt("commit %s...", shortrev), NULL, NULL,
408− ctx.qry.head, fullrev, 0);
470+ ctx.qry.head, fullrev, NULL, 0);
409471 return;
410472 } else if (obj->type == OBJ_TREE)
411473 page = "tree";
@@ -417,7 +479,7 @@ void cgit_object_link(struct object *obj) · 5 unmodified lines
417479 reporevlink(page, name, NULL, NULL, ctx.qry.head, fullrev, NULL);
418480 }
419481
420−void cgit_print_date(time_t secs, char *format, int local_time)
482+void cgit_print_date(time_t secs, const char *format, int local_time)
421483 {
422484 char buf[64];
423485 struct tm *time;
@@ -432,7 +494,7 @@ void cgit_print_date(time_t secs, char *format, int local_time) · 8 unmodified lines
432494 html_txt(buf);
433495 }
434496
435−void cgit_print_age(time_t t, time_t max_relative, char *format)
497+void cgit_print_age(time_t t, time_t max_relative, const char *format)
436498 {
437499 time_t now, secs;
438500
@@ -531,7 +593,7 @@ void cgit_print_docstart(struct cgit_context *ctx) · 92 unmodified lines
531593 html("<link rel='alternate' title='Atom feed' href='");
532594 html(cgit_httpscheme());
533595 html_attr(cgit_hosturl());
534− html_attr(cgit_fileurl(ctx->repo->url, "atom", ctx->qry.path,
596+ html_attr(cgit_fileurl(ctx->repo->url, "atom", ctx->qry.vpath,
535597 fmt("h=%s", ctx->qry.head)));
536598 html("' type='application/atom+xml'/>\n");
537599 }
@@ -611,14 +673,15 @@ int print_archive_ref(const char *refname, const unsigned char *sha1, · 73 unmodified lines
611673 return 0;
612674 }
613675
614−void cgit_add_hidden_formfields(int incl_head, int incl_search, char *page)
676+void cgit_add_hidden_formfields(int incl_head, int incl_search,
677+ const char *page)
615678 {
616679 char *url;
617680
618681 if (!ctx.cfg.virtual_root) {
619682 url = fmt("%s/%s", ctx.qry.repo, page);
620− if (ctx.qry.path)
621− url = fmt("%s/%s", url, ctx.qry.path);
683+ if (ctx.qry.vpath)
684+ url = fmt("%s/%s", url, ctx.qry.vpath);
622685 html_hidden("url", url);
623686 }
624687
@@ -641,11 +704,30 @@ void cgit_add_hidden_formfields(int incl_head, int incl_search, char *page) · 16 unmodified lines
641704 }
642705 }
643706
644−const char *fallback_cmd = "repolist";
707+static const char *hc(struct cgit_context *ctx, const char *page)
708+{
709+ return strcmp(ctx->qry.page, page) ? NULL : "active";
710+}
645711
646−char *hc(struct cgit_cmd *cmd, const char *page)
712+static void cgit_print_path_crumbs(struct cgit_context *ctx, char *path)
647713 {
648− return (strcmp(cmd ? cmd->name : fallback_cmd, page) ? NULL : "active");
714+ char *old_path = ctx->qry.path;
715+ char *p = path, *q, *end = path + strlen(path);
716+
717+ ctx->qry.path = NULL;
718+ cgit_self_link("root", NULL, NULL, ctx);
719+ ctx->qry.path = p = path;
720+ while (p < end) {
721+ if (!(q = strchr(p, '/')))
722+ q = end;
723+ *q = '\0';
724+ html_txt("/");
725+ cgit_self_link(p, NULL, NULL, ctx);
726+ if (q < end)
727+ *q = '/';
728+ p = q + 1;
729+ }
730+ ctx->qry.path = old_path;
649731 }
650732
651733 static void print_header(struct cgit_context *ctx)
@@ -697,41 +779,37 @@ static void print_header(struct cgit_context *ctx) · 45 unmodified lines
697779
698780 void cgit_print_pageheader(struct cgit_context *ctx)
699781 {
700− struct cgit_cmd *cmd = cgit_get_cmd(ctx);
701−
702− if (!cmd && ctx->repo)
703− fallback_cmd = "summary";
704−
705782 html("<div id='cgit'>");
706783 if (!ctx->cfg.noheader)
707784 print_header(ctx);
708785
709786 html("<table class='tabs'><tr><td>\n");
710787 if (ctx->repo) {
711− cgit_summary_link("summary", NULL, hc(cmd, "summary"),
788+ cgit_summary_link("summary", NULL, hc(ctx, "summary"),
712789 ctx->qry.head);
713− cgit_refs_link("refs", NULL, hc(cmd, "refs"), ctx->qry.head,
714− ctx->qry.sha1, NULL);
715− cgit_log_link("log", NULL, hc(cmd, "log"), ctx->qry.head,
716− NULL, NULL, 0, NULL, NULL, ctx->qry.showmsg);
717− cgit_tree_link("tree", NULL, hc(cmd, "tree"), ctx->qry.head,
790+ cgit_refs_link("refs", NULL, hc(ctx, "refs"), ctx->qry.head,
718791 ctx->qry.sha1, NULL);
719− cgit_commit_link("commit", NULL, hc(cmd, "commit"),
720− ctx->qry.head, ctx->qry.sha1, 0);
721− cgit_diff_link("diff", NULL, hc(cmd, "diff"), ctx->qry.head,
722− ctx->qry.sha1, ctx->qry.sha2, NULL, 0);
792+ cgit_log_link("log", NULL, hc(ctx, "log"), ctx->qry.head,
793+ NULL, ctx->qry.vpath, 0, NULL, NULL,
794+ ctx->qry.showmsg);
795+ cgit_tree_link("tree", NULL, hc(ctx, "tree"), ctx->qry.head,
796+ ctx->qry.sha1, ctx->qry.vpath);
797+ cgit_commit_link("commit", NULL, hc(ctx, "commit"),
798+ ctx->qry.head, ctx->qry.sha1, ctx->qry.vpath, 0);
799+ cgit_diff_link("diff", NULL, hc(ctx, "diff"), ctx->qry.head,
800+ ctx->qry.sha1, ctx->qry.sha2, ctx->qry.vpath, 0);
723801 if (ctx->repo->max_stats)
724− cgit_stats_link("stats", NULL, hc(cmd, "stats"),
725− ctx->qry.head, NULL);
802+ cgit_stats_link("stats", NULL, hc(ctx, "stats"),
803+ ctx->qry.head, ctx->qry.vpath);
726804 if (ctx->repo->readme)
727805 reporevlink("about", "about", NULL,
728− hc(cmd, "about"), ctx->qry.head, NULL,
806+ hc(ctx, "about"), ctx->qry.head, NULL,
729807 NULL);
730808 html("</td><td class='form'>");
731809 html("<form class='right' method='get' action='");
732810 if (ctx->cfg.virtual_root)
733811 html_url_path(cgit_fileurl(ctx->qry.repo, "log",
734− ctx->qry.path, NULL));
812+ ctx->qry.vpath, NULL));
735813 html("'>\n");
736814 cgit_add_hidden_formfields(1, 0, "log");
737815 html("<select name='qt'>\n");
@@ -745,9 +823,9 @@ void cgit_print_pageheader(struct cgit_context *ctx) · 7 unmodified lines
745823 html("<input type='submit' value='search'/>\n");
746824 html("</form>\n");
747825 } else {
748− site_link(NULL, "index", NULL, hc(cmd, "repolist"), NULL, 0);
826+ site_link(NULL, "index", NULL, hc(ctx, "repolist"), NULL, 0);
749827 if (ctx->cfg.root_readme)
750− site_link("about", "about", NULL, hc(cmd, "about"),
828+ site_link("about", "about", NULL, hc(ctx, "about"),
751829 NULL, 0);
752830 html("</td><td class='form'>");
753831 html("<form method='get' action='");
@@ -760,6 +838,12 @@ void cgit_print_pageheader(struct cgit_context *ctx) · 6 unmodified lines
760838 html("</form>");
761839 }
762840 html("</td></tr></table>\n");
841+ if (ctx->qry.vpath) {
842+ html("<div class='path'>");
843+ html("path: ");
844+ cgit_print_path_crumbs(ctx, ctx->qry.vpath);
845+ html("</div>");
846+ }
763847 html("<div class='content'>");
764848 }
765849
ui-shared.h+43−29
@@ -10,36 +10,50 @@ extern char *cgit_fileurl(const char *reponame, const char *pagename, · 9 unmodified lines
1010 extern char *cgit_pageurl(const char *reponame, const char *pagename,
1111 const char *query);
1212
13−extern void cgit_index_link(char *name, char *title, char *class,
14− char *pattern, int ofs);
15−extern void cgit_summary_link(char *name, char *title, char *class, char *head);
16−extern void cgit_tag_link(char *name, char *title, char *class, char *head,
17− char *rev);
18−extern void cgit_tree_link(char *name, char *title, char *class, char *head,
19− char *rev, char *path);
20−extern void cgit_plain_link(char *name, char *title, char *class, char *head,
21− char *rev, char *path);
22−extern void cgit_log_link(char *name, char *title, char *class, char *head,
23− char *rev, char *path, int ofs, char *grep,
24− char *pattern, int showmsg);
25−extern void cgit_commit_link(char *name, char *title, char *class, char *head,
26− char *rev, int toggle_ssdiff);
27−extern void cgit_patch_link(char *name, char *title, char *class, char *head,
28− char *rev);
29−extern void cgit_refs_link(char *name, char *title, char *class, char *head,
30− char *rev, char *path);
31−extern void cgit_snapshot_link(char *name, char *title, char *class,
32− char *head, char *rev, char *archivename);
33−extern void cgit_diff_link(char *name, char *title, char *class, char *head,
34− char *new_rev, char *old_rev, char *path,
35− int toggle_ssdiff);
36−extern void cgit_stats_link(char *name, char *title, char *class, char *head,
37− char *path);
13+extern void cgit_index_link(const char *name, const char *title,
14+ const char *class, const char *pattern, int ofs);
15+extern void cgit_summary_link(const char *name, const char *title,
16+ const char *class, const char *head);
17+extern void cgit_tag_link(const char *name, const char *title,
18+ const char *class, const char *head,
19+ const char *rev);
20+extern void cgit_tree_link(const char *name, const char *title,
21+ const char *class, const char *head,
22+ const char *rev, const char *path);
23+extern void cgit_plain_link(const char *name, const char *title,
24+ const char *class, const char *head,
25+ const char *rev, const char *path);
26+extern void cgit_log_link(const char *name, const char *title,
27+ const char *class, const char *head, const char *rev,
28+ const char *path, int ofs, const char *grep,
29+ const char *pattern, int showmsg);
30+extern void cgit_commit_link(char *name, const char *title,
31+ const char *class, const char *head,
32+ const char *rev, const char *path,
33+ int toggle_ssdiff);
34+extern void cgit_patch_link(const char *name, const char *title,
35+ const char *class, const char *head,
36+ const char *rev, const char *path);
37+extern void cgit_refs_link(const char *name, const char *title,
38+ const char *class, const char *head,
39+ const char *rev, const char *path);
40+extern void cgit_snapshot_link(const char *name, const char *title,
41+ const char *class, const char *head,
42+ const char *rev, const char *archivename);
43+extern void cgit_diff_link(const char *name, const char *title,
44+ const char *class, const char *head,
45+ const char *new_rev, const char *old_rev,
46+ const char *path, int toggle_ssdiff);
47+extern void cgit_stats_link(const char *name, const char *title,
48+ const char *class, const char *head,
49+ const char *path);
50+extern void cgit_self_link(char *name, const char *title,
51+ const char *class, struct cgit_context *ctx);
3852 extern void cgit_object_link(struct object *obj);
3953
40−extern void cgit_print_error(char *msg);
41−extern void cgit_print_date(time_t secs, char *format, int local_time);
42−extern void cgit_print_age(time_t t, time_t max_relative, char *format);
54+extern void cgit_print_error(const char *msg);
55+extern void cgit_print_date(time_t secs, const char *format, int local_time);
56+extern void cgit_print_age(time_t t, time_t max_relative, const char *format);
4357 extern void cgit_print_http_headers(struct cgit_context *ctx);
4458 extern void cgit_print_docstart(struct cgit_context *ctx);
4559 extern void cgit_print_docend();
@@ -48,5 +62,5 @@ extern void cgit_print_filemode(unsigned short mode); · 2 unmodified lines
4862 extern void cgit_print_snapshot_links(const char *repo, const char *head,
4963 const char *hex, int snapshots);
5064 extern void cgit_add_hidden_formfields(int incl_head, int incl_search,
51− char *page);
65+ const char *page);
5266 #endif /* UI_SHARED_H */
ui-tree.c+2−13
@@ -102,10 +102,10 @@ static void print_object(const unsigned char *sha1, char *path, const char *base · 101 unmodified lines
102102 return;
103103 }
104104
105− html(" (");
105+ htmlf("blob: %s (", sha1_to_hex(sha1));
106106 cgit_plain_link("plain", NULL, NULL, ctx.qry.head,
107107 curr_rev, path);
108− htmlf(")<br/>blob: %s\n", sha1_to_hex(sha1));
108+ html(")\n");
109109
110110 if (ctx.cfg.max_blob_size && size / 1024 > ctx.cfg.max_blob_size) {
111111 htmlf("<div class='error'>blob size (%dKB) exceeds display size limit (%dKB).</div>",
@@ -225,17 +225,10 @@ static int walk_tree(const unsigned char *sha1, const char *base, int baselen, · 113 unmodified lines
225225 {
226226 static int state;
227227 static char buffer[PATH_MAX];
228− char *url;
229228
230229 if (state == 0) {
231230 memcpy(buffer, base, baselen);
232231 strcpy(buffer+baselen, pathname);
233− url = cgit_pageurl(ctx.qry.repo, "tree",
234− fmt("h=%s&amp;path=%s", curr_rev, buffer));
235− html("/");
236− cgit_tree_link(xstrdup(pathname), NULL, NULL, ctx.qry.head,
237− curr_rev, buffer);
238−
239232 if (strcmp(match_path, buffer))
240233 return READ_TREE_RECURSIVE;
241234
@@ -278,10 +271,6 @@ void cgit_print_tree(const char *rev, char *path) · 36 unmodified lines
278271 return;
279272 }
280273
281− html("path: <a href='");
282− html_attr(cgit_pageurl(ctx.qry.repo, "tree", fmt("h=%s", rev)));
283− html("'>root</a>");
284−
285274 if (path == NULL) {
286275 ls_tree(commit->tree->object.sha1, NULL);
287276 return;