stagit

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

commit
cfbe277f7795e53658cd06adad2e801538b3e415
parent
da7dd53f107b35057ec7c883f05c902af1949b30
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2020-03-29 18:59
rm stagit-index

Diffstat

M Makefile 12 +++---------
D stagit-index.1 42 ------------------------------------------
D stagit-index.c 220 ------------------------------------------------------------

3 files changed, 3 insertions, 271 deletions


diff --git a/Makefile b/Makefile

@@ -20,16 +20,13 @@ STAGIT_LDFLAGS = ${LIBGIT_LIB} ${CMARKLIBS} ${LDFLAGS}
   20    20 STAGIT_CPPFLAGS = -D_XOPEN_SOURCE=700 -D_DEFAULT_SOURCE -D_BSD_SOURCE ${CMARKFLAGS}
   21    21 
   22    22 SRC = \
   23    -1 	stagit.c\
   24    -1 	stagit-index.c
   -1    23 	stagit.c
   25    24 COMPATSRC = \
   26    25 	strlcpy.c
   27    26 BIN = \
   28    -1 	stagit\
   29    -1 	stagit-index
   -1    27 	stagit
   30    28 MAN1 = \
   31    -1 	stagit.1\
   32    -1 	stagit-index.1
   -1    29 	stagit.1
   33    30 DOC = \
   34    31 	LICENSE\
   35    32 	README
@@ -65,9 +62,6 @@ ${OBJ}: ${HDR}
   65    62 stagit: stagit.o ${COMPATOBJ}
   66    63 	${CC} -o $@ stagit.o ${COMPATOBJ} ${STAGIT_LDFLAGS}
   67    64 
   68    -1 stagit-index: stagit-index.o ${COMPATOBJ}
   69    -1 	${CC} -o $@ stagit-index.o ${COMPATOBJ} ${STAGIT_LDFLAGS}
   70    -1 
   71    65 clean:
   72    66 	rm -f ${BIN} ${OBJ} ${NAME}-${VERSION}.tar.gz
   73    67 

diff --git a/stagit-index.1 b/stagit-index.1

@@ -1,42 +0,0 @@
    1    -1 .Dd December 26, 2015
    2    -1 .Dt STAGIT-INDEX 1
    3    -1 .Os
    4    -1 .Sh NAME
    5    -1 .Nm stagit-index
    6    -1 .Nd static git index page generator
    7    -1 .Sh SYNOPSIS
    8    -1 .Nm
    9    -1 .Op Ar repodir...
   10    -1 .Sh DESCRIPTION
   11    -1 .Nm
   12    -1 will create an index HTML page for the repositories specified and writes
   13    -1 the HTML data to stdout.
   14    -1 The repos in the index are in the same order as the arguments
   15    -1 .Ar repodir
   16    -1 specified.
   17    -1 .Pp
   18    -1 The basename of the directory is used as the repository name.
   19    -1 The suffix ".git" is removed from the basename, this suffix is commonly used
   20    -1 for "bare" repos.
   21    -1 .Pp
   22    -1 The content of the follow files specifies the meta data for each repository:
   23    -1 .Bl -tag -width Ds
   24    -1 .It .git/description or description (bare repos).
   25    -1 description
   26    -1 .It .git/owner or owner (bare repo).
   27    -1 owner of repository
   28    -1 .El
   29    -1 .Pp
   30    -1 For changing the style of the page you can use the following files:
   31    -1 .Bl -tag -width Ds
   32    -1 .It favicon.png
   33    -1 favicon image.
   34    -1 .It logo.png
   35    -1 32x32 logo.
   36    -1 .It style.css
   37    -1 CSS stylesheet.
   38    -1 .El
   39    -1 .Sh SEE ALSO
   40    -1 .Xr stagit 1
   41    -1 .Sh AUTHORS
   42    -1 .An Hiltjo Posthuma Aq Mt hiltjo@codemadness.org

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

@@ -1,220 +0,0 @@
    1    -1 #include <err.h>
    2    -1 #include <limits.h>
    3    -1 #include <stdio.h>
    4    -1 #include <stdlib.h>
    5    -1 #include <string.h>
    6    -1 #include <time.h>
    7    -1 #include <unistd.h>
    8    -1 
    9    -1 #include <git2.h>
   10    -1 
   11    -1 static git_repository *repo;
   12    -1 
   13    -1 static const char *relpath = "";
   14    -1 
   15    -1 static char description[255] = "Repositories";
   16    -1 static char *name = "";
   17    -1 static char owner[255];
   18    -1 
   19    -1 void
   20    -1 joinpath(char *buf, size_t bufsiz, const char *path, const char *path2)
   21    -1 {
   22    -1 	int r;
   23    -1 
   24    -1 	r = snprintf(buf, bufsiz, "%s%s%s",
   25    -1 		path, path[0] && path[strlen(path) - 1] != '/' ? "/" : "", path2);
   26    -1 	if (r < 0 || (size_t)r >= bufsiz)
   27    -1 		errx(1, "path truncated: '%s%s%s'",
   28    -1 			path, path[0] && path[strlen(path) - 1] != '/' ? "/" : "", path2);
   29    -1 }
   30    -1 
   31    -1 /* Escape characters below as HTML 2.0 / XML 1.0. */
   32    -1 void
   33    -1 xmlencode(FILE *fp, const char *s, size_t len)
   34    -1 {
   35    -1 	size_t i;
   36    -1 
   37    -1 	for (i = 0; *s && i < len; s++, i++) {
   38    -1 		switch(*s) {
   39    -1 		case '<':  fputs("&lt;",   fp); break;
   40    -1 		case '>':  fputs("&gt;",   fp); break;
   41    -1 		case '\'': fputs("&#39;" , fp); break;
   42    -1 		case '&':  fputs("&amp;",  fp); break;
   43    -1 		case '"':  fputs("&quot;", fp); break;
   44    -1 		default:   fputc(*s, fp);
   45    -1 		}
   46    -1 	}
   47    -1 }
   48    -1 
   49    -1 void
   50    -1 printtimeshort(FILE *fp, const git_time *intime)
   51    -1 {
   52    -1 	struct tm *intm;
   53    -1 	time_t t;
   54    -1 	char out[32];
   55    -1 
   56    -1 	t = (time_t)intime->time;
   57    -1 	if (!(intm = gmtime(&t)))
   58    -1 		return;
   59    -1 	strftime(out, sizeof(out), "%Y-%m-%d %H:%M", intm);
   60    -1 	fputs(out, fp);
   61    -1 }
   62    -1 
   63    -1 void
   64    -1 writeheader(FILE *fp)
   65    -1 {
   66    -1 	fputs("<!DOCTYPE html>\n"
   67    -1 		"<html>\n<head>\n"
   68    -1 		"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n"
   69    -1 		"<title>", fp);
   70    -1 	xmlencode(fp, description, strlen(description));
   71    -1 	fprintf(fp, "</title>\n<link rel=\"icon\" type=\"image/png\" href=\"%sfavicon.png\" />\n", relpath);
   72    -1 	fprintf(fp, "<link rel=\"stylesheet\" type=\"text/css\" href=\"%sstyle.css\" />\n", relpath);
   73    -1 	fputs("</head>\n<body>\n", fp);
   74    -1 	fprintf(fp, "<table>\n<tr><td><img src=\"%slogo.png\" alt=\"\" width=\"32\" height=\"32\" /></td>\n"
   75    -1 	        "<td><span class=\"desc\">", relpath);
   76    -1 	xmlencode(fp, description, strlen(description));
   77    -1 	fputs("</span></td></tr><tr><td></td><td>\n"
   78    -1 		"</td></tr>\n</table>\n<hr/>\n<div id=\"content\">\n"
   79    -1 		"<table id=\"index\"><thead>\n"
   80    -1 		"<tr><td><b>Name</b></td><td><b>Description</b></td><td><b>Owner</b></td>"
   81    -1 		"<td><b>Last commit</b></td></tr>"
   82    -1 		"</thead><tbody>\n", fp);
   83    -1 }
   84    -1 
   85    -1 void
   86    -1 writefooter(FILE *fp)
   87    -1 {
   88    -1 	fputs("</tbody>\n</table>\n</div>\n</body>\n</html>\n", fp);
   89    -1 }
   90    -1 
   91    -1 int
   92    -1 writelog(FILE *fp)
   93    -1 {
   94    -1 	git_commit *commit = NULL;
   95    -1 	const git_signature *author;
   96    -1 	git_revwalk *w = NULL;
   97    -1 	git_oid id;
   98    -1 	char *stripped_name = NULL, *p;
   99    -1 	int ret = 0;
  100    -1 
  101    -1 	git_revwalk_new(&w, repo);
  102    -1 	git_revwalk_push_head(w);
  103    -1 	git_revwalk_simplify_first_parent(w);
  104    -1 
  105    -1 	if (git_revwalk_next(&id, w) ||
  106    -1 	    git_commit_lookup(&commit, repo, &id)) {
  107    -1 		ret = -1;
  108    -1 		goto err;
  109    -1 	}
  110    -1 
  111    -1 	author = git_commit_author(commit);
  112    -1 
  113    -1 	/* strip .git suffix */
  114    -1 	if (!(stripped_name = strdup(name)))
  115    -1 		err(1, "strdup");
  116    -1 	if ((p = strrchr(stripped_name, '.')))
  117    -1 		if (!strcmp(p, ".git"))
  118    -1 			*p = '\0';
  119    -1 
  120    -1 	fputs("<tr><td><a href=\"", fp);
  121    -1 	xmlencode(fp, stripped_name, strlen(stripped_name));
  122    -1 	fputs("/log.html\">", fp);
  123    -1 	xmlencode(fp, stripped_name, strlen(stripped_name));
  124    -1 	fputs("</a></td><td>", fp);
  125    -1 	xmlencode(fp, description, strlen(description));
  126    -1 	fputs("</td><td>", fp);
  127    -1 	xmlencode(fp, owner, strlen(owner));
  128    -1 	fputs("</td><td>", fp);
  129    -1 	if (author)
  130    -1 		printtimeshort(fp, &(author->when));
  131    -1 	fputs("</td></tr>", fp);
  132    -1 
  133    -1 	git_commit_free(commit);
  134    -1 err:
  135    -1 	git_revwalk_free(w);
  136    -1 	free(stripped_name);
  137    -1 
  138    -1 	return ret;
  139    -1 }
  140    -1 
  141    -1 int
  142    -1 main(int argc, char *argv[])
  143    -1 {
  144    -1 	FILE *fp;
  145    -1 	char path[PATH_MAX], repodirabs[PATH_MAX + 1];
  146    -1 	const char *repodir;
  147    -1 	int i, ret = 0;
  148    -1 
  149    -1 	if (argc < 2) {
  150    -1 		fprintf(stderr, "%s [repodir...]\n", argv[0]);
  151    -1 		return 1;
  152    -1 	}
  153    -1 
  154    -1 	git_libgit2_init();
  155    -1 
  156    -1 #ifdef __OpenBSD__
  157    -1 	for (i = 1; i < argc; i++)
  158    -1 		if (unveil(argv[i], "r") == -1)
  159    -1 			err(1, "unveil: %s", argv[i]);
  160    -1 
  161    -1 	if (pledge("stdio rpath", NULL) == -1)
  162    -1 		err(1, "pledge");
  163    -1 #endif
  164    -1 
  165    -1 	writeheader(stdout);
  166    -1 
  167    -1 	for (i = 1; i < argc; i++) {
  168    -1 		repodir = argv[i];
  169    -1 		if (!realpath(repodir, repodirabs))
  170    -1 			err(1, "realpath");
  171    -1 
  172    -1 		if (git_repository_open_ext(&repo, repodir,
  173    -1 		    GIT_REPOSITORY_OPEN_NO_SEARCH, NULL)) {
  174    -1 			fprintf(stderr, "%s: cannot open repository\n", argv[0]);
  175    -1 			ret = 1;
  176    -1 			continue;
  177    -1 		}
  178    -1 
  179    -1 		/* use directory name as name */
  180    -1 		if ((name = strrchr(repodirabs, '/')))
  181    -1 			name++;
  182    -1 		else
  183    -1 			name = "";
  184    -1 
  185    -1 		/* read description or .git/description */
  186    -1 		joinpath(path, sizeof(path), repodir, "description");
  187    -1 		if (!(fp = fopen(path, "r"))) {
  188    -1 			joinpath(path, sizeof(path), repodir, ".git/description");
  189    -1 			fp = fopen(path, "r");
  190    -1 		}
  191    -1 		description[0] = '\0';
  192    -1 		if (fp) {
  193    -1 			if (!fgets(description, sizeof(description), fp))
  194    -1 				description[0] = '\0';
  195    -1 			fclose(fp);
  196    -1 		}
  197    -1 
  198    -1 		/* read owner or .git/owner */
  199    -1 		joinpath(path, sizeof(path), repodir, "owner");
  200    -1 		if (!(fp = fopen(path, "r"))) {
  201    -1 			joinpath(path, sizeof(path), repodir, ".git/owner");
  202    -1 			fp = fopen(path, "r");
  203    -1 		}
  204    -1 		owner[0] = '\0';
  205    -1 		if (fp) {
  206    -1 			if (!fgets(owner, sizeof(owner), fp))
  207    -1 				owner[0] = '\0';
  208    -1 			owner[strcspn(owner, "\n")] = '\0';
  209    -1 			fclose(fp);
  210    -1 		}
  211    -1 		writelog(stdout);
  212    -1 	}
  213    -1 	writefooter(stdout);
  214    -1 
  215    -1 	/* cleanup */
  216    -1 	git_repository_free(repo);
  217    -1 	git_libgit2_shutdown();
  218    -1 
  219    -1 	return ret;
  220    -1 }