diff options
context:
space:
mode:
Diffstat (limited to 'source/cgit.c')
-rw-r--r--source/cgit.c30
1 file changed, 27 insertions, 3 deletions
diff --git a/source/cgit.c b/source/cgit.c
index 12981c2..f284ad9 100644
--- a/source/cgit.c
+++ b/source/cgit.c
@@ -792,6 +792,25 @@ static void authenticate_cookie(void)
ctx.env.authenticated = cgit_close_filter(ctx.cfg.auth_filter);
}
+/*
+ * Only a full object id names content that can never change. The id parameter
+ * accepts anything git can resolve, so a ref name or an abbreviation arrives
+ * here just as marked as a real id, and a page pinned to one of those must
+ * not be cached under the never-expiring static ttl.
+ */
+static int is_full_oid(const char *rev)
+{
+ size_t len = strlen(rev);
+
+ if (len != GIT_SHA1_HEXSZ && len != GIT_SHA256_HEXSZ)
+ return 0;
+ for (; *rev; rev++) {
+ if (!isxdigit(*rev))
+ return 0;
+ }
+ return 1;
+}
+
// Every cache-*-ttl setting is written in minutes, and so is this.
static int calc_ttl(void)
{
@@ -804,12 +823,17 @@ static int calc_ttl(void)
if (!strcmp(ctx.qry.page, "about"))
return ctx.cfg.cache_about_ttl;
+ // Checked ahead of the snapshot ttl, because a tarball pinned to an
+ // object id can never come out differently and is the most expensive
+ // page to rebuild.
+ if (ctx.qry.has_oid &&
+ (!ctx.qry.oid || is_full_oid(ctx.qry.oid)) &&
+ (!ctx.qry.oid2 || is_full_oid(ctx.qry.oid2)))
+ return ctx.cfg.cache_static_ttl;
+
if (!strcmp(ctx.qry.page, "snapshot"))
return ctx.cfg.cache_snapshot_ttl;
- if (ctx.qry.has_oid)
- return ctx.cfg.cache_static_ttl;
-
if (ctx.qry.has_symref)
return ctx.cfg.cache_dynamic_ttl;