X-Git-Url: https://git.cameronkatri.com/cgit.git/blobdiff_plain/a1429dbc89f9c0945e32cea9fd3424d2fe56aeab..f32a2da636ffa6eaa6b8d0d3f35a673fa12e404a:/cgit.c diff --git a/cgit.c b/cgit.c index 51ca78a..6f44ef2 100644 --- a/cgit.c +++ b/cgit.c @@ -1,7 +1,7 @@ /* cgit.c: cgi for the git scm * * Copyright (C) 2006 Lars Hjemli - * Copyright (C) 2010 Jason A. Donenfeld + * Copyright (C) 2010, 2012 Jason A. Donenfeld * * Licensed under GNU General Public License v2 * (see COPYING for full license text) @@ -18,7 +18,7 @@ const char *cgit_version = CGIT_VERSION; -void add_mimetype(const char *name, const char *value) +static void add_mimetype(const char *name, const char *value) { struct string_list_item *item; @@ -26,7 +26,7 @@ void add_mimetype(const char *name, const char *value) item->util = xstrdup(value); } -struct cgit_filter *new_filter(const char *cmd, filter_type filtertype) +static struct cgit_filter *new_filter(const char *cmd, filter_type filtertype) { struct cgit_filter *f; int args_size = 0; @@ -58,8 +58,10 @@ struct cgit_filter *new_filter(const char *cmd, filter_type filtertype) static void process_cached_repolist(const char *path); -void repo_config(struct cgit_repo *repo, const char *name, const char *value) +static void repo_config(struct cgit_repo *repo, const char *name, const char *value) { + struct string_list_item *item; + if (!strcmp(name, "name")) repo->name = xstrdup(value); else if (!strcmp(name, "clone-url")) @@ -73,20 +75,33 @@ void repo_config(struct cgit_repo *repo, const char *name, const char *value) else if (!strcmp(name, "snapshots")) repo->snapshots = ctx.cfg.snapshots & cgit_parse_snapshots_mask(value); else if (!strcmp(name, "enable-commit-graph")) - repo->enable_commit_graph = ctx.cfg.enable_commit_graph * atoi(value); + repo->enable_commit_graph = atoi(value); else if (!strcmp(name, "enable-log-filecount")) - repo->enable_log_filecount = ctx.cfg.enable_log_filecount * atoi(value); + repo->enable_log_filecount = atoi(value); else if (!strcmp(name, "enable-log-linecount")) - repo->enable_log_linecount = ctx.cfg.enable_log_linecount * atoi(value); + repo->enable_log_linecount = atoi(value); else if (!strcmp(name, "enable-remote-branches")) repo->enable_remote_branches = atoi(value); else if (!strcmp(name, "enable-subject-links")) repo->enable_subject_links = atoi(value); - else if (!strcmp(name, "max-stats")) + else if (!strcmp(name, "branch-sort")) { + if (!strcmp(value, "age")) + repo->branch_sort = 1; + if (!strcmp(value, "name")) + repo->branch_sort = 0; + } else if (!strcmp(name, "commit-sort")) { + if (!strcmp(value, "date")) + repo->commit_sort = 1; + if (!strcmp(value, "topo")) + repo->commit_sort = 2; + } else if (!strcmp(name, "max-stats")) repo->max_stats = cgit_find_stats_period(value, NULL); else if (!strcmp(name, "module-link")) repo->module_link= xstrdup(value); - else if (!strcmp(name, "section")) + else if (!prefixcmp(name, "module-link.")) { + item = string_list_append(&repo->submodules, name + 12); + item->util = xstrdup(value); + } else if (!strcmp(name, "section")) repo->section = xstrdup(value); else if (!strcmp(name, "readme") && value != NULL) repo->readme = xstrdup(value); @@ -104,7 +119,7 @@ void repo_config(struct cgit_repo *repo, const char *name, const char *value) } } -void config_cb(const char *name, const char *value) +static void config_cb(const char *name, const char *value) { if (!strcmp(name, "section") || !strcmp(name, "repo.group")) ctx.cfg.section = xstrdup(value); @@ -145,9 +160,7 @@ void config_cb(const char *name, const char *value) else if (!strcmp(name, "strict-export")) ctx.cfg.strict_export = xstrdup(value); else if (!strcmp(name, "virtual-root")) { - ctx.cfg.virtual_root = trim_end(value, '/'); - if (!ctx.cfg.virtual_root && (!strcmp(value, "/"))) - ctx.cfg.virtual_root = ""; + ctx.cfg.virtual_root = ensure_end(value, '/'); } else if (!strcmp(name, "nocache")) ctx.cfg.nocache = atoi(value); else if (!strcmp(name, "noplainemail")) @@ -158,12 +171,12 @@ void config_cb(const char *name, const char *value) ctx.cfg.snapshots = cgit_parse_snapshots_mask(value); else if (!strcmp(name, "enable-filter-overrides")) ctx.cfg.enable_filter_overrides = atoi(value); - else if (!strcmp(name, "enable-gitweb-owner")) - ctx.cfg.enable_gitweb_owner = atoi(value); else if (!strcmp(name, "enable-http-clone")) ctx.cfg.enable_http_clone = atoi(value); else if (!strcmp(name, "enable-index-links")) ctx.cfg.enable_index_links = atoi(value); + else if (!strcmp(name, "enable-index-owner")) + ctx.cfg.enable_index_owner = atoi(value); else if (!strcmp(name, "enable-commit-graph")) ctx.cfg.enable_commit_graph = atoi(value); else if (!strcmp(name, "enable-log-filecount")) @@ -176,6 +189,8 @@ void config_cb(const char *name, const char *value) ctx.cfg.enable_subject_links = atoi(value); else if (!strcmp(name, "enable-tree-linenumbers")) ctx.cfg.enable_tree_linenumbers = atoi(value); + else if (!strcmp(name, "enable-git-config")) + ctx.cfg.enable_git_config = atoi(value); else if (!strcmp(name, "max-stats")) ctx.cfg.max_stats = cgit_find_stats_period(value, NULL); else if (!strcmp(name, "cache-size")) @@ -192,6 +207,8 @@ void config_cb(const char *name, const char *value) ctx.cfg.cache_static_ttl = atoi(value); else if (!strcmp(name, "cache-dynamic-ttl")) ctx.cfg.cache_dynamic_ttl = atoi(value); + else if (!strcmp(name, "case-sensitive-sort")) + ctx.cfg.case_sensitive_sort = atoi(value); else if (!strcmp(name, "about-filter")) ctx.cfg.about_filter = new_filter(value, ABOUT); else if (!strcmp(name, "commit-filter")) @@ -224,6 +241,10 @@ void config_cb(const char *name, const char *value) ctx.cfg.scan_hidden_path = atoi(value); else if (!strcmp(name, "section-from-path")) ctx.cfg.section_from_path = atoi(value); + else if (!strcmp(name, "repository-sort")) + ctx.cfg.repository_sort = xstrdup(value); + else if (!strcmp(name, "section-sort")) + ctx.cfg.section_sort = atoi(value); else if (!strcmp(name, "source-filter")) ctx.cfg.source_filter = new_filter(value, SOURCE); else if (!strcmp(name, "summary-log")) @@ -236,6 +257,8 @@ void config_cb(const char *name, const char *value) ctx.cfg.ssdiff = atoi(value); else if (!strcmp(name, "agefile")) ctx.cfg.agefile = xstrdup(value); + else if (!strcmp(name, "mimetype-file")) + ctx.cfg.mimetype_file = xstrdup(value); else if (!strcmp(name, "renamelimit")) ctx.cfg.renamelimit = atoi(value); else if (!strcmp(name, "remove-suffix")) @@ -248,7 +271,17 @@ void config_cb(const char *name, const char *value) ctx.cfg.clone_url = xstrdup(value); else if (!strcmp(name, "local-time")) ctx.cfg.local_time = atoi(value); - else if (!prefixcmp(name, "mimetype.")) + else if (!strcmp(name, "commit-sort")) { + if (!strcmp(value, "date")) + ctx.cfg.commit_sort = 1; + if (!strcmp(value, "topo")) + ctx.cfg.commit_sort = 2; + } else if (!strcmp(name, "branch-sort")) { + if (!strcmp(value, "age")) + ctx.cfg.branch_sort = 1; + if (!strcmp(value, "name")) + ctx.cfg.branch_sort = 0; + } else if (!prefixcmp(name, "mimetype.")) add_mimetype(name + 9, value); else if (!strcmp(name, "include")) parse_configfile(expand_macros(value), config_cb); @@ -290,7 +323,7 @@ static void querystring_cb(const char *name, const char *value) ctx.qry.name = xstrdup(value); } else if (!strcmp(name, "mimetype")) { ctx.qry.mimetype = xstrdup(value); - } else if (!strcmp(name, "s")){ + } else if (!strcmp(name, "s")) { ctx.qry.sort = xstrdup(value); } else if (!strcmp(name, "showmsg")) { ctx.qry.showmsg = atoi(value); @@ -298,6 +331,7 @@ static void querystring_cb(const char *name, const char *value) ctx.qry.period = xstrdup(value); } else if (!strcmp(name, "ss")) { ctx.qry.ssdiff = atoi(value); + ctx.qry.has_ssdiff = 1; } else if (!strcmp(name, "all")) { ctx.qry.show_all = atoi(value); } else if (!strcmp(name, "context")) { @@ -307,11 +341,6 @@ static void querystring_cb(const char *name, const char *value) } } -char *xstrdupn(const char *str) -{ - return (str ? xstrdup(str) : NULL); -} - static void prepare_context(struct cgit_context *ctx) { memset(ctx, 0, sizeof(*ctx)); @@ -325,12 +354,16 @@ static void prepare_context(struct cgit_context *ctx) ctx->cfg.cache_root_ttl = 5; ctx->cfg.cache_scanrc_ttl = 15; ctx->cfg.cache_static_ttl = -1; + ctx->cfg.case_sensitive_sort = 1; + ctx->cfg.branch_sort = 0; + ctx->cfg.commit_sort = 0; ctx->cfg.css = "/cgit.css"; ctx->cfg.logo = "/cgit.png"; ctx->cfg.local_time = 0; - ctx->cfg.enable_gitweb_owner = 1; ctx->cfg.enable_http_clone = 1; + ctx->cfg.enable_index_owner = 1; ctx->cfg.enable_tree_linenumbers = 1; + ctx->cfg.enable_git_config = 0; ctx->cfg.max_repo_count = 50; ctx->cfg.max_commit_count = 50; ctx->cfg.max_lock_attempts = 5; @@ -338,7 +371,6 @@ static void prepare_context(struct cgit_context *ctx) ctx->cfg.max_repodesc_len = 80; ctx->cfg.max_blob_size = 0; ctx->cfg.max_stats = 0; - ctx->cfg.module_link = "./?repo=%s&page=commit&id=%s"; ctx->cfg.project_list = NULL; ctx->cfg.renamelimit = -1; ctx->cfg.remove_suffix = 0; @@ -348,21 +380,23 @@ static void prepare_context(struct cgit_context *ctx) ctx->cfg.scan_hidden_path = 0; ctx->cfg.script_name = CGIT_SCRIPT_NAME; ctx->cfg.section = ""; + ctx->cfg.repository_sort = "name"; + ctx->cfg.section_sort = 1; ctx->cfg.summary_branches = 10; ctx->cfg.summary_log = 10; ctx->cfg.summary_tags = 10; ctx->cfg.max_atom_items = 10; ctx->cfg.ssdiff = 0; - ctx->env.cgit_config = xstrdupn(getenv("CGIT_CONFIG")); - ctx->env.http_host = xstrdupn(getenv("HTTP_HOST")); - ctx->env.https = xstrdupn(getenv("HTTPS")); - ctx->env.no_http = xstrdupn(getenv("NO_HTTP")); - ctx->env.path_info = xstrdupn(getenv("PATH_INFO")); - ctx->env.query_string = xstrdupn(getenv("QUERY_STRING")); - ctx->env.request_method = xstrdupn(getenv("REQUEST_METHOD")); - ctx->env.script_name = xstrdupn(getenv("SCRIPT_NAME")); - ctx->env.server_name = xstrdupn(getenv("SERVER_NAME")); - ctx->env.server_port = xstrdupn(getenv("SERVER_PORT")); + ctx->env.cgit_config = getenv("CGIT_CONFIG"); + ctx->env.http_host = getenv("HTTP_HOST"); + ctx->env.https = getenv("HTTPS"); + ctx->env.no_http = getenv("NO_HTTP"); + ctx->env.path_info = getenv("PATH_INFO"); + ctx->env.query_string = getenv("QUERY_STRING"); + ctx->env.request_method = getenv("REQUEST_METHOD"); + ctx->env.script_name = getenv("SCRIPT_NAME"); + ctx->env.server_name = getenv("SERVER_NAME"); + ctx->env.server_port = getenv("SERVER_PORT"); ctx->page.mimetype = "text/html"; ctx->page.charset = PAGE_ENCODING; ctx->page.filename = NULL; @@ -372,9 +406,9 @@ static void prepare_context(struct cgit_context *ctx) ctx->page.etag = NULL; memset(&ctx->cfg.mimetypes, 0, sizeof(struct string_list)); if (ctx->env.script_name) - ctx->cfg.script_name = ctx->env.script_name; + ctx->cfg.script_name = xstrdup(ctx->env.script_name); if (ctx->env.query_string) - ctx->qry.raw = ctx->env.query_string; + ctx->qry.raw = xstrdup(ctx->env.query_string); if (!ctx->env.cgit_config) ctx->env.cgit_config = CGIT_CONFIG; } @@ -385,8 +419,8 @@ struct refmatch { int match; }; -int find_current_ref(const char *refname, const unsigned char *sha1, - int flags, void *cb_data) +static int find_current_ref(const char *refname, const unsigned char *sha1, + int flags, void *cb_data) { struct refmatch *info; @@ -398,7 +432,13 @@ int find_current_ref(const char *refname, const unsigned char *sha1, return info->match; } -char *find_default_branch(struct cgit_repo *repo) +static void free_refmatch_inner(struct refmatch *info) +{ + if (info->first_ref) + free(info->first_ref); +} + +static char *find_default_branch(struct cgit_repo *repo) { struct refmatch info; char *ref; @@ -413,35 +453,78 @@ char *find_default_branch(struct cgit_repo *repo) ref = info.first_ref; if (ref) ref = xstrdup(ref); + free_refmatch_inner(&info); + return ref; } +static char *guess_defbranch(void) +{ + const char *ref; + unsigned char sha1[20]; + + ref = resolve_ref_unsafe("HEAD", sha1, 0, NULL); + if (!ref || prefixcmp(ref, "refs/heads/")) + return "master"; + return xstrdup(ref + 11); +} + static int prepare_repo_cmd(struct cgit_context *ctx) { - char *tmp; + char *user_home; + char *xdg_home; unsigned char sha1[20]; int nongit = 0; + int rc; + /* The path to the git repository. */ setenv("GIT_DIR", ctx->repo->path, 1); + + /* Do not look in /etc/ for gitconfig and gitattributes. */ + setenv("GIT_CONFIG_NOSYSTEM", "1", 1); + setenv("GIT_ATTR_NOSYSTEM", "1", 1); + + /* We unset HOME and XDG_CONFIG_HOME before calling the git setup function + * so that we don't make unneccessary filesystem accesses. */ + user_home = getenv("HOME"); + xdg_home = getenv("XDG_CONFIG_HOME"); + unsetenv("HOME"); + unsetenv("XDG_CONFIG_HOME"); + + /* Setup the git directory and initialize the notes system. Both of these + * load local configuration from the git repository, so we do them both while + * the HOME variables are unset. */ setup_git_directory_gently(&nongit); + init_display_notes(NULL); + + /* We restore the unset variables afterward. */ + if (user_home) + setenv("HOME", user_home, 1); + if (xdg_home) + setenv("XDG_CONFIG_HOME", xdg_home, 1); + if (nongit) { - ctx->page.title = fmt("%s - %s", ctx->cfg.root_title, - "config error"); - tmp = fmt("Not a git repository: '%s'", ctx->repo->path); + const char *name = ctx->repo->name; + rc = errno; + ctx->page.title = fmtalloc("%s - %s", ctx->cfg.root_title, + "config error"); ctx->repo = NULL; cgit_print_http_headers(ctx); cgit_print_docstart(ctx); cgit_print_pageheader(ctx); - cgit_print_error(tmp); + cgit_print_error("Failed to open %s: %s", name, + rc ? strerror(rc) : "Not a valid git repository"); cgit_print_docend(); return 1; } - ctx->page.title = fmt("%s - %s", ctx->repo->name, ctx->repo->desc); + ctx->page.title = fmtalloc("%s - %s", ctx->repo->name, ctx->repo->desc); + + if (!ctx->repo->defbranch) + ctx->repo->defbranch = guess_defbranch(); if (!ctx->qry.head) { ctx->qry.nohead = 1; ctx->qry.head = find_default_branch(ctx->repo); - ctx->repo->defbranch = ctx->qry.head; } if (!ctx->qry.head) { @@ -454,17 +537,18 @@ static int prepare_repo_cmd(struct cgit_context *ctx) } if (get_sha1(ctx->qry.head, sha1)) { - tmp = xstrdup(ctx->qry.head); + char *tmp = xstrdup(ctx->qry.head); ctx->qry.head = ctx->repo->defbranch; ctx->page.status = 404; ctx->page.statusmsg = "Not found"; cgit_print_http_headers(ctx); cgit_print_docstart(ctx); cgit_print_pageheader(ctx); - cgit_print_error(fmt("Invalid branch: %s", tmp)); + cgit_print_error("Invalid branch: %s", tmp); cgit_print_docend(); return 1; } + sort_string_list(&ctx->repo->submodules); cgit_prepare_repo_env(ctx->repo); return 0; } @@ -502,7 +586,7 @@ static void process_request(void *cbdata) cgit_print_http_headers(ctx); cgit_print_docstart(ctx); cgit_print_pageheader(ctx); - cgit_print_error(fmt("No repository selected")); + cgit_print_error("No repository selected"); cgit_print_docend(); return; } @@ -522,33 +606,28 @@ static void process_request(void *cbdata) cgit_print_docend(); } -int cmp_repos(const void *a, const void *b) +static int cmp_repos(const void *a, const void *b) { const struct cgit_repo *ra = a, *rb = b; return strcmp(ra->url, rb->url); } -char *build_snapshot_setting(int bitmap) +static char *build_snapshot_setting(int bitmap) { const struct cgit_snapshot_format *f; - char *result = xstrdup(""); - char *tmp; - int len; + struct strbuf result = STRBUF_INIT; for (f = cgit_snapshot_formats; f->suffix; f++) { if (f->bit & bitmap) { - tmp = result; - result = xstrdup(fmt("%s%s ", tmp, f->suffix)); - free(tmp); + if (result.len) + strbuf_addch(&result, ' '); + strbuf_addstr(&result, f->suffix); } } - len = strlen(result); - if (len) - result[len - 1] = '\0'; - return result; + return strbuf_detach(&result, NULL); } -char *get_first_line(char *txt) +static char *get_first_line(char *txt) { char *t = xstrdup(txt); char *p = strchr(t, '\n'); @@ -557,7 +636,7 @@ char *get_first_line(char *txt) return t; } -void print_repo(FILE *f, struct cgit_repo *repo) +static void print_repo(FILE *f, struct cgit_repo *repo) { fprintf(f, "repo.url=%s\n", repo->url); fprintf(f, "repo.name=%s\n", repo->name); @@ -593,7 +672,7 @@ void print_repo(FILE *f, struct cgit_repo *repo) fprintf(f, "repo.source-filter=%s\n", repo->source_filter->cmd); if (repo->snapshots != ctx.cfg.snapshots) { char *tmp = build_snapshot_setting(repo->snapshots); - fprintf(f, "repo.snapshots=%s\n", tmp); + fprintf(f, "repo.snapshots=%s\n", tmp ? tmp : ""); free(tmp); } if (repo->max_stats != ctx.cfg.max_stats) @@ -602,11 +681,11 @@ void print_repo(FILE *f, struct cgit_repo *repo) fprintf(f, "\n"); } -void print_repolist(FILE *f, struct cgit_repolist *list, int start) +static void print_repolist(FILE *f, struct cgit_repolist *list, int start) { int i; - for(i = start; i < list->count; i++) + for (i = start; i < list->count; i++) print_repo(f, &list->repos[i]); } @@ -615,20 +694,22 @@ void print_repolist(FILE *f, struct cgit_repolist *list, int start) */ static int generate_cached_repolist(const char *path, const char *cached_rc) { - char *locked_rc; + struct strbuf locked_rc = STRBUF_INIT; + int result = 0; int idx; FILE *f; - locked_rc = xstrdup(fmt("%s.lock", cached_rc)); - f = fopen(locked_rc, "wx"); + strbuf_addf(&locked_rc, "%s.lock", cached_rc); + f = fopen(locked_rc.buf, "wx"); if (!f) { /* Inform about the error unless the lockfile already existed, * since that only means we've got concurrent requests. */ - if (errno != EEXIST) + result = errno; + if (result != EEXIST) fprintf(stderr, "[cgit] Error opening %s: %s (%d)\n", - locked_rc, strerror(errno), errno); - return errno; + locked_rc.buf, strerror(result), result); + goto out; } idx = cgit_repolist.count; if (ctx.cfg.project_list) @@ -636,55 +717,59 @@ static int generate_cached_repolist(const char *path, const char *cached_rc) else scan_tree(path, repo_config); print_repolist(f, &cgit_repolist, idx); - if (rename(locked_rc, cached_rc)) + if (rename(locked_rc.buf, cached_rc)) fprintf(stderr, "[cgit] Error renaming %s to %s: %s (%d)\n", - locked_rc, cached_rc, strerror(errno), errno); + locked_rc.buf, cached_rc, strerror(errno), errno); fclose(f); - return 0; +out: + strbuf_release(&locked_rc); + return result; } static void process_cached_repolist(const char *path) { struct stat st; - char *cached_rc; + struct strbuf cached_rc = STRBUF_INIT; time_t age; unsigned long hash; hash = hash_str(path); if (ctx.cfg.project_list) hash += hash_str(ctx.cfg.project_list); - cached_rc = xstrdup(fmt("%s/rc-%8lx", ctx.cfg.cache_root, hash)); + strbuf_addf(&cached_rc, "%s/rc-%8lx", ctx.cfg.cache_root, hash); - if (stat(cached_rc, &st)) { + if (stat(cached_rc.buf, &st)) { /* Nothing is cached, we need to scan without forking. And * if we fail to generate a cached repolist, we need to * invoke scan_tree manually. */ - if (generate_cached_repolist(path, cached_rc)) { + if (generate_cached_repolist(path, cached_rc.buf)) { if (ctx.cfg.project_list) scan_projects(path, ctx.cfg.project_list, repo_config); else scan_tree(path, repo_config); } - return; + goto out; } - parse_configfile(cached_rc, config_cb); + parse_configfile(cached_rc.buf, config_cb); /* If the cached configfile hasn't expired, lets exit now */ age = time(NULL) - st.st_mtime; if (age <= (ctx.cfg.cache_scanrc_ttl * 60)) - return; + goto out; /* The cached repolist has been parsed, but it was old. So lets * rescan the specified path and generate a new cached repolist * in a child-process to avoid latency for the current request. */ if (fork()) - return; + goto out; - exit(generate_cached_repolist(path, cached_rc)); + exit(generate_cached_repolist(path, cached_rc.buf)); +out: + strbuf_release(&cached_rc); } static void cgit_parse_args(int argc, const char **argv) @@ -694,7 +779,7 @@ static void cgit_parse_args(int argc, const char **argv) for (i = 1; i < argc; i++) { if (!strncmp(argv[i], "--cache=", 8)) { - ctx.cfg.cache_root = xstrdup(argv[i]+8); + ctx.cfg.cache_root = xstrdup(argv[i] + 8); } if (!strcmp(argv[i], "--nocache")) { ctx.cfg.nocache = 1; @@ -703,24 +788,24 @@ static void cgit_parse_args(int argc, const char **argv) ctx.env.no_http = "1"; } if (!strncmp(argv[i], "--query=", 8)) { - ctx.qry.raw = xstrdup(argv[i]+8); + ctx.qry.raw = xstrdup(argv[i] + 8); } if (!strncmp(argv[i], "--repo=", 7)) { - ctx.qry.repo = xstrdup(argv[i]+7); + ctx.qry.repo = xstrdup(argv[i] + 7); } if (!strncmp(argv[i], "--page=", 7)) { - ctx.qry.page = xstrdup(argv[i]+7); + ctx.qry.page = xstrdup(argv[i] + 7); } if (!strncmp(argv[i], "--head=", 7)) { - ctx.qry.head = xstrdup(argv[i]+7); + ctx.qry.head = xstrdup(argv[i] + 7); ctx.qry.has_symref = 1; } if (!strncmp(argv[i], "--sha1=", 7)) { - ctx.qry.sha1 = xstrdup(argv[i]+7); + ctx.qry.sha1 = xstrdup(argv[i] + 7); ctx.qry.has_sha1 = 1; } if (!strncmp(argv[i], "--ofs=", 6)) { - ctx.qry.ofs = atoi(argv[i]+6); + ctx.qry.ofs = atoi(argv[i] + 6); } if (!strncmp(argv[i], "--scan-tree=", 12) || !strncmp(argv[i], "--scan-path=", 12)) { @@ -766,7 +851,6 @@ static int calc_ttl() int main(int argc, const char **argv) { const char *path; - char *qry; int err, ttl; prepare_context(&ctx); @@ -783,11 +867,8 @@ int main(int argc, const char **argv) * that virtual-root equals SCRIPT_NAME, minus any possibly * trailing slashes. */ - if (!ctx.cfg.virtual_root && ctx.cfg.script_name) { - ctx.cfg.virtual_root = trim_end(ctx.cfg.script_name, '/'); - if (!ctx.cfg.virtual_root) - ctx.cfg.virtual_root = ""; - } + if (!ctx.cfg.virtual_root && ctx.cfg.script_name) + ctx.cfg.virtual_root = ensure_end(ctx.cfg.script_name, '/'); /* If no url parameter is specified on the querystring, lets * use PATH_INFO as url. This allows cgit to work with virtual @@ -800,16 +881,16 @@ int main(int argc, const char **argv) path++; ctx.qry.url = xstrdup(path); if (ctx.qry.raw) { - qry = ctx.qry.raw; - ctx.qry.raw = xstrdup(fmt("%s?%s", path, qry)); - free(qry); + char *newqry = fmtalloc("%s?%s", path, ctx.qry.raw); + free(ctx.qry.raw); + ctx.qry.raw = newqry; } else ctx.qry.raw = xstrdup(ctx.qry.url); cgit_parse_url(ctx.qry.url); } ttl = calc_ttl(); - ctx.page.expires += ttl*60; + ctx.page.expires += ttl * 60; if (ctx.env.request_method && !strcmp(ctx.env.request_method, "HEAD")) ctx.cfg.nocache = 1; if (ctx.cfg.nocache) @@ -817,7 +898,7 @@ int main(int argc, const char **argv) err = cache_process(ctx.cfg.cache_size, ctx.cfg.cache_root, ctx.qry.raw, ttl, process_request, &ctx); if (err) - cgit_print_error(fmt("Error processing page: %s (%d)", - strerror(err), err)); + cgit_print_error("Error processing page: %s (%d)", + strerror(err), err); return err; }