summaryrefslogtreecommitdiff
path: root/0001-Add-default-tab-option-and-explicit-summary-page-URL.patch
diff options
context:
space:
mode:
Diffstat (limited to '0001-Add-default-tab-option-and-explicit-summary-page-URL.patch')
-rw-r--r--0001-Add-default-tab-option-and-explicit-summary-page-URL.patch206
1 files changed, 206 insertions, 0 deletions
diff --git a/0001-Add-default-tab-option-and-explicit-summary-page-URL.patch b/0001-Add-default-tab-option-and-explicit-summary-page-URL.patch
new file mode 100644
index 0000000..881ff98
--- /dev/null
+++ b/0001-Add-default-tab-option-and-explicit-summary-page-URL.patch
@@ -0,0 +1,206 @@
+From a6b8305ef4f10bb1f9929536e656dca7b5805119 Mon Sep 17 00:00:00 2001
+From: tslil <tslil@l-3.space>
+Date: Sun, 30 Aug 2026 14:34:19 +0000
+Subject: [PATCH] Add default-tab option and explicit summary page URLs
+
+A bare repository URL (/repo/) is currently always served as the
+summary page. With a readme configured, however, the about page is
+often a better landing page. Add a new global cgitrc option,
+default-tab, which configures the page that /repo/ should land on:
+
+ default-tab=about
+
+When default-tab is set to anything other than the summary page, a
+request for the bare repository URL is redirected to /repo/<tab>/.
+Repository name links (header breadcrumb, repository list on the
+index page) keep pointing at the bare repository URL, so they follow
+the redirect.
+
+The summary tab in the page header, and the summary button on the
+index page, previously pointed at the bare repository URL as well,
+which made them land on whatever the bare URL redirected to. They
+now explicitly point at /repo/summary/. A new cgit_repo_link()
+emits the bare repository URL for the links that should follow the
+default-tab redirect, while cgit_summary_link() now always points at
+the summary page.
+
+Finally, the fallback in about_fn() for repositories without a
+readme and without a homepage used to redirect to the repository
+URL with ../ appended (e.g. /repo/about../), relying on the web
+server to mangle that back to the summary page. It now redirects
+straight to /repo/summary/.
+
+Signed-off-by: tslil <tslil@l-3.space>
+---
+ cgit.c | 31 +++++++++++++++++++++++++++++++
+ cgit.h | 1 +
+ cgitrc.5.txt | 14 ++++++++++++++
+ cmd.c | 11 ++++++-----
+ ui-repolist.c | 2 +-
+ ui-shared.c | 8 +++++++-
+ ui-shared.h | 2 ++
+ 7 files changed, 62 insertions(+), 7 deletions(-)
+
+diff --git a/cgit.c b/cgit.c
+index ca318e8..bf62d40 100644
+--- a/cgit.c
++++ b/cgit.c
+@@ -163,6 +163,25 @@ static void config_cb(const char *name, const char *value)
+ ctx.cfg.logo_link = strdup_first_line(value);
+ else if (!strcmp(name, "module-link"))
+ ctx.cfg.module_link = strdup_first_line(value);
++ else if (!strcmp(name, "default-tab")) {
++ const char *tabs[] = {
++ "summary", "about", "log", "tree", "refs",
++ "commit", "stats"
++ };
++ const char *valid = NULL;
++ size_t i;
++ for (i = 0; i < sizeof(tabs)/sizeof(*tabs); i++)
++ if (!strcmp(value, tabs[i])) {
++ valid = tabs[i];
++ break;
++ }
++ if (valid)
++ ctx.cfg.default_tab = strdup_first_line(valid);
++ else
++ fprintf(stderr,
++ "[cgit] ignoring invalid default-tab value '%s'\n",
++ value);
++ }
+ else if (!strcmp(name, "strict-export"))
+ ctx.cfg.strict_export = strdup_first_line(value);
+ else if (!strcmp(name, "virtual-root"))
+@@ -734,6 +753,18 @@ static void process_request(void)
+ if (ctx.repo)
+ prepare_repo_env(&nongit);
+
++ /* Redirect a bare repository URL to the configured default tab, if
++ * one is set. The summary page is the native handler for the bare
++ * URL, so no redirect is needed for it. */
++ if (ctx.repo && !ctx.qry.page &&
++ ctx.cfg.default_tab && strcmp(ctx.cfg.default_tab, "summary")) {
++ char *url = cgit_pageurl(ctx.repo->url, ctx.cfg.default_tab,
++ NULL);
++ cgit_redirect(url, false);
++ free(url);
++ return;
++ }
++
+ cmd = cgit_get_cmd();
+ if (!cmd) {
+ ctx.page.title = "cgit error";
+diff --git a/cgit.h b/cgit.h
+index 7d7ece7..48dfc17 100644
+--- a/cgit.h
++++ b/cgit.h
+@@ -198,6 +198,7 @@ struct cgit_config {
+ char *cache_root;
+ char *clone_prefix;
+ char *clone_url;
++ char *default_tab;
+ char *favicon;
+ char *footer;
+ char *head_include;
+diff --git a/cgitrc.5.txt b/cgitrc.5.txt
+index 7c39bf9..c488478 100644
+--- a/cgitrc.5.txt
++++ b/cgitrc.5.txt
+@@ -129,6 +129,20 @@ css::
+ Default value: "/cgit.css". May be given multiple times, each
+ css URL path is added in the head section of the document in turn.
+
++default-tab::
++ The page to use as the default landing page for a repository. When
++ set to a value other than "summary", a request for the bare repository
++ URL (e.g. /repo/) is redirected to /repo/<tab>/, so the named tab
++ becomes the repository's landing page. Repository name links (the
++ header breadcrumb and the repository list on the index page) point at
++ the bare repository URL and therefore follow this redirect. The value
++ must be one of: "summary", "about", "log", "tree", "refs", "commit",
++ or "stats". Default value: "summary" (the bare repository URL serves
++ the summary page directly, as in stock cgit). Note that an about page
++ only exists for repositories which have a configured readme file (see
++ "repo.readme"); for repositories without one, /repo/about/ redirects
++ to /repo/summary/. See also: "REPOSITORY SETTINGS".
++
+ email-filter::
+ Specifies a command which will be invoked to format names and email
+ address of committers, authors, and taggers, as represented in various
+diff --git a/cmd.c b/cmd.c
+index 0eb75b1..6c1777e 100644
+--- a/cmd.c
++++ b/cmd.c
+@@ -54,11 +54,12 @@ static void about_fn(void)
+ else if (ctx.repo->homepage)
+ cgit_redirect(ctx.repo->homepage, false);
+ else {
+- char *currenturl = cgit_currenturl();
+- char *redirect = fmtalloc("%s../", currenturl);
+- cgit_redirect(redirect, false);
+- free(currenturl);
+- free(redirect);
++ /* No readme and no homepage: fall back to the
++ * summary page. */
++ char *url = cgit_pageurl(ctx.repo->url, "summary",
++ NULL);
++ cgit_redirect(url, false);
++ free(url);
+ }
+ } else
+ cgit_print_site_readme();
+diff --git a/ui-repolist.c b/ui-repolist.c
+index 1b224cf..e5ec5a9 100644
+--- a/ui-repolist.c
++++ b/ui-repolist.c
+@@ -321,7 +321,7 @@ void cgit_print_repolist(void)
+ }
+ htmlf("<tr><td class='%s'>",
+ !sorted && section ? "sublevel-repo" : "toplevel-repo");
+- cgit_summary_link(ctx.repo->name, NULL, NULL, NULL);
++ cgit_repo_link(ctx.repo->name, NULL, NULL, NULL);
+ html("</td><td>");
+ repourl = cgit_repourl(ctx.repo->url);
+ html_link_open(repourl, NULL, NULL);
+diff --git a/ui-shared.c b/ui-shared.c
+index df52a9b..da78b67 100644
+--- a/ui-shared.c
++++ b/ui-shared.c
+@@ -332,6 +332,12 @@ static void reporevlink(const char *page, const char *name, const char *title,
+
+ void cgit_summary_link(const char *name, const char *title, const char *class,
+ const char *head)
++{
++ reporevlink("summary", name, title, class, head, NULL, NULL);
++}
++
++void cgit_repo_link(const char *name, const char *title, const char *class,
++ const char *head)
+ {
+ reporevlink(NULL, name, title, class, head, NULL, NULL);
+ }
+@@ -1041,7 +1047,7 @@ static void print_header(void)
+ if (ctx.repo) {
+ cgit_index_link("index", NULL, NULL, NULL, NULL, 0, 1);
+ html(" : ");
+- cgit_summary_link(ctx.repo->name, NULL, NULL, NULL);
++ cgit_repo_link(ctx.repo->name, NULL, NULL, NULL);
+ if (ctx.env.authenticated) {
+ html("</td><td class='form'>");
+ html("<form method='get'>\n");
+diff --git a/ui-shared.h b/ui-shared.h
+index 2a3a7f5..99ae667 100644
+--- a/ui-shared.h
++++ b/ui-shared.h
+@@ -19,6 +19,8 @@ extern void cgit_index_link(const char *name, const char *title,
+ const char *class, const char *pattern, const char *sort, int ofs, int always_root);
+ extern void cgit_summary_link(const char *name, const char *title,
+ const char *class, const char *head);
++extern void cgit_repo_link(const char *name, const char *title,
++ const char *class, const char *head);
+ extern void cgit_tag_link(const char *name, const char *title,
+ const char *class, const char *tag);
+ extern void cgit_tree_link(const char *name, const char *title,
+--
+2.55.0
+