From: Dhruvin Gandhi Subject: show_repo_category To: gameoftrees@openbsd.org Date: Mon, 27 Nov 2023 13:00:35 +0530 Gitweb supports these per-repository configuration files [1]: [x] description [ ] category [x] cloneurl [x] gitweb.owner (or gotweb.owner) Note: x means the feature is present in gotwebd. This diff adds support for labeling repos with a category. Currently, category is shown wherever the description is shown. Rationale behind using a category column in index: gotwebd list pages have pagination implemented. When introducting categories web can employ below approaches: 1. Paginate first, and then group entries by category: This works in practice, but each page has varying number of categories at various indices. To me, it looks a bit out of place. 2. Categorize first, and then paginate entries starting from alphabetically sorted categories: This brings up all repos under "archived" category to the first page. I believe this is undesirable. 3. No grouping, just label repositories with category metadata: This is quite simple to implement. We can, in a later commit, allow filtering repositories by category. These ideas are subject to my understanding of how the user inteface should look like and I'm open to change them. [1] https://git-scm.com/docs/gitweb#_per_repository_gitweb_configuration PS: This is my first contribution to gameoftrees. Let me know if I got anything wrong while sending a diff to mailing list. diff refs/heads/main refs/heads/show_repo_category commit - 2bde3e78a5bd6619af838df19eec530e23783c0b commit + 99fcb0c39edde5fec8b7752c079e8c9fe878b802 blob - 2980f56caa8182e5f1e54b32e8d915bf78dd1308 blob + 36383a7197171f46fcd2358275424b2d00c76c7e --- TODO +++ TODO @@ -55,8 +55,6 @@ gotwebd: page. - add a "rawdiff" page to serve a diff as text/plain (or text/x-patch), or maybe "rawcommit" that includes the commentary too. -- support category grouping a-la gitweb/cgit with the gitweb.category - config option or via the "category" file in the root of the repo. - consider changing the URL scheme to avoid so many query parameters gotd: blob - 67b8328cafa8a92842599b49698d625a536119bd blob + bb4866199b15665bf92bfa9dd7b13a86205f1c20 --- gotwebd/files/htdocs/gotwebd/gotweb.css +++ gotwebd/files/htdocs/gotwebd/gotweb.css @@ -255,24 +255,27 @@ header.subtitle h2 { #index_header { background-color: Khaki; } -.index_project, .index_project_description, .index_project_owner, -.index_project_age { +.index_project, .index_project_description, .index_project_category, +.index_project_owner, .index_project_age { display: inline-block; padding: 10px; overflow: hidden; vertical-align: middle; } .index_project { - width: 20%; + width: 15%; } .index_project_description { - width: 30%; + width: 25%; } +.index_project_category { + width: 20%; +} .index_project_owner { - width: 25%; + width: 20%; } .index_project_age { - width: 25%; + width: 20%; } .index_project a { color: #444444; blob - af7ddea86d0f5f5e689b53e6aa57e44387ec4a1c blob + dd33c6f9937687236160a4084565fda7361e3cb9 --- gotwebd/gotweb.c +++ gotwebd/gotweb.c @@ -91,6 +91,8 @@ static const struct got_error *gotweb_load_got_path(st struct repo_dir *); static const struct got_error *gotweb_get_repo_description(char **, struct server *, const char *, int); +static const struct got_error *gotweb_get_repo_category(char **, + struct server *, const char *, int); static const struct got_error *gotweb_get_clone_url(char **, struct server *, const char *, int); @@ -701,6 +703,7 @@ gotweb_free_repo_dir(struct repo_dir *repo_dir) if (repo_dir != NULL) { free(repo_dir->name); free(repo_dir->owner); + free(repo_dir->category); free(repo_dir->description); free(repo_dir->url); free(repo_dir->path); @@ -1161,6 +1164,10 @@ open_repo: repo_dir->path, dirfd(dt)); if (error) goto err; + error = gotweb_get_repo_category(&repo_dir->category, srv, + repo_dir->path, dirfd(dt)); + if (error) + goto err; error = got_get_repo_owner(&repo_dir->owner, c); if (error) goto err; @@ -1252,6 +1259,52 @@ done: } static const struct got_error * +gotweb_get_repo_category(char **category, struct server *srv, + const char *dirpath, int dir) +{ + const struct got_error *error = NULL; + struct stat sb; + int fd = -1; + off_t len; + + *category = NULL; + if (srv->show_repo_category == 0) + return NULL; + + fd = openat(dir, "category", O_RDONLY); + if (fd == -1) { + if (errno != ENOENT && errno != EACCES) { + error = got_error_from_errno_fmt("openat %s/%s", + dirpath, "category"); + } + goto done; + } + + if (fstat(fd, &sb) == -1) { + error = got_error_from_errno_fmt("fstat %s/%s", + dirpath, "category"); + goto done; + } + + len = sb.st_size; + if (len > GOTWEBD_MAXCATSZ - 1) + len = GOTWEBD_MAXCATSZ - 1; + + *category = calloc(len + 1, sizeof(**category)); + if (*category == NULL) { + error = got_error_from_errno("calloc"); + goto done; + } + + if (read(fd, *category, len) == -1) + error = got_error_from_errno("read"); +done: + if (fd != -1 && close(fd) == -1 && error == NULL) + error = got_error_from_errno("close"); + return error; +} + +static const struct got_error * gotweb_get_clone_url(char **url, struct server *srv, const char *dirpath, int dir) { blob - 0a41fb98df13059fc8f142e386a1d099a8d24de9 blob + 464ebbe06ba7bb41e36302a46b948e7a6308391b --- gotwebd/gotwebd.conf.5 +++ gotwebd/gotwebd.conf.5 @@ -136,6 +136,11 @@ Toggle display of the repository description. The .Pa description file in the repository should be updated with an appropriate description. +.It Ic show_repo_category Ar on | off +Toggle display of the repository category. +This requires the creation of a +.Pa category +file inside the repository. .It Ic show_repo_owner Ar on | off Set whether to display the repository owner. Displaying the owner requires owner information to be added to the @@ -192,6 +197,7 @@ server "localhost-unix" { #show_repo_owner on #show_repo_age on #show_repo_description on + #show_repo_category on #show_repo_cloneurl on #respect_exportok off blob - 8005d4db4e8e1da67b226c26b8e1640b5c42645d blob + 3d2de659bcce54a65d534cc39223102ba3f571d0 --- gotwebd/gotwebd.h +++ gotwebd/gotwebd.h @@ -40,6 +40,7 @@ #define GOTWEBD_USER "www" #define GOTWEBD_MAXDESCRSZ 1024 +#define GOTWEBD_MAXCATSZ 64 #define GOTWEBD_MAXCLONEURLSZ 1024 #define GOTWEBD_CACHESIZE 1024 #define GOTWEBD_MAXCLIENTS 1024 @@ -73,6 +74,7 @@ #define D_SHOWSOWNER 1 #define D_SHOWAGE 1 #define D_SHOWDESC 1 +#define D_SHOWCAT 1 #define D_SHOWURL 1 #define D_RESPECTEXPORTOK 0 #define D_MAXREPO 0 @@ -165,6 +167,7 @@ struct repo_dir { char *name; char *owner; char *description; + char *category; char *url; time_t age; char *path; @@ -306,6 +309,7 @@ struct server { int show_repo_owner; int show_repo_age; int show_repo_description; + int show_repo_category; int show_repo_cloneurl; int respect_exportok; blob - d04e49122cc951bb2815072249af493a694624f3 blob + 32831eb25c20a494bf0dccf6670049b248d29f0c --- gotwebd/pages.tmpl +++ gotwebd/pages.tmpl @@ -174,6 +174,11 @@ static inline int rss_author(struct template *, char *
Project
+ {{ if srv->show_repo_category }} +
+ Category +
+ {{ end }} {{ if srv->show_repo_description }}
Description @@ -232,6 +237,11 @@ static inline int rss_author(struct template *, char * + {{ if srv->show_repo_category }} +
+ {{ repo_dir->category }} +
+ {{ end }} {{ if srv->show_repo_description }}
{{ repo_dir->description }} @@ -885,6 +895,10 @@ static inline int rss_author(struct template *, char * struct got_reflist_head *refs = &t->refs; !}
+ {{ if srv->show_repo_category }} +
Category:
+
{{ t->repo_dir->category }}
+ {{ end }} {{ if srv->show_repo_description }}
Description:
{{ t->repo_dir->description }}
blob - 207d9f20026688bdc8849f0125e73b94a285504e blob + dfed531e40bc3b2b0d3b5103b2e9b4c19943d972 --- gotwebd/parse.y +++ gotwebd/parse.y @@ -386,6 +386,9 @@ serveropts1 : REPOS_PATH STRING { | SHOW_REPO_DESCRIPTION boolean { new_srv->show_repo_description = $2; } + | SHOW_REPO_CATEGORY boolean { + new_srv->show_repo_category = $2; + } | SHOW_REPO_CLONEURL boolean { new_srv->show_repo_cloneurl = $2; } @@ -470,6 +473,7 @@ lookup(char *s) { "respect_exportok", RESPECT_EXPORTOK }, { "server", SERVER }, { "show_repo_age", SHOW_REPO_AGE }, + { "show_repo_category", SHOW_REPO_CATEGORY }, { "show_repo_cloneurl", SHOW_REPO_CLONEURL }, { "show_repo_description", SHOW_REPO_DESCRIPTION }, { "show_repo_owner", SHOW_REPO_OWNER }, @@ -904,6 +908,7 @@ conf_new_server(const char *name) srv->show_repo_owner = D_SHOWROWNER; srv->show_repo_age = D_SHOWAGE; srv->show_repo_description = D_SHOWDESC; + srv->show_repo_category = D_SHOWCAT; srv->show_repo_cloneurl = D_SHOWURL; srv->respect_exportok = D_RESPECTEXPORTOK;