diff options
| author | Bryce Kwon <bryce@brycekwon.com> | |
|---|---|---|
| committer | Bryce Kwon <bryce@brycekwon.com> | |
| commit | ||
| parent | ||
| tree | ||
| download | ||
Date repositories from HEAD and guard its branch
The index derived a repository's age from `refs/heads/master` alone,
so a repository on any other default branch showed no age. HEAD is
repo-controlled and the age stat walks under `refs/heads`, so a branch
name carrying a parent-directory component is rejected.
Diffstat (limited to '')
| -rw-r--r-- | source/ui-repolist.c | 29 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
1 file changed, 27 insertions, 2 deletions
diff --git a/source/ui-repolist.c b/source/ui-repolist.c index 5174c5a..fc198e5 100644 --- a/source/ui-repolist.c +++ b/source/ui-repolist.c @@ -35,8 +35,10 @@ static time_t read_agefile(const char *path) static int get_repo_modtime(const struct cgit_repo *repo, time_t *mtime) { struct strbuf path = STRBUF_INIT; + struct strbuf head = STRBUF_INIT; struct stat s; struct cgit_repo *r = (struct cgit_repo *)repo; + const char *branch; if (repo->mtime != -1) { *mtime = repo->mtime; @@ -51,9 +53,31 @@ static int get_repo_modtime(const struct cgit_repo *repo, time_t *mtime) } } + /* Stat the tip of the default branch. Prefer a configured defbranch, + * otherwise read HEAD so a repo on "main" (or any branch name) is + * handled, not only "master". + */ + branch = repo->defbranch; + if (!branch) { + strbuf_reset(&path); + strbuf_addf(&path, "%s/HEAD", repo->path); + if (strbuf_read_file(&head, path.buf, 0) > 0) { + strbuf_rtrim(&head); + if (!skip_prefix(head.buf, "ref: refs/heads/", &branch)) + branch = NULL; + /* HEAD is repo-controlled, so a crafted target such as + * "ref: refs/heads/../../.." must not let the stat() + * below walk outside the repository. Git forbids ".." + * in ref names anyway. */ + if (branch && strstr(branch, "..")) + branch = NULL; + } + if (!branch) + branch = "master"; + } + strbuf_reset(&path); - strbuf_addf(&path, "%s/refs/heads/%s", repo->path, - repo->defbranch ? repo->defbranch : "master"); + strbuf_addf(&path, "%s/refs/heads/%s", repo->path, branch); if (stat(path.buf, &s) == 0) { *mtime = s.st_mtime; r->mtime = *mtime; @@ -72,6 +96,7 @@ static int get_repo_modtime(const struct cgit_repo *repo, time_t *mtime) r->mtime = *mtime; end: strbuf_release(&path); + strbuf_release(&head); return (r->mtime != 0); } |
