aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cgit.c39
-rw-r--r--cgit.css27
-rw-r--r--cgit.h7
-rw-r--r--cgitrc.5.txt52
-rw-r--r--cmd.c44
-rw-r--r--cmd.h3
-rwxr-xr-xfilters/commit-links.sh11
-rwxr-xr-xfilters/syntax-highlighting.sh11
-rw-r--r--html.c8
-rw-r--r--html.h1
-rw-r--r--shared.c32
-rw-r--r--ui-commit.c16
-rw-r--r--ui-diff.c83
-rw-r--r--ui-diff.h4
-rw-r--r--ui-log.c29
-rw-r--r--ui-repolist.c17
-rw-r--r--ui-snapshot.c2
-rw-r--r--ui-stats.c51
-rw-r--r--ui-summary.c2
-rw-r--r--ui-tree.c2
20 files changed, 317 insertions, 124 deletions
diff --git a/cgit.c b/cgit.c
index e498030..6be3754 100644
--- a/cgit.c
+++ b/cgit.c
@@ -26,14 +26,27 @@ void add_mimetype(const char *name, const char *value)
26 item->util = xstrdup(value); 26 item->util = xstrdup(value);
27} 27}
28 28
29struct cgit_filter *new_filter(const char *cmd, int extra_args) 29struct cgit_filter *new_filter(const char *cmd, filter_type filtertype)
30{ 30{
31 struct cgit_filter *f; 31 struct cgit_filter *f;
32 int args_size = 0; 32 int args_size = 0;
33 int extra_args;
33 34
34 if (!cmd || !cmd[0]) 35 if (!cmd || !cmd[0])
35 return NULL; 36 return NULL;
36 37
38 switch (filtertype) {
39 case SOURCE:
40 extra_args = 1;
41 break;
42
43 case ABOUT:
44 case COMMIT:
45 default:
46 extra_args = 0;
47 break;
48 }
49
37 f = xmalloc(sizeof(struct cgit_filter)); 50 f = xmalloc(sizeof(struct cgit_filter));
38 f->cmd = xstrdup(cmd); 51 f->cmd = xstrdup(cmd);
39 args_size = (2 + extra_args) * sizeof(char *); 52 args_size = (2 + extra_args) * sizeof(char *);
@@ -83,11 +96,11 @@ void repo_config(struct cgit_repo *repo, const char *name, const char *value)
83 repo->logo_link = xstrdup(value); 96 repo->logo_link = xstrdup(value);
84 else if (ctx.cfg.enable_filter_overrides) { 97 else if (ctx.cfg.enable_filter_overrides) {
85 if (!strcmp(name, "about-filter")) 98 if (!strcmp(name, "about-filter"))
86 repo->about_filter = new_filter(value, 0); 99 repo->about_filter = new_filter(value, ABOUT);
87 else if (!strcmp(name, "commit-filter")) 100 else if (!strcmp(name, "commit-filter"))
88 repo->commit_filter = new_filter(value, 0); 101 repo->commit_filter = new_filter(value, COMMIT);
89 else if (!strcmp(name, "source-filter")) 102 else if (!strcmp(name, "source-filter"))
90 repo->source_filter = new_filter(value, 1); 103 repo->source_filter = new_filter(value, SOURCE);
91 } 104 }
92} 105}
93 106
@@ -147,6 +160,8 @@ void config_cb(const char *name, const char *value)
147 ctx.cfg.enable_filter_overrides = atoi(value); 160 ctx.cfg.enable_filter_overrides = atoi(value);
148 else if (!strcmp(name, "enable-gitweb-owner")) 161 else if (!strcmp(name, "enable-gitweb-owner"))
149 ctx.cfg.enable_gitweb_owner = atoi(value); 162 ctx.cfg.enable_gitweb_owner = atoi(value);
163 else if (!strcmp(name, "enable-http-clone"))
164 ctx.cfg.enable_http_clone = atoi(value);
150 else if (!strcmp(name, "enable-index-links")) 165 else if (!strcmp(name, "enable-index-links"))
151 ctx.cfg.enable_index_links = atoi(value); 166 ctx.cfg.enable_index_links = atoi(value);
152 else if (!strcmp(name, "enable-commit-graph")) 167 else if (!strcmp(name, "enable-commit-graph"))
@@ -178,9 +193,9 @@ void config_cb(const char *name, const char *value)
178 else if (!strcmp(name, "cache-dynamic-ttl")) 193 else if (!strcmp(name, "cache-dynamic-ttl"))
179 ctx.cfg.cache_dynamic_ttl = atoi(value); 194 ctx.cfg.cache_dynamic_ttl = atoi(value);
180 else if (!strcmp(name, "about-filter")) 195 else if (!strcmp(name, "about-filter"))
181 ctx.cfg.about_filter = new_filter(value, 0); 196 ctx.cfg.about_filter = new_filter(value, ABOUT);
182 else if (!strcmp(name, "commit-filter")) 197 else if (!strcmp(name, "commit-filter"))
183 ctx.cfg.commit_filter = new_filter(value, 0); 198 ctx.cfg.commit_filter = new_filter(value, COMMIT);
184 else if (!strcmp(name, "embedded")) 199 else if (!strcmp(name, "embedded"))
185 ctx.cfg.embedded = atoi(value); 200 ctx.cfg.embedded = atoi(value);
186 else if (!strcmp(name, "max-atom-items")) 201 else if (!strcmp(name, "max-atom-items"))
@@ -210,7 +225,7 @@ void config_cb(const char *name, const char *value)
210 else if (!strcmp(name, "section-from-path")) 225 else if (!strcmp(name, "section-from-path"))
211 ctx.cfg.section_from_path = atoi(value); 226 ctx.cfg.section_from_path = atoi(value);
212 else if (!strcmp(name, "source-filter")) 227 else if (!strcmp(name, "source-filter"))
213 ctx.cfg.source_filter = new_filter(value, 1); 228 ctx.cfg.source_filter = new_filter(value, SOURCE);
214 else if (!strcmp(name, "summary-log")) 229 else if (!strcmp(name, "summary-log"))
215 ctx.cfg.summary_log = atoi(value); 230 ctx.cfg.summary_log = atoi(value);
216 else if (!strcmp(name, "summary-branches")) 231 else if (!strcmp(name, "summary-branches"))
@@ -312,6 +327,7 @@ static void prepare_context(struct cgit_context *ctx)
312 ctx->cfg.logo = "/cgit.png"; 327 ctx->cfg.logo = "/cgit.png";
313 ctx->cfg.local_time = 0; 328 ctx->cfg.local_time = 0;
314 ctx->cfg.enable_gitweb_owner = 1; 329 ctx->cfg.enable_gitweb_owner = 1;
330 ctx->cfg.enable_http_clone = 1;
315 ctx->cfg.enable_tree_linenumbers = 1; 331 ctx->cfg.enable_tree_linenumbers = 1;
316 ctx->cfg.max_repo_count = 50; 332 ctx->cfg.max_repo_count = 50;
317 ctx->cfg.max_commit_count = 50; 333 ctx->cfg.max_commit_count = 50;
@@ -439,7 +455,7 @@ static int prepare_repo_cmd(struct cgit_context *ctx)
439 tmp = xstrdup(ctx->qry.head); 455 tmp = xstrdup(ctx->qry.head);
440 ctx->qry.head = ctx->repo->defbranch; 456 ctx->qry.head = ctx->repo->defbranch;
441 ctx->page.status = 404; 457 ctx->page.status = 404;
442 ctx->page.statusmsg = "not found"; 458 ctx->page.statusmsg = "Not found";
443 cgit_print_http_headers(ctx); 459 cgit_print_http_headers(ctx);
444 cgit_print_docstart(ctx); 460 cgit_print_docstart(ctx);
445 cgit_print_pageheader(ctx); 461 cgit_print_pageheader(ctx);
@@ -458,6 +474,8 @@ static void process_request(void *cbdata)
458 cmd = cgit_get_cmd(ctx); 474 cmd = cgit_get_cmd(ctx);
459 if (!cmd) { 475 if (!cmd) {
460 ctx->page.title = "cgit error"; 476 ctx->page.title = "cgit error";
477 ctx->page.status = 404;
478 ctx->page.statusmsg = "Not found";
461 cgit_print_http_headers(ctx); 479 cgit_print_http_headers(ctx);
462 cgit_print_docstart(ctx); 480 cgit_print_docstart(ctx);
463 cgit_print_pageheader(ctx); 481 cgit_print_pageheader(ctx);
@@ -466,6 +484,11 @@ static void process_request(void *cbdata)
466 return; 484 return;
467 } 485 }
468 486
487 if (!ctx->cfg.enable_http_clone && cmd->is_clone) {
488 html_status(404, "Not found", 0);
489 return;
490 }
491
469 /* If cmd->want_vpath is set, assume ctx->qry.path contains a "virtual" 492 /* If cmd->want_vpath is set, assume ctx->qry.path contains a "virtual"
470 * in-project path limit to be made available at ctx->qry.vpath. 493 * in-project path limit to be made available at ctx->qry.vpath.
471 * Otherwise, no path limit is in effect (ctx->qry.vpath = NULL). 494 * Otherwise, no path limit is in effect (ctx->qry.vpath = NULL).
diff --git a/cgit.css b/cgit.css
index 1d90057..55afa94 100644
--- a/cgit.css
+++ b/cgit.css
@@ -331,6 +331,33 @@ table.commit-info {
331 margin-top: 1.5em; 331 margin-top: 1.5em;
332} 332}
333 333
334div.cgit-panel {
335 float: right;
336 margin-top: 1.5em;
337}
338
339div.cgit-panel table {
340 border-collapse: collapse;
341 border: solid 1px #aaa;
342 background-color: #eee;
343}
344
345div.cgit-panel th {
346 text-align: center;
347}
348
349div.cgit-panel td {
350 padding: 0.25em 0.5em;
351}
352
353div.cgit-panel td.label {
354 padding-right: 0.5em;
355}
356
357div.cgit-panel td.ctrl {
358 padding-left: 0.5em;
359}
360
334table.commit-info th { 361table.commit-info th {
335 text-align: left; 362 text-align: left;
336 font-weight: normal; 363 font-weight: normal;
diff --git a/cgit.h b/cgit.h
index b5f00fc..caa9d8e 100644
--- a/cgit.h
+++ b/cgit.h
@@ -51,6 +51,10 @@ typedef void (*configfn)(const char *name, const char *value);
51typedef void (*filepair_fn)(struct diff_filepair *pair); 51typedef void (*filepair_fn)(struct diff_filepair *pair);
52typedef void (*linediff_fn)(char *line, int len); 52typedef void (*linediff_fn)(char *line, int len);
53 53
54typedef enum {
55 ABOUT, COMMIT, SOURCE
56} filter_type;
57
54struct cgit_filter { 58struct cgit_filter {
55 char *cmd; 59 char *cmd;
56 char **argv; 60 char **argv;
@@ -191,6 +195,7 @@ struct cgit_config {
191 int embedded; 195 int embedded;
192 int enable_filter_overrides; 196 int enable_filter_overrides;
193 int enable_gitweb_owner; 197 int enable_gitweb_owner;
198 int enable_http_clone;
194 int enable_index_links; 199 int enable_index_links;
195 int enable_commit_graph; 200 int enable_commit_graph;
196 int enable_log_filecount; 201 int enable_log_filecount;
@@ -314,7 +319,7 @@ extern const char *cgit_repobasename(const char *reponame);
314 319
315extern int cgit_parse_snapshots_mask(const char *str); 320extern int cgit_parse_snapshots_mask(const char *str);
316 321
317extern int cgit_open_filter(struct cgit_filter *filter); 322extern int cgit_open_filter(struct cgit_filter *filter, struct cgit_repo * repo);
318extern int cgit_close_filter(struct cgit_filter *filter); 323extern int cgit_close_filter(struct cgit_filter *filter);
319 324
320extern int readfile(const char *path, char **buf, size_t *size); 325extern int readfile(const char *path, char **buf, size_t *size);
diff --git a/cgitrc.5.txt b/cgitrc.5.txt
index 65b210f..5903a93 100644
--- a/cgitrc.5.txt
+++ b/cgitrc.5.txt
@@ -31,7 +31,7 @@ about-filter::
31 about pages (both top-level and for each repository). The command will 31 about pages (both top-level and for each repository). The command will
32 get the content of the about-file on its STDIN, and the STDOUT from the 32 get the content of the about-file on its STDIN, and the STDOUT from the
33 command will be included verbatim on the about page. Default value: 33 command will be included verbatim on the about page. Default value:
34 none. 34 none. See also: "FILTER API".
35 35
36agefile:: 36agefile::
37 Specifies a path, relative to each repository path, which can be used 37 Specifies a path, relative to each repository path, which can be used
@@ -81,6 +81,7 @@ commit-filter::
81 The command will get the message on its STDIN, and the STDOUT from the 81 The command will get the message on its STDIN, and the STDOUT from the
82 command will be included verbatim as the commit message, i.e. this can 82 command will be included verbatim as the commit message, i.e. this can
83 be used to implement bugtracker integration. Default value: none. 83 be used to implement bugtracker integration. Default value: none.
84 See also: "FILTER API".
84 85
85css:: 86css::
86 Url which specifies the css document to include in all cgit pages. 87 Url which specifies the css document to include in all cgit pages.
@@ -105,6 +106,11 @@ enable-gitweb-owner::
105 for the git config value "gitweb.owner" to determine the owner. 106 for the git config value "gitweb.owner" to determine the owner.
106 Default value: "1". See also: scan-path. 107 Default value: "1". See also: scan-path.
107 108
109enable-http-clone::
110 If set to "1", cgit will act as an dumb HTTP endpoint for git clones.
111 If you use an alternate way of serving git repositories, you may wish
112 to disable this. Default value: "1".
113
108enable-index-links:: 114enable-index-links::
109 Flag which, when set to "1", will make cgit generate extra links for 115 Flag which, when set to "1", will make cgit generate extra links for
110 each repo in the repository index (specifically, to the "summary", 116 each repo in the repository index (specifically, to the "summary",
@@ -318,7 +324,7 @@ source-filter::
318 and the name of the blob as its only command line argument. The STDOUT 324 and the name of the blob as its only command line argument. The STDOUT
319 from the command will be included verbatim as the blob contents, i.e. 325 from the command will be included verbatim as the blob contents, i.e.
320 this can be used to implement e.g. syntax highlighting. Default value: 326 this can be used to implement e.g. syntax highlighting. Default value:
321 none. 327 none. See also: "FILTER API".
322 328
323summary-branches:: 329summary-branches::
324 Specifies the number of branches to display in the repository "summary" 330 Specifies the number of branches to display in the repository "summary"
@@ -351,7 +357,7 @@ REPOSITORY SETTINGS
351------------------- 357-------------------
352repo.about-filter:: 358repo.about-filter::
353 Override the default about-filter. Default value: none. See also: 359 Override the default about-filter. Default value: none. See also:
354 "enable-filter-overrides". 360 "enable-filter-overrides". See also: "FILTER API".
355 361
356repo.clone-url:: 362repo.clone-url::
357 A list of space-separated urls which can be used to clone this repo. 363 A list of space-separated urls which can be used to clone this repo.
@@ -359,7 +365,7 @@ repo.clone-url::
359 365
360repo.commit-filter:: 366repo.commit-filter::
361 Override the default commit-filter. Default value: none. See also: 367 Override the default commit-filter. Default value: none. See also:
362 "enable-filter-overrides". 368 "enable-filter-overrides". See also: "FILTER API".
363 369
364repo.defbranch:: 370repo.defbranch::
365 The name of the default branch for this repository. If no such branch 371 The name of the default branch for this repository. If no such branch
@@ -430,7 +436,7 @@ repo.section::
430 436
431repo.source-filter:: 437repo.source-filter::
432 Override the default source-filter. Default value: none. See also: 438 Override the default source-filter. Default value: none. See also:
433 "enable-filter-overrides". 439 "enable-filter-overrides". See also: "FILTER API".
434 440
435repo.url:: 441repo.url::
436 The relative url used to access the repository. This must be the first 442 The relative url used to access the repository. This must be the first
@@ -450,6 +456,42 @@ Note: the "repo." prefix is dropped from the option names in repo-specific
450config files, e.g. "repo.desc" becomes "desc". 456config files, e.g. "repo.desc" becomes "desc".
451 457
452 458
459FILTER API
460----------
461- about filter::
462 This filter is given no arguments.
463 The about text that is to be filtered is available on standard input and the
464 filtered text is expected on standard output.
465- commit filter::
466 This filter is given no arguments.
467 The commit message text that is to be filtered is available on standard input
468 and the filtered text is expected on standard output.
469- source filter::
470 This filter is given a single parameter: the filename of the source file to
471 filter. The filter can use the filename to determine (for example) the syntax
472 highlighting mode.
473 The contents of the source file that is to be filtered is available on
474 standard input and the filtered contents is expected on standard output.
475
476Also, all filters are handed the following environment variables:
477- CGIT_REPO_URL ( = repo.url setting )
478- CGIT_REPO_NAME ( = repo.name setting )
479- CGIT_REPO_PATH ( = repo.path setting )
480- CGIT_REPO_OWNER ( = repo.owner setting )
481- CGIT_REPO_DEFBRANCH ( = repo.defbranch setting )
482- CGIT_REPO_SECTION ( = section setting )
483- CGIT_REPO_CLONE_URL ( = repo.clone-url setting )
484
485If a setting is not defined for a repository and the corresponding global
486setting is also not defined (if applicable), then the corresponding
487environment variable will be an empty string.
488
489Note that under normal circumstance all these environment variables are
490defined. If however the total size of the defined settings exceed the
491allocated buffer within cgit then only the environment variables that fit
492in the allocated buffer are handed to the filter.
493
494
453EXAMPLE CGITRC FILE 495EXAMPLE CGITRC FILE
454------------------- 496-------------------
455 497
diff --git a/cmd.c b/cmd.c
index 536515b..5a3d157 100644
--- a/cmd.c
+++ b/cmd.c
@@ -56,7 +56,7 @@ static void commit_fn(struct cgit_context *ctx)
56 56
57static void diff_fn(struct cgit_context *ctx) 57static void diff_fn(struct cgit_context *ctx)
58{ 58{
59 cgit_print_diff(ctx->qry.sha1, ctx->qry.sha2, ctx->qry.path); 59 cgit_print_diff(ctx->qry.sha1, ctx->qry.sha2, ctx->qry.path, 1);
60} 60}
61 61
62static void info_fn(struct cgit_context *ctx) 62static void info_fn(struct cgit_context *ctx)
@@ -130,31 +130,31 @@ static void tree_fn(struct cgit_context *ctx)
130 cgit_print_tree(ctx->qry.sha1, ctx->qry.path); 130 cgit_print_tree(ctx->qry.sha1, ctx->qry.path);
131} 131}
132 132
133#define def_cmd(name, want_repo, want_layout, want_vpath) \ 133#define def_cmd(name, want_repo, want_layout, want_vpath, is_clone) \
134 {#name, name##_fn, want_repo, want_layout, want_vpath} 134 {#name, name##_fn, want_repo, want_layout, want_vpath, is_clone}
135 135
136struct cgit_cmd *cgit_get_cmd(struct cgit_context *ctx) 136struct cgit_cmd *cgit_get_cmd(struct cgit_context *ctx)
137{ 137{
138 static struct cgit_cmd cmds[] = { 138 static struct cgit_cmd cmds[] = {
139 def_cmd(HEAD, 1, 0, 0), 139 def_cmd(HEAD, 1, 0, 0, 1),
140 def_cmd(atom, 1, 0, 0), 140 def_cmd(atom, 1, 0, 0, 0),
141 def_cmd(about, 0, 1, 0), 141 def_cmd(about, 0, 1, 0, 0),
142 def_cmd(blob, 1, 0, 0), 142 def_cmd(blob, 1, 0, 0, 0),
143 def_cmd(commit, 1, 1, 1), 143 def_cmd(commit, 1, 1, 1, 0),
144 def_cmd(diff, 1, 1, 1), 144 def_cmd(diff, 1, 1, 1, 0),
145 def_cmd(info, 1, 0, 0), 145 def_cmd(info, 1, 0, 0, 1),
146 def_cmd(log, 1, 1, 1), 146 def_cmd(log, 1, 1, 1, 0),
147 def_cmd(ls_cache, 0, 0, 0), 147 def_cmd(ls_cache, 0, 0, 0, 0),
148 def_cmd(objects, 1, 0, 0), 148 def_cmd(objects, 1, 0, 0, 1),
149 def_cmd(patch, 1, 0, 1), 149 def_cmd(patch, 1, 0, 1, 0),
150 def_cmd(plain, 1, 0, 0), 150 def_cmd(plain, 1, 0, 0, 0),
151 def_cmd(refs, 1, 1, 0), 151 def_cmd(refs, 1, 1, 0, 0),
152 def_cmd(repolist, 0, 0, 0), 152 def_cmd(repolist, 0, 0, 0, 0),
153 def_cmd(snapshot, 1, 0, 0), 153 def_cmd(snapshot, 1, 0, 0, 0),
154 def_cmd(stats, 1, 1, 1), 154 def_cmd(stats, 1, 1, 1, 0),
155 def_cmd(summary, 1, 1, 0), 155 def_cmd(summary, 1, 1, 0, 0),
156 def_cmd(tag, 1, 1, 0), 156 def_cmd(tag, 1, 1, 0, 0),
157 def_cmd(tree, 1, 1, 1), 157 def_cmd(tree, 1, 1, 1, 0),
158 }; 158 };
159 int i; 159 int i;
160 160
diff --git a/cmd.h b/cmd.h
index 8dc01bd..eb5bc87 100644
--- a/cmd.h
+++ b/cmd.h
@@ -8,7 +8,8 @@ struct cgit_cmd {
8 cgit_cmd_fn fn; 8 cgit_cmd_fn fn;
9 unsigned int want_repo:1, 9 unsigned int want_repo:1,
10 want_layout:1, 10 want_layout:1,
11 want_vpath:1; 11 want_vpath:1,
12 is_clone:1;
12}; 13};
13 14
14extern struct cgit_cmd *cgit_get_cmd(struct cgit_context *ctx); 15extern struct cgit_cmd *cgit_get_cmd(struct cgit_context *ctx);
diff --git a/filters/commit-links.sh b/filters/commit-links.sh
index 110c609..d2cd2b3 100755
--- a/filters/commit-links.sh
+++ b/filters/commit-links.sh
@@ -3,6 +3,17 @@
3# 3#
4# To use this script, refer to this file with either the commit-filter or the 4# To use this script, refer to this file with either the commit-filter or the
5# repo.commit-filter options in cgitrc. 5# repo.commit-filter options in cgitrc.
6#
7# The following environment variables can be used to retrieve the configuration
8# of the repository for which this script is called:
9# CGIT_REPO_URL ( = repo.url setting )
10# CGIT_REPO_NAME ( = repo.name setting )
11# CGIT_REPO_PATH ( = repo.path setting )
12# CGIT_REPO_OWNER ( = repo.owner setting )
13# CGIT_REPO_DEFBRANCH ( = repo.defbranch setting )
14# CGIT_REPO_SECTION ( = section setting )
15# CGIT_REPO_CLONE_URL ( = repo.clone-url setting )
16#
6 17
7# This expression generates links to commits referenced by their SHA1. 18# This expression generates links to commits referenced by their SHA1.
8regex=$regex' 19regex=$regex'
diff --git a/filters/syntax-highlighting.sh b/filters/syntax-highlighting.sh
index 6b1c576..6283ce9 100755
--- a/filters/syntax-highlighting.sh
+++ b/filters/syntax-highlighting.sh
@@ -23,6 +23,17 @@
23# table.blob .kwb { color:#830000; } 23# table.blob .kwb { color:#830000; }
24# table.blob .kwc { color:#000000; font-weight:bold; } 24# table.blob .kwc { color:#000000; font-weight:bold; }
25# table.blob .kwd { color:#010181; } 25# table.blob .kwd { color:#010181; }
26#
27# The following environment variables can be used to retrieve the configuration
28# of the repository for which this script is called:
29# CGIT_REPO_URL ( = repo.url setting )
30# CGIT_REPO_NAME ( = repo.name setting )
31# CGIT_REPO_PATH ( = repo.path setting )
32# CGIT_REPO_OWNER ( = repo.owner setting )
33# CGIT_REPO_DEFBRANCH ( = repo.defbranch setting )
34# CGIT_REPO_SECTION ( = section setting )
35# CGIT_REPO_CLONE_URL ( = repo.clone-url setting )
36#
26 37
27# store filename and extension in local vars 38# store filename and extension in local vars
28BASENAME="$1" 39BASENAME="$1"
diff --git a/html.c b/html.c
index 24a03a5..eb1c25d 100644
--- a/html.c
+++ b/html.c
@@ -215,6 +215,14 @@ void html_option(const char *value, const char *text, const char *selected_value
215 html("</option>\n"); 215 html("</option>\n");
216} 216}
217 217
218void html_intoption(int value, const char *text, int selected_value)
219{
220 htmlf("<option value='%d'%s>", value,
221 value == selected_value ? " selected='selected'" : "");
222 html_txt(text);
223 html("</option>");
224}
225
218void html_link_open(const char *url, const char *title, const char *class) 226void html_link_open(const char *url, const char *title, const char *class)
219{ 227{
220 html("<a href='"); 228 html("<a href='");
diff --git a/html.h b/html.h
index 1135fb8..20e1dc2 100644
--- a/html.h
+++ b/html.h
@@ -17,6 +17,7 @@ extern void html_url_path(const char *txt);
17extern void html_url_arg(const char *txt); 17extern void html_url_arg(const char *txt);
18extern void html_hidden(const char *name, const char *value); 18extern void html_hidden(const char *name, const char *value);
19extern void html_option(const char *value, const char *text, const char *selected_value); 19extern void html_option(const char *value, const char *text, const char *selected_value);
20extern void html_intoption(int value, const char *text, int selected_value);
20extern void html_link_open(const char *url, const char *title, const char *class); 21extern void html_link_open(const char *url, const char *title, const char *class);
21extern void html_link_close(void); 22extern void html_link_close(void);
22extern void html_fileperm(unsigned short mode); 23extern void html_fileperm(unsigned short mode);
diff --git a/shared.c b/shared.c
index 3778a5b..be2ae59 100644
--- a/shared.c
+++ b/shared.c
@@ -7,6 +7,8 @@
7 */ 7 */
8 8
9#include "cgit.h" 9#include "cgit.h"
10#include <stdio.h>
11#include <linux/limits.h>
10 12
11struct cgit_repolist cgit_repolist; 13struct cgit_repolist cgit_repolist;
12struct cgit_context ctx; 14struct cgit_context ctx;
@@ -367,7 +369,33 @@ int cgit_parse_snapshots_mask(const char *str)
367 return rv; 369 return rv;
368} 370}
369 371
370int cgit_open_filter(struct cgit_filter *filter) 372typedef struct {
373 char * name;
374 char * value;
375} cgit_env_var;
376
377static void prepare_env(struct cgit_repo * repo) {
378 cgit_env_var env_vars[] = {
379 { .name = "CGIT_REPO_URL", .value = repo->url },
380 { .name = "CGIT_REPO_NAME", .value = repo->name },
381 { .name = "CGIT_REPO_PATH", .value = repo->path },
382 { .name = "CGIT_REPO_OWNER", .value = repo->owner },
383 { .name = "CGIT_REPO_DEFBRANCH", .value = repo->defbranch },
384 { .name = "CGIT_REPO_SECTION", .value = repo->section },
385 { .name = "CGIT_REPO_CLONE_URL", .value = repo->clone_url }
386 };
387 int env_var_count = ARRAY_SIZE(env_vars);
388 cgit_env_var *p, *q;
389 static char *warn = "cgit warning: failed to set env: %s=%s\n";
390
391 p = env_vars;
392 q = p + env_var_count;
393 for (; p < q; p++)
394 if (setenv(p->name, p->value, 1))
395 fprintf(stderr, warn, p->name, p->value);
396}
397
398int cgit_open_filter(struct cgit_filter *filter, struct cgit_repo * repo)
371{ 399{
372 400
373 filter->old_stdout = chk_positive(dup(STDOUT_FILENO), 401 filter->old_stdout = chk_positive(dup(STDOUT_FILENO),
@@ -378,6 +406,8 @@ int cgit_open_filter(struct cgit_filter *filter)
378 close(filter->pipe_fh[1]); 406 close(filter->pipe_fh[1]);
379 chk_non_negative(dup2(filter->pipe_fh[0], STDIN_FILENO), 407 chk_non_negative(dup2(filter->pipe_fh[0], STDIN_FILENO),
380 "Unable to use pipe as STDIN"); 408 "Unable to use pipe as STDIN");
409 if (repo)
410 prepare_env(repo);
381 execvp(filter->cmd, filter->argv); 411 execvp(filter->cmd, filter->argv);
382 die("Unable to exec subprocess %s: %s (%d)", filter->cmd, 412 die("Unable to exec subprocess %s: %s (%d)", filter->cmd,
383 strerror(errno), errno); 413 strerror(errno), errno);
diff --git a/ui-commit.c b/ui-commit.c
index 2b4f677..a69dec6 100644
--- a/ui-commit.c
+++ b/ui-commit.c
@@ -39,7 +39,8 @@ void cgit_print_commit(char *hex, const char *prefix)
39 format_note(NULL, sha1, &notes, PAGE_ENCODING, 0); 39 format_note(NULL, sha1, &notes, PAGE_ENCODING, 0);
40 40
41 load_ref_decorations(DECORATE_FULL_REFS); 41 load_ref_decorations(DECORATE_FULL_REFS);
42 42
43 cgit_print_diff_ctrls();
43 html("<table summary='commit info' class='commit-info'>\n"); 44 html("<table summary='commit info' class='commit-info'>\n");
44 html("<tr><th>author</th><td>"); 45 html("<tr><th>author</th><td>");
45 html_txt(info->author); 46 html_txt(info->author);
@@ -64,11 +65,6 @@ void cgit_print_commit(char *hex, const char *prefix)
64 cgit_commit_link(tmp, NULL, NULL, ctx.qry.head, tmp, prefix, 0); 65 cgit_commit_link(tmp, NULL, NULL, ctx.qry.head, tmp, prefix, 0);
65 html(" ("); 66 html(" (");
66 cgit_patch_link("patch", NULL, NULL, NULL, tmp, prefix); 67 cgit_patch_link("patch", NULL, NULL, NULL, tmp, prefix);
67 html(") (");
68 if ((ctx.qry.ssdiff && !ctx.cfg.ssdiff) || (!ctx.qry.ssdiff && ctx.cfg.ssdiff))
69 cgit_commit_link("unidiff", NULL, NULL, ctx.qry.head, tmp, prefix, 1);
70 else
71 cgit_commit_link("side-by-side diff", NULL, NULL, ctx.qry.head, tmp, prefix, 1);
72 html(")</td></tr>\n"); 68 html(")</td></tr>\n");
73 html("<tr><th>tree</th><td colspan='2' class='sha1'>"); 69 html("<tr><th>tree</th><td colspan='2' class='sha1'>");
74 tmp = xstrdup(hex); 70 tmp = xstrdup(hex);
@@ -110,7 +106,7 @@ void cgit_print_commit(char *hex, const char *prefix)
110 html("</table>\n"); 106 html("</table>\n");
111 html("<div class='commit-subject'>"); 107 html("<div class='commit-subject'>");
112 if (ctx.repo->commit_filter) 108 if (ctx.repo->commit_filter)
113 cgit_open_filter(ctx.repo->commit_filter); 109 cgit_open_filter(ctx.repo->commit_filter, ctx.repo);
114 html_txt(info->subject); 110 html_txt(info->subject);
115 if (ctx.repo->commit_filter) 111 if (ctx.repo->commit_filter)
116 cgit_close_filter(ctx.repo->commit_filter); 112 cgit_close_filter(ctx.repo->commit_filter);
@@ -118,7 +114,7 @@ void cgit_print_commit(char *hex, const char *prefix)
118 html("</div>"); 114 html("</div>");
119 html("<div class='commit-msg'>"); 115 html("<div class='commit-msg'>");
120 if (ctx.repo->commit_filter) 116 if (ctx.repo->commit_filter)
121 cgit_open_filter(ctx.repo->commit_filter); 117 cgit_open_filter(ctx.repo->commit_filter, ctx.repo);
122 html_txt(info->msg); 118 html_txt(info->msg);
123 if (ctx.repo->commit_filter) 119 if (ctx.repo->commit_filter)
124 cgit_close_filter(ctx.repo->commit_filter); 120 cgit_close_filter(ctx.repo->commit_filter);
@@ -127,7 +123,7 @@ void cgit_print_commit(char *hex, const char *prefix)
127 html("<div class='notes-header'>Notes</div>"); 123 html("<div class='notes-header'>Notes</div>");
128 html("<div class='notes'>"); 124 html("<div class='notes'>");
129 if (ctx.repo->commit_filter) 125 if (ctx.repo->commit_filter)
130 cgit_open_filter(ctx.repo->commit_filter); 126 cgit_open_filter(ctx.repo->commit_filter, ctx.repo);
131 html_txt(notes.buf); 127 html_txt(notes.buf);
132 if (ctx.repo->commit_filter) 128 if (ctx.repo->commit_filter)
133 cgit_close_filter(ctx.repo->commit_filter); 129 cgit_close_filter(ctx.repo->commit_filter);
@@ -139,7 +135,7 @@ void cgit_print_commit(char *hex, const char *prefix)
139 tmp = sha1_to_hex(commit->parents->item->object.sha1); 135 tmp = sha1_to_hex(commit->parents->item->object.sha1);
140 else 136 else
141 tmp = NULL; 137 tmp = NULL;
142 cgit_print_diff(ctx.qry.sha1, tmp, prefix); 138 cgit_print_diff(ctx.qry.sha1, tmp, prefix, 0);
143 } 139 }
144 strbuf_release(&notes); 140 strbuf_release(&notes);
145 cgit_free_commitinfo(info); 141 cgit_free_commitinfo(info);
diff --git a/ui-diff.c b/ui-diff.c
index d21541b..868ceec 100644
--- a/ui-diff.c
+++ b/ui-diff.c
@@ -167,7 +167,7 @@ static void inspect_filepair(struct diff_filepair *pair)
167void cgit_print_diffstat(const unsigned char *old_sha1, 167void cgit_print_diffstat(const unsigned char *old_sha1,
168 const unsigned char *new_sha1, const char *prefix) 168 const unsigned char *new_sha1, const char *prefix)
169{ 169{
170 int i, save_context = ctx.qry.context; 170 int i;
171 171
172 html("<div class='diffstat-header'>"); 172 html("<div class='diffstat-header'>");
173 cgit_diff_link("Diffstat", NULL, NULL, ctx.qry.head, ctx.qry.sha1, 173 cgit_diff_link("Diffstat", NULL, NULL, ctx.qry.head, ctx.qry.sha1,
@@ -177,19 +177,6 @@ void cgit_print_diffstat(const unsigned char *old_sha1,
177 html_txt(prefix); 177 html_txt(prefix);
178 html("')"); 178 html("')");
179 } 179 }
180 html(" (");
181 ctx.qry.context = (save_context > 0 ? save_context : 3) << 1;
182 cgit_self_link("more", NULL, NULL, &ctx);
183 html("/");
184 ctx.qry.context = (save_context > 3 ? save_context : 3) >> 1;
185 cgit_self_link("less", NULL, NULL, &ctx);
186 ctx.qry.context = save_context;
187 html(" context)");
188 html(" (");
189 ctx.qry.ignorews = (ctx.qry.ignorews + 1) % 2;
190 cgit_self_link(ctx.qry.ignorews ? "ignore" : "show", NULL, NULL, &ctx);
191 ctx.qry.ignorews = (ctx.qry.ignorews + 1) % 2;
192 html(" whitespace changes)");
193 html("</div>"); 180 html("</div>");
194 html("<table summary='diffstat' class='diffstat'>"); 181 html("<table summary='diffstat' class='diffstat'>");
195 max_changes = 0; 182 max_changes = 0;
@@ -278,19 +265,6 @@ static void header(unsigned char *sha1, char *path1, int mode1,
278 html("</div>"); 265 html("</div>");
279} 266}
280 267
281static void print_ssdiff_link()
282{
283 if (!strcmp(ctx.qry.page, "diff")) {
284 if (use_ssdiff)
285 cgit_diff_link("Unidiff", NULL, NULL, ctx.qry.head,
286 ctx.qry.sha1, ctx.qry.sha2, ctx.qry.path, 1);
287 else
288 cgit_diff_link("Side-by-side diff", NULL, NULL,
289 ctx.qry.head, ctx.qry.sha1,
290 ctx.qry.sha2, ctx.qry.path, 1);
291 }
292}
293
294static void filepair_cb(struct diff_filepair *pair) 268static void filepair_cb(struct diff_filepair *pair)
295{ 269{
296 unsigned long old_size = 0; 270 unsigned long old_size = 0;
@@ -330,7 +304,56 @@ static void filepair_cb(struct diff_filepair *pair)
330 cgit_ssdiff_footer(); 304 cgit_ssdiff_footer();
331} 305}
332 306
333void cgit_print_diff(const char *new_rev, const char *old_rev, const char *prefix) 307void cgit_print_diff_ctrls()
308{
309 int i, curr;
310
311 html("<div class='cgit-panel'>");
312 html("<b>diff options</b>");
313 html("<form method='get' action='.'>");
314 cgit_add_hidden_formfields(1, 0, ctx.qry.page);
315 html("<table>");
316 html("<tr><td colspan='2'/></tr>");
317 html("<tr>");
318 html("<td class='label'>context:</td>");
319 html("<td class='ctrl'>");
320 html("<select name='context' onchange='this.form.submit();'>");
321 curr = ctx.qry.context;
322 if (!curr)
323 curr = 3;
324 for (i = 1; i <= 10; i++)
325 html_intoption(i, fmt("%d", i), curr);
326 for (i = 15; i <= 40; i += 5)
327 html_intoption(i, fmt("%d", i), curr);
328 html("</select>");
329 html("</td>");
330 html("</tr><tr>");
331 html("<td class='label'>space:</td>");
332 html("<td class='ctrl'>");
333 html("<select name='ignorews' onchange='this.form.submit();'>");
334 html_intoption(0, "include", ctx.qry.ignorews);
335 html_intoption(1, "ignore", ctx.qry.ignorews);
336 html("</select>");
337 html("</td>");
338 html("</tr><tr>");
339 html("<td class='label'>mode:</td>");
340 html("<td class='ctrl'>");
341 html("<select name='ss' onchange='this.form.submit();'>");
342 curr = ctx.qry.ssdiff;
343 if (!curr && ctx.cfg.ssdiff)
344 curr = 1;
345 html_intoption(0, "unified", curr);
346 html_intoption(1, "ssdiff", curr);
347 html("</select></td></tr>");
348 html("<tr><td/><td class='ctrl'>");
349 html("<noscript><input type='submit' value='reload'/></noscript>");
350 html("</td></tr></table>");
351 html("</form>");
352 html("</div>");
353}
354
355void cgit_print_diff(const char *new_rev, const char *old_rev,
356 const char *prefix, int show_ctrls)
334{ 357{
335 enum object_type type; 358 enum object_type type;
336 unsigned long size; 359 unsigned long size;
@@ -373,7 +396,9 @@ void cgit_print_diff(const char *new_rev, const char *old_rev, const char *prefi
373 if ((ctx.qry.ssdiff && !ctx.cfg.ssdiff) || (!ctx.qry.ssdiff && ctx.cfg.ssdiff)) 396 if ((ctx.qry.ssdiff && !ctx.cfg.ssdiff) || (!ctx.qry.ssdiff && ctx.cfg.ssdiff))
374 use_ssdiff = 1; 397 use_ssdiff = 1;
375 398
376 print_ssdiff_link(); 399 if (show_ctrls)
400 cgit_print_diff_ctrls();
401
377 cgit_print_diffstat(old_rev_sha1, new_rev_sha1, prefix); 402 cgit_print_diffstat(old_rev_sha1, new_rev_sha1, prefix);
378 403
379 if (use_ssdiff) { 404 if (use_ssdiff) {
diff --git a/ui-diff.h b/ui-diff.h
index 12d0c62..0161ffb 100644
--- a/ui-diff.h
+++ b/ui-diff.h
@@ -1,11 +1,13 @@
1#ifndef UI_DIFF_H 1#ifndef UI_DIFF_H
2#define UI_DIFF_H 2#define UI_DIFF_H
3 3
4extern void cgit_print_diff_ctrls();
5
4extern void cgit_print_diffstat(const unsigned char *old_sha1, 6extern void cgit_print_diffstat(const unsigned char *old_sha1,
5 const unsigned char *new_sha1); 7 const unsigned char *new_sha1);
6 8
7extern void cgit_print_diff(const char *new_hex, const char *old_hex, 9extern void cgit_print_diff(const char *new_hex, const char *old_hex,
8 const char *prefix); 10 const char *prefix, int show_ctrls);
9 11
10extern struct diff_filespec *cgit_get_current_old_file(void); 12extern struct diff_filespec *cgit_get_current_old_file(void);
11extern struct diff_filespec *cgit_get_current_new_file(void); 13extern struct diff_filespec *cgit_get_current_new_file(void);
diff --git a/ui-log.c b/ui-log.c
index 15ed6a3..4a295bd 100644
--- a/ui-log.c
+++ b/ui-log.c
@@ -99,11 +99,10 @@ void print_commit(struct commit *commit, struct rev_info *revs)
99 struct strbuf graphbuf = STRBUF_INIT; 99 struct strbuf graphbuf = STRBUF_INIT;
100 struct strbuf msgbuf = STRBUF_INIT; 100 struct strbuf msgbuf = STRBUF_INIT;
101 101
102 if (ctx.repo->enable_log_filecount) { 102 if (ctx.repo->enable_log_filecount)
103 cols++;
104 if (ctx.repo->enable_log_linecount)
103 cols++; 105 cols++;
104 if (ctx.repo->enable_log_linecount)
105 cols++;
106 }
107 106
108 if (revs->graph) { 107 if (revs->graph) {
109 /* Advance graph until current commit */ 108 /* Advance graph until current commit */
@@ -170,18 +169,18 @@ void print_commit(struct commit *commit, struct rev_info *revs)
170 cgit_print_age(commit->date, TM_WEEK * 2, FMT_SHORTDATE); 169 cgit_print_age(commit->date, TM_WEEK * 2, FMT_SHORTDATE);
171 } 170 }
172 171
173 if (ctx.repo->enable_log_filecount) { 172 if (ctx.repo->enable_log_filecount || ctx.repo->enable_log_linecount) {
174 files = 0; 173 files = 0;
175 add_lines = 0; 174 add_lines = 0;
176 rem_lines = 0; 175 rem_lines = 0;
177 cgit_diff_commit(commit, inspect_files, ctx.qry.vpath); 176 cgit_diff_commit(commit, inspect_files, ctx.qry.vpath);
178 html("</td><td>");
179 htmlf("%d", files);
180 if (ctx.repo->enable_log_linecount) {
181 html("</td><td>");
182 htmlf("-%d/+%d", rem_lines, add_lines);
183 }
184 } 177 }
178
179 if (ctx.repo->enable_log_filecount)
180 htmlf("</td><td>%d", files);
181 if (ctx.repo->enable_log_linecount)
182 htmlf("</td><td>-%d/+%d", rem_lines, add_lines);
183
185 html("</td></tr>\n"); 184 html("</td></tr>\n");
186 185
187 if (revs->graph || ctx.qry.showmsg) { /* Print a second table row */ 186 if (revs->graph || ctx.qry.showmsg) { /* Print a second table row */
@@ -370,10 +369,10 @@ void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern
370 if (ctx.repo->enable_log_filecount) { 369 if (ctx.repo->enable_log_filecount) {
371 html("<th class='left'>Files</th>"); 370 html("<th class='left'>Files</th>");
372 columns++; 371 columns++;
373 if (ctx.repo->enable_log_linecount) { 372 }
374 html("<th class='left'>Lines</th>"); 373 if (ctx.repo->enable_log_linecount) {
375 columns++; 374 html("<th class='left'>Lines</th>");
376 } 375 columns++;
377 } 376 }
378 html("</tr>\n"); 377 html("</tr>\n");
379 378
diff --git a/ui-repolist.c b/ui-repolist.c
index e138f59..dce2eac 100644
--- a/ui-repolist.c
+++ b/ui-repolist.c
@@ -46,11 +46,20 @@ static int get_repo_modtime(const struct cgit_repo *repo, time_t *mtime)
46 } 46 }
47 47
48 path = fmt("%s/refs/heads/%s", repo->path, repo->defbranch); 48 path = fmt("%s/refs/heads/%s", repo->path, repo->defbranch);
49 if (stat(path, &s) == 0) 49 if (stat(path, &s) == 0) {
50 *mtime = s.st_mtime; 50 *mtime = s.st_mtime;
51 else 51 r->mtime = *mtime;
52 *mtime = 0; 52 return 1;
53 }
54
55 path = fmt("%s/%s", repo->path, "packed-refs");
56 if (stat(path, &s) == 0) {
57 *mtime = s.st_mtime;
58 r->mtime = *mtime;
59 return 1;
60 }
53 61
62 *mtime = 0;
54 r->mtime = *mtime; 63 r->mtime = *mtime;
55 return (r->mtime != 0); 64 return (r->mtime != 0);
56} 65}
@@ -291,7 +300,7 @@ void cgit_print_site_readme()
291 if (!ctx.cfg.root_readme) 300 if (!ctx.cfg.root_readme)
292 return; 301 return;
293 if (ctx.cfg.about_filter) 302 if (ctx.cfg.about_filter)
294 cgit_open_filter(ctx.cfg.about_filter); 303 cgit_open_filter(ctx.cfg.about_filter, NULL);
295 html_include(ctx.cfg.root_readme); 304 html_include(ctx.cfg.root_readme);
296 if (ctx.cfg.about_filter) 305 if (ctx.cfg.about_filter)
297 cgit_close_filter(ctx.cfg.about_filter); 306 cgit_close_filter(ctx.cfg.about_filter);
diff --git a/ui-snapshot.c b/ui-snapshot.c
index 07cc944..126779d 100644
--- a/ui-snapshot.c
+++ b/ui-snapshot.c
@@ -19,7 +19,7 @@ static int write_compressed_tar_archive(struct archiver_args *args,const char *f
19 f.argv = malloc(2 * sizeof(char *)); 19 f.argv = malloc(2 * sizeof(char *));
20 f.argv[0] = f.cmd; 20 f.argv[0] = f.cmd;
21 f.argv[1] = NULL; 21 f.argv[1] = NULL;
22 cgit_open_filter(&f); 22 cgit_open_filter(&f, NULL);
23 rv = write_tar_archive(args); 23 rv = write_tar_archive(args);
24 cgit_close_filter(&f); 24 cgit_close_filter(&f);
25 return rv; 25 return rv;
diff --git a/ui-stats.c b/ui-stats.c
index 2a0c174..59f4c1e 100644
--- a/ui-stats.c
+++ b/ui-stats.c
@@ -386,6 +386,33 @@ void cgit_show_stats(struct cgit_context *ctx)
386 top = ctx->qry.ofs; 386 top = ctx->qry.ofs;
387 if (!top) 387 if (!top)
388 top = 10; 388 top = 10;
389
390 html("<div class='cgit-panel'>");
391 html("<b>stat options</b>");
392 html("<form method='get' action=''>");
393 cgit_add_hidden_formfields(1, 0, "stats");
394 html("<table><tr><td colspan='2'/></tr>");
395 if (ctx->repo->max_stats > 1) {
396 html("<tr><td class='label'>Period:</td>");
397 html("<td class='ctrl'><select name='period' onchange='this.form.submit();'>");
398 for (i = 0; i < ctx->repo->max_stats; i++)
399 html_option(fmt("%c", periods[i].code),
400 periods[i].name, fmt("%c", period->code));
401 html("</select></td></tr>");
402 }
403 html("<tr><td class='label'>Authors:</td>");
404 html("<td class='ctrl'><select name='ofs' onchange='this.form.submit();'>");
405 html_intoption(10, "10", top);
406 html_intoption(25, "25", top);
407 html_intoption(50, "50", top);
408 html_intoption(100, "100", top);
409 html_intoption(-1, "all", top);
410 html("</select></td></tr>");
411 html("<tr><td/><td class='ctrl'>");
412 html("<noscript><input type='submit' value='Reload'/></noscript>");
413 html("</td></tr></table>");
414 html("</form>");
415 html("</div>");
389 htmlf("<h2>Commits per author per %s", period->name); 416 htmlf("<h2>Commits per author per %s", period->name);
390 if (ctx->qry.path) { 417 if (ctx->qry.path) {
391 html(" (path '"); 418 html(" (path '");
@@ -393,30 +420,6 @@ void cgit_show_stats(struct cgit_context *ctx)
393 html("')"); 420 html("')");
394 } 421 }
395 html("</h2>"); 422 html("</h2>");
396
397 html("<form method='get' action='' style='float: right; text-align: right;'>");
398 cgit_add_hidden_formfields(1, 0, "stats");
399 if (ctx->repo->max_stats > 1) {
400 html("Period: ");
401 html("<select name='period' onchange='this.form.submit();'>");
402 for (i = 0; i < ctx->repo->max_stats; i++)
403 htmlf("<option value='%c'%s>%s</option>",
404 periods[i].code,
405 period == &periods[i] ? " selected" : "",
406 periods[i].name);
407 html("</select><br/><br/>");
408 }
409 html("Authors: ");
410 html("");
411 html("<select name='ofs' onchange='this.form.submit();'>");
412 htmlf("<option value='10'%s>10</option>", top == 10 ? " selected" : "");
413 htmlf("<option value='25'%s>25</option>", top == 25 ? " selected" : "");
414 htmlf("<option value='50'%s>50</option>", top == 50 ? " selected" : "");
415 htmlf("<option value='100'%s>100</option>", top == 100 ? " selected" : "");
416 htmlf("<option value='-1'%s>All</option>", top == -1 ? " selected" : "");
417 html("</select>");
418 html("<noscript>&nbsp;&nbsp;<input type='submit' value='Reload'/></noscript>");
419 html("</form>");
420 print_authors(&authors, top, period); 423 print_authors(&authors, top, period);
421} 424}
422 425
diff --git a/ui-summary.c b/ui-summary.c
index 5be2545..1e9a1b6 100644
--- a/ui-summary.c
+++ b/ui-summary.c
@@ -113,7 +113,7 @@ void cgit_print_repo_readme(char *path)
113 */ 113 */
114 html("<div id='summary'>"); 114 html("<div id='summary'>");
115 if (ctx.repo->about_filter) 115 if (ctx.repo->about_filter)
116 cgit_open_filter(ctx.repo->about_filter); 116 cgit_open_filter(ctx.repo->about_filter, ctx.repo);
117 if (ref) 117 if (ref)
118 cgit_print_file(tmp, ref); 118 cgit_print_file(tmp, ref);
119 else 119 else
diff --git a/ui-tree.c b/ui-tree.c
index 442b6be..2d8d2f3 100644
--- a/ui-tree.c
+++ b/ui-tree.c
@@ -45,7 +45,7 @@ static void print_text_buffer(const char *name, char *buf, unsigned long size)
45 if (ctx.repo->source_filter) { 45 if (ctx.repo->source_filter) {
46 html("<td class='lines'><pre><code>"); 46 html("<td class='lines'><pre><code>");
47 ctx.repo->source_filter->argv[1] = xstrdup(name); 47 ctx.repo->source_filter->argv[1] = xstrdup(name);
48 cgit_open_filter(ctx.repo->source_filter); 48 cgit_open_filter(ctx.repo->source_filter, ctx.repo);
49 html_raw(buf, size); 49 html_raw(buf, size);
50 cgit_close_filter(ctx.repo->source_filter); 50 cgit_close_filter(ctx.repo->source_filter);
51 free(ctx.repo->source_filter->argv[1]); 51 free(ctx.repo->source_filter->argv[1]);