ctucx.git: stagit

ctucx' stagit fork

commit 415e3fdd55b2ecdf2f35680694362a4b35fd1a05
parent bda4633633a0701bbd2f7861674a8e612d961fb7
Author: Hiltjo Posthuma <hiltjo@codemadness.org>
Date: Sat, 5 Dec 2015 20:22:57 +0100

rewrite in C with libgit2, first version
2 files changed, 222 insertions(+), 135 deletions(-)
D
urmoms
|
135
-------------------------------------------------------------------------------
A
urmoms.c
|
222
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/urmoms b/urmoms
@@ -1,135 +0,0 @@
-#!/bin/sh
-
-# DEBUG
-#set -e -x
-
-usage() {
-	printf '%s <repodir> <htmldir>\n' "$0"
-	exit 1
-}
-
-header() {
-	cat <<!__EOF__
-<!DOCTYPE HTML>
-<html dir="ltr" lang="en">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
-<meta http-equiv="Content-Language" content="en" />
-<title>${name} - ${description}</title>
-<link rel="stylesheet" type="text/css" href="style.css" />
-</head>
-<body>
-<center>
-<h1><img src="${relpath}logo.png" alt="" /> ${name}</h1>
-<span class="desc">${description}</span><br/>
-<a href="${relpath}log.html">Log</a> |
-<a href="${relpath}files.html">Files</a> |
-<a href="${relpath}stats.html">Stats</a> |
-<a href="${relpath}readme.html">README</a> |
-<a href="${relpath}license.html">LICENSE</a>
-</center>
-<hr/>
-<pre>
-!__EOF__
-}
-
-footer() {
-	cat <<!__EOF__
-</pre>
-</body>
-</html>
-!__EOF__
-}
-
-# usage: repodir and htmldir must be set.
-if test x"$1" = x"" || test x"$2" = x""; then
-	usage
-fi
-
-# make absolute path to htmldir.
-htmldir="$(readlink -f $2)"
-mkdir -p "${htmldir}"
-
-# repodir must be a directory to go to.
-cd "$1" || usage
-
-# default index page (symlink).
-indexpage="log.html"
-
-# project name, if bare repo remove .git suffix.
-name=$(basename "$(pwd)" ".git")
-
-# read .git/description.
-description=""
-test -f ".git/description" && description="$(cat '.git/description')"
-
-# make diff for each commit (all files).
-relpath="../"
-mkdir -p "${htmldir}/commit"
-git log --pretty='%H' | while read -r commit; do
-	test -e "${htmldir}/commit/${commit}.html" && continue
-
-	header > "${htmldir}/commit/${commit}.html"
-	git show --pretty=full "${commit}" | \
-		sed -E 's@^commit (.*)$@commit <a href="'${relpath}'commit/\1.html">\1</a>@g' >> "${htmldir}/commit/${commit}.html"
-	footer >> "${htmldir}/commit/${commit}.html"
-done 
-
-# make log with all commits.
-relpath=""
-header > "${htmldir}/log.html"
-printf '<table border="0">' >> "${htmldir}/log.html"
-git log --pretty='<tr><td align="right">%cr</td><td><a href="'${relpath}'commit/%H.html">%H</a></td><td>%an</td><td>%s</td></tr>' >> "${htmldir}/log.html"
-printf '</table>' >> "${htmldir}/log.html"
-footer >> "${htmldir}/log.html"
-
-# make index with file links.
-relpath=""
-header >> "${htmldir}/files.html"
-printf '<table><tr><td><b>Mode</b></td><td><b>Name</b></td><td><b>Size</b></td><td></td></tr>' >> "${htmldir}/files.html"
-git ls-tree -r -l master | while read -r mode type object size file; do
-	git log -1 --pretty='<tr><td>'${mode}'</td><td><a href="'${relpath}'commit/%H.html#file-'${file}'">'${file}'</a></td><td>'${size}'</td><td><a href="file/'${file}'">[plain]</a></td></tr>' "${file}"
-done >> "${htmldir}/files.html"
-printf '</table>' >> "${htmldir}/files.html"
-footer >> "${htmldir}/files.html"
-
-# readme page
-# find README file.
-relpath=""
-readme=""
-for f in README README.md readme.md; do
-	test -e "${f}" && readme="${f}"
-done
-# make page.
-header > "${htmldir}/readme.html"
-if test x"${readme}" != x""; then
-	cat "${readme}" >> "${htmldir}/readme.html"
-else
-	echo "no README file found" >> "${htmldir}/readme.html"
-fi
-footer >> "${htmldir}/readme.html"
-
-# license page
-# find LICENSE file.
-relpath=""
-license=""
-for f in LICENSE LICENSE.md; do
-	test -e "${f}" && license="${f}"
-done
-# make page.
-header > "${htmldir}/license.html"
-if test x"${readme}" != x""; then
-	cat "${license}" >> "${htmldir}/license.html"
-else
-	echo "unknown license" >> "${htmldir}/license.html"
-fi
-footer >> "${htmldir}/license.html"
-
-# stats (authors).
-relpath=""
-header > "${htmldir}/stats.html"
-git shortlog -n -s >> "${htmldir}/stats.html"
-footer >> "${htmldir}/stats.html"
-
-# symlink to index page.
-ln -sf "$indexpage" "${htmldir}/index.html"
diff --git a/urmoms.c b/urmoms.c
@@ -0,0 +1,222 @@
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "git2.h"
+
+static const char *relpath = "";
+static const char *name = "";
+static const char *description = "";
+
+static const char *repodir = ".";
+
+static git_repository *repo;
+
+FILE *
+efopen(const char *name, const char *flags)
+{
+	FILE *fp;
+
+	fp = fopen(name, flags);
+	if (!fp)
+		err(1, "fopen");
+
+	return fp;
+}
+
+static void
+printtime(FILE *fp, const git_time * intime, const char *prefix)
+{
+	struct tm *intm;
+	time_t t;
+	int offset, hours, minutes;
+	char sign, out[32];
+
+	offset = intime->offset;
+	if (offset < 0) {
+		sign = '-';
+		offset = -offset;
+	} else {
+		sign = '+';
+	}
+
+	hours = offset / 60;
+	minutes = offset % 60;
+
+	t = (time_t) intime->time + (intime->offset * 60);
+
+	intm = gmtime(&t);
+	strftime(out, sizeof(out), "%a %b %e %T %Y", intm);
+
+	fprintf(fp, "%s%s %c%02d%02d\n", prefix, out, sign, hours, minutes);
+}
+
+static void
+printcommit(FILE *fp, git_commit * commit)
+{
+	const git_signature *sig;
+	char buf[GIT_OID_HEXSZ + 1];
+	int i, count;
+	const char *scan, *eol;
+
+	git_oid_tostr(buf, sizeof(buf), git_commit_id(commit));
+	fprintf(fp, "commit <a href=\"commit/%s.html\">%s</a>\n", buf, buf);
+
+	if ((count = (int)git_commit_parentcount(commit)) > 1) {
+		fprintf(fp, "Merge:");
+		for (i = 0; i < count; ++i) {
+			git_oid_tostr(buf, 8, git_commit_parent_id(commit, i));
+			fprintf(fp, " %s", buf);
+		}
+		fprintf(fp, "\n");
+	}
+	if ((sig = git_commit_author(commit)) != NULL) {
+		fprintf(fp, "Author: <a href=\"author/%s.html\">%s</a> <%s>\n",
+			sig->name, sig->name, sig->email);
+		printtime(fp, &sig->when, "Date:   ");
+	}
+	fprintf(fp, "\n");
+
+	for (scan = git_commit_message(commit); scan && *scan;) {
+		for (eol = scan; *eol && *eol != '\n'; ++eol)	/* find eol */
+			;
+
+		fprintf(fp, "    %.*s\n", (int) (eol - scan), scan);
+		scan = *eol ? eol + 1 : NULL;
+	}
+	fprintf(fp, "\n");
+}
+
+int
+writeheader(FILE *fp)
+{
+	fprintf(fp, "<!DOCTYPE HTML>"
+		"<html dir=\"ltr\" lang=\"en\"><head>"
+		"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />"
+		"<meta http-equiv=\"Content-Language\" content=\"en\" />");
+	fprintf(fp, "<title>%s - %s</title>", name, description);
+	fprintf(fp, "<link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\" />"
+		"</head><body><center>");
+	fprintf(fp, "<h1><img src=\"%slogo.png\" alt=\"\" /> %s</h1>", relpath, name);
+	fprintf(fp, "<span class=\"desc\">%s</span><br/>", description);
+	fprintf(fp, "<a href=\"%slog.html\">Log</a> |", relpath);
+	fprintf(fp, "<a href=\"%sfiles.html\">Files</a>| ", relpath);
+	fprintf(fp, "<a href=\"%sstats.html\">Stats</a> | ", relpath);
+	fprintf(fp, "<a href=\"%sreadme.html\">README</a> | ", relpath);
+	fprintf(fp, "<a href=\"%slicense.html\">LICENSE</a>", relpath);
+	fprintf(fp, "</center><hr/><pre>");
+
+	return 0;
+}
+
+int
+writefooter(FILE *fp)
+{
+	fprintf(fp, "</pre></body></html>");
+
+	return 0;
+}
+
+int
+writelog(FILE *fp)
+{
+	git_revwalk *w = NULL;
+	git_oid id;
+	git_commit *c = NULL;
+
+	git_revwalk_new(&w, repo);
+	git_revwalk_push_head(w);
+
+	while (!git_revwalk_next(&id, w)) {
+		if (git_commit_lookup(&c, repo, &id))
+			return 1;
+		printcommit(fp, c);
+		git_commit_free(c);
+	}
+	git_revwalk_free(w);
+
+	return 0;
+}
+
+int
+writefiles(FILE *fp)
+{
+	git_index *index;
+	const git_index_entry *entry;
+	size_t count, i;
+
+	git_repository_index(&index, repo);
+
+	count = git_index_entrycount(index);
+	for (i = 0; i < count; i++) {
+		entry = git_index_get_byindex(index, i);
+		fprintf(fp, "name: %s, size: %lu, mode: %lu\n",
+			entry->path, entry->file_size, entry->mode);
+	}
+
+	return 0;
+}
+
+#if 0
+int
+writebranches(FILE *fp)
+{
+	git_branch_iterator *branchit = NULL;
+	git_branch_t branchtype;
+	git_reference *branchref;
+	char branchbuf[BUFSIZ] = "";
+	int status;
+
+	git_branch_iterator_new(&branchit, repo, GIT_BRANCH_LOCAL);
+
+	while ((status = git_branch_next(&branchref, &branchtype, branchit)) == GIT_ITEROVER) {
+		git_reference_normalize_name(branchbuf, sizeof(branchbuf), git_reference_name(branchref), GIT_REF_FORMAT_ALLOW_ONELEVEL | GIT_REF_FORMAT_REFSPEC_SHORTHAND);
+
+		/* fprintf(fp, "branch: |%s|\n", branchbuf); */
+	}
+
+	git_branch_iterator_free(branchit);
+
+	return 0;
+}
+#endif
+
+int
+main(int argc, char *argv[])
+{
+	int status;
+	const git_error *e = NULL;
+	FILE *fp;
+
+	if (argc != 2) {
+		fprintf(stderr, "%s <repodir>\n", argv[0]);
+		return 1;
+	}
+	repodir = argv[1];
+
+	git_libgit2_init();
+
+	if ((status = git_repository_open(&repo, repodir)) < 0) {
+		e = giterr_last();
+		fprintf(stderr, "error %d/%d: %s\n", status, e->klass, e->message);
+		exit(status);
+	}
+
+	fp = efopen("logs.html", "w+b");
+	writeheader(fp);
+	writelog(fp);
+	writefooter(fp);
+	fclose(fp);
+
+	fp = efopen("files.html", "w+b");
+	writeheader(fp);
+	writefiles(fp);
+	writefooter(fp);
+	fclose(fp);
+
+	/* cleanup */
+	git_repository_free(repo);
+	git_libgit2_shutdown();
+
+	return 0;
+}