diff options
| -rw-r--r-- | ui-repolist.c | 92 |
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"); |
