rewrite in C with libgit2, first version - stagit-gopher - A git gopher fronten… | |
git clone git://bitreich.org/stagit-gopher/ git://enlrupgkhuxnvlhsf6lc3fziv5h2h… | |
Log | |
Files | |
Refs | |
Tags | |
README | |
LICENSE | |
--- | |
commit 415e3fdd55b2ecdf2f35680694362a4b35fd1a05 | |
parent bda4633633a0701bbd2f7861674a8e612d961fb7 | |
Author: Hiltjo Posthuma <[email protected]> | |
Date: Sat, 5 Dec 2015 20:22:57 +0100 | |
rewrite in C with libgit2, first version | |
Diffstat: | |
D urmoms | 135 -----------------------------… | |
A urmoms.c | 222 ++++++++++++++++++++++++++++++ | |
2 files changed, 222 insertions(+), 135 deletions(-) | |
--- | |
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.… | |
- 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}'commi… | |
-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… | |
-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}'co… | |
-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 e… | |
+ ; | |
+ | |
+ 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; charse… | |
+ "<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.c… | |
+ "</head><body><center>"); | |
+ fprintf(fp, "<h1><img src=\"%slogo.png\" alt=\"\" /> %s</h1>", relpath… | |
+ 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_reference_normalize_name(branchbuf, sizeof(branchbuf), git… | |
+ | |
+ /* 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->mess… | |
+ 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; | |
+} |