Diff options
| author | Bryce Kwon <bryce@brycekwon.com> | |
|---|---|---|
| committer | Bryce Kwon <bryce@brycekwon.com> | |
| commit | ||
| parent | ||
| tree | ||
| download | ||
Move cgit.c's own helpers out of shared.c
Diffstat (limited to 'source/cgit.c')
| -rw-r--r-- | source/cgit.c | 84 |
1 file changed, 78 insertions, 6 deletions
diff --git a/source/cgit.c b/source/cgit.c index dd90fed..3ae895d 100644 --- a/source/cgit.c +++ b/source/cgit.c @@ -86,6 +86,13 @@ static NORETURN void die_routine(const char *msg, va_list params) exit(0); } +static char *ensure_end(const char *str, char c) +{ + size_t len = strlen(str); + + return len && str[len - 1] == c ? xstrdup(str) : xstrfmt("%s%c", str, c); +} + static void prepare_context(void) { const char *script_name = getenv("SCRIPT_NAME"); @@ -154,7 +161,7 @@ static void prepare_context(void) string_list_init_dup(&ctx.cfg.mimetypes); if (script_name) ctx.cfg.script_name = xstrdup(script_name); - ctx.cfg.virtual_root = cgit_ensure_end(ctx.cfg.script_name, '/'); + ctx.cfg.virtual_root = ensure_end(ctx.cfg.script_name, '/'); if (ctx.env.query_string) ctx.qry.raw = xstrdup(ctx.env.query_string); if (!ctx.env.cgit_config) @@ -463,6 +470,46 @@ static void add_mimetype(const char *name, const char *value) item->util = xstrdup(value); } +/* + * Accept only the date formats cgit documents, leaving mode unchanged for + * anything else. Git's parse_date_format dies on anything unknown, which would + * turn a cgitrc typo into a failed request. + */ +static void parse_date_setting(const char *format, struct date_mode *mode) +{ + static const char * const names[] = { + "default", "human", "iso", "iso-strict", "iso8601", + "iso8601-strict", "raw", "relative", "rfc", + "rfc2822", "short", "unix", + }; + const char *rest; + size_t i; + + if (skip_prefix(format, "format:", &rest)) { + // An empty strftime format would render every date blank. + if (*rest) + parse_date_format(format, mode); + return; + } + + // git reads local only as a whole alias of default-local, and dies on + // it with a suffix of its own. + if (!strcmp(format, "local")) { + parse_date_format(format, mode); + return; + } + + for (i = 0; i < ARRAY_SIZE(names); i++) { + if (!skip_prefix(format, names[i], &rest)) + continue; + // "iso" also prefixes "iso8601", so a partial hit is skipped. + if (*rest && strcmp(rest, "-local")) + continue; + parse_date_format(format, mode); + return; + } +} + static void apply_config(const char *name, const char *value) { const char *arg; @@ -504,7 +551,7 @@ static void apply_config(const char *name, const char *value) else if (!strcmp(name, "strict-export")) ctx.cfg.strict_export = cgit_strdup_first_line(value); else if (!strcmp(name, "virtual-root")) - ctx.cfg.virtual_root = cgit_ensure_end(value, '/'); + ctx.cfg.virtual_root = ensure_end(value, '/'); else if (!strcmp(name, "enable-plain-email")) ctx.cfg.enable_plain_email = atoi(value); else if (!strcmp(name, "enable-header")) @@ -656,7 +703,7 @@ static void apply_config(const char *name, const char *value) else if (!strcmp(name, "local-time")) ctx.cfg.local_time = atoi(value); else if (!strcmp(name, "date-format")) - cgit_parse_date_format(value, &ctx.cfg.date_mode); + parse_date_setting(value, &ctx.cfg.date_mode); else if (!strcmp(name, "commit-sort")) { if (!strcmp(value, "date")) ctx.cfg.commit_sort = 1; @@ -1024,6 +1071,31 @@ static void choose_readme(struct cgit_repo *repo) string_list_append(&repo->readme, filename)->util = ref; } +/* + * Export the CGIT_REPO_* variables that filters and hooks read. + */ +static void prepare_repo_env(struct cgit_repo *repo) +{ + const struct { + const char *name; + const char *value; + } 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 } + }; + size_t i; + + for (i = 0; i < ARRAY_SIZE(vars); i++) + if (vars[i].value && setenv(vars[i].name, vars[i].value, 1)) + fprintf(stderr, "[cgit] Unable to set %s=%s: %s (%d)\n", + vars[i].name, vars[i].value, strerror(errno), errno); +} + static void open_repo(int *nongit, int *err) { // A repository configured without a path has nothing to open. @@ -1085,14 +1157,14 @@ static int prepare_repo_cmd(int nongit, int err, int clone) // The dumb transport serves refs and objects off the disk and // asks nothing of the head, and an empty repository clones. if (clone) { - cgit_prepare_repo_env(ctx.repo); + prepare_repo_env(ctx.repo); return 0; } ctx.empty_repo = 1; // Before the document starts, since the <head> carries // <link rel='vcs-git'> and those clone urls expand macros such // as $CGIT_REPO_URL out of this environment. - cgit_prepare_repo_env(ctx.repo); + prepare_repo_env(ctx.repo); cgit_print_layout_start(); cgit_print_empty_repo(); cgit_print_layout_end(); @@ -1116,7 +1188,7 @@ static int prepare_repo_cmd(int nongit, int err, int clone) return 1; } string_list_sort(&ctx.repo->submodules); - cgit_prepare_repo_env(ctx.repo); + prepare_repo_env(ctx.repo); choose_readme(ctx.repo); return 0; } |
