aboutsummaryrefslogtreecommitdiffstats
path: root/ui-repolist.c
diff options
context:
space:
mode:
Diffstat (limited to 'ui-repolist.c')
-rw-r--r--ui-repolist.c92
1 files changed, 92 insertions, 0 deletions
diff --git a/ui-repolist.c b/ui-repolist.c
index d12e3dd..9aae04f 100644
--- a/ui-repolist.c
+++ b/ui-repolist.c
@@ -6,6 +6,8 @@
* (see COPYING for full license text)
*/
+#define USE_THE_REPOSITORY_VARIABLE
+
#include "cgit.h"
#include "ui-repolist.h"
#include "html.h"
@@ -32,6 +34,90 @@ static time_t read_agefile(const char *path)
return result;
}
+struct max_commit_ctx {
+ struct repository *r;
+ timestamp_t max_ct;
+};
+
+// try to peel the given oid to a commit
+static struct commit *peel_to_commit(struct repository *r, const char *refname,
+ const struct object_id *oid)
+{
+ struct object *obj = parse_object(r, oid);
+ if (!obj) return NULL;
+
+ if (obj->type == OBJ_COMMIT) {
+ return (struct commit *)obj;
+ } else if (obj->type == OBJ_TAG) {
+ obj = deref_tag(r, (struct object *)obj, refname, 0);
+ if (obj && obj->type == OBJ_COMMIT)
+ return (struct commit *)obj;
+ return NULL;
+ } else {
+ return NULL;
+ }
+}
+
+static int max_commit_from_ref(const char *refname,
+ const char *referent,
+ const struct object_id *oid,
+ int flags, void *cb_data)
+{
+ struct max_commit_ctx *ctx = cb_data;
+
+ // skip symbolic refs
+ if (flags & REF_ISSYMREF) return 0;
+
+ struct commit *c = peel_to_commit(ctx->r, refname, oid);
+ if (!c) return 0;
+
+ // ensure commit is parsed
+ if (repo_parse_commit(ctx->r, c)) return 0;
+
+ if (c->date > ctx->max_ct) ctx->max_ct = c->date;
+
+ return 0;
+}
+
+static timestamp_t repo_latest_commit_ctime(struct repository *r, int include_tags)
+{
+ struct max_commit_ctx ctx = { .r = r, .max_ct = 0 };
+
+ struct ref_store *refs = get_main_ref_store(r);
+ if (!refs) {
+ error("failed to get ref store for repo at %s", r->gitdir);
+ return 0;
+ }
+
+ refs_for_each_branch_ref(refs, max_commit_from_ref, &ctx);
+
+ return ctx.max_ct;
+}
+
+static int repo_last_activity_time(const struct cgit_repo *repo,
+ int include_tags,
+ time_t *out)
+{
+ repo_clear(the_repository);
+
+ struct repository *r = xcalloc(1, sizeof(*r));
+ if (repo_init(r, repo->path, NULL)) {
+ error("failed to init repository at %s", repo->path);
+ free(r);
+ return 0;
+ }
+
+ repo_set_hash_algo(the_repository, hash_algo_by_ptr(r->hash_algo));
+
+ timestamp_t t1 = repo_latest_commit_ctime(r, include_tags);
+ timestamp_t best = t1;
+
+ if (best <= 0) { *out = 0; return 0; }
+ *out = (time_t)best;
+ return 1;
+}
+
+
static int get_repo_modtime(const struct cgit_repo *repo, time_t *mtime)
{
struct strbuf path = STRBUF_INIT;
@@ -42,6 +128,7 @@ static int get_repo_modtime(const struct cgit_repo *repo, time_t *mtime)
*mtime = repo->mtime;
return 1;
}
+
strbuf_addf(&path, "%s/%s", repo->path, ctx.cfg.agefile);
if (stat(path.buf, &s) == 0) {
*mtime = read_agefile(path.buf);
@@ -51,6 +138,11 @@ static int get_repo_modtime(const struct cgit_repo *repo, time_t *mtime)
}
}
+ if (repo_last_activity_time(repo, 1, mtime)) {
+ r->mtime = *mtime;
+ goto end;
+ }
+
strbuf_reset(&path);
strbuf_addf(&path, "%s/refs/heads/%s", repo->path,
repo->defbranch ? repo->defbranch : "master");