Diff options
| author | Bryce Kwon <bryce@brycekwon.com> | |
|---|---|---|
| committer | Bryce Kwon <bryce@brycekwon.com> | |
| commit | ||
| parent | ||
| tree | ||
| download | ||
Key the cached scan on every setting it uses
Two cgitrc files sharing a cache-root read one list, so strict-export
and trust-scan-config set in one applied to the other, and a changed
setting stayed stale until the list expired. The first request after
an upgrade scans again, and the files under the old names are never
read.
Diffstat (limited to 'source/cgit.c')
| -rw-r--r-- | source/cgit.c | 62 |
1 file changed, 57 insertions, 5 deletions
diff --git a/source/cgit.c b/source/cgit.c index f8795d7..3571bc4 100644 --- a/source/cgit.c +++ b/source/cgit.c @@ -376,18 +376,70 @@ out: */ static void apply_config(const char *name, const char *value); +/* + * The cached list is read back as trusted config, so it is kept under a name + * drawn from every setting that changes what the scan writes, from the scan + * itself to the defaults cgit_add_repo hands each repository. Two sites + * sharing a cache-root, or one that changed a setting, would otherwise read + * a list scanned under other settings until it expired. + */ +static void build_scan_key(struct strbuf *key, const char *path) +{ + const char *texts[] = { + path, + ctx.cfg.project_list, + ctx.cfg.strict_export, + ctx.cfg.section, + ctx.cfg.module_link, + ctx.cfg.clone_url, + }; + const int numbers[] = { + ctx.cfg.scan_hidden_path, + ctx.cfg.remove_suffix, + ctx.cfg.section_from_path, + ctx.cfg.enable_git_config, + ctx.cfg.trust_scan_config, + ctx.cfg.snapshots, + ctx.cfg.max_stats, + ctx.cfg.branch_sort, + ctx.cfg.commit_sort, + ctx.cfg.enable_blame, + ctx.cfg.enable_commit_graph, + ctx.cfg.enable_commit_trailers, + ctx.cfg.enable_follow_links, + ctx.cfg.enable_gitmodules_links, + ctx.cfg.enable_html_serving, + ctx.cfg.enable_log_filecount, + ctx.cfg.enable_log_linecount, + ctx.cfg.enable_mailmap, + ctx.cfg.enable_remote_branches, + ctx.cfg.enable_subject_links, + }; + size_t i; + + // Each text goes behind its length so no value can run into the next, + // and an unset one is told apart from an empty one. + for (i = 0; i < ARRAY_SIZE(texts); i++) { + if (texts[i]) + strbuf_addf(key, "%zu|%s", strlen(texts[i]), texts[i]); + else + strbuf_addch(key, '-'); + } + for (i = 0; i < ARRAY_SIZE(numbers); i++) + strbuf_addf(key, "%d|", numbers[i]); +} + static void process_cached_repolist(const char *path) { struct stat st; + struct strbuf key = STRBUF_INIT; struct strbuf cached_rc = STRBUF_INIT; time_t age; - unsigned long hash; int devnull; - hash = cache_hash_str(path); - if (ctx.cfg.project_list) - hash += cache_hash_str(ctx.cfg.project_list); - strbuf_addf(&cached_rc, "%s/rc-%8lx", ctx.cfg.cache_root, hash); + build_scan_key(&key, path); + strbuf_addf(&cached_rc, "%s/rc-%8lx", ctx.cfg.cache_root, cache_hash_str(key.buf)); + strbuf_release(&key); if (stat(cached_rc.buf, &st)) { // Nothing is cached yet, so this request scans in its own |
