Diff options
| author | Bryce Kwon <bryce@brycekwon.com> | |
|---|---|---|
| committer | Bryce Kwon <bryce@brycekwon.com> | |
| commit | ||
| parent | ||
| tree | ||
| download | ||
Read the description file without repo.desc
Only a scanned repository fell back to its description file, so one
listed in cgitrc without repo.desc showed "[no description]" however
its file read. repo.desc may follow repo.path, so the file is read
where a page shows the description, which also spares every other
request the reads.
| -rw-r--r-- | MANUAL.txt | 8 | |
| -rw-r--r-- | source/cgit.c | 1 | |
| -rw-r--r-- | source/cgit.h | 3 | |
| -rw-r--r-- | source/scan-tree.c | 15 | |
| -rw-r--r-- | source/shared.c | 21 | |
| -rw-r--r-- | source/shared.h | 8 | |
| -rw-r--r-- | source/ui-repolist.c | 5 | |
| -rwxr-xr-x | tests/setup.sh | 3 | |
| -rwxr-xr-x | tests/t0101-index.sh | 26 |
9 files changed, 71 insertions, 19 deletions
@@ -603,10 +603,10 @@ repo.defbranch:: if there is no suitable HEAD. repo.desc:: - The value to show as repository description. When repositories are found - by scan-path the description file inside the repository is read as a - fallback, unless it still holds git's "Unnamed repository" boilerplate. - Default value: "[no description]". + The value to show as repository description. Without one, the first + line of the description file inside the repository is shown, unless it + still holds git's "Unnamed repository" boilerplate. Default value: + "[no description]". repo.email-filter:: Override the default email-filter. Default value: <email-filter>. See diff --git a/source/cgit.c b/source/cgit.c index 180cd82..0017d75 100644 --- a/source/cgit.c +++ b/source/cgit.c @@ -1184,6 +1184,7 @@ static int prepare_repo_cmd(int nongit, int err, int clone) } strbuf_addf(&title, "%s - %s", ctx.repo->name, ctx.cfg.root_title); ctx.page.title = title.buf; + cgit_read_repo_desc(ctx.repo); if (!ctx.repo->defbranch) ctx.repo->defbranch = guess_defbranch(); diff --git a/source/cgit.h b/source/cgit.h index da202b7..c56578c 100644 --- a/source/cgit.h +++ b/source/cgit.h @@ -113,6 +113,9 @@ struct cgit_repo { struct string_list submodules; int hide; int ignore; + // Set once the description file has been looked at, so a scanned + // repository whose file held nothing usable is not read again. + int desc_read; }; struct cgit_repolist { diff --git a/source/scan-tree.c b/source/scan-tree.c index 6c1f854..87dd10c 100644 --- a/source/scan-tree.c +++ b/source/scan-tree.c @@ -9,11 +9,6 @@ #include "scan-tree.h" #include "shared.h" -// Git writes this line into the description file of every repository it -// creates, so a repository still carrying it gets cgit's own default instead. -static const char *default_git_desc = - "Unnamed repository; edit this file 'description' to name the repository."; - // The config callbacks are handed only a name and a value, so the repository // being filled in waits here for the length of one add_repo call. static struct cgit_repo *current_repo; @@ -242,15 +237,7 @@ static void add_repo(const char *base, struct strbuf *path) } } - if (current_repo->desc == cgit_default_repo_desc) { - strbuf_addstr(path, "description"); - cgit_read_first_line(path->buf, ¤t_repo->desc); - strbuf_setlen(path, pathlen); - if (current_repo->desc && !strcmp(current_repo->desc, default_git_desc)) { - free(current_repo->desc); - current_repo->desc = cgit_default_repo_desc; - } - } + cgit_read_repo_desc(current_repo); if (ctx.cfg.section_from_path) set_section_from_path(&relpath, ctx.cfg.section_from_path); diff --git a/source/shared.c b/source/shared.c index 1cfe4b0..c189b11 100644 --- a/source/shared.c +++ b/source/shared.c @@ -14,6 +14,11 @@ #define MAX_FIRST_LINE_READ (1024 * 64) +// Git writes this line into the description file of every repository it +// creates, so a repository still carrying it gets cgit's own default instead. +static const char *default_git_desc = + "Unnamed repository; edit this file 'description' to name the repository."; + struct cgit_repolist cgit_repolist; struct cgit_context ctx; char cgit_default_repo_desc[] = "[no description]"; @@ -325,6 +330,22 @@ char *cgit_strdup_first_line(const char *text) return line; } +void cgit_read_repo_desc(struct cgit_repo *repo) +{ + struct strbuf path = STRBUF_INIT; + char *desc = NULL; + + if (repo->desc != cgit_default_repo_desc || !repo->path || repo->desc_read) + return; + repo->desc_read = 1; + strbuf_addf(&path, "%s/description", repo->path); + if (!cgit_read_first_line(path.buf, &desc) && strcmp(desc, default_git_desc)) + repo->desc = desc; + else + free(desc); + strbuf_release(&path); +} + /* * The lead-byte ranges fold in the overlong, surrogate and out-of-range * cases, so 0 is the only error signal a caller needs. diff --git a/source/shared.h b/source/shared.h index 302b752..f182962 100644 --- a/source/shared.h +++ b/source/shared.h @@ -75,6 +75,14 @@ extern int cgit_read_first_line(const char *path, char **buf); extern char *cgit_strdup_first_line(const char *text); /* + * Give a repository that cgitrc left without a description the first line of + * the description file git keeps in it, unless that is still git's + * placeholder. Pages call it only for the repositories they show, so a request + * reads no more of these files than it needs. + */ +extern void cgit_read_repo_desc(struct cgit_repo *repo); + +/* * How many bytes the UTF-8 sequence at p holds, or 0 when it is invalid, * looking at most left bytes ahead. */ diff --git a/source/ui-repolist.c b/source/ui-repolist.c index 4e4f61b..87abf0b 100644 --- a/source/ui-repolist.c +++ b/source/ui-repolist.c @@ -392,6 +392,11 @@ void cgit_print_repolist(void) int shown = 0; int i; + // Ahead of the search and the sort, which both look at descriptions. + for (i = 0; i < cgit_repolist.count; i++) + if (!cgit_repolist.repos[i].hide && !cgit_repolist.repos[i].ignore) + cgit_read_repo_desc(&cgit_repolist.repos[i]); + if (!any_repos_visible()) { cgit_print_error_page(404, "Not Found", "No repositories found"); return; diff --git a/tests/setup.sh b/tests/setup.sh index 92451b7..421e043 100755 --- a/tests/setup.sh +++ b/tests/setup.sh @@ -130,7 +130,8 @@ clone-url=git://example.org/\$CGIT_REPO_URL.git repo.url=foo repo.path=$PWD/repos/foo/.git -# No repo.desc here, so the [no description] default gets exercised. +# No repo.desc here, and the description file holds git's placeholder, so +# the [no description] default gets exercised. repo.url=bar repo.path=$PWD/repos/bar/.git diff --git a/tests/t0101-index.sh b/tests/t0101-index.sh index 9b02a18..0953b8d 100755 --- a/tests/t0101-index.sh +++ b/tests/t0101-index.sh @@ -93,4 +93,30 @@ test_expect_success 'a scan lists repositories in path order' ' test_cmp expect order ' +# A repository listed without repo.desc shows the first line of its own +# description file, as a scanned one does. A repo.desc after the repo.path +# still wins, and git's placeholder still reads as no description. +test_expect_success 'a repository without repo.desc reads its description file' ' + mkrepo repos/described 1 && + printf "told by the file\nsecond line\n" >repos/described/.git/description && + { + echo "virtual-root=/" && + echo "cache-size=0" && + echo "repo.url=described" && + echo "repo.path=$PWD/repos/described/.git" && + echo "repo.url=overridden" && + echo "repo.path=$PWD/repos/described/.git" && + echo "repo.desc=from cgitrc" && + echo "repo.url=placeholder" && + echo "repo.path=$PWD/repos/foo/.git" + } >describedrc && + cgit_rc describedrc "url=" >tmp && + grep "href=./described/.>told by the file</a>" tmp && + grep "href=./overridden/.>from cgitrc</a>" tmp && + grep "href=./placeholder/.>\[no description\]</a>" tmp && + ! grep "second line" tmp && + cgit_rc describedrc "url=described/" >tmp && + grep "<meta name=.description. content=.told by the file.>" tmp +' + test_done |
