mirror of
https://git.zx2c4.com/cgit
synced 2024-11-26 02:18:42 +00:00
Merge branch 'fh/filter-api'
Conflicts: cgit.c
This commit is contained in:
commit
ab350a77b1
27
cgit.c
27
cgit.c
@ -26,14 +26,27 @@ void add_mimetype(const char *name, const char *value)
|
||||
item->util = xstrdup(value);
|
||||
}
|
||||
|
||||
struct cgit_filter *new_filter(const char *cmd, int extra_args)
|
||||
struct cgit_filter *new_filter(const char *cmd, filter_type filtertype)
|
||||
{
|
||||
struct cgit_filter *f;
|
||||
int args_size = 0;
|
||||
int extra_args;
|
||||
|
||||
if (!cmd || !cmd[0])
|
||||
return NULL;
|
||||
|
||||
switch (filtertype) {
|
||||
case SOURCE:
|
||||
extra_args = 1;
|
||||
break;
|
||||
|
||||
case ABOUT:
|
||||
case COMMIT:
|
||||
default:
|
||||
extra_args = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
f = xmalloc(sizeof(struct cgit_filter));
|
||||
f->cmd = xstrdup(cmd);
|
||||
args_size = (2 + extra_args) * sizeof(char *);
|
||||
@ -83,11 +96,11 @@ void repo_config(struct cgit_repo *repo, const char *name, const char *value)
|
||||
repo->logo_link = xstrdup(value);
|
||||
else if (ctx.cfg.enable_filter_overrides) {
|
||||
if (!strcmp(name, "about-filter"))
|
||||
repo->about_filter = new_filter(value, 0);
|
||||
repo->about_filter = new_filter(value, ABOUT);
|
||||
else if (!strcmp(name, "commit-filter"))
|
||||
repo->commit_filter = new_filter(value, 0);
|
||||
repo->commit_filter = new_filter(value, COMMIT);
|
||||
else if (!strcmp(name, "source-filter"))
|
||||
repo->source_filter = new_filter(value, 1);
|
||||
repo->source_filter = new_filter(value, SOURCE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -180,9 +193,9 @@ void config_cb(const char *name, const char *value)
|
||||
else if (!strcmp(name, "cache-dynamic-ttl"))
|
||||
ctx.cfg.cache_dynamic_ttl = atoi(value);
|
||||
else if (!strcmp(name, "about-filter"))
|
||||
ctx.cfg.about_filter = new_filter(value, 0);
|
||||
ctx.cfg.about_filter = new_filter(value, ABOUT);
|
||||
else if (!strcmp(name, "commit-filter"))
|
||||
ctx.cfg.commit_filter = new_filter(value, 0);
|
||||
ctx.cfg.commit_filter = new_filter(value, COMMIT);
|
||||
else if (!strcmp(name, "embedded"))
|
||||
ctx.cfg.embedded = atoi(value);
|
||||
else if (!strcmp(name, "max-atom-items"))
|
||||
@ -212,7 +225,7 @@ void config_cb(const char *name, const char *value)
|
||||
else if (!strcmp(name, "section-from-path"))
|
||||
ctx.cfg.section_from_path = atoi(value);
|
||||
else if (!strcmp(name, "source-filter"))
|
||||
ctx.cfg.source_filter = new_filter(value, 1);
|
||||
ctx.cfg.source_filter = new_filter(value, SOURCE);
|
||||
else if (!strcmp(name, "summary-log"))
|
||||
ctx.cfg.summary_log = atoi(value);
|
||||
else if (!strcmp(name, "summary-branches"))
|
||||
|
6
cgit.h
6
cgit.h
@ -51,6 +51,10 @@ typedef void (*configfn)(const char *name, const char *value);
|
||||
typedef void (*filepair_fn)(struct diff_filepair *pair);
|
||||
typedef void (*linediff_fn)(char *line, int len);
|
||||
|
||||
typedef enum {
|
||||
ABOUT, COMMIT, SOURCE
|
||||
} filter_type;
|
||||
|
||||
struct cgit_filter {
|
||||
char *cmd;
|
||||
char **argv;
|
||||
@ -315,7 +319,7 @@ extern const char *cgit_repobasename(const char *reponame);
|
||||
|
||||
extern int cgit_parse_snapshots_mask(const char *str);
|
||||
|
||||
extern int cgit_open_filter(struct cgit_filter *filter);
|
||||
extern int cgit_open_filter(struct cgit_filter *filter, struct cgit_repo * repo);
|
||||
extern int cgit_close_filter(struct cgit_filter *filter);
|
||||
|
||||
extern int readfile(const char *path, char **buf, size_t *size);
|
||||
|
47
cgitrc.5.txt
47
cgitrc.5.txt
@ -31,7 +31,7 @@ about-filter::
|
||||
about pages (both top-level and for each repository). The command will
|
||||
get the content of the about-file on its STDIN, and the STDOUT from the
|
||||
command will be included verbatim on the about page. Default value:
|
||||
none.
|
||||
none. See also: "FILTER API".
|
||||
|
||||
agefile::
|
||||
Specifies a path, relative to each repository path, which can be used
|
||||
@ -81,6 +81,7 @@ commit-filter::
|
||||
The command will get the message on its STDIN, and the STDOUT from the
|
||||
command will be included verbatim as the commit message, i.e. this can
|
||||
be used to implement bugtracker integration. Default value: none.
|
||||
See also: "FILTER API".
|
||||
|
||||
css::
|
||||
Url which specifies the css document to include in all cgit pages.
|
||||
@ -323,7 +324,7 @@ source-filter::
|
||||
and the name of the blob as its only command line argument. The STDOUT
|
||||
from the command will be included verbatim as the blob contents, i.e.
|
||||
this can be used to implement e.g. syntax highlighting. Default value:
|
||||
none.
|
||||
none. See also: "FILTER API".
|
||||
|
||||
summary-branches::
|
||||
Specifies the number of branches to display in the repository "summary"
|
||||
@ -356,7 +357,7 @@ REPOSITORY SETTINGS
|
||||
-------------------
|
||||
repo.about-filter::
|
||||
Override the default about-filter. Default value: none. See also:
|
||||
"enable-filter-overrides".
|
||||
"enable-filter-overrides". See also: "FILTER API".
|
||||
|
||||
repo.clone-url::
|
||||
A list of space-separated urls which can be used to clone this repo.
|
||||
@ -364,7 +365,7 @@ repo.clone-url::
|
||||
|
||||
repo.commit-filter::
|
||||
Override the default commit-filter. Default value: none. See also:
|
||||
"enable-filter-overrides".
|
||||
"enable-filter-overrides". See also: "FILTER API".
|
||||
|
||||
repo.defbranch::
|
||||
The name of the default branch for this repository. If no such branch
|
||||
@ -435,7 +436,7 @@ repo.section::
|
||||
|
||||
repo.source-filter::
|
||||
Override the default source-filter. Default value: none. See also:
|
||||
"enable-filter-overrides".
|
||||
"enable-filter-overrides". See also: "FILTER API".
|
||||
|
||||
repo.url::
|
||||
The relative url used to access the repository. This must be the first
|
||||
@ -455,6 +456,42 @@ Note: the "repo." prefix is dropped from the option names in repo-specific
|
||||
config files, e.g. "repo.desc" becomes "desc".
|
||||
|
||||
|
||||
FILTER API
|
||||
----------
|
||||
- about filter::
|
||||
This filter is given no arguments.
|
||||
The about text that is to be filtered is available on standard input and the
|
||||
filtered text is expected on standard output.
|
||||
- commit filter::
|
||||
This filter is given no arguments.
|
||||
The commit message text that is to be filtered is available on standard input
|
||||
and the filtered text is expected on standard output.
|
||||
- source filter::
|
||||
This filter is given a single parameter: the filename of the source file to
|
||||
filter. The filter can use the filename to determine (for example) the syntax
|
||||
highlighting mode.
|
||||
The contents of the source file that is to be filtered is available on
|
||||
standard input and the filtered contents is expected on standard output.
|
||||
|
||||
Also, all filters are handed the following environment variables:
|
||||
- CGIT_REPO_URL ( = repo.url setting )
|
||||
- CGIT_REPO_NAME ( = repo.name setting )
|
||||
- CGIT_REPO_PATH ( = repo.path setting )
|
||||
- CGIT_REPO_OWNER ( = repo.owner setting )
|
||||
- CGIT_REPO_DEFBRANCH ( = repo.defbranch setting )
|
||||
- CGIT_REPO_SECTION ( = section setting )
|
||||
- CGIT_REPO_CLONE_URL ( = repo.clone-url setting )
|
||||
|
||||
If a setting is not defined for a repository and the corresponding global
|
||||
setting is also not defined (if applicable), then the corresponding
|
||||
environment variable will be an empty string.
|
||||
|
||||
Note that under normal circumstance all these environment variables are
|
||||
defined. If however the total size of the defined settings exceed the
|
||||
allocated buffer within cgit then only the environment variables that fit
|
||||
in the allocated buffer are handed to the filter.
|
||||
|
||||
|
||||
EXAMPLE CGITRC FILE
|
||||
-------------------
|
||||
|
||||
|
@ -3,6 +3,17 @@
|
||||
#
|
||||
# To use this script, refer to this file with either the commit-filter or the
|
||||
# repo.commit-filter options in cgitrc.
|
||||
#
|
||||
# The following environment variables can be used to retrieve the configuration
|
||||
# of the repository for which this script is called:
|
||||
# CGIT_REPO_URL ( = repo.url setting )
|
||||
# CGIT_REPO_NAME ( = repo.name setting )
|
||||
# CGIT_REPO_PATH ( = repo.path setting )
|
||||
# CGIT_REPO_OWNER ( = repo.owner setting )
|
||||
# CGIT_REPO_DEFBRANCH ( = repo.defbranch setting )
|
||||
# CGIT_REPO_SECTION ( = section setting )
|
||||
# CGIT_REPO_CLONE_URL ( = repo.clone-url setting )
|
||||
#
|
||||
|
||||
# This expression generates links to commits referenced by their SHA1.
|
||||
regex=$regex'
|
||||
|
@ -23,6 +23,17 @@
|
||||
# table.blob .kwb { color:#830000; }
|
||||
# table.blob .kwc { color:#000000; font-weight:bold; }
|
||||
# table.blob .kwd { color:#010181; }
|
||||
#
|
||||
# The following environment variables can be used to retrieve the configuration
|
||||
# of the repository for which this script is called:
|
||||
# CGIT_REPO_URL ( = repo.url setting )
|
||||
# CGIT_REPO_NAME ( = repo.name setting )
|
||||
# CGIT_REPO_PATH ( = repo.path setting )
|
||||
# CGIT_REPO_OWNER ( = repo.owner setting )
|
||||
# CGIT_REPO_DEFBRANCH ( = repo.defbranch setting )
|
||||
# CGIT_REPO_SECTION ( = section setting )
|
||||
# CGIT_REPO_CLONE_URL ( = repo.clone-url setting )
|
||||
#
|
||||
|
||||
# store filename and extension in local vars
|
||||
BASENAME="$1"
|
||||
|
32
shared.c
32
shared.c
@ -7,6 +7,8 @@
|
||||
*/
|
||||
|
||||
#include "cgit.h"
|
||||
#include <stdio.h>
|
||||
#include <linux/limits.h>
|
||||
|
||||
struct cgit_repolist cgit_repolist;
|
||||
struct cgit_context ctx;
|
||||
@ -367,7 +369,33 @@ int cgit_parse_snapshots_mask(const char *str)
|
||||
return rv;
|
||||
}
|
||||
|
||||
int cgit_open_filter(struct cgit_filter *filter)
|
||||
typedef struct {
|
||||
char * name;
|
||||
char * value;
|
||||
} cgit_env_var;
|
||||
|
||||
static void prepare_env(struct cgit_repo * repo) {
|
||||
cgit_env_var env_vars[] = {
|
||||
{ .name = "CGIT_REPO_URL", .value = repo->url },
|
||||
{ .name = "CGIT_REPO_NAME", .value = repo->name },
|
||||
{ .name = "CGIT_REPO_PATH", .value = repo->path },
|
||||
{ .name = "CGIT_REPO_OWNER", .value = repo->owner },
|
||||
{ .name = "CGIT_REPO_DEFBRANCH", .value = repo->defbranch },
|
||||
{ .name = "CGIT_REPO_SECTION", .value = repo->section },
|
||||
{ .name = "CGIT_REPO_CLONE_URL", .value = repo->clone_url }
|
||||
};
|
||||
int env_var_count = ARRAY_SIZE(env_vars);
|
||||
cgit_env_var *p, *q;
|
||||
static char *warn = "cgit warning: failed to set env: %s=%s\n";
|
||||
|
||||
p = env_vars;
|
||||
q = p + env_var_count;
|
||||
for (; p < q; p++)
|
||||
if (setenv(p->name, p->value, 1))
|
||||
fprintf(stderr, warn, p->name, p->value);
|
||||
}
|
||||
|
||||
int cgit_open_filter(struct cgit_filter *filter, struct cgit_repo * repo)
|
||||
{
|
||||
|
||||
filter->old_stdout = chk_positive(dup(STDOUT_FILENO),
|
||||
@ -378,6 +406,8 @@ int cgit_open_filter(struct cgit_filter *filter)
|
||||
close(filter->pipe_fh[1]);
|
||||
chk_non_negative(dup2(filter->pipe_fh[0], STDIN_FILENO),
|
||||
"Unable to use pipe as STDIN");
|
||||
if (repo)
|
||||
prepare_env(repo);
|
||||
execvp(filter->cmd, filter->argv);
|
||||
die("Unable to exec subprocess %s: %s (%d)", filter->cmd,
|
||||
strerror(errno), errno);
|
||||
|
@ -110,7 +110,7 @@ void cgit_print_commit(char *hex, const char *prefix)
|
||||
html("</table>\n");
|
||||
html("<div class='commit-subject'>");
|
||||
if (ctx.repo->commit_filter)
|
||||
cgit_open_filter(ctx.repo->commit_filter);
|
||||
cgit_open_filter(ctx.repo->commit_filter, ctx.repo);
|
||||
html_txt(info->subject);
|
||||
if (ctx.repo->commit_filter)
|
||||
cgit_close_filter(ctx.repo->commit_filter);
|
||||
@ -118,7 +118,7 @@ void cgit_print_commit(char *hex, const char *prefix)
|
||||
html("</div>");
|
||||
html("<div class='commit-msg'>");
|
||||
if (ctx.repo->commit_filter)
|
||||
cgit_open_filter(ctx.repo->commit_filter);
|
||||
cgit_open_filter(ctx.repo->commit_filter, ctx.repo);
|
||||
html_txt(info->msg);
|
||||
if (ctx.repo->commit_filter)
|
||||
cgit_close_filter(ctx.repo->commit_filter);
|
||||
@ -127,7 +127,7 @@ void cgit_print_commit(char *hex, const char *prefix)
|
||||
html("<div class='notes-header'>Notes</div>");
|
||||
html("<div class='notes'>");
|
||||
if (ctx.repo->commit_filter)
|
||||
cgit_open_filter(ctx.repo->commit_filter);
|
||||
cgit_open_filter(ctx.repo->commit_filter, ctx.repo);
|
||||
html_txt(notes.buf);
|
||||
if (ctx.repo->commit_filter)
|
||||
cgit_close_filter(ctx.repo->commit_filter);
|
||||
|
@ -291,7 +291,7 @@ void cgit_print_site_readme()
|
||||
if (!ctx.cfg.root_readme)
|
||||
return;
|
||||
if (ctx.cfg.about_filter)
|
||||
cgit_open_filter(ctx.cfg.about_filter);
|
||||
cgit_open_filter(ctx.cfg.about_filter, NULL);
|
||||
html_include(ctx.cfg.root_readme);
|
||||
if (ctx.cfg.about_filter)
|
||||
cgit_close_filter(ctx.cfg.about_filter);
|
||||
|
@ -19,7 +19,7 @@ static int write_compressed_tar_archive(struct archiver_args *args,const char *f
|
||||
f.argv = malloc(2 * sizeof(char *));
|
||||
f.argv[0] = f.cmd;
|
||||
f.argv[1] = NULL;
|
||||
cgit_open_filter(&f);
|
||||
cgit_open_filter(&f, NULL);
|
||||
rv = write_tar_archive(args);
|
||||
cgit_close_filter(&f);
|
||||
return rv;
|
||||
|
@ -113,7 +113,7 @@ void cgit_print_repo_readme(char *path)
|
||||
*/
|
||||
html("<div id='summary'>");
|
||||
if (ctx.repo->about_filter)
|
||||
cgit_open_filter(ctx.repo->about_filter);
|
||||
cgit_open_filter(ctx.repo->about_filter, ctx.repo);
|
||||
if (ref)
|
||||
cgit_print_file(tmp, ref);
|
||||
else
|
||||
|
@ -45,7 +45,7 @@ static void print_text_buffer(const char *name, char *buf, unsigned long size)
|
||||
if (ctx.repo->source_filter) {
|
||||
html("<td class='lines'><pre><code>");
|
||||
ctx.repo->source_filter->argv[1] = xstrdup(name);
|
||||
cgit_open_filter(ctx.repo->source_filter);
|
||||
cgit_open_filter(ctx.repo->source_filter, ctx.repo);
|
||||
html_raw(buf, size);
|
||||
cgit_close_filter(ctx.repo->source_filter);
|
||||
free(ctx.repo->source_filter->argv[1]);
|
||||
|
Loading…
Reference in New Issue
Block a user