Commit Diff


commit - af0d6ce18919928a2cc636c0fabbbeb578acee4f
commit + 3c14c1f2875343bc03f7ef656f03bfa85ba1b4bf
blob - 007e537ce8e97a3eb1ad847d2a702c748a8e7c7e
blob + 69754261053b65ed03d8c5a1d8be6e36f3945103
--- gotwebd/got_operations.c
+++ gotwebd/got_operations.c
@@ -793,8 +793,9 @@ err:
 	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,"<div class='tree_wrapper'>\n"
-			    "<div class='tree_line'>") == -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, "</div>\n" /* .tree_line */
-			    "<div class='tree_line_blank'>&nbsp;</div>\n"
-			    "</div>\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, "<div class='tree_wrapper'>\n"
-			    "<div class='tree_line'>") == -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, "</div>\n" /* .tree_line */
-			    "<div class='tree_line_blank'>") == -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,
-			    "</div>\n"		/* .tree_line_blank */
-			    "</div>\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 - 108dce82337acd8a391aba5ce326b01a7088da89
blob + dc2eae333e9de20f449a1ed77bff33762053d477
--- gotwebd/gotweb.c
+++ gotwebd/gotweb.c
@@ -99,7 +99,6 @@ static const struct got_error *gotweb_render_diff(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 *);
@@ -307,11 +306,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:
@@ -1117,63 +1118,6 @@ done:
 	free(age);
 	free(escaped_refname);
 	got_ref_list_free(&refs);
-	return error;
-}
-
-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, "<div id='tree_title_wrapper'>\n"
-	    "<div id='tree_title'>Tree</div>\n"
-	    "</div>\n"		/* #tree_title_wrapper */
-	    "<div id='tree_content'>\n"
-	    "<div id='tree_header_wrapper'>\n"
-	    "<div id='tree_header'>\n"
-	    "<div id='header_tree_title'>Tree:</div>\n"
-	    "<div id='header_tree'>%s</div>\n"
-	    "<div class='header_age_title'>Date:</div>\n"
-	    "<div class='header_age'>%s</div>\n"
-	    "<div id='header_commit_msg_title'>Message:</div>\n"
-	    "<div id='header_commit_msg'>%s</div>\n"
-	    "</div>\n"		/* #tree_header */
-	    "</div>\n"		/* #tree_header_wrapper */
-	    "<div class='dotted_line'></div>\n"
-	    "<div id='tree'>\n",
-	    rc->tree_id,
-	    age,
-	    msg);
-	if (r == -1)
-		goto done;
-
-	error = got_output_repo_tree(c);
-	if (error)
-		goto done;
-
-	fcgi_printf(c, "</div>\n"); /* #tree */
-	fcgi_printf(c, "</div>\n"); /* #tree_content */
-done:
-	free(age);
-	free(msg);
 	return error;
 }
 
blob - c62d1d14bbb893e14e794d76756166451dcd25ec
blob + b3f1e23a856b74f0e7fa42acdbab7498cfd2e4b8
--- gotwebd/gotwebd.h
+++ gotwebd/gotwebd.h
@@ -119,6 +119,7 @@
 
 /* Forward declaration */
 struct got_blob_object;
+struct got_tree_entry;
 
 enum imsg_type {
 	IMSG_CFG_SRV = IMSG_PROC_MAX,
@@ -469,6 +470,7 @@ int	gotweb_render_briefs(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 */
@@ -497,7 +499,8 @@ const struct got_error *got_get_repo_commits(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 (*)(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
blob + 4990d4532fe8a87678d718337343c8101501b84d
--- gotwebd/pages.tmpl
+++ gotwebd/pages.tmpl
@@ -18,20 +18,26 @@
 
 #include <sys/types.h>
 #include <sys/queue.h>
+#include <sys/stat.h>
 
 #include <ctype.h>
 #include <event.h>
 #include <stdint.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sha1.h>
 #include <imsg.h>
 
+#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 *);
@@ -453,7 +459,113 @@ gotweb_render_age(struct template *tp, time_t time, in
     <a href="#line{{ lineno }}">{{ lineno }}</a>
   </div>
   <div class="blob_code">{{ line }}</div>
+</div>
+{{ 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);
+!}
+<div id="tree_title_wrapper">
+  <div id="tree_title">Tree</div>
+</div>
+<div id="tree_content">
+  <div id="tree_header_wrapper">
+    <div id="tree_header">
+      <div id="header_tree_title">Tree:</div>
+      <div id="header_tree">{{ rc->tree_id }}</div>
+      <div class="header_age_title">Date:</div>
+      <div class="header_age">
+        {{ render gotweb_render_age(tp, rc->committer_time, TM_LONG) }}
+      </div>
+      <div id="header_commit_msg_title">Message:</div>
+      <div id="header_commit_msg">{{ rc->commit_msg }}</div>
+    </div>
+  </div>
+  <div class="dotted_line"></div>
+  <div id="tree">
+    {{ render got_output_repo_tree(c, gotweb_render_tree_item) }}
+  </div>
+</div>
+{{ 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 = "*";
+!}
+<div class="tree_wrapper">
+  {{ if S_ISDIR(mode) }}
+    <div class="tree_line">
+      <a href="{{ render gotweb_render_url(c, &url) }}">
+        {{ name }}{{ modestr }}
+      </a>
+    </div>
+    <div class="tree_line_blank">&nbsp;</div>
+  {{ else }}
+    <div class="tree_line">
+      <a href="{{ render gotweb_render_url(c, &url) }}">
+        {{ name }}{{ modestr }}
+      </a>
+    </div>
+    <div class="tree_line_blank">
+      {! url.action = COMMITS; !}
+      <a href="{{ render gotweb_render_url(c, &url) }}">
+        commits
+      </a>
+      {{ " | " }}
+      {! url.action = BLAME; !}
+      <a href="{{ render gotweb_render_url(c, &url) }}">
+        blame
+      </a>
+    </div>
+  {{ end }}
 </div>
+{{ finally }}
+{!
+	free(dir);
+!}
 {{ end }}
 
 {{ define gotweb_render_rss(struct template *tp) }}