List for cgit developers and users
 help / color / mirror / Atom feed
* [PATCHv2 0/2] Collapsible Section Support
@ 2016-09-12 22:01 andy.doan
  2016-09-12 22:01 ` [PATCH 1/2] ui-repolist: provide hyperlinks on section names andy.doan
                   ` (4 more replies)
  0 siblings, 5 replies; 15+ messages in thread
From: andy.doan @ 2016-09-12 22:01 UTC (permalink / raw)


This series adds hyperlinks to sections and allows them to be collapsed.

Changes since v1:
 - combined these 2 patches into a series


Andy Doan (2):
  ui-repolist: provide hyperlinks on section names
  ui-repolist: Allow sections to be collapsible

 cgit.c        | 27 +++++++++++++++++++++++----
 cgit.h        | 13 +++++++++++--
 cgitrc.5.txt  |  5 +++++
 scan-tree.c   |  6 +++---
 shared.c      |  5 ++++-
 ui-repolist.c | 29 ++++++++++++++++-------------
 6 files changed, 62 insertions(+), 23 deletions(-)

--
2.7.4



^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 1/2] ui-repolist: provide hyperlinks on section names
  2016-09-12 22:01 [PATCHv2 0/2] Collapsible Section Support andy.doan
@ 2016-09-12 22:01 ` andy.doan
  2016-09-12 23:08   ` john
  2016-09-12 22:01 ` [PATCH 2/2] ui-repolist: Allow sections to be collapsible andy.doan
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 15+ messages in thread
From: andy.doan @ 2016-09-12 22:01 UTC (permalink / raw)


This makes it easier to traverse into a section of git repositories.

Signed-off-by: Andy Doan <andy.doan at linaro.org>
---
 ui-repolist.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ui-repolist.c b/ui-repolist.c
index 30915df..f6b6b47 100644
--- a/ui-repolist.c
+++ b/ui-repolist.c
@@ -322,7 +322,7 @@ void cgit_print_repolist(void)
 		     strcmp(section, last_section)))) {
 			htmlf("<tr class='nohover'><td colspan='%d' class='reposection'>",
 			      columns);
-			html_txt(section);
+			htmlf("<a href='%s'>%s</a>", section, section);
 			html("</td></tr>");
 			last_section = section;
 		}
-- 
2.7.4



^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 2/2] ui-repolist: Allow sections to be collapsible
  2016-09-12 22:01 [PATCHv2 0/2] Collapsible Section Support andy.doan
  2016-09-12 22:01 ` [PATCH 1/2] ui-repolist: provide hyperlinks on section names andy.doan
@ 2016-09-12 22:01 ` andy.doan
  2016-09-13  3:54 ` [PATCHv3 0/2] Collapsible Section Support andy.doan
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 15+ messages in thread
From: andy.doan @ 2016-09-12 22:01 UTC (permalink / raw)


The index page can be difficult to navigate for really large git
servers. This change allows a configuration like:

 section-collapse=people
 section-collapse=tests

And an index page would only display the "people" and "tests" section
headers entries (not their repos) with a hyperlink that can be used to
drill down into each section.

Additionally the boolean logic around displaying sections in
ui-repolist.c was simplified to eliminate an impossible condition.

Signed-off-by: Andy Doan <andy.doan at linaro.org>
Reviewed-by: John Keeping <john at keeping.me.uk>
---
 cgit.c        | 27 +++++++++++++++++++++++----
 cgit.h        | 13 +++++++++++--
 cgitrc.5.txt  |  5 +++++
 scan-tree.c   |  6 +++---
 shared.c      |  5 ++++-
 ui-repolist.c | 29 ++++++++++++++++-------------
 6 files changed, 62 insertions(+), 23 deletions(-)

diff --git a/cgit.c b/cgit.c
index 9427c4a..c769e35 100644
--- a/cgit.c
+++ b/cgit.c
@@ -77,7 +77,7 @@ static void repo_config(struct cgit_repo *repo, const char *name, const char *va
 		item = string_list_append(&repo->submodules, xstrdup(name + 12));
 		item->util = xstrdup(value);
 	} else if (!strcmp(name, "section"))
-		repo->section = xstrdup(value);
+		repo->section = get_or_create_section(value);
 	else if (!strcmp(name, "readme") && value != NULL) {
 		if (repo->readme.items == ctx.cfg.readme.items)
 			memset(&repo->readme, 0, sizeof(repo->readme));
@@ -107,7 +107,7 @@ static void repo_config(struct cgit_repo *repo, const char *name, const char *va
 static void config_cb(const char *name, const char *value)
 {
 	if (!strcmp(name, "section") || !strcmp(name, "repo.group"))
-		ctx.cfg.section = xstrdup(value);
+		ctx.cfg.section = get_or_create_section(value);
 	else if (!strcmp(name, "repo.url"))
 		ctx.repo = cgit_add_repo(value);
 	else if (ctx.repo && !strcmp(name, "repo.path"))
@@ -242,6 +242,8 @@ static void config_cb(const char *name, const char *value)
 		ctx.cfg.section_from_path = atoi(value);
 	else if (!strcmp(name, "repository-sort"))
 		ctx.cfg.repository_sort = xstrdup(value);
+	else if (!strcmp(name, "section-collapse"))
+		get_or_create_section(value)->collapse = 1;
 	else if (!strcmp(name, "section-sort"))
 		ctx.cfg.section_sort = atoi(value);
 	else if (!strcmp(name, "source-filter"))
@@ -385,7 +387,7 @@ static void prepare_context(void)
 	ctx.cfg.root_desc = "a fast webinterface for the git dscm";
 	ctx.cfg.scan_hidden_path = 0;
 	ctx.cfg.script_name = CGIT_SCRIPT_NAME;
-	ctx.cfg.section = "";
+	ctx.cfg.section = NULL;
 	ctx.cfg.repository_sort = "name";
 	ctx.cfg.section_sort = 1;
 	ctx.cfg.summary_branches = 10;
@@ -794,7 +796,7 @@ static void print_repo(FILE *f, struct cgit_repo *repo)
 	if (repo->module_link)
 		fprintf(f, "repo.module-link=%s\n", repo->module_link);
 	if (repo->section)
-		fprintf(f, "repo.section=%s\n", repo->section);
+		fprintf(f, "repo.section=%s\n", repo->section->name);
 	if (repo->homepage)
 		fprintf(f, "repo.homepage=%s\n", repo->homepage);
 	if (repo->clone_url)
@@ -1026,6 +1028,23 @@ static int calc_ttl(void)
 	return ctx.cfg.cache_repo_ttl;
 }

+struct cgit_section* get_or_create_section(const char *section)
+{
+	struct cgit_section *ptr = ctx.sections;
+	while(ptr) {
+		if (!strcmp(section, ptr->name))
+			return ptr;
+		ptr = ptr->next;
+	}
+	/* Not found insert into head of list */
+	ptr = xmalloc(sizeof(*ptr));
+	ptr->name = xstrdup(section);
+	ptr->collapse = 0;
+	ptr->next = ctx.sections;
+	ctx.sections = ptr;
+	return ptr;
+}
+
 int main(int argc, const char **argv)
 {
 	const char *path;
diff --git a/cgit.h b/cgit.h
index 325432b..d940ae3 100644
--- a/cgit.h
+++ b/cgit.h
@@ -75,6 +75,12 @@ struct cgit_exec_filter {
 	int pid;
 };

+struct cgit_section {
+	unsigned int collapse : 1;
+	char *name;
+	struct cgit_section *next;
+};
+
 struct cgit_repo {
 	char *url;
 	char *name;
@@ -85,7 +91,7 @@ struct cgit_repo {
 	char *defbranch;
 	char *module_link;
 	struct string_list readme;
-	char *section;
+	struct cgit_section *section;
 	char *clone_url;
 	char *logo;
 	char *logo_link;
@@ -208,7 +214,7 @@ struct cgit_config {
 	char *root_desc;
 	char *root_readme;
 	char *script_name;
-	char *section;
+	struct cgit_section *section;
 	char *repository_sort;
 	char *virtual_root;	/* Always ends with '/'. */
 	char *strict_export;
@@ -305,6 +311,7 @@ struct cgit_context {
 	struct cgit_config cfg;
 	struct cgit_repo *repo;
 	struct cgit_page page;
+	struct cgit_section *sections;
 };

 typedef int (*write_archive_fn_t)(const char *, const char *);
@@ -322,6 +329,8 @@ extern struct cgit_repolist cgit_repolist;
 extern struct cgit_context ctx;
 extern const struct cgit_snapshot_format cgit_snapshot_formats[];

+extern struct cgit_section* get_or_create_section(const char *section);
+
 extern char *cgit_default_repo_desc;
 extern struct cgit_repo *cgit_add_repo(const char *url);
 extern struct cgit_repo *cgit_get_repoinfo(const char *url);
diff --git a/cgitrc.5.txt b/cgitrc.5.txt
index 9fcf445..2762657 100644
--- a/cgitrc.5.txt
+++ b/cgitrc.5.txt
@@ -404,6 +404,11 @@ section::
 	after this option will inherit the current section name. Default value:
 	none.

+section-collapse::
+	Name of a section to "collapse" and not display on the index page.
+	Multiple config entries can be specified and each one will be
+	collapsed.
+
 section-sort::
 	Flag which, when set to "1", will sort the sections on the repository
 	listing by name. Set this flag to "0" if the order in the cgitrc file should
diff --git a/scan-tree.c b/scan-tree.c
index 1cb4e5d..fa21fc4 100644
--- a/scan-tree.c
+++ b/scan-tree.c
@@ -164,10 +164,10 @@ static void add_repo(const char *base, struct strbuf *path, repo_config_fn fn)
 		}
 		if (slash && !n) {
 			*slash = '\0';
-			repo->section = xstrdup(rel.buf);
+			repo->section = get_or_create_section(rel.buf);
 			*slash = '/';
-			if (starts_with(repo->name, repo->section)) {
-				repo->name += strlen(repo->section);
+			if (starts_with(repo->name, repo->section->name)) {
+				repo->name += strlen(repo->section->name);
 				if (*repo->name == '/')
 					repo->name++;
 			}
diff --git a/shared.c b/shared.c
index a63633b..8348581 100644
--- a/shared.c
+++ b/shared.c
@@ -444,13 +444,16 @@ typedef struct {

 void cgit_prepare_repo_env(struct cgit_repo * repo)
 {
+	char *section = NULL;
+	if (repo->section)
+		section = repo->section->name;
 	cgit_env_var env_vars[] = {
 		{ .name = "CGIT_REPO_URL", .value = repo->url },
 		{ .name = "CGIT_REPO_NAME", .value = repo->name },
 		{ .name = "CGIT_REPO_PATH", .value = repo->path },
 		{ .name = "CGIT_REPO_OWNER", .value = repo->owner },
 		{ .name = "CGIT_REPO_DEFBRANCH", .value = repo->defbranch },
-		{ .name = "CGIT_REPO_SECTION", .value = repo->section },
+		{ .name = "CGIT_REPO_SECTION", .value = section },
 		{ .name = "CGIT_REPO_CLONE_URL", .value = repo->clone_url }
 	};
 	int env_var_count = ARRAY_SIZE(env_vars);
diff --git a/ui-repolist.c b/ui-repolist.c
index f6b6b47..fc8121e 100644
--- a/ui-repolist.c
+++ b/ui-repolist.c
@@ -188,10 +188,16 @@ static int sort_section(const void *a, const void *b)
 {
 	const struct cgit_repo *r1 = a;
 	const struct cgit_repo *r2 = b;
+	const char *s1 = "";
+	const char *s2 = "";
 	int result;
 	time_t t;

-	result = cmp(r1->section, r2->section);
+	if (r1->section)
+		s1 = r1->section->name;
+	if (r2->section)
+		s2 = r2->section->name;
+	result = cmp(s1, s2);
 	if (!result) {
 		if (!strcmp(ctx.cfg.repository_sort, "age")) {
 			// get_repo_modtime caches the value in r->mtime, so we don't
@@ -273,8 +279,8 @@ static int sort_repolist(char *field)
 void cgit_print_repolist(void)
 {
 	int i, columns = 3, hits = 0, header = 0;
-	char *last_section = NULL;
-	char *section;
+	struct cgit_section *last_section = NULL;
+	struct cgit_section *section;
 	int sorted = 0;

 	if (!any_repos_visible()) {
@@ -294,12 +300,10 @@ void cgit_print_repolist(void)

 	if (ctx.cfg.index_header)
 		html_include(ctx.cfg.index_header);
-
 	if (ctx.qry.sort)
 		sorted = sort_repolist(ctx.qry.sort);
 	else if (ctx.cfg.section_sort)
 		sort_repolist("section");
-
 	html("<table summary='repository list' class='list nowrap'>");
 	for (i = 0; i < cgit_repolist.count; i++) {
 		ctx.repo = &cgit_repolist.repos[i];
@@ -313,19 +317,18 @@ void cgit_print_repolist(void)
 		if (!header++)
 			print_header();
 		section = ctx.repo->section;
-		if (section && !strcmp(section, ""))
+		if (section && !strcmp(section->name, ""))
 			section = NULL;
-		if (!sorted &&
-		    ((last_section == NULL && section != NULL) ||
-		    (last_section != NULL && section == NULL) ||
-		    (last_section != NULL && section != NULL &&
-		     strcmp(section, last_section)))) {
+		if (!sorted && section && last_section != section ) {
 			htmlf("<tr class='nohover'><td colspan='%d' class='reposection'>",
 			      columns);
-			htmlf("<a href='%s'>%s</a>", section, section);
+			htmlf("<a href='%s'>%s</a>", section->name, section->name);
 			html("</td></tr>");
-			last_section = section;
 		}
+		last_section = section;
+		if (section && section->collapse && !strstr(ctx.qry.url, section->name))
+			continue;
+
 		htmlf("<tr><td class='%s'>",
 		      !sorted && section ? "sublevel-repo" : "toplevel-repo");
 		cgit_summary_link(ctx.repo->name, ctx.repo->name, NULL, NULL);
--
2.7.4



^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 1/2] ui-repolist: provide hyperlinks on section names
  2016-09-12 22:01 ` [PATCH 1/2] ui-repolist: provide hyperlinks on section names andy.doan
@ 2016-09-12 23:08   ` john
  0 siblings, 0 replies; 15+ messages in thread
From: john @ 2016-09-12 23:08 UTC (permalink / raw)


On Mon, Sep 12, 2016 at 05:01:49PM -0500, Andy Doan wrote:
> This makes it easier to traverse into a section of git repositories.
> 
> Signed-off-by: Andy Doan <andy.doan at linaro.org>
> ---
>  ui-repolist.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/ui-repolist.c b/ui-repolist.c
> index 30915df..f6b6b47 100644
> --- a/ui-repolist.c
> +++ b/ui-repolist.c
> @@ -322,7 +322,7 @@ void cgit_print_repolist(void)
>  		     strcmp(section, last_section)))) {
>  			htmlf("<tr class='nohover'><td colspan='%d' class='reposection'>",
>  			      columns);
> -			html_txt(section);
> +			htmlf("<a href='%s'>%s</a>", section, section);

I probably should have spotted this before, but "section" isn't being
properly escaped after this patch.  This needs to be:

	html("<a href='");
	html_attr(section);
	html("'>");
	html_txt(section);
	html("</a>");

(although the first and last strings could be combined with the
surrounding statements).

>  			html("</td></tr>");
>  			last_section = section;
>  		}
> -- 
> 2.7.4


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCHv3 0/2] Collapsible Section Support
  2016-09-12 22:01 [PATCHv2 0/2] Collapsible Section Support andy.doan
  2016-09-12 22:01 ` [PATCH 1/2] ui-repolist: provide hyperlinks on section names andy.doan
  2016-09-12 22:01 ` [PATCH 2/2] ui-repolist: Allow sections to be collapsible andy.doan
@ 2016-09-13  3:54 ` andy.doan
  2016-09-13  3:54   ` [PATCHv3 1/2] ui-repolist: provide hyperlinks on section names andy.doan
  2016-09-13  3:54   ` [PATCHv3 2/2] ui-repolist: Allow sections to be collapsible andy.doan
  2016-10-01 20:50 ` [PATCHv2 0/2] Collapsible Section Support Jason
  2016-10-03 18:10 ` tim
  4 siblings, 2 replies; 15+ messages in thread
From: andy.doan @ 2016-09-13  3:54 UTC (permalink / raw)


This series adds hyperlinks to sections and allows them to be collapsed.
A running version of cgit with this change can be seen here:

  https://git-ap.linaro.org/cgit/

Changes since v2:
 - use proper html escaping for section hyperlinks.

Andy Doan (2):
  ui-repolist: provide hyperlinks on section names
  ui-repolist: Allow sections to be collapsible

 cgit.c        | 27 +++++++++++++++++++++++----
 cgit.h        | 13 +++++++++++--
 cgitrc.5.txt  |  5 +++++
 scan-tree.c   |  6 +++---
 shared.c      |  5 ++++-
 ui-repolist.c | 33 ++++++++++++++++++++-------------
 6 files changed, 66 insertions(+), 23 deletions(-)

--
2.7.4



^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCHv3 1/2] ui-repolist: provide hyperlinks on section names
  2016-09-13  3:54 ` [PATCHv3 0/2] Collapsible Section Support andy.doan
@ 2016-09-13  3:54   ` andy.doan
  2016-09-13  3:54   ` [PATCHv3 2/2] ui-repolist: Allow sections to be collapsible andy.doan
  1 sibling, 0 replies; 15+ messages in thread
From: andy.doan @ 2016-09-13  3:54 UTC (permalink / raw)


This makes it easier to traverse into a section of git repositories.

Signed-off-by: Andy Doan <andy.doan at linaro.org>
---
 ui-repolist.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/ui-repolist.c b/ui-repolist.c
index 30915df..3f967a8 100644
--- a/ui-repolist.c
+++ b/ui-repolist.c
@@ -322,7 +322,11 @@ void cgit_print_repolist(void)
 		     strcmp(section, last_section)))) {
 			htmlf("<tr class='nohover'><td colspan='%d' class='reposection'>",
 			      columns);
+			html("<a href='");
+			html_attr(section);
+			html("'>");
 			html_txt(section);
+			html("</a>");
 			html("</td></tr>");
 			last_section = section;
 		}
-- 
2.7.4



^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCHv3 2/2] ui-repolist: Allow sections to be collapsible
  2016-09-13  3:54 ` [PATCHv3 0/2] Collapsible Section Support andy.doan
  2016-09-13  3:54   ` [PATCHv3 1/2] ui-repolist: provide hyperlinks on section names andy.doan
@ 2016-09-13  3:54   ` andy.doan
  1 sibling, 0 replies; 15+ messages in thread
From: andy.doan @ 2016-09-13  3:54 UTC (permalink / raw)


The index page can be difficult to navigate for really large git
servers. This change allows a configuration like:

 section-collapse=people
 section-collapse=tests

And an index page would only display the "people" and "tests" section
headers entries (not their repos) with a hyperlink that can be used to
drill down into each section.

Additionally the boolean logic around displaying sections in
ui-repolist.c was simplified to eliminate an impossible condition.

Signed-off-by: Andy Doan <andy.doan at linaro.org>
Reviewed-by: John Keeping <john at keeping.me.uk>
---
 cgit.c        | 27 +++++++++++++++++++++++----
 cgit.h        | 13 +++++++++++--
 cgitrc.5.txt  |  5 +++++
 scan-tree.c   |  6 +++---
 shared.c      |  5 ++++-
 ui-repolist.c | 31 +++++++++++++++++--------------
 6 files changed, 63 insertions(+), 24 deletions(-)

diff --git a/cgit.c b/cgit.c
index 9427c4a..c769e35 100644
--- a/cgit.c
+++ b/cgit.c
@@ -77,7 +77,7 @@ static void repo_config(struct cgit_repo *repo, const char *name, const char *va
 		item = string_list_append(&repo->submodules, xstrdup(name + 12));
 		item->util = xstrdup(value);
 	} else if (!strcmp(name, "section"))
-		repo->section = xstrdup(value);
+		repo->section = get_or_create_section(value);
 	else if (!strcmp(name, "readme") && value != NULL) {
 		if (repo->readme.items == ctx.cfg.readme.items)
 			memset(&repo->readme, 0, sizeof(repo->readme));
@@ -107,7 +107,7 @@ static void repo_config(struct cgit_repo *repo, const char *name, const char *va
 static void config_cb(const char *name, const char *value)
 {
 	if (!strcmp(name, "section") || !strcmp(name, "repo.group"))
-		ctx.cfg.section = xstrdup(value);
+		ctx.cfg.section = get_or_create_section(value);
 	else if (!strcmp(name, "repo.url"))
 		ctx.repo = cgit_add_repo(value);
 	else if (ctx.repo && !strcmp(name, "repo.path"))
@@ -242,6 +242,8 @@ static void config_cb(const char *name, const char *value)
 		ctx.cfg.section_from_path = atoi(value);
 	else if (!strcmp(name, "repository-sort"))
 		ctx.cfg.repository_sort = xstrdup(value);
+	else if (!strcmp(name, "section-collapse"))
+		get_or_create_section(value)->collapse = 1;
 	else if (!strcmp(name, "section-sort"))
 		ctx.cfg.section_sort = atoi(value);
 	else if (!strcmp(name, "source-filter"))
@@ -385,7 +387,7 @@ static void prepare_context(void)
 	ctx.cfg.root_desc = "a fast webinterface for the git dscm";
 	ctx.cfg.scan_hidden_path = 0;
 	ctx.cfg.script_name = CGIT_SCRIPT_NAME;
-	ctx.cfg.section = "";
+	ctx.cfg.section = NULL;
 	ctx.cfg.repository_sort = "name";
 	ctx.cfg.section_sort = 1;
 	ctx.cfg.summary_branches = 10;
@@ -794,7 +796,7 @@ static void print_repo(FILE *f, struct cgit_repo *repo)
 	if (repo->module_link)
 		fprintf(f, "repo.module-link=%s\n", repo->module_link);
 	if (repo->section)
-		fprintf(f, "repo.section=%s\n", repo->section);
+		fprintf(f, "repo.section=%s\n", repo->section->name);
 	if (repo->homepage)
 		fprintf(f, "repo.homepage=%s\n", repo->homepage);
 	if (repo->clone_url)
@@ -1026,6 +1028,23 @@ static int calc_ttl(void)
 	return ctx.cfg.cache_repo_ttl;
 }
 
+struct cgit_section* get_or_create_section(const char *section)
+{
+	struct cgit_section *ptr = ctx.sections;
+	while(ptr) {
+		if (!strcmp(section, ptr->name))
+			return ptr;
+		ptr = ptr->next;
+	}
+	/* Not found insert into head of list */
+	ptr = xmalloc(sizeof(*ptr));
+	ptr->name = xstrdup(section);
+	ptr->collapse = 0;
+	ptr->next = ctx.sections;
+	ctx.sections = ptr;
+	return ptr;
+}
+
 int main(int argc, const char **argv)
 {
 	const char *path;
diff --git a/cgit.h b/cgit.h
index 325432b..d940ae3 100644
--- a/cgit.h
+++ b/cgit.h
@@ -75,6 +75,12 @@ struct cgit_exec_filter {
 	int pid;
 };
 
+struct cgit_section {
+	unsigned int collapse : 1;
+	char *name;
+	struct cgit_section *next;
+};
+
 struct cgit_repo {
 	char *url;
 	char *name;
@@ -85,7 +91,7 @@ struct cgit_repo {
 	char *defbranch;
 	char *module_link;
 	struct string_list readme;
-	char *section;
+	struct cgit_section *section;
 	char *clone_url;
 	char *logo;
 	char *logo_link;
@@ -208,7 +214,7 @@ struct cgit_config {
 	char *root_desc;
 	char *root_readme;
 	char *script_name;
-	char *section;
+	struct cgit_section *section;
 	char *repository_sort;
 	char *virtual_root;	/* Always ends with '/'. */
 	char *strict_export;
@@ -305,6 +311,7 @@ struct cgit_context {
 	struct cgit_config cfg;
 	struct cgit_repo *repo;
 	struct cgit_page page;
+	struct cgit_section *sections;
 };
 
 typedef int (*write_archive_fn_t)(const char *, const char *);
@@ -322,6 +329,8 @@ extern struct cgit_repolist cgit_repolist;
 extern struct cgit_context ctx;
 extern const struct cgit_snapshot_format cgit_snapshot_formats[];
 
+extern struct cgit_section* get_or_create_section(const char *section);
+
 extern char *cgit_default_repo_desc;
 extern struct cgit_repo *cgit_add_repo(const char *url);
 extern struct cgit_repo *cgit_get_repoinfo(const char *url);
diff --git a/cgitrc.5.txt b/cgitrc.5.txt
index 9fcf445..2762657 100644
--- a/cgitrc.5.txt
+++ b/cgitrc.5.txt
@@ -404,6 +404,11 @@ section::
 	after this option will inherit the current section name. Default value:
 	none.
 
+section-collapse::
+	Name of a section to "collapse" and not display on the index page.
+	Multiple config entries can be specified and each one will be
+	collapsed.
+
 section-sort::
 	Flag which, when set to "1", will sort the sections on the repository
 	listing by name. Set this flag to "0" if the order in the cgitrc file should
diff --git a/scan-tree.c b/scan-tree.c
index 1cb4e5d..fa21fc4 100644
--- a/scan-tree.c
+++ b/scan-tree.c
@@ -164,10 +164,10 @@ static void add_repo(const char *base, struct strbuf *path, repo_config_fn fn)
 		}
 		if (slash && !n) {
 			*slash = '\0';
-			repo->section = xstrdup(rel.buf);
+			repo->section = get_or_create_section(rel.buf);
 			*slash = '/';
-			if (starts_with(repo->name, repo->section)) {
-				repo->name += strlen(repo->section);
+			if (starts_with(repo->name, repo->section->name)) {
+				repo->name += strlen(repo->section->name);
 				if (*repo->name == '/')
 					repo->name++;
 			}
diff --git a/shared.c b/shared.c
index a63633b..8348581 100644
--- a/shared.c
+++ b/shared.c
@@ -444,13 +444,16 @@ typedef struct {
 
 void cgit_prepare_repo_env(struct cgit_repo * repo)
 {
+	char *section = NULL;
+	if (repo->section)
+		section = repo->section->name;
 	cgit_env_var env_vars[] = {
 		{ .name = "CGIT_REPO_URL", .value = repo->url },
 		{ .name = "CGIT_REPO_NAME", .value = repo->name },
 		{ .name = "CGIT_REPO_PATH", .value = repo->path },
 		{ .name = "CGIT_REPO_OWNER", .value = repo->owner },
 		{ .name = "CGIT_REPO_DEFBRANCH", .value = repo->defbranch },
-		{ .name = "CGIT_REPO_SECTION", .value = repo->section },
+		{ .name = "CGIT_REPO_SECTION", .value = section },
 		{ .name = "CGIT_REPO_CLONE_URL", .value = repo->clone_url }
 	};
 	int env_var_count = ARRAY_SIZE(env_vars);
diff --git a/ui-repolist.c b/ui-repolist.c
index 3f967a8..e9676b8 100644
--- a/ui-repolist.c
+++ b/ui-repolist.c
@@ -188,10 +188,16 @@ static int sort_section(const void *a, const void *b)
 {
 	const struct cgit_repo *r1 = a;
 	const struct cgit_repo *r2 = b;
+	const char *s1 = "";
+	const char *s2 = "";
 	int result;
 	time_t t;
 
-	result = cmp(r1->section, r2->section);
+	if (r1->section)
+		s1 = r1->section->name;
+	if (r2->section)
+		s2 = r2->section->name;
+	result = cmp(s1, s2);
 	if (!result) {
 		if (!strcmp(ctx.cfg.repository_sort, "age")) {
 			// get_repo_modtime caches the value in r->mtime, so we don't
@@ -273,8 +279,8 @@ static int sort_repolist(char *field)
 void cgit_print_repolist(void)
 {
 	int i, columns = 3, hits = 0, header = 0;
-	char *last_section = NULL;
-	char *section;
+	struct cgit_section *last_section = NULL;
+	struct cgit_section *section;
 	int sorted = 0;
 
 	if (!any_repos_visible()) {
@@ -294,12 +300,10 @@ void cgit_print_repolist(void)
 
 	if (ctx.cfg.index_header)
 		html_include(ctx.cfg.index_header);
-
 	if (ctx.qry.sort)
 		sorted = sort_repolist(ctx.qry.sort);
 	else if (ctx.cfg.section_sort)
 		sort_repolist("section");
-
 	html("<table summary='repository list' class='list nowrap'>");
 	for (i = 0; i < cgit_repolist.count; i++) {
 		ctx.repo = &cgit_repolist.repos[i];
@@ -313,23 +317,22 @@ void cgit_print_repolist(void)
 		if (!header++)
 			print_header();
 		section = ctx.repo->section;
-		if (section && !strcmp(section, ""))
+		if (section && !strcmp(section->name, ""))
 			section = NULL;
-		if (!sorted &&
-		    ((last_section == NULL && section != NULL) ||
-		    (last_section != NULL && section == NULL) ||
-		    (last_section != NULL && section != NULL &&
-		     strcmp(section, last_section)))) {
+		if (!sorted && section && last_section != section ) {
 			htmlf("<tr class='nohover'><td colspan='%d' class='reposection'>",
 			      columns);
 			html("<a href='");
-			html_attr(section);
+			html_attr(section->name);
 			html("'>");
-			html_txt(section);
+			html_txt(section->name);
 			html("</a>");
 			html("</td></tr>");
-			last_section = section;
 		}
+		last_section = section;
+		if (section && section->collapse && !strstr(ctx.qry.url, section->name))
+			continue;
+
 		htmlf("<tr><td class='%s'>",
 		      !sorted && section ? "sublevel-repo" : "toplevel-repo");
 		cgit_summary_link(ctx.repo->name, ctx.repo->name, NULL, NULL);
-- 
2.7.4



^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCHv2 0/2] Collapsible Section Support
  2016-09-12 22:01 [PATCHv2 0/2] Collapsible Section Support andy.doan
                   ` (2 preceding siblings ...)
  2016-09-13  3:54 ` [PATCHv3 0/2] Collapsible Section Support andy.doan
@ 2016-10-01 20:50 ` Jason
  2016-10-03 15:44   ` andy.doan
  2016-10-03 18:10 ` tim
  4 siblings, 1 reply; 15+ messages in thread
From: Jason @ 2016-10-01 20:50 UTC (permalink / raw)


Hey Andy,

One issue with this is -- isn't this the sort of thing that would be
better taken care of with css3 or css+javascript? That is to say you
list the children of some elements as being display:none until they're
clicked, and then upon click you make it visible? This seems like it'd
be a bit slicker of an interface too. Would this be an acceptable
interface?

Regards,
Jason


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCHv2 0/2] Collapsible Section Support
  2016-10-01 20:50 ` [PATCHv2 0/2] Collapsible Section Support Jason
@ 2016-10-03 15:44   ` andy.doan
  2016-10-03 15:54     ` Jason
  0 siblings, 1 reply; 15+ messages in thread
From: andy.doan @ 2016-10-03 15:44 UTC (permalink / raw)


On 10/01/2016 03:50 PM, Jason A. Donenfeld wrote:
> Hey Andy,
> 
> One issue with this is -- isn't this the sort of thing that would be
> better taken care of with css3 or css+javascript? That is to say you
> list the children of some elements as being display:none until they're
> clicked, and then upon click you make it visible? This seems like it'd
> be a bit slicker of an interface too. Would this be an acceptable
> interface?

That's okay with me and I'll work up a patch to demonstrate it. For a
company with many repos like Linaro, not displaying them does make the
front page load faster, but I've already sensed momentary confusion when
people try out our UI:

 https://git-ap.linaro.org/cgit/

I'll work up a dynamic version this today and throw it on another Linaro
mirror so you can compare the differences.



^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCHv2 0/2] Collapsible Section Support
  2016-10-03 15:44   ` andy.doan
@ 2016-10-03 15:54     ` Jason
  2016-10-03 15:56       ` Jason
  0 siblings, 1 reply; 15+ messages in thread
From: Jason @ 2016-10-03 15:54 UTC (permalink / raw)


On Mon, Oct 3, 2016 at 5:44 PM, Andy Doan <andy.doan at linaro.org> wrote:
> I'll work up a dynamic version this today and throw it on another Linaro
> mirror so you can compare the differences.

Great! The unicode characters ?, ?, ?, and ? might come in handy,
depending on how you implement it.


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCHv2 0/2] Collapsible Section Support
  2016-10-03 15:54     ` Jason
@ 2016-10-03 15:56       ` Jason
  2016-10-03 18:04         ` andy.doan
  2016-10-03 20:52         ` andy.doan
  0 siblings, 2 replies; 15+ messages in thread
From: Jason @ 2016-10-03 15:56 UTC (permalink / raw)


Also, to clarify --

The patch for cgit for this should probably be just adding
id="section_name" to the various divs. Then users' stylesheets and js
files can contain the necessary logic for which to hide and when to
hide it. That is, unless you can think of some really slick way to
roll this out to everybody that isn't too invasive. But I'm leaning
toward the, "possible via section name IDs" approach.


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCHv2 0/2] Collapsible Section Support
  2016-10-03 15:56       ` Jason
@ 2016-10-03 18:04         ` andy.doan
  2016-10-03 20:52         ` andy.doan
  1 sibling, 0 replies; 15+ messages in thread
From: andy.doan @ 2016-10-03 18:04 UTC (permalink / raw)


On 10/03/2016 10:56 AM, Jason A. Donenfeld wrote:
> Also, to clarify --
> 
> The patch for cgit for this should probably be just adding
> id="section_name" to the various divs. Then users' stylesheets and js
> files can contain the necessary logic for which to hide and when to
> hide it. That is, unless you can think of some really slick way to
> roll this out to everybody that isn't too invasive. But I'm leaning
> toward the, "possible via section name IDs" approach.

The difficulty with this is that:

1) we use table-row elements rather than divs for "sections"
2) because of #1, we require some type of java-script logic
3) there doesn't seem to be any support for user-supplied java-script

Its all doable, but as I start to look into this the diff is going to
grow a little more than you might be expecting.


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCHv2 0/2] Collapsible Section Support
  2016-09-12 22:01 [PATCHv2 0/2] Collapsible Section Support andy.doan
                   ` (3 preceding siblings ...)
  2016-10-01 20:50 ` [PATCHv2 0/2] Collapsible Section Support Jason
@ 2016-10-03 18:10 ` tim
  4 siblings, 0 replies; 15+ messages in thread
From: tim @ 2016-10-03 18:10 UTC (permalink / raw)


On 09/12/2016 05:01 PM, Andy Doan wrote:
> This series adds hyperlinks to sections and allows them to be collapsed.
>
> Changes since v1:
>   - combined these 2 patches into a series
>
>
> Andy Doan (2):
>    ui-repolist: provide hyperlinks on section names
>    ui-repolist: Allow sections to be collapsible
>
>   cgit.c        | 27 +++++++++++++++++++++++----
>   cgit.h        | 13 +++++++++++--
>   cgitrc.5.txt  |  5 +++++
>   scan-tree.c   |  6 +++---
>   shared.c      |  5 ++++-
>   ui-repolist.c | 29 ++++++++++++++++-------------
>   6 files changed, 62 insertions(+), 23 deletions(-)
>
> --
> 2.7.4
>

Adding to the discussion that I submitted a patch for something akin to 
this changeset back in March, albeit, I'm no longer working at the 
company that I was when I submitted it (as such I don't have as much 
vested interest in getting that patchset in). In that case, I had 
patched in section name filters so that the end user could organize it 
however they pleased.  The net result is similar to what this patch 
series does.

Patch series: https://lists.zx2c4.com/pipermail/cgit/2016-March/002961.html
Example implementation: http://git.logicpd.com

- Tim




^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCHv2 0/2] Collapsible Section Support
  2016-10-03 15:56       ` Jason
  2016-10-03 18:04         ` andy.doan
@ 2016-10-03 20:52         ` andy.doan
  2016-10-11 16:15           ` andy.doan
  1 sibling, 1 reply; 15+ messages in thread
From: andy.doan @ 2016-10-03 20:52 UTC (permalink / raw)


On 10/03/2016 10:56 AM, Jason A. Donenfeld wrote:
> Also, to clarify --
> 
> The patch for cgit for this should probably be just adding
> id="section_name" to the various divs. Then users' stylesheets and js
> files can contain the necessary logic for which to hide and when to
> hide it. That is, unless you can think of some really slick way to
> roll this out to everybody that isn't too invasive. But I'm leaning
> toward the, "possible via section name IDs" approach.

I've just found a way to do this with having to only change one line of
code (add an "id" to each section row):

diff --git a/ui-repolist.c b/ui-repolist.c
index 30915df..c64d145 100644
--- a/ui-repolist.c
+++ b/ui-repolist.c
@@ -320,8 +320,8 @@ void cgit_print_repolist(void)
                    (last_section != NULL && section == NULL) ||
                    (last_section != NULL && section != NULL &&
                     strcmp(section, last_section)))) {
-                       htmlf("<tr class='nohover'><td colspan='%d'
class='reposection'>",
-                             columns);
+                       htmlf("<tr id='%s' class='nohover'><td
colspan='%d' class='reposection'>",
+                             section, columns);
                        html_txt(section);
                        html("</td></tr>");
                        last_section = section;

With that simple change, I was able to use your pluggable "header"
option to create something that works. The JS isn't exactly something I
would be proud of, but it does accomplish what you've described:

 http://paste.ubuntu.com/23271843/

You can compare the two approaches:

 new js hackery: https://git-ap.linaro.org/cgit/
 original patch: https://git-ie.linaro.org/cgit/

My page loads are almost 2x slower with the new approach. However, they
still seem "fast enough".

Let me know what you think, and I can re-submit this one-liner if you
prefer.

-andy


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCHv2 0/2] Collapsible Section Support
  2016-10-03 20:52         ` andy.doan
@ 2016-10-11 16:15           ` andy.doan
  0 siblings, 0 replies; 15+ messages in thread
From: andy.doan @ 2016-10-11 16:15 UTC (permalink / raw)


Any opinions on this?

On 10/03/2016 03:52 PM, Andy Doan wrote:
> On 10/03/2016 10:56 AM, Jason A. Donenfeld wrote:
>> Also, to clarify --
>>
>> The patch for cgit for this should probably be just adding
>> id="section_name" to the various divs. Then users' stylesheets and js
>> files can contain the necessary logic for which to hide and when to
>> hide it. That is, unless you can think of some really slick way to
>> roll this out to everybody that isn't too invasive. But I'm leaning
>> toward the, "possible via section name IDs" approach.
> 
> I've just found a way to do this with having to only change one line of
> code (add an "id" to each section row):
> 
> diff --git a/ui-repolist.c b/ui-repolist.c
> index 30915df..c64d145 100644
> --- a/ui-repolist.c
> +++ b/ui-repolist.c
> @@ -320,8 +320,8 @@ void cgit_print_repolist(void)
>                     (last_section != NULL && section == NULL) ||
>                     (last_section != NULL && section != NULL &&
>                      strcmp(section, last_section)))) {
> -                       htmlf("<tr class='nohover'><td colspan='%d'
> class='reposection'>",
> -                             columns);
> +                       htmlf("<tr id='%s' class='nohover'><td
> colspan='%d' class='reposection'>",
> +                             section, columns);
>                         html_txt(section);
>                         html("</td></tr>");
>                         last_section = section;
> 
> With that simple change, I was able to use your pluggable "header"
> option to create something that works. The JS isn't exactly something I
> would be proud of, but it does accomplish what you've described:
> 
>  http://paste.ubuntu.com/23271843/
> 
> You can compare the two approaches:
> 
>  new js hackery: https://git-ap.linaro.org/cgit/
>  original patch: https://git-ie.linaro.org/cgit/
> 
> My page loads are almost 2x slower with the new approach. However, they
> still seem "fast enough".
> 
> Let me know what you think, and I can re-submit this one-liner if you
> prefer.
> 
> -andy
> 



^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2016-10-11 16:15 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-12 22:01 [PATCHv2 0/2] Collapsible Section Support andy.doan
2016-09-12 22:01 ` [PATCH 1/2] ui-repolist: provide hyperlinks on section names andy.doan
2016-09-12 23:08   ` john
2016-09-12 22:01 ` [PATCH 2/2] ui-repolist: Allow sections to be collapsible andy.doan
2016-09-13  3:54 ` [PATCHv3 0/2] Collapsible Section Support andy.doan
2016-09-13  3:54   ` [PATCHv3 1/2] ui-repolist: provide hyperlinks on section names andy.doan
2016-09-13  3:54   ` [PATCHv3 2/2] ui-repolist: Allow sections to be collapsible andy.doan
2016-10-01 20:50 ` [PATCHv2 0/2] Collapsible Section Support Jason
2016-10-03 15:44   ` andy.doan
2016-10-03 15:54     ` Jason
2016-10-03 15:56       ` Jason
2016-10-03 18:04         ` andy.doan
2016-10-03 20:52         ` andy.doan
2016-10-11 16:15           ` andy.doan
2016-10-03 18:10 ` tim

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).