stagit

static git page generator  https://git.ce9e.org
git clone https://git.ce9e.org/stagit.git

commit
ef7acbd601b5f200c7cab6c4a218c3f45664ea4f
parent
976716284746fd7f485dcf0139828983f133121c
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2020-03-30 19:52
convert to T macro

Diffstat

M Makefile 5 ++++-
A ctpl.py 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
R stagit.c -> stagit.c.in 277 ++++++++++++++++++++++++++-----------------------------------

3 files changed, 184 insertions, 161 deletions


diff --git a/Makefile b/Makefile

@@ -35,6 +35,9 @@ HDR = compat.h config.h
   35    35 COMPATOBJ = \
   36    36 	strlcpy.o
   37    37 
   -1    38 %.c: %.c.in ctpl.py
   -1    39 	python ctpl.py $< > $@
   -1    40 
   38    41 OBJ = ${SRC:.c=.o} ${COMPATOBJ}
   39    42 
   40    43 all: ${BIN}
@@ -63,7 +66,7 @@ stagit: stagit.o ${COMPATOBJ}
   63    66 	${CC} -o $@ stagit.o ${COMPATOBJ} ${STAGIT_LDFLAGS}
   64    67 
   65    68 clean:
   66    -1 	rm -f ${BIN} ${OBJ} ${NAME}-${VERSION}.tar.gz
   -1    69 	rm -f ${BIN} ${OBJ} ${NAME}-${VERSION}.tar.gz stagit.c
   67    70 
   68    71 install: all
   69    72 	# installing executable files.

diff --git a/ctpl.py b/ctpl.py

@@ -0,0 +1,63 @@
   -1     1 import sys
   -1     2 import re
   -1     3 
   -1     4 
   -1     5 def tokenize(s):
   -1     6 	tokens = []
   -1     7 	start = 0
   -1     8 	for i, c in enumerate(s):
   -1     9 		if c == '{':
   -1    10 			if i > start:
   -1    11 				tokens.append((True, s[start:i]))
   -1    12 			start = i + 1
   -1    13 		elif c == '}':
   -1    14 			if i > start:
   -1    15 				tokens.append((False, s[start:i]))
   -1    16 			start = i + 1
   -1    17 	if i + 1 > start:
   -1    18 		tokens.append((True, s[start:i+1]))
   -1    19 	return tokens
   -1    20 
   -1    21 
   -1    22 def print_safe(s, args, indent):
   -1    23 	if args:
   -1    24 		print(indent + 'fprintf(fp, "%s", %s);' % (s, ', '.join(args)))
   -1    25 	elif s:
   -1    26 		print(indent + 'fputs("%s", fp);' % s)
   -1    27 
   -1    28 
   -1    29 def parse_line(indent, tpl):
   -1    30 	s = ''
   -1    31 	args = []
   -1    32 	for is_text, token in tokenize(tpl):
   -1    33 		if is_text:
   -1    34 			s += token
   -1    35 		elif ':%' in token:
   -1    36 			arg, placeholder = token.split(':', 1)
   -1    37 			s += placeholder
   -1    38 			args.append(arg)
   -1    39 		else:
   -1    40 			print_safe(s, args, indent)
   -1    41 			s = ''
   -1    42 			args = []
   -1    43 
   -1    44 			if ':' in token:
   -1    45 				arg, l = token.split(':', 1)
   -1    46 			else:
   -1    47 				arg = token
   -1    48 				l = 'strlen(%s)' % token
   -1    49 
   -1    50 			print(indent + 'xmlencode(fp, %s, %s);' % (arg, l))
   -1    51 
   -1    52 	print_safe(s, args, indent)
   -1    53 
   -1    54 
   -1    55 if __name__ == '__main__':
   -1    56 	fh = open(sys.argv[1])
   -1    57 
   -1    58 	for line in fh:
   -1    59 		match = re.match(r'(\s*)T\("(.*)"\);\n$', line)
   -1    60 		if match:
   -1    61 			parse_line(*match.groups())
   -1    62 		else:
   -1    63 			print(line.rstrip())

diff --git a/stagit.c b/stagit.c.in

@@ -21,6 +21,8 @@
   21    21 #include "compat.h"
   22    22 #include "config.h"
   23    23 
   -1    24 #define T(S) (fputs((S), fp))
   -1    25 
   24    26 struct deltainfo {
   25    27 	git_patch *patch;
   26    28 
@@ -313,61 +315,50 @@ printtimeshort(FILE *fp, const git_time *intime)
  313   315 void
  314   316 write_header(FILE *fp, const char *title, const char *relpath)
  315   317 {
  316    -1 	fputs("<!DOCTYPE html>\n", fp);
  317    -1 	fputs("<html>\n", fp);
  318    -1 	fputs("<head>\n", fp);
  319    -1 	fputs("<meta charset=\"UTF-8\"><title>", fp);
  320    -1 	xmlencode(fp, title, strlen(title));
   -1   318 	T("<!DOCTYPE html>\n");
   -1   319 	T("<html>\n");
   -1   320 	T("<head>\n");
   -1   321 	T("<meta charset=\"UTF-8\"><title>");
   -1   322 	T("{title}");
  321   323 	if (title[0] && reponame[0])
  322    -1 		fputs(" - ", fp);
  323    -1 	xmlencode(fp, reponame, strlen(reponame));
   -1   324 		T(" - ");
   -1   325 	T("{reponame}");
  324   326 	if (description[0]) {
  325    -1 		fputs(": ", fp);
  326    -1 		xmlencode(fp, description, strlen(description));
   -1   327 		T(": {description}");
  327   328 	}
  328    -1 	fputs("</title>\n", fp);
   -1   329 	T("</title>\n");
  329   330 	if (favicon[0])
  330    -1 		fprintf(fp, "<link rel=\"icon\" type=\"image/png\" href=\"%s\" />\n", favicon);
  331    -1 	fputs("<link rel=\"alternate\" type=\"application/atom+xml\" title=\"", fp);
  332    -1 	xmlencode(fp, reponame, strlen(reponame));
  333    -1 	fprintf(fp, " Atom Feed\" href=\"%satom.xml\" />\n", relpath);
   -1   331 		T("<link rel=\"icon\" type=\"image/png\" href=\"{favicon:%s}\" />\n");
   -1   332 	T("<link rel=\"alternate\" type=\"application/atom+xml\" title=\"{reponame} Atom Feed\" href=\"{relpath:%s}atom.xml\" />\n");
  334   333 	if (stylesheet[0])
  335    -1 		fprintf(fp, "<link rel=\"stylesheet\" type=\"text/css\" href=\"%s\" />\n", stylesheet);
  336    -1 	fputs("</head>\n", fp);
  337    -1 	fputs("<body>\n", fp);
  338    -1 	fputs("<header>\n", fp);
   -1   334 		T("<link rel=\"stylesheet\" type=\"text/css\" href=\"{stylesheet:%s}\" />\n");
   -1   335 	T("</head>\n");
   -1   336 	T("<body>\n");
   -1   337 	T("<header>\n");
  339   338 	if (logo[0])
  340    -1 		fprintf(fp, "<a href=\"%s..\"><img src=\"%s\" alt=\"\" width=\"32\" height=\"32\" /></a>",
  341    -1 			relpath, logo);
  342    -1 	fputs("<div>\n", fp);
  343    -1 	fputs("<h1>", fp);
  344    -1 	xmlencode(fp, reponame, strlen(reponame));
  345    -1 	fputs("</h1>\n", fp);
   -1   339 		T("<a href=\"{relpath:%s}..\"><img src=\"{logo:%s}\" alt=\"\" width=\"32\" height=\"32\" /></a>");
   -1   340 	T("<div>\n");
   -1   341 	T("<h1>{reponame}</h1>");
  346   342 	if (description[0]) {
  347    -1 		fputs("<div class=\"desc\">", fp);
  348    -1 		xmlencode(fp, description, strlen(description));
  349    -1 		fputs("</div>", fp);
   -1   343 		T("<div class=\"desc\">{description}</div>");
  350   344 	}
  351   345 	if (cloneurl[0]) {
  352    -1 		fputs("<div class=\"cloneurl\">git clone ", fp);
  353    -1 		xmlencode(fp, cloneurl, strlen(cloneurl));
  354    -1 		xmlencode(fp, reponame, strlen(reponame));
  355    -1 		fputs("</div>\n", fp);
   -1   346 		T("<div class=\"cloneurl\">git clone {cloneurl}{reponame}</div>\n");
  356   347 	}
  357    -1 	fputs("<nav>\n", fp);
  358    -1 	fprintf(fp, "<a href=\"%s.\">Files</a> |\n", relpath);
  359    -1 	fprintf(fp, "<a href=\"%slog.html\">Log</a>\n", relpath);
  360    -1 	fputs("</nav>\n", fp);
  361    -1 	fputs("</div>\n", fp);
  362    -1 	fputs("</header>\n", fp);
  363    -1 	fputs("<hr/>\n", fp);
  364    -1 	fputs("<main id=\"content\">\n", fp);
   -1   348 	T("<nav>\n");
   -1   349 	T("<a href=\"{relpath:%s}.\">Files</a> |\n");
   -1   350 	T("<a href=\"{relpath:%s}log.html\">Log</a>\n");
   -1   351 	T("</nav>\n");
   -1   352 	T("</div>\n");
   -1   353 	T("</header>\n");
   -1   354 	T("<hr/>\n");
   -1   355 	T("<main id=\"content\">\n");
  365   356 }
  366   357 
  367   358 void
  368   359 write_footer(FILE *fp)
  369   360 {
  370    -1 	fputs("</main>\n</body>\n</html>\n", fp);
   -1   361 	T("</main>\n</body>\n</html>\n");
  371   362 }
  372   363 
  373   364 void
@@ -378,14 +369,14 @@ write_readme(FILE *fp, const git_blob *blob)
  378   369 
  379   370 #ifdef CMARK
  380   371 	char *rendered = cmark_markdown_to_html(raw, len, CMARK_OPT_SAFE);
  381    -1 	fputs("<div id=\"readme\">\n", fp);
   -1   372 	T("<div id=\"readme\">\n");
  382   373 	fputs(rendered, fp);
  383    -1 	fputs("</div>\n", fp);
   -1   374 	T("</div>\n");
  384   375 	free(rendered);
  385   376 #else
  386    -1 	fputs("<pre id=\"readme\">\n", fp);
   -1   377 	T("<pre id=\"readme\">\n");
  387   378 	fwrite(raw, 1, len, fp);
  388    -1 	fputs("</pre>\n", fp);
   -1   379 	T("</pre>\n");
  389   380 #endif
  390   381 }
  391   382 
@@ -409,26 +400,25 @@ write_commit_statline(FILE *fp, struct deltainfo *di, size_t i)
  409   400 	default:                   c = ' '; break;
  410   401 	}
  411   402 
  412    -1 	fputs("<tr>\n", fp);
  413    -1 	fprintf(fp, "<td class=\"%c\">%c</td>\n", c, c);
  414    -1 	fprintf(fp, "<td><a href=\"#h%zu\">", i);
  415    -1 	xmlencode(fp, delta->old_file.path, strlen(delta->old_file.path));
   -1   403 	T("<tr>\n");
   -1   404 	T("<td class=\"{c:%c}\">{c:%c}</td>\n");
   -1   405 	T("<td><a href=\"#h{i:%zu}\">");
   -1   406 	T("{delta->old_file.path}");
  416   407 	if (strcmp(delta->old_file.path, delta->new_file.path)) {
  417    -1 		fputs(" -&gt; ", fp);
  418    -1 		xmlencode(fp, delta->new_file.path, strlen(delta->new_file.path));
   -1   408 		T(" -&gt; {delta->new_file.path}");
  419   409 	}
  420    -1 	fputs("</a></td>\n", fp);
   -1   410 	T("</a></td>\n");
  421   411 
  422   412 	total = di->addcount + di->delcount;
  423    -1 	fprintf(fp, "<td class=\"num\">%i</td>\n", total);
  424    -1 	fputs("<td><span class=\"i\">", fp);
   -1   413 	T("<td class=\"num\">{total:%i}</td>\n");
   -1   414 	T("<td><span class=\"i\">");
  425   415 	for (j = 0; j < di->addcount && j * total < di->addcount * 60; j++)
  426   416 		fputc('+', fp);
  427    -1 	fputs("</span><span class=\"d\">", fp);
   -1   417 	T("</span><span class=\"d\">");
  428   418 	for (j = 0; j < di->delcount && j * total < di->delcount * 60; j++)
  429   419 		fputc('-', fp);
  430   420 
  431    -1 	fputs("</tr>\n", fp);
   -1   421 	T("</tr>\n");
  432   422 }
  433   423 
  434   424 void
@@ -443,47 +433,38 @@ write_commit_file(FILE *fp, struct deltainfo *di, size_t i)
  443   433 	delta = git_patch_get_delta(di->patch);
  444   434 	nhunks = git_patch_num_hunks(di->patch);
  445   435 
  446    -1 	fprintf(fp, "<h2 id=\"h%zu\">\n", i);
  447    -1 	fputs("diff --git\n", fp);
  448    -1 	fprintf(fp, "a/<a href=\"../blob/");
  449    -1 	xmlencode(fp, delta->old_file.path, strlen(delta->old_file.path));
  450    -1 	fputs("\">", fp);
  451    -1 	xmlencode(fp, delta->old_file.path, strlen(delta->old_file.path));
  452    -1 	fputs("</a>\n", fp);
  453    -1 	fprintf(fp, "b/<a href=\"../blob/");
  454    -1 	xmlencode(fp, delta->new_file.path, strlen(delta->new_file.path));
  455    -1 	fputs("\">", fp);
  456    -1 	xmlencode(fp, delta->new_file.path, strlen(delta->new_file.path));
  457    -1 	fputs("</a>\n", fp);
  458    -1 	fputs("</h2>\n", fp);
   -1   436 	T("<h2 id=\"h{i:%zu}\">\n");
   -1   437 	T("diff --git\n");
   -1   438 	T("a/<a href=\"../blob/{delta->old_file.path}\">{delta->old_file.path}</a>\n");
   -1   439 	T("b/<a href=\"../blob/{delta->new_file.path}\">{delta->new_file.path}</a>\n");
   -1   440 	T("</h2>\n");
  459   441 
  460   442 	if (delta->flags & GIT_DIFF_FLAG_BINARY) {
  461    -1 		fputs("Binary files differ.\n", fp);
   -1   443 		T("Binary files differ.\n");
  462   444 		return;
  463   445 	}
  464   446 
  465   447 	if (nhunks == 0)
  466   448 		return;
  467   449 
  468    -1 	fputs("<pre class=\"diff\">\n", fp);
   -1   450 	T("<pre class=\"diff\">\n");
  469   451 	for (j = 0; j < nhunks; j++) {
  470   452 		if (git_patch_get_hunk(&hunk, &nhunklines, di->patch, j))
  471   453 			break;
  472    -1 		fprintf(fp, "<a href=\"#h%zu-%zu\" id=\"h%zu-%zu\" class=\"h\">", i, j, i, j);
  473    -1 		xmlencode(fp, hunk->header, hunk->header_len - 1);
  474    -1 		fputs("</a>\n", fp);
   -1   454 		T("<a href=\"#h{i:%zu}-{j:%zu}\" id=\"h{i:%zu}-{j:%zu}\" class=\"h\">");
   -1   455 		T("{hunk->header:hunk->header_len - 1}");
   -1   456 		T("</a>\n");
  475   457 		for (k = 0; k < nhunklines; k++) {
  476   458 			if (git_patch_get_line_in_hunk(&line, di->patch, j, k))
  477   459 				break;
  478   460 			tag = line->old_lineno == -1 ? "ins" : line->new_lineno == -1 ? "del" : "span";
  479    -1 			fprintf(fp, "<%s class=\"line\" id=\"h%zu-%zu-%zu\">", tag, i, j, k);
  480    -1 			fprintf(fp, "<a href=\"#h%zu-%zu-%zu\" tabindex=\"-1\">%5i %5i</a> ",
  481    -1 				i, j, k, line->old_lineno, line->new_lineno);
  482    -1 			xmlencode(fp, line->content, line->content_len - 1);
  483    -1 			fprintf(fp, "</%s>\n", tag);
   -1   461 			T("<{tag:%s} class=\"line\" id=\"h{i:%zu}-{j:%zu}-{k:%zu}\">");
   -1   462 			T("<a href=\"#h{i:%zu}-{j:%zu}-{k:%zu}\" tabindex=\"-1\">{line->old_lineno:%5i} {line->new_lineno:%5i}</a> ");
   -1   463 			T("{line->content:line->content_len - 1}");
   -1   464 			T("</{tag:%s}>\n");
  484   465 		}
  485   466 	}
  486    -1 	fputs("</pre>\n", fp);
   -1   467 	T("</pre>\n");
  487   468 }
  488   469 
  489   470 void
@@ -492,27 +473,20 @@ write_commit(FILE *fp, struct commitinfo *ci)
  492   473 	size_t i;
  493   474 	struct commitstats *cs = commitinfo_getstats(ci);
  494   475 
  495    -1 	fputs("<dl>\n", fp);
  496    -1 	fprintf(fp, "<dt>commit</dt><dd><a href=\"\">%s</a></dd>\n", ci->oid);
   -1   476 	T("<dl>\n");
   -1   477 	T("<dt>commit</dt><dd><a href=\"\">{ci->oid:%s}</a></dd>\n");
  497   478 	if (ci->parentoid[0])
  498    -1 		fprintf(fp, "<dt>parent</dt><dd><a href=\"%s.html\">%s</a></dd>\n",
  499    -1 			ci->parentoid, ci->parentoid);
   -1   479 		T("<dt>parent</dt><dd><a href=\"{ci->parentoid:%s}.html\">{ci->parentoid:%s}</a></dd>\n");
  500   480 	if (ci->author) {
  501    -1 		fputs("<dt>Author</dt><dd>", fp);
  502    -1 		xmlencode(fp, ci->author->name, strlen(ci->author->name));
  503    -1 		fputs(" &lt;<a href=\"mailto:", fp);
  504    -1 		xmlencode(fp, ci->author->email, strlen(ci->author->email));
  505    -1 		fputs("\">", fp);
  506    -1 		xmlencode(fp, ci->author->email, strlen(ci->author->email));
  507    -1 		fputs("</a>&gt;</dd>\n<dt>Date</dt><dd>", fp);
   -1   481 		T("<dt>Author</dt><dd>{ci->author->name} ");
   -1   482 		T("&lt;<a href=\"mailto:{ci->author->email}\">{ci->author->email}</a>&gt;");
   -1   483 		T("</dd>\n<dt>Date</dt><dd>");
  508   484 		printtimeshort(fp, &(ci->author->when));
  509    -1 		fputs("</dd>\n", fp);
   -1   485 		T("</dd>\n");
  510   486 	}
  511    -1 	fputs("</dl>\n", fp);
   -1   487 	T("</dl>\n");
  512   488 	if (ci->msg) {
  513    -1 		fputs("<pre>", fp);
  514    -1 		xmlencode(fp, ci->msg, strlen(ci->msg));
  515    -1 		fputs("</pre>\n", fp);
   -1   489 		T("<pre>{ci->msg}</pre>\n");
  516   490 	}
  517   491 
  518   492 	if (!cs->deltas)
@@ -523,25 +497,22 @@ write_commit(FILE *fp, struct commitinfo *ci)
  523   497 			cs->addcount > 100000 ||
  524   498 			cs->delcount > 100000
  525   499 		) {
  526    -1 		fputs("Diff is too large, output suppressed.\n", fp);
   -1   500 		T("Diff is too large, output suppressed.\n");
  527   501 		goto err;
  528   502 	}
  529   503 
  530    -1 	fputs("<h2>Diffstat</h2>\n", fp);
  531    -1 	fputs("<table>\n", fp);
   -1   504 	T("<h2>Diffstat</h2>\n");
   -1   505 	T("<table>\n");
  532   506 
  533   507 	for (i = 0; i < cs->ndeltas; i++) {
  534   508 		write_commit_statline(fp, cs->deltas[i], i);
  535   509 	}
  536   510 
  537    -1 	fputs("</table>\n", fp);
  538    -1 	fputs("<p>", fp);
  539    -1 	fprintf(fp, "<p>%zu file%s changed, %zu insertion%s, %zu deletion%s</p>\n",
  540    -1 		cs->ndeltas, cs->ndeltas == 1 ? "" : "s",
  541    -1 		cs->addcount, cs->addcount  == 1 ? "" : "s",
  542    -1 		cs->delcount, cs->delcount  == 1 ? "" : "s");
  543    -1 	fputs("</p>\n", fp);
  544    -1 	fputs("<hr/>\n", fp);
   -1   511 	T("</table>\n");
   -1   512 	T("<p>");
   -1   513 	T("<p>{cs->ndeltas:%zu} files changed, {cs->addcount:%zu} insertions, {cs->delcount:%zu} deletions</p>\n");
   -1   514 	T("</p>\n");
   -1   515 	T("<hr/>\n");
  545   516 
  546   517 	for (i = 0; i < cs->ndeltas; i++) {
  547   518 		write_commit_file(fp, cs->deltas[i], i);
@@ -554,93 +525,84 @@ err:
  554   525 void
  555   526 write_log_header(FILE *fp)
  556   527 {
  557    -1 	fputs("<table id=\"log\">\n", fp);
  558    -1 	fputs("<thead>\n", fp);
  559    -1 	fputs("<tr><th>Date</th><th class=\"text\">Commit message</th><th>Author</th></tr>\n", fp);
  560    -1 	fputs("</thead>\n", fp);
  561    -1 	fputs("<tbody>\n", fp);
   -1   528 	T("<table id=\"log\">\n");
   -1   529 	T("<thead>\n");
   -1   530 	T("<tr><th>Date</th><th class=\"text\">Commit message</th><th>Author</th></tr>\n");
   -1   531 	T("</thead>\n");
   -1   532 	T("<tbody>\n");
  562   533 }
  563   534 
  564   535 void
  565   536 write_log_line(FILE *fp, struct commitinfo *ci)
  566   537 {
  567    -1 	fputs("<tr><td>", fp);
   -1   538 	T("<tr><td>");
  568   539 	if (ci->author) {
  569    -1 		fprintf(fp, "<a href=\"commit/%s.html\">", ci->oid);
   -1   540 		T("<a href=\"commit/{ci->oid:%s}.html\">");
  570   541 		printtimeshort(fp, &(ci->author->when));
  571    -1 		fputs("</a>", fp);
   -1   542 		T("</a>");
  572   543 	}
  573    -1 	fputs("</td><td class=\"text\">", fp);
   -1   544 	T("</td><td class=\"text\">");
  574   545 	if (ci->summary)
  575    -1 		xmlencode(fp, ci->summary, strlen(ci->summary));
  576    -1 	fputs("</td><td>", fp);
   -1   546 		T("{ci->summary}");
   -1   547 	T("</td><td>");
  577   548 	if (ci->author)
  578    -1 		xmlencode(fp, ci->author->name, strlen(ci->author->name));
  579    -1 	fputs("</td></tr>\n", fp);
   -1   549 		T("{ci->author->name}");
   -1   550 	T("</td></tr>\n");
  580   551 }
  581   552 
  582   553 void
  583   554 write_log_footer(FILE *fp)
  584   555 {
  585    -1 	fputs("</tbody>\n", fp);
  586    -1 	fputs("</table>\n", fp);
   -1   556 	T("</tbody>\n</table>\n");
  587   557 }
  588   558 
  589   559 void
  590   560 write_atom_header(FILE *fp)
  591   561 {
  592    -1 	fputs("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", fp);
  593    -1 	fputs("<feed xmlns=\"http://www.w3.org/2005/Atom\">\n", fp);
  594    -1 	fputs("<title>", fp);
  595    -1 	xmlencode(fp, reponame, strlen(reponame));
  596    -1 	fputs(", branch HEAD</title>\n<subtitle>", fp);
  597    -1 	xmlencode(fp, description, strlen(description));
  598    -1 	fputs("</subtitle>\n", fp);
   -1   562 	T("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
   -1   563 	T("<feed xmlns=\"http://www.w3.org/2005/Atom\">\n");
   -1   564 	T("<title>{reponame}, branch HEAD</title>\n");
   -1   565 	T("<subtitle>{description}</subtitle>\n");
  599   566 }
  600   567 
  601   568 void
  602   569 write_atom_entry(FILE *fp, struct commitinfo *ci)
  603   570 {
  604    -1 	fputs("<entry>\n", fp);
   -1   571 	T("<entry>\n");
  605   572 
  606    -1 	fprintf(fp, "<id>%s</id>\n", ci->oid);
   -1   573 	T("<id>{ci->oid:%s}</id>\n");
  607   574 	if (ci->author) {
  608    -1 		fputs("<published>", fp);
   -1   575 		T("<published>");
  609   576 		printtimez(fp, &(ci->author->when));
  610    -1 		fputs("</published>\n", fp);
   -1   577 		T("</published>\n");
  611   578 	}
  612   579 	if (ci->committer) {
  613    -1 		fputs("<updated>", fp);
   -1   580 		T("<updated>");
  614   581 		printtimez(fp, &(ci->committer->when));
  615    -1 		fputs("</updated>\n", fp);
   -1   582 		T("</updated>\n");
  616   583 	}
  617   584 	if (ci->summary) {
  618    -1 		fputs("<title type=\"text\">", fp);
  619    -1 		xmlencode(fp, ci->summary, strlen(ci->summary));
  620    -1 		fputs("</title>\n", fp);
   -1   585 		T("<title type=\"text\">{ci->summary}</title>\n");
  621   586 	}
  622    -1 	fprintf(fp, "<link rel=\"alternate\" type=\"text/html\" href=\"commit/%s.html\" />\n", ci->oid);
   -1   587 	T("<link rel=\"alternate\" type=\"text/html\" href=\"commit/{ci->oid:%s}.html\" />\n");
  623   588 
  624   589 	if (ci->author) {
  625    -1 		fputs("<author>\n<name>", fp);
  626    -1 		xmlencode(fp, ci->author->name, strlen(ci->author->name));
  627    -1 		fputs("</name>\n<email>", fp);
  628    -1 		xmlencode(fp, ci->author->email, strlen(ci->author->email));
  629    -1 		fputs("</email>\n</author>\n", fp);
   -1   590 		T("<author>\n");
   -1   591 		T("<name>{ci->author->name}</name>\n");
   -1   592 		T("<email>{ci->author->email}</email>\n");
   -1   593 		T("</author>\n");
  630   594 	}
  631   595 
  632   596 	if (ci->msg) {
  633    -1 		fputs("<content type=\"text\">\n", fp);
  634    -1 		xmlencode(fp, ci->msg, strlen(ci->msg));
  635    -1 		fputs("\n</content>\n", fp);
   -1   597 		T("<content type=\"text\">{ci->msg}</content>\n");
  636   598 	}
  637    -1 	fputs("</entry>\n", fp);
   -1   599 	T("</entry>\n");
  638   600 }
  639   601 
  640   602 void
  641   603 write_atom_footer(FILE *fp)
  642   604 {
  643    -1 	fputs("</feed>\n", fp);
   -1   605 	T("</feed>\n");
  644   606 }
  645   607 
  646   608 void
@@ -670,28 +632,23 @@ copy_blob(git_object *obj, const char *fpath)
  670   632 void
  671   633 write_files_header(FILE *fp)
  672   634 {
  673    -1 	fputs("<table id=\"files\">\n", fp);
  674    -1 	fputs("<thead>\n", fp);
  675    -1 	fputs("<tr><th>Name</th><th class=\"num\">Size</th></tr>\n", fp);
  676    -1 	fputs("</thead>\n", fp);
  677    -1 	fputs("<tbody>\n", fp);
   -1   635 	T("<table id=\"files\">\n");
   -1   636 	T("<thead>\n");
   -1   637 	T("<tr><th>Name</th><th class=\"num\">Size</th></tr>\n");
   -1   638 	T("</thead>\n");
   -1   639 	T("<tbody>\n");
  678   640 }
  679   641 
  680   642 void
  681   643 write_files_line(FILE *fp, char *entrypath, char *filepath, uintmax_t size)
  682   644 {
  683    -1 	fputs("<tr><td><a href=\"", fp);
  684    -1 	xmlencode(fp, filepath, strlen(filepath));
  685    -1 	fputs("\">", fp);
  686    -1 	xmlencode(fp, entrypath, strlen(entrypath));
  687    -1 	fprintf(fp, "</a></td><td class=\"num\">%juB</td></tr>\n", size);
   -1   645 	T("<tr><td><a href=\"{filepath}\">{entrypath}</a></td><td class=\"num\">{size:%ju}B</td></tr>\n");
  688   646 }
  689   647 
  690   648 void
  691   649 write_files_footer(FILE *fp)
  692   650 {
  693    -1 	fputs("</tbody>\n", fp);
  694    -1 	fputs("</table>\n", fp);
   -1   651 	T("</tbody>\n</table>\n");
  695   652 }
  696   653 
  697   654 void