From: Omar Polo Subject: gotwebd: templateify gotweb_render_tree To: gameoftrees@openbsd.org Date: Thu, 05 Jan 2023 12:41:25 +0100 shouldn't introduce any difference with the current output, links for the BLOBRAW page will be added as follow-up. my instance is running with latest main + this applied. I don't like too much changing the functions in got_operations.c from `const struct got_error *' to int to please the template, but for the moment is the quickest way to move forward. Once everything is running with the templates I'd like to clean this a bit more so that we first acquire the resources needed (i.e. open the tree) and only then output. This way the only failures in the template code path will be from ENOMEM and clients closing the connection before we've finished. (see for example how BLOB is handled, that's the idea.) ok? diff /home/op/w/got commit - 5eeb13e79b508eacc001662d742ea375c069d7f7 path + /home/op/w/got blob - 9d187ce1e16a66d113377842fd55ccbd016fd2e3 file + gotwebd/got_operations.c --- gotwebd/got_operations.c +++ gotwebd/got_operations.c @@ -793,8 +793,9 @@ const struct got_error * return error; } -const struct got_error * -got_output_repo_tree(struct request *c) +int +got_output_repo_tree(struct request *c, + int (*cb)(struct template *, struct got_tree_entry *)) { const struct got_error *error = NULL; struct transport *t = c->t; @@ -805,10 +806,10 @@ got_output_repo_tree(struct request *c) struct got_object_id *tree_id = NULL, *commit_id = NULL; struct got_reflist_head refs; struct got_tree_object *tree = NULL; + struct got_tree_entry *te; struct repo_dir *repo_dir = t->repo_dir; - const char *name, *folder; char *escaped_name = NULL, *path = NULL; - int nentries, i, r; + int nentries, i; TAILQ_INIT(&refs); @@ -845,106 +846,10 @@ got_output_repo_tree(struct request *c) nentries = got_object_tree_get_nentries(tree); - folder = qs->folder ? qs->folder : ""; - for (i = 0; i < nentries; i++) { - const char *modestr; - struct got_tree_entry *te; - mode_t mode; - te = got_object_tree_get_entry(tree, i); - - mode = got_tree_entry_get_mode(te); - if (got_object_tree_entry_is_submodule(te)) - modestr = "$"; - else if (S_ISLNK(mode)) - modestr = "@"; - else if (S_ISDIR(mode)) - modestr = "/"; - else if (mode & S_IXUSR) - modestr = "*"; - else - modestr = ""; - - name = got_tree_entry_get_name(te); - error = gotweb_escape_html(&escaped_name, name); - if (error) - goto done; - - if (S_ISDIR(mode)) { - struct gotweb_url url = { - .index_page = -1, - .page = -1, - .action = TREE, - .commit = rc->commit_id, - .path = qs->path, - /* `folder' is filled later */ - }; - char *path = NULL; - - if (fcgi_printf(c,"
\n" - "
") == -1) - goto done; - - if (asprintf(&path, "%s/%s", folder, name) == -1) { - error = got_error_from_errno("asprintf"); - goto done; - } - url.folder = path; - r = gotweb_link(c, &url, "%s%s", escaped_name, - modestr); - free(path); - if (r == -1) - goto done; - - if (fcgi_printf(c, "
\n" /* .tree_line */ - "
 
\n" - "
\n") == -1) - goto done; - } else { - struct gotweb_url url = { - .index_page = -1, - .page = -1, - .path = qs->path, - .commit = rc->commit_id, - .folder = folder, - .file = name, - }; - - if (fcgi_printf(c, "
\n" - "
") == -1) - goto done; - - url.action = BLOB; - r = gotweb_link(c, &url, "%s%s", escaped_name, - modestr); - if (r == -1) - goto done; - - if (fcgi_printf(c, "
\n" /* .tree_line */ - "
") == -1) - goto done; - - url.action = COMMITS; - r = gotweb_link(c, &url, "commits"); - if (r == -1) - goto done; - - if (fcgi_printf(c, " | ") == -1) - goto done; - - url.action = BLAME; - r = gotweb_link(c, &url, "blame"); - if (r == -1) - goto done; - - if (fcgi_printf(c, - "
\n" /* .tree_line_blank */ - "
\n") == -1) /* .tree_wrapper */ - goto done; - } - free(escaped_name); - escaped_name = NULL; + if (cb(c->tp, te) == -1) + break; } done: free(escaped_name); @@ -956,7 +861,11 @@ done: got_object_tree_close(tree); free(commit_id); free(tree_id); - return error; + if (error) { + log_warnx("%s: %s", __func__, error->msg); + return -1; + } + return 0; } const struct got_error * blob - 37d8624ec792d91e8f7438d5cc3682be3a54d179 file + gotwebd/gotweb.c --- gotwebd/gotweb.c +++ gotwebd/gotweb.c @@ -98,7 +98,6 @@ static const struct got_error *gotweb_render_tree(stru static const struct got_error *gotweb_render_summary(struct request *); static const struct got_error *gotweb_render_tag(struct request *); static const struct got_error *gotweb_render_tags(struct request *); -static const struct got_error *gotweb_render_tree(struct request *); static const struct got_error *gotweb_render_branches(struct request *); static void gotweb_free_querystring(struct querystring *); @@ -306,11 +305,13 @@ render: } break; case TREE: - error = gotweb_render_tree(c); + error = got_get_repo_commits(c, 1); if (error) { log_warnx("%s: %s", __func__, error->msg); goto err; } + if (gotweb_render_tree(c->tp) == -1) + goto err; break; case ERR: default: @@ -1120,63 +1121,6 @@ gotweb_render_tree(struct request *c) } static const struct got_error * -gotweb_render_tree(struct request *c) -{ - const struct got_error *error = NULL; - struct transport *t = c->t; - struct repo_commit *rc = NULL; - char *age = NULL, *msg = NULL; - int r; - - error = got_get_repo_commits(c, 1); - if (error) - return error; - - rc = TAILQ_FIRST(&t->repo_commits); - - error = gotweb_get_time_str(&age, rc->committer_time, TM_LONG); - if (error) - goto done; - - error = gotweb_escape_html(&msg, rc->commit_msg); - if (error) - goto done; - - r = fcgi_printf(c, "
\n" - "
Tree
\n" - "
\n" /* #tree_title_wrapper */ - "
\n" - "
\n" - "
\n" - "
Tree:
\n" - "
%s
\n" - "
Date:
\n" - "
%s
\n" - "
Message:
\n" - "
%s
\n" - "
\n" /* #tree_header */ - "
\n" /* #tree_header_wrapper */ - "
\n" - "
\n", - rc->tree_id, - age, - msg); - if (r == -1) - goto done; - - error = got_output_repo_tree(c); - if (error) - goto done; - - fcgi_printf(c, "
\n"); /* #tree */ - fcgi_printf(c, "
\n"); /* #tree_content */ -done: - free(age); - free(msg); - return error; -} - -static const struct got_error * gotweb_render_diff(struct request *c) { const struct got_error *error = NULL; blob - e4e23bf9c198a25c2338660068796cd385a8498c file + gotwebd/gotwebd.h --- gotwebd/gotwebd.h +++ gotwebd/gotwebd.h @@ -117,6 +117,7 @@ struct got_blob_object; /* Forward declaration */ struct got_blob_object; +struct got_tree_entry; enum imsg_type { IMSG_CFG_SRV = IMSG_PROC_MAX, @@ -467,6 +468,7 @@ int gotweb_render_rss(struct template *); int gotweb_render_navs(struct template *); int gotweb_render_commits(struct template *); int gotweb_render_blob(struct template *, struct got_blob_object *); +int gotweb_render_tree(struct template *); int gotweb_render_rss(struct template *); /* parse.y */ @@ -495,7 +497,8 @@ const struct got_error *got_output_repo_tree(struct re const struct got_error *got_get_repo_tags(struct request *, int); const struct got_error *got_get_repo_heads(struct request *); const struct got_error *got_output_repo_diff(struct request *); -const struct got_error *got_output_repo_tree(struct request *); +int got_output_repo_tree(struct request *, + int (*cb)(struct template *, struct got_tree_entry *)); const struct got_error *got_open_blob_for_output(struct got_blob_object **, int *, int *, struct request *); const struct got_error *got_output_file_blob(struct request *); blob - 5dac668e8a6c3b5de586bc8484746a6397e29dfb file + gotwebd/pages.tmpl --- gotwebd/pages.tmpl +++ gotwebd/pages.tmpl @@ -18,20 +18,26 @@ #include #include +#include #include #include #include +#include #include #include +#include #include +#include "got_object.h" + #include "proc.h" #include "gotwebd.h" #include "tmpl.h" static int gotweb_render_blob_line(struct template *, const char *, size_t); +static int gotweb_render_tree_item(struct template *, struct got_tree_entry *); static inline int rss_tag_item(struct template *, struct repo_tag *); static inline int rss_author(struct template *, char *); @@ -456,6 +462,112 @@ gotweb_render_age(struct template *tp, time_t time, in {{ end }} +{{ define gotweb_render_tree(struct template *tp) }} +{! + struct request *c = tp->tp_arg; + struct transport *t = c->t; + struct repo_commit *rc = TAILQ_FIRST(&t->repo_commits); +!} +
+
Tree
+
+
+
+
+
Tree:
+
{{ rc->tree_id }}
+
Date:
+
+ {{ render gotweb_render_age(tp, rc->committer_time, TM_LONG) }} +
+
Message:
+
{{ rc->commit_msg }}
+
+
+
+
+ {{ render got_output_repo_tree(c, gotweb_render_tree_item) }} +
+
+{{ end }} + +{{ define gotweb_render_tree_item(struct template *tp, + struct got_tree_entry *te) }} +{! + struct request *c = tp->tp_arg; + struct transport *t = c->t; + struct querystring *qs = t->qs; + struct repo_commit *rc = TAILQ_FIRST(&t->repo_commits); + const char *modestr = ""; + const char *name; + const char *folder; + char *dir = NULL; + mode_t mode; + struct gotweb_url url = { + .index_page = -1, + .page = -1, + .commit = rc->commit_id, + .path = qs->path, + }; + + name = got_tree_entry_get_name(te); + mode = got_tree_entry_get_mode(te); + + folder = qs->folder ? qs->folder : ""; + if (S_ISDIR(mode)) { + if (asprintf(&dir, "%s/%s", folder, name) == -1) + return (-1); + + url.action = TREE; + url.folder = dir; + } else { + url.action = BLOB; + url.folder = folder; + url.file = name; + } + + if (got_object_tree_entry_is_submodule(te)) + modestr = "$"; + else if (S_ISLNK(mode)) + modestr = "@"; + else if (S_ISDIR(mode)) + modestr = "/"; + else if (mode & S_IXUSR) + modestr = "*"; +!} +
+ {{ if S_ISDIR(mode) }} + +
 
+ {{ else }} + +
+ {! url.action = COMMITS; !} + + commits + + {{ " | " }} + {! url.action = BLAME; !} + + blame + +
+ {{ end }} +
+{{ finally }} +{! + free(dir); +!} +{{ end }} + {{ define gotweb_render_rss(struct template *tp) }} {! struct request *c = tp->tp_arg;