"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
Omar Polo <op@omarpolo.com>
Subject:
gotwebd: add patch action
To:
gameoftrees@openbsd.org
Date:
Fri, 01 Dec 2023 19:47:58 +0100

Download raw body.

Thread
This adds a "patch" action to serve diffs as plain text over http(s).
There's an example here:

https://got.omarpolo.com/?action=patch&commit=446026cb9332485a4c570afd42fb493d451f7251&headref=HEAD&path=got.git

I personally find it useful to have diffs served via http, especially
when dealing with ports.

concerns/comments/ok?

diff /home/op/w/got
commit - 4ba8b606a0a1ebe0d9a9daf6909948315c313d36
path + /home/op/w/got
blob - 45a8a36ea39f6f705bfc81c145d550389dd82872
file + gotwebd/got_operations.c
--- gotwebd/got_operations.c
+++ gotwebd/got_operations.c
@@ -259,7 +259,7 @@ got_get_repo_commit(struct request *c, struct repo_com
 	if (error)
 		return error;
 
-	if (qs->action == DIFF) {
+	if (qs->action == DIFF || qs->action == PATCH) {
 		parent_id = STAILQ_FIRST(
 		    got_object_commit_get_parent_ids(commit));
 		if (parent_id != NULL) {
blob - e5f7034e08396bd55ab20a409d6dbd8d8acf4c88
file + gotwebd/gotweb.c
--- gotwebd/gotweb.c
+++ gotwebd/gotweb.c
@@ -72,6 +72,7 @@ static const struct action_keys action_keys[] = {
 	{ "diff",	DIFF },
 	{ "error",	ERR },
 	{ "index",	INDEX },
+	{ "patch",	PATCH },
 	{ "summary",	SUMMARY },
 	{ "tag",	TAG },
 	{ "tags",	TAGS },
@@ -187,7 +188,8 @@ gotweb_process_request(struct request *c)
 	 */
 
 	if (qs->action == BLAME || qs->action == BLOB ||
-	    qs->action == BLOBRAW || qs->action == DIFF) {
+	    qs->action == BLOBRAW || qs->action == DIFF ||
+	    qs->action == PATCH) {
 		if (qs->commit == NULL) {
 			error = got_error(GOT_ERR_BAD_QUERYSTRING);
 			goto err;
@@ -314,6 +316,21 @@ gotweb_process_request(struct request *c)
 			return;
 		gotweb_render_page(c->tp, gotweb_render_index);
 		return;
+	case PATCH:
+		error = got_get_repo_commits(c, 1);
+		if (error) {
+			log_warnx("%s: %s", __func__, error->msg);
+			goto err;
+		}
+		error = got_open_diff_for_output(&c->t->fp, c);
+		if (error) {
+			log_warnx("%s: %s", __func__, error->msg);
+			goto err;
+		}
+		if (gotweb_reply(c, 200, "text/plain", NULL) == -1)
+			return;
+		gotweb_render_patch(c->tp);
+		return;
 	case RSS:
 		error = got_get_repo_tags(c, D_MAXSLCOMMDISP);
 		if (error)
@@ -987,6 +1004,8 @@ gotweb_action_name(int action)
 		return "err";
 	case INDEX:
 		return "index";
+	case PATCH:
+		return "patch";
 	case SUMMARY:
 		return "summary";
 	case TAG:
blob - 8005d4db4e8e1da67b226c26b8e1640b5c42645d
file + gotwebd/gotwebd.h
--- gotwebd/gotwebd.h
+++ gotwebd/gotwebd.h
@@ -436,6 +436,7 @@ enum query_actions {
 	DIFF,
 	ERR,
 	INDEX,
+	PATCH,
 	SUMMARY,
 	TAG,
 	TAGS,
@@ -493,6 +494,7 @@ int	gotweb_render_diff(struct template *);
 int	gotweb_render_branches(struct template *, struct got_reflist_head *);
 int	gotweb_render_summary(struct template *);
 int	gotweb_render_blame(struct template *);
+int	gotweb_render_patch(struct template *);
 int	gotweb_render_rss(struct template *);
 
 /* parse.y */
blob - bac391d8a08e90c6c0b28bba4f935029591ab0c8
file + gotwebd/pages.tmpl
--- gotwebd/pages.tmpl
+++ gotwebd/pages.tmpl
@@ -346,7 +346,7 @@ nextsep(char *s, char **t)
 	struct querystring	*qs = c->t->qs;
 	struct repo_commit	*rc;
 	struct repo_dir		*repo_dir = t->repo_dir;
-	struct gotweb_url	 diff_url, tree_url;
+	struct gotweb_url	 diff_url, patch_url, tree_url;
 	char			*tmp;
 
 	diff_url = (struct gotweb_url){
@@ -356,6 +356,13 @@ nextsep(char *s, char **t)
 		.path = repo_dir->name,
 		.headref = qs->headref,
 	};
+	patch_url = (struct gotweb_url){
+		.action = PATCH,
+		.index_page = -1,
+		.page = -1,
+		.path = repo_dir->name,
+		.headref = qs->headref,
+	};
 	tree_url = (struct gotweb_url){
 		.action = TREE,
 		.index_page = -1,
@@ -371,6 +378,7 @@ nextsep(char *s, char **t)
   {{ tailq-foreach rc &t->repo_commits entry }}
     {!
 	diff_url.commit = rc->commit_id;
+	patch_url.commit = rc->commit_id;
 	tree_url.commit = rc->commit_id;
 
 	tmp = strchr(rc->committer, '<');
@@ -405,6 +413,8 @@ nextsep(char *s, char **t)
       <div class="navs">
         <a href="{{ render gotweb_render_url(tp->tp_arg, &diff_url) }}">diff</a>
 	{{ " | " }}
+        <a href="{{ render gotweb_render_url(tp->tp_arg, &patch_url) }}">patch</a>
+	{{ " | " }}
 	<a href="{{ render gotweb_render_url(tp->tp_arg, &tree_url) }}">tree</a>
       </div>
     </div>
@@ -479,7 +489,7 @@ nextsep(char *s, char **t)
 	struct transport	*t = c->t;
 	struct repo_dir		*repo_dir = t->repo_dir;
 	struct repo_commit	*rc;
-	struct gotweb_url	 diff, tree;
+	struct gotweb_url	 diff, patch, tree;
 
 	diff = (struct gotweb_url){
 		.action = DIFF,
@@ -487,6 +497,12 @@ nextsep(char *s, char **t)
 		.page = -1,
 		.path = repo_dir->name,
 	};
+	patch = (struct gotweb_url){
+		.action = PATCH,
+		.index_page = -1,
+		.page = -1,
+		.path = repo_dir->name,
+	};
 	tree = (struct gotweb_url){
 		.action = TREE,
 		.index_page = -1,
@@ -501,6 +517,7 @@ nextsep(char *s, char **t)
   {{ tailq-foreach rc &t->repo_commits entry }}
     {!
 	diff.commit = rc->commit_id;
+	patch.commit = rc->commit_id;
 	tree.commit = rc->commit_id;
     !}
     <div class="page_header_wrapper">
@@ -528,6 +545,8 @@ nextsep(char *s, char **t)
       <div class="navs">
         <a href="{{ render gotweb_render_url(c, &diff) }}">diff</a>
 	{{ " | " }}
+        <a href="{{ render gotweb_render_url(c, &patch) }}">patch</a>
+	{{ " | " }}
         <a href="{{ render gotweb_render_url(c, &tree) }}">tree</a>
       </div>
     </div>
@@ -989,7 +1008,7 @@ nextsep(char *s, char **t)
 	struct transport	*t = c->t;
 	struct got_reflist_head	*refs = &t->refs;
 !}
-<dl id="summary_wrapper">
+<dl id="summary_wrapper" class="page_header_wrapper">
   {{ if srv->show_repo_description }}
     <dt>Description:</dt>
     <dd>{{ t->repo_dir->description }}</dd>
@@ -1118,6 +1137,39 @@ nextsep(char *s, char **t)
 </div>
 {{ end }}
 
+{{ define gotweb_render_patch(struct template *tp) }}
+{!
+	struct request		*c = tp->tp_arg;
+	struct transport	*t = c->t;
+	struct repo_commit	*rc = TAILQ_FIRST(&t->repo_commits);
+	struct tm		 tm;
+	char			 buf[BUFSIZ], datebuf[64];
+	size_t			 r;
+
+	if (gmtime_r(&rc->committer_time, &tm) == NULL ||
+	    strftime(datebuf, sizeof(datebuf), "%a %b %d %T %Y UTC", &tm) == 0)
+		return (-1);
+!}
+commit {{ rc->commit_id }} {{ "\n" }}
+from: {{ rc->author | unsafe }} {{ "\n" }}
+{{ if strcmp(rc->committer, rc->author) != 0 }}
+via: {{ rc->committer | unsafe }} {{ "\n" }}
+{{ end }}
+date: {{ datebuf }} {{ "\n" }}
+{{ "\n" }}
+{{ rc->commit_msg | unsafe }} {{ "\n" }}
+{!
+	if (template_flush(tp) == -1)
+		return (-1);
+	for (;;) {
+		r = fread(buf, 1, sizeof(buf), t->fp);
+		if (fcgi_write(c, buf, r) == -1 ||
+		    r != sizeof(buf))
+			break;
+	}
+!}
+{{ end }}
+
 {{ define gotweb_render_rss(struct template *tp) }}
 {!
 	struct request		*c = tp->tp_arg;