Commit Diff


commit - b09f5680b0faed8e85a339b02c8a146926f9a61d
commit + 1cd5d437cd303d5c73dd23294496c760a641f7ca
blob - c150f18032558d56a7b6dfc278031ffebb97a57c
blob + c86f07553d7eb1c99193170a4649f32df77eedc3
--- gotwebd/got_operations.c
+++ gotwebd/got_operations.c
@@ -1027,13 +1027,6 @@ got_output_blob_by_lines(struct template *tp, struct g
 	return 0;
 }
 
-struct blame_line {
-	int annotated;
-	char *id_str;
-	char *committer;
-	char datebuf[11]; /* YYYY-MM-DD + NUL */
-};
-
 struct blame_cb_args {
 	struct blame_line *lines;
 	int nlines;
@@ -1043,6 +1036,7 @@ struct blame_cb_args {
 	FILE *f;
 	struct got_repository *repo;
 	struct request *c;
+	got_render_blame_line_cb cb;
 };
 
 static const struct got_error *
@@ -1053,14 +1047,11 @@ got_gotweb_blame_cb(void *arg, int nlines, int lineno,
 	struct blame_cb_args *a = arg;
 	struct blame_line *bline;
 	struct request *c = a->c;
-	struct transport *t = c->t;
-	struct repo_dir *repo_dir = t->repo_dir;
-	char *line = NULL, *eline = NULL;
+	char *line = NULL;
 	size_t linesize = 0;
 	off_t offset;
 	struct tm tm;
 	time_t committer_time;
-	int r;
 
 	if (nlines != a->nlines ||
 	    (lineno != -1 && lineno < 1) || lineno > a->nlines)
@@ -1105,76 +1096,26 @@ got_gotweb_blame_cb(void *arg, int nlines, int lineno,
 	}
 
 	while (a->lineno_cur <= a->nlines && bline->annotated) {
-		char *smallerthan, *at, *nl, *committer;
-		size_t len;
-
 		if (getline(&line, &linesize, a->f) == -1) {
 			if (ferror(a->f))
 				err = got_error_from_errno("getline");
 			break;
 		}
-
-		committer = bline->committer;
-		smallerthan = strchr(committer, '<');
-		if (smallerthan && smallerthan[1] != '\0')
-			committer = smallerthan + 1;
-		at = strchr(committer, '@');
-		if (at)
-			*at = '\0';
-		len = strlen(committer);
-		if (len >= 9)
-			committer[8] = '\0';
 
-		nl = strchr(line, '\n');
-		if (nl)
-			*nl = '\0';
-
-		err = gotweb_escape_html(&eline, line);
-		if (err)
-			goto done;
-
-		if (fcgi_printf(c, "<div class='blame_wrapper'>"
-		    "<div class='blame_number'>%.*d</div>"
-		    "<div class='blame_hash'>",
-		    a->nlines_prec, a->lineno_cur) == -1)
-			goto done;
-
-		r = gotweb_link(c, &(struct gotweb_url){
-			.action = DIFF,
-			.index_page = -1,
-			.page = -1,
-			.path = repo_dir->name,
-			.commit = bline->id_str,
-		    }, "%.8s", bline->id_str);
-		if (r == -1)
-			goto done;
-
-		r = fcgi_printf(c,
-		    "</div>"
-		    "<div class='blame_date'>%s</div>"
-		    "<div class='blame_author'>%s</div>"
-		    "<div class='blame_code'>%s</div>"
-		    "</div>",	/* .blame_wrapper */
-		    bline->datebuf,
-		    committer,
-		    eline);
-		if (r == -1)
-			goto done;
+		if (a->cb(c->tp, line, bline, a->nlines_prec,
+		    a->lineno_cur) == -1)
+			break;
 
 		a->lineno_cur++;
 		bline = &a->lines[a->lineno_cur - 1];
-
-		free(eline);
-		eline = NULL;
 	}
 done:
 	free(line);
-	free(eline);
 	return err;
 }
 
 const struct got_error *
-got_output_file_blame(struct request *c)
+got_output_file_blame(struct request *c, got_render_blame_line_cb cb)
 {
 	const struct got_error *error = NULL;
 	struct transport *t = c->t;
@@ -1194,6 +1135,7 @@ got_output_file_blame(struct request *c)
 	TAILQ_INIT(&refs);
 	bca.f = NULL;
 	bca.lines = NULL;
+	bca.cb = cb;
 
 	if (asprintf(&path, "%s%s%s", qs->folder ? qs->folder : "",
 	    qs->folder ? "/" : "", qs->file) == -1) {
blob - 89835b809483926295d4f94fdd520e86acc5b32e
blob + f1b36bfe4953cf0397b23423bd71b0801f678f65
--- gotwebd/gotweb.c
+++ gotwebd/gotweb.c
@@ -94,7 +94,6 @@ static const struct got_error *gotweb_get_repo_descrip
     struct server *, const char *, int);
 static const struct got_error *gotweb_get_clone_url(char **, struct server *,
     const char *, int);
-static const struct got_error *gotweb_render_blame(struct request *);
 
 static void gotweb_free_querystring(struct querystring *);
 static void gotweb_free_repo_dir(struct repo_dir *);
@@ -246,11 +245,13 @@ render:
 
 	switch(qs->action) {
 	case BLAME:
-		error = gotweb_render_blame(c);
+		error = got_get_repo_commits(c, 1);
 		if (error) {
 			log_warnx("%s: %s", __func__, error->msg);
 			goto err;
 		}
+		if (gotweb_render_blame(c->tp) == -1)
+			goto done;
 		break;
 	case BLOB:
 		if (gotweb_render_blob(c->tp, blob) == -1)
@@ -972,59 +973,6 @@ done:
 	}
 	if (d != NULL && closedir(d) == EOF && error == NULL)
 		error = got_error_from_errno("closedir");
-	return error;
-}
-
-static const struct got_error *
-gotweb_render_blame(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='blame_title_wrapper'>\n"
-	    "<div id='blame_title'>Blame</div>\n"
-	    "</div>\n"		/* #blame_title_wrapper */
-	    "<div id='blame_content'>\n"
-	    "<div id='blame_header_wrapper'>\n"
-	    "<div id='blame_header'>\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"		/* #blame_header */
-	    "</div>\n"		/* #blame_header_wrapper */
-	    "<div class='dotted_line'></div>\n"
-	    "<div id='blame'>\n",
-	    age,
-	    msg);
-	if (r == -1)
-		goto done;
-
-	error = got_output_file_blame(c);
-	if (error)
-		goto done;
-
-	fcgi_printf(c, "</div>\n"	/* #blame */
-	    "</div>\n");		/* #blame_content */
-done:
-	free(age);
-	free(msg);
 	return error;
 }
 
blob - 94bb71fb582793f9bab63b019ba12be89ea61ef1
blob + b763c41784157572b726d047cb45a220b60c30fb
--- gotwebd/gotwebd.h
+++ gotwebd/gotwebd.h
@@ -144,6 +144,13 @@ struct fcgi_record_header {
 	uint8_t		padding_len;
 	uint8_t		reserved;
 }__attribute__((__packed__));
+
+struct blame_line {
+	int		 annotated;
+	char		*id_str;
+	char		*committer;
+	char		 datebuf[11]; /* YYYY-MM-DD + NUL */
+};
 
 struct repo_dir {
 	char			*name;
@@ -433,6 +440,9 @@ enum gotweb_ref_tm {
 
 extern struct gotwebd	*gotwebd_env;
 
+typedef int (*got_render_blame_line_cb)(struct template *, const char *,
+    struct blame_line *, int, int);
+
 /* sockets.c */
 void sockets(struct privsep *, struct privsep_proc *);
 void sockets_shutdown(void);
@@ -477,6 +487,7 @@ int	gotweb_render_tag(struct template *);
 int	gotweb_render_diff(struct template *, FILE *);
 int	gotweb_render_branches(struct template *, struct got_reflist_head *);
 int	gotweb_render_summary(struct template *, struct got_reflist_head *);
+int	gotweb_render_blame(struct template *);
 int	gotweb_render_rss(struct template *);
 
 /* parse.y */
@@ -514,7 +525,8 @@ const struct got_error *got_open_blob_for_output(struc
 const struct got_error *got_output_file_blob(struct request *);
 int got_output_blob_by_lines(struct template *, struct got_blob_object *,
     int (*)(struct template *, const char *, size_t));
-const struct got_error *got_output_file_blame(struct request *);
+const struct got_error *got_output_file_blame(struct request *,
+    got_render_blame_line_cb);
 
 /* config.c */
 int config_setserver(struct gotwebd *, struct server *);
blob - dc3656edae244fbc586f81ad359f6b9ca8c8085d
blob + 87784038ab934f1448d0562b439b954d3e2e2348
--- gotwebd/pages.tmpl
+++ gotwebd/pages.tmpl
@@ -39,6 +39,8 @@
 
 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 int blame_line(struct template *, const char *, struct blame_line *,
+    int, int);
 
 static inline int diff_line(struct template *, char *);
 static inline int tag_item(struct template *, struct repo_tag *);
@@ -869,6 +871,77 @@ gotweb_render_age(struct template *tp, time_t time, in
 {{ render gotweb_render_branches(tp, refs) }}
 {{ end }}
 
+{{ define gotweb_render_blame(struct template *tp) }}
+{!
+	const struct got_error	*err;
+	struct request		*c = tp->tp_arg;
+	struct transport	*t = c->t;
+	struct repo_commit	*rc = TAILQ_FIRST(&t->repo_commits);
+!}
+<div id="blame_title_wrapper">
+  <div id="blame_title">Blame</div>
+</div>
+<div id="blame_content">
+  <div id="blame_header_wrapper">
+    <div id="blame_header">
+      <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="blame">
+    {{ "\n" }}
+    {!
+	err = got_output_file_blame(c, &blame_line);
+	if (err) {
+		log_warnx("%s: got_output_file_blame: %s", __func__,
+		    err->msg);
+		return (-1);
+	}
+    !}
+  </div>
+</div>
+{{ end }}
+
+{{ define blame_line(struct template *tp, const char *line,
+    struct blame_line *bline, int lprec, int lcur) }}
+{!
+	struct request		*c = tp->tp_arg;
+	struct transport	*t = c->t;
+	struct repo_dir		*repo_dir = t->repo_dir;
+	char			*committer, *s;
+	struct gotweb_url	 url = {
+		.action = DIFF,
+		.index_page = -1,
+		.page = -1,
+		.path = repo_dir->name,
+		.commit = bline->id_str,
+	};
+
+	s = strchr(bline->committer, '<');
+	committer = s ? s + 1 : bline->committer;
+
+	s = strchr(committer, '@');
+	if (s)
+		*s = '\0';
+!}
+<div class="blame_wrapper">
+  <div class="blame_number">{{ printf "%.*d", lprec, lcur }}</div>
+  <div class="blame_hash">
+    <a href="{{ render gotweb_render_url(c, &url) }}">
+      {{ printf "%.8s", bline->id_str }}
+    </a>
+  </div>
+  <div class="blame_date">{{ bline->datebuf }}</div>
+  <div class="blame_author">{{ printf "%.9s", committer }}</div>
+  <div class="blame_code">{{ line }}</div>
+</div>
+{{ end }}
+
 {{ define gotweb_render_rss(struct template *tp) }}
 {!
 	struct request		*c = tp->tp_arg;