[PATCH] Add "default-tab" and "root-default-tab" configuration options

[PATCH] Add "default-tab" and "root-default-tab" configuration options

From: equa
These options allow the user to specify a page to display at the root
repository/index location instead of the default summary or repository list.

Signed-off-by: equa <equaa@protonmail.com>
---
 cgit.c        | 10 ++++++++++
 cgit.h        |  3 +++
 cgitrc.5.txt  | 11 +++++++++++
 cmd.c         |  6 +++---
 shared.c      |  1 +
 ui-repolist.c |  2 +-
 ui-shared.c   | 24 ++++++++++++++++++++----
 ui-shared.h   |  2 ++
 8 files changed, 51 insertions(+), 8 deletions(-)

diff --git a/cgit.c b/cgit.c
index 08d81a1..f1c2224 100644
--- a/cgit.c
+++ b/cgit.c
@@ -56,6 +56,8 @@ static void repo_config(struct cgit_repo *repo, const char *name, const char *va
 		repo->homepage = xstrdup(value);
 	else if (!strcmp(name, "defbranch"))
 		repo->defbranch = xstrdup(value);
+	else if (!strcmp(name, "default-tab"))
+		repo->default_tab = xstrdup(value);
 	else if (!strcmp(name, "extra-head-content"))
 		repo->extra_head_content = xstrdup(value);
 	else if (!strcmp(name, "snapshots"))
@@ -285,6 +287,10 @@ static void config_cb(const char *name, const char *value)
 		ctx.cfg.clone_url = xstrdup(value);
 	else if (!strcmp(name, "local-time"))
 		ctx.cfg.local_time = atoi(value);
+	else if (!strcmp(name, "default-tab"))
+		ctx.cfg.default_tab = xstrdup(value);
+	else if (!strcmp(name, "root-default-tab"))
+		ctx.cfg.root_default_tab = xstrdup(value);
 	else if (!strcmp(name, "commit-sort")) {
 		if (!strcmp(value, "date"))
 			ctx.cfg.commit_sort = 1;
@@ -373,6 +379,8 @@ static void prepare_context(void)
 	ctx.cfg.cache_scanrc_ttl = 15;
 	ctx.cfg.cache_dynamic_ttl = 5;
 	ctx.cfg.cache_static_ttl = -1;
+	ctx.cfg.default_tab = "summary";
+	ctx.cfg.root_default_tab = "repolist";
 	ctx.cfg.case_sensitive_sort = 1;
 	ctx.cfg.branch_sort = 0;
 	ctx.cfg.commit_sort = 0;
@@ -816,6 +824,8 @@ static void print_repo(FILE *f, struct cgit_repo *repo)
 		fprintf(f, "repo.homepage=%s\n", repo->homepage);
 	if (repo->clone_url)
 		fprintf(f, "repo.clone-url=%s\n", repo->clone_url);
+	if (repo->default_tab)
+		fprintf(f, "repo.default-tab=%s\n", repo->default_tab);
 	fprintf(f, "repo.enable-blame=%d\n",
 	        repo->enable_blame);
 	fprintf(f, "repo.enable-commit-graph=%d\n",
diff --git a/cgit.h b/cgit.h
index 69b5c13..bb555cf 100644
--- a/cgit.h
+++ b/cgit.h
@@ -86,6 +86,7 @@ struct cgit_repo {
 	char *owner;
 	char *homepage;
 	char *defbranch;
+	char *default_tab;
 	char *module_link;
 	struct string_list readme;
 	char *section;
@@ -215,6 +216,8 @@ struct cgit_config {
 	char *repository_sort;
 	char *virtual_root;	/* Always ends with '/'. */
 	char *strict_export;
+	char *default_tab;
+	char *root_default_tab;
 	int cache_size;
 	int cache_dynamic_ttl;
 	int cache_max_create_time;
diff --git a/cgitrc.5.txt b/cgitrc.5.txt
index 33a6a8c..f32fb33 100644
--- a/cgitrc.5.txt
+++ b/cgitrc.5.txt
@@ -128,6 +128,10 @@ css::
 	Url which specifies the css document to include in all cgit pages.
 	Default value: "/cgit.css".

+default-tab::
+	Specifies the tab to automatically load in the root page of a repository.
+	Default value: "summary". See also: root-default-tab, repo.default-tab.
+
 email-filter::
 	Specifies a command which will be invoked to format names and email
 	address of committers, authors, and taggers, as represented in various
@@ -352,6 +356,10 @@ robots::
 	Text used as content for the "robots" meta-tag. Default value:
 	"index, nofollow".

+root-default-tab::
+	Specifies the tab to automatically load as the root index page.
+	Default value: "repolist". See also: default-tab, repo.default-tab.
+
 root-desc::
 	Text printed below the heading on the repository index page. Default
 	value: "a fast webinterface for the git dscm".
@@ -481,6 +489,9 @@ repo.defbranch::
 	as default instead. Default value: branch pointed to by HEAD, or
 	"master" if there is no suitable HEAD.

+repo.default-tab::
+	Override the global default-tab. Default value: none.
+
 repo.desc::
 	The value to show as repository description. Default value: none.

diff --git a/cmd.c b/cmd.c
index 0eb75b1..64f6639 100644
--- a/cmd.c
+++ b/cmd.c
@@ -55,7 +55,7 @@ static void about_fn(void)
 			cgit_redirect(ctx.repo->homepage, false);
 		else {
 			char *currenturl = cgit_currenturl();
-			char *redirect = fmtalloc("%s../", currenturl);
+			char *redirect = cgit_pageurl(ctx.repo->url, "summary", NULL);
 			cgit_redirect(redirect, false);
 			free(currenturl);
 			free(redirect);
@@ -196,9 +196,9 @@ struct cgit_cmd *cgit_get_cmd(void)

 	if (ctx.qry.page == NULL) {
 		if (ctx.repo)
-			ctx.qry.page = "summary";
+			ctx.qry.page = ctx.repo->default_tab;
 		else
-			ctx.qry.page = "repolist";
+			ctx.qry.page = ctx.cfg.root_default_tab;
 	}

 	for (i = 0; i < sizeof(cmds)/sizeof(*cmds); i++)
diff --git a/shared.c b/shared.c
index 8115469..b1090a6 100644
--- a/shared.c
+++ b/shared.c
@@ -79,6 +79,7 @@ struct cgit_repo *cgit_add_repo(const char *url)
 	ret->clone_url = ctx.cfg.clone_url;
 	ret->submodules.strdup_strings = 1;
 	ret->hide = ret->ignore = 0;
+	ret->default_tab = ctx.cfg.default_tab;
 	return ret;
 }

diff --git a/ui-repolist.c b/ui-repolist.c
index 529a203..75db72a 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, ctx.repo->name, NULL, NULL);
+		cgit_repo_link(ctx.repo->name, ctx.repo->name, 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 acd8ab5..17b1e49 100644
--- a/ui-shared.c
+++ b/ui-shared.c
@@ -203,6 +203,9 @@ static void site_url(const char *page, const char *search, const char *sort, int
 {
 	char *delim = "?";

+	if (!strcmp(page ? page : "", ctx.cfg.root_default_tab))
+		page = NULL;
+
 	if (always_root || page)
 		html_attr(cgit_rooturl());
 	else {
@@ -257,7 +260,7 @@ static void site_link(const char *page, const char *name, const char *title,
 void cgit_index_link(const char *name, const char *title, const char *class,
 		     const char *pattern, const char *sort, int ofs, int always_root)
 {
-	site_link(NULL, name, title, class, pattern, sort, ofs, always_root);
+	site_link("repolist", name, title, class, pattern, sort, ofs, always_root);
 }

 static char *repolink(const char *title, const char *class, const char *page,
@@ -317,6 +320,12 @@ static void reporevlink(const char *page, const char *name, const char *title,
 {
 	char *delim;

+	if (page
+	    && !rev
+	    && !path
+	    && !strcmp(page, ctx.repo->default_tab))
+		page = NULL;
+
 	delim = repolink(title, class, page, head, path);
 	if (rev && ctx.qry.head != NULL && strcmp(rev, ctx.qry.head)) {
 		html(delim);
@@ -328,10 +337,17 @@ static void reporevlink(const char *page, const char *name, const char *title,
 	html("</a>");
 }

+void cgit_repo_link(const char *name, const char *title, const char *class,
+		    const char *head)
+{
+	reporevlink(NULL, name, title, class, head, NULL, NULL);
+}
+
+
 void cgit_summary_link(const char *name, const char *title, const char *class,
 		       const char *head)
 {
-	reporevlink(NULL, name, title, class, head, NULL, NULL);
+	reporevlink("summary", name, title, class, head, NULL, NULL);
 }

 void cgit_tag_link(const char *name, const char *title, const char *class,
@@ -995,7 +1011,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, ctx.repo->name, NULL, NULL);
+		cgit_repo_link(ctx.repo->name, ctx.repo->name, NULL, NULL);
 		if (ctx.env.authenticated) {
 			html("</td><td class='form'>");
 			html("<form method='get'>\n");
@@ -1084,7 +1100,7 @@ void cgit_print_pageheader(void)
 		html("</form>\n");
 	} else if (ctx.env.authenticated) {
 		char *currenturl = cgit_currenturl();
-		site_link(NULL, "index", NULL, hc("repolist"), NULL, NULL, 0, 1);
+		site_link("repolist", "index", NULL, hc("repolist"), NULL, NULL, 0, 1);
 		if (ctx.cfg.root_readme)
 			site_link("about", "about", NULL, hc("about"),
 				  NULL, NULL, 0, 1);
diff --git a/ui-shared.h b/ui-shared.h
index 6964873..9faf2ba 100644
--- a/ui-shared.h
+++ b/ui-shared.h
@@ -17,6 +17,8 @@ extern void cgit_add_clone_urls(void (*fn)(const char *));

 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_repo_link(const char *name, const char *title,
+			   const char *class, const char *head);
 extern void cgit_summary_link(const char *name, const char *title,
 			      const char *class, const char *head);
 extern void cgit_tag_link(const char *name, const char *title,
--
2.30.2

Re: [PATCH] Add "default-tab" and "root-default-tab" configuration options

From: equa
There are a few problems with this patch in retrospect, I think.
I intended to make the default page show up at the empty url but
gracefully fall back to the full URL (for example, a link to the
tree, if the tree was the default page, would be linked to as
just "repo/", but the files within it would be "repo/tree/files".)
This passes initial inspection but it doesn't work for about pages
that have subpages: since the output HTML isn't filtered at all
relative links will based the repository root. It may be better
to turn this into a redirect instead, which would also mean pages
are more consistent even if the defaults change.

Re: [PATCH] Add "default-tab" and "root-default-tab" configuration options

From: june
To: equa
> On Feb 22, 2022, at 20:40, equa <equaa@protonmail.com> wrote:
> 
> There are a few problems with this patch in retrospect, I think.
> I intended to make the default page show up at the empty url but
> gracefully fall back to the full URL (for example, a link to the
> tree, if the tree was the default page, would be linked to as
> just "repo/", but the files within it would be "repo/tree/files".)
> This passes initial inspection but it doesn't work for about pages
> that have subpages: since the output HTML isn't filtered at all
> relative links will based the repository root. It may be better
> to turn this into a redirect instead, which would also mean pages
> are more consistent even if the defaults change.

Hm, it's a shame about the about pages. I guess redirects are the
better solution, though it's a little disappointing.

Re: [PATCH] Add "default-tab" and "root-default-tab" configuration options

From: equa
To: june
(messed up cc on last email, apologies.)

a possibility is modifying the filters instead. we could
pass as an argument the base URL for any links the filters
encounter. i'd have to see if this is feasible to add to the
existing filters, but i'm curious what you'd think of such an
implementation.

Re: [PATCH] Add "default-tab" and "root-default-tab" configuration options

From: june
To: equa
> On Apr 28, 2022, at 21:33, equa <equaa@protonmail.com> wrote:
> 
> (messed up cc on last email, apologies.)
> 
> a possibility is modifying the filters instead. we could
> pass as an argument the base URL for any links the filters
> encounter. i'd have to see if this is feasible to add to the
> existing filters, but i'm curious what you'd think of such an
> implementation.

That's actually a great idea! If that works it would also make it
possible to render the README on the summary page itself which would
be really neat.