Personal build of stagit static git page generator.
log | files | refs | readme | license

commit 6b5445a8fe009ef9597311dca90f2add4185e8fa
parent 87a1776027258e21a2afba254c8d9db3813bca32
Author: Michael Skec
Date:   Fri, 10 Nov 2023 10:53:24 +1100

Apply modifications

Set up to work with our folder structure (/pub for public repos).  Some
stylistic changes.  writeblob modified so that line numbers and code are
separate.

Diffstat:
A.gitignore | 3+++
A0001-initial.patch | 108+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MMakefile | 5-----
Dexample_create.sh | 43-------------------------------------------
Dexample_post-receive.sh | 73-------------------------------------------------------------------------
Astagit-create.sh | 41+++++++++++++++++++++++++++++++++++++++++
Mstagit-index.c | 26++++++++++++++++----------
Astagit-post-receive.sh | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mstagit.c | 98++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Mstyle.css | 32+++++++++++++++++++++++++++++++-
10 files changed, 348 insertions(+), 153 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1,3 @@ +*.o +stagit +stagit-index diff --git a/0001-initial.patch b/0001-initial.patch @@ -0,0 +1,108 @@ +diff --git a/.gitignore b/.gitignore +new file mode 100644 +index 0000000..61ad020 +--- /dev/null ++++ b/.gitignore +@@ -0,0 +1,3 @@ ++*.o ++stagit ++stagit-index +diff --git a/example_create.sh b/example_create.sh +index 24bcec5..cbf4cfc 100755 +--- a/example_create.sh ++++ b/example_create.sh +@@ -16,22 +16,20 @@ + # - sh example_create.sh + + # path must be absolute. +-reposdir="/var/www/domains/git.codemadness.nl/home/src" ++reposdir="/home/git" + curdir="$(pwd)" + + # make index. +-stagit-index "${reposdir}/"*/ > "${curdir}/index.html" ++stagit-index "${reposdir}/pub/"*/ > "${curdir}/index.html" + + # make files per repo. +-for dir in "${reposdir}/"*/; do +- # strip .git suffix. +- r=$(basename "${dir}") ++for dir in "${reposdir}/pub/"*/; do + d=$(basename "${dir}" ".git") + printf "%s... " "${d}" + + mkdir -p "${curdir}/${d}" + cd "${curdir}/${d}" || continue +- stagit -c ".cache" -u "https://git.codemadness.nl/$d/" "${reposdir}/${r}" ++ stagit -c ".cache" -u "https://git.skec.site/$d/" "${reposdir}/pub/${d}" + + # symlinks + ln -sf log.html index.html +diff --git a/example_post-receive.sh b/example_post-receive.sh +index 5e8d32b..696344d 100755 +--- a/example_post-receive.sh ++++ b/example_post-receive.sh +@@ -19,9 +19,9 @@ fi + + # config + # paths must be absolute. +-reposdir="/home/src/src" +-dir="${reposdir}/${name}" +-htmldir="/home/www/domains/git.codemadness.org/htdocs" ++reposdir="/home/git" ++dir="${reposdir}/pub/${name}" ++htmldir="/var/www/htdocs/git.skec.site" + stagitdir="/" + destdir="${htmldir}${stagitdir}" + cachefile=".htmlcache" +@@ -35,24 +35,24 @@ cd "${dir}" || exit 1 + + # detect git push -f + force=0 +-while read -r old new ref; do +- test "${old}" = "0000000000000000000000000000000000000000" && continue +- test "${new}" = "0000000000000000000000000000000000000000" && continue +- +- hasrevs=$(git rev-list "${old}" "^${new}" | sed 1q) +- if test -n "${hasrevs}"; then +- force=1 +- break +- fi +-done ++# TODO: fix ++#while read -r old new ref; do ++# test "${old}" = "0000000000000000000000000000000000000000" && continue ++# test "${new}" = "0000000000000000000000000000000000000000" && continue ++# ++# hasrevs=$(git rev-list "${old}" "^${new}" | sed 1q) ++# if test -n "${hasrevs}"; then ++# force=1 ++# break ++# fi ++#done + + # strip .git suffix. +-r=$(basename "${name}") + d=$(basename "${name}" ".git") + printf "[%s] stagit HTML pages... " "${d}" + +-mkdir -p "${destdir}/${d}" +-cd "${destdir}/${d}" || exit 1 ++mkdir -p "${destdir}/pub/${d}" ++cd "${destdir}/pub/${d}" || exit 1 + + # remove commits and ${cachefile} on git push -f, this recreated later on. + if test "${force}" = "1"; then +@@ -61,10 +61,10 @@ if test "${force}" = "1"; then + fi + + # make index. +-stagit-index "${reposdir}/"*/ > "${destdir}/index.html" ++stagit-index "${reposdir}/pub/"*/ > "${destdir}/index.html" + + # make pages. +-stagit -c "${cachefile}" -u "https://git.codemadness.nl/$d/" "${reposdir}/${r}" ++stagit -c "${cachefile}" -u "https://git.skec.site/pub/${d}/" "${reposdir}/pub/${d}" + + ln -sf log.html index.html + ln -sf ../style.css style.css diff --git a/Makefile b/Makefile @@ -58,7 +58,6 @@ dist: mkdir -p ${NAME}-${VERSION} cp -f ${MAN1} ${HDR} ${SRC} ${COMPATSRC} ${DOC} \ Makefile favicon.png logo.png style.css \ - example_create.sh example_post-receive.sh \ ${NAME}-${VERSION} # make tarball tar -cf - ${NAME}-${VERSION} | \ @@ -86,8 +85,6 @@ install: all cp -f style.css\ favicon.png\ logo.png\ - example_create.sh\ - example_post-receive.sh\ README\ ${DESTDIR}${DOCPREFIX} # installing manual pages. @@ -103,8 +100,6 @@ uninstall: ${DESTDIR}${DOCPREFIX}/style.css\ ${DESTDIR}${DOCPREFIX}/favicon.png\ ${DESTDIR}${DOCPREFIX}/logo.png\ - ${DESTDIR}${DOCPREFIX}/example_create.sh\ - ${DESTDIR}${DOCPREFIX}/example_post-receive.sh\ ${DESTDIR}${DOCPREFIX}/README -rmdir ${DESTDIR}${DOCPREFIX} # removing manual pages. diff --git a/example_create.sh b/example_create.sh @@ -1,43 +0,0 @@ -#!/bin/sh -# - Makes index for repositories in a single directory. -# - Makes static pages for each repository directory. -# -# NOTE, things to do manually (once) before running this script: -# - copy style.css, logo.png and favicon.png manually, a style.css example -# is included. -# -# - write clone URL, for example "git://git.codemadness.org/dir" to the "url" -# file for each repo. -# - write owner of repo to the "owner" file. -# - write description in "description" file. -# -# Usage: -# - mkdir -p htmldir && cd htmldir -# - sh example_create.sh - -# path must be absolute. -reposdir="/var/www/domains/git.codemadness.nl/home/src" -curdir="$(pwd)" - -# make index. -stagit-index "${reposdir}/"*/ > "${curdir}/index.html" - -# make files per repo. -for dir in "${reposdir}/"*/; do - # strip .git suffix. - r=$(basename "${dir}") - d=$(basename "${dir}" ".git") - printf "%s... " "${d}" - - mkdir -p "${curdir}/${d}" - cd "${curdir}/${d}" || continue - stagit -c ".cache" -u "https://git.codemadness.nl/$d/" "${reposdir}/${r}" - - # symlinks - ln -sf log.html index.html - ln -sf ../style.css style.css - ln -sf ../logo.png logo.png - ln -sf ../favicon.png favicon.png - - echo "done" -done diff --git a/example_post-receive.sh b/example_post-receive.sh @@ -1,73 +0,0 @@ -#!/bin/sh -# generic git post-receive hook. -# change the config options below and call this script in your post-receive -# hook or symlink it. -# -# usage: $0 [name] -# -# if name is not set the basename of the current directory is used, -# this is the directory of the repo when called from the post-receive script. - -# NOTE: needs to be set for correct locale (expects UTF-8) otherwise the -# default is LC_CTYPE="POSIX". -export LC_CTYPE="en_US.UTF-8" - -name="$1" -if test "${name}" = ""; then - name=$(basename "$(pwd)") -fi - -# config -# paths must be absolute. -reposdir="/home/src/src" -dir="${reposdir}/${name}" -htmldir="/home/www/domains/git.codemadness.org/htdocs" -stagitdir="/" -destdir="${htmldir}${stagitdir}" -cachefile=".htmlcache" -# /config - -if ! test -d "${dir}"; then - echo "${dir} does not exist" >&2 - exit 1 -fi -cd "${dir}" || exit 1 - -# detect git push -f -force=0 -while read -r old new ref; do - test "${old}" = "0000000000000000000000000000000000000000" && continue - test "${new}" = "0000000000000000000000000000000000000000" && continue - - hasrevs=$(git rev-list "${old}" "^${new}" | sed 1q) - if test -n "${hasrevs}"; then - force=1 - break - fi -done - -# strip .git suffix. -r=$(basename "${name}") -d=$(basename "${name}" ".git") -printf "[%s] stagit HTML pages... " "${d}" - -mkdir -p "${destdir}/${d}" -cd "${destdir}/${d}" || exit 1 - -# remove commits and ${cachefile} on git push -f, this recreated later on. -if test "${force}" = "1"; then - rm -f "${cachefile}" - rm -rf "commit" -fi - -# make index. -stagit-index "${reposdir}/"*/ > "${destdir}/index.html" - -# make pages. -stagit -c "${cachefile}" -u "https://git.codemadness.nl/$d/" "${reposdir}/${r}" - -ln -sf log.html index.html -ln -sf ../style.css style.css -ln -sf ../logo.png logo.png - -echo "done" diff --git a/stagit-create.sh b/stagit-create.sh @@ -0,0 +1,41 @@ +#!/bin/sh +# - Makes index for repositories in a single directory. +# - Makes static pages for each repository directory. +# +# NOTE, things to do manually (once) before running this script: +# - copy style.css, logo.png and favicon.png manually, a style.css example +# is included. +# +# - write clone URL, for example "git://git.codemadness.org/dir" to the "url" +# file for each repo. +# - write owner of repo to the "owner" file. +# - write description in "description" file. +# +# Usage: +# - mkdir -p htmldir && cd htmldir +# - sh example_create.sh + +# path must be absolute. +reposdir="/home/git" +curdir="$(pwd)" + +# make index. +stagit-index "${reposdir}/pub/"*/ > "${curdir}/index.html" + +# make files per repo. +for dir in "${reposdir}/pub/"*/; do + d=$(basename "${dir}") + printf "%s... " "pub/${d}" + + mkdir -p "${curdir}/pub/${d}" + cd "${curdir}/pub/${d}" || continue + stagit -c ".cache" -u "https://git.skec.site/$d/" "${reposdir}/pub/${d}" + + # symlinks + ln -sf log.html index.html + ln -sf ../../style.css style.css + ln -sf ../../logo.png logo.png + ln -sf ../../favicon.png favicon.png + + echo "done" +done diff --git a/stagit-index.c b/stagit-index.c @@ -12,7 +12,7 @@ static git_repository *repo; static const char *relpath = ""; -static char description[255] = "Repositories"; +static char description[255] = "skec.site git repositories"; static char *name = ""; static char owner[255]; @@ -128,9 +128,12 @@ writelog(FILE *fp) const git_signature *author; git_revwalk *w = NULL; git_oid id; - char *stripped_name = NULL, *p; + char *reponame = NULL, *p; int ret = 0; +#define REPO_PREFIX "pub/" +#define STRIP_NAME 0 + git_revwalk_new(&w, repo); git_revwalk_push_head(w); @@ -142,17 +145,20 @@ writelog(FILE *fp) author = git_commit_author(commit); - /* strip .git suffix */ - if (!(stripped_name = strdup(name))) + if (!(reponame = strdup(name))) err(1, "strdup"); - if ((p = strrchr(stripped_name, '.'))) + +#if STRIP_NAME + /* strip .git suffix */ + if ((p = strrchr(reponame, '.'))) if (!strcmp(p, ".git")) *p = '\0'; +#endif - fputs("<tr><td><a href=\"", fp); - percentencode(fp, stripped_name, strlen(stripped_name)); - fputs("/log.html\">", fp); - xmlencode(fp, stripped_name, strlen(stripped_name)); + fputs("<tr><td><a href=\"" REPO_PREFIX, fp); + percentencode(fp, reponame, strlen(reponame)); + fputs("/\">", fp); + xmlencode(fp, reponame, strlen(reponame)); fputs("</a></td><td>", fp); xmlencode(fp, description, strlen(description)); fputs("</td><td>", fp); @@ -165,7 +171,7 @@ writelog(FILE *fp) git_commit_free(commit); err: git_revwalk_free(w); - free(stripped_name); + free(reponame); return ret; } diff --git a/stagit-post-receive.sh b/stagit-post-receive.sh @@ -0,0 +1,72 @@ +#!/bin/sh +# generic git post-receive hook. +# change the config options below and call this script in your post-receive +# hook or symlink it. +# +# usage: $0 [name] +# +# if name is not set the basename of the current directory is used, +# this is the directory of the repo when called from the post-receive script. + +# NOTE: needs to be set for correct locale (expects UTF-8) otherwise the +# default is LC_CTYPE="POSIX". +export LC_CTYPE="en_US.UTF-8" + +name="$1" +if test "${name}" = ""; then + name=$(basename "$(pwd)") +fi + +# config +# paths must be absolute. +reposdir="/home/git" +dir="${reposdir}/pub/${name}" +htmldir="/var/www/htdocs/git.skec.site" +stagitdir="/" +destdir="${htmldir}${stagitdir}" +cachefile=".htmlcache" +# /config + +if ! test -d "${dir}"; then + echo "${dir} does not exist" >&2 + exit 1 +fi +cd "${dir}" || exit 1 + +# detect git push -f +force=0 +# TODO: fix +#while read -r old new ref; do +# test "${old}" = "0000000000000000000000000000000000000000" && continue +# test "${new}" = "0000000000000000000000000000000000000000" && continue +# +# hasrevs=$(git rev-list "${old}" "^${new}" | sed 1q) +# if test -n "${hasrevs}"; then +# force=1 +# break +# fi +#done + +d=$(basename "${name}") +printf "[%s] stagit HTML pages... " "${d}" + +mkdir -p "${destdir}/pub/${d}" +cd "${destdir}/pub/${d}" || exit 1 + +# remove commits and ${cachefile} on git push -f, this recreated later on. +if test "${force}" = "1"; then + rm -f "${cachefile}" + rm -rf "commit" +fi + +# make index. +stagit-index "${reposdir}/pub/"*/ > "${destdir}/index.html" + +# make pages. +stagit -c "${cachefile}" -u "https://git.skec.site/pub/${d}/" "${reposdir}/pub/${d}" + +ln -sf log.html index.html +ln -sf ../../style.css style.css +ln -sf ../../logo.png logo.png + +echo "done" diff --git a/stagit.c b/stagit.c @@ -63,7 +63,6 @@ static const char *relpath = ""; static const char *repodir; static char *name = ""; -static char *strippedname = ""; static char description[255]; static char cloneurl[1024]; static char *submodules; @@ -504,10 +503,13 @@ writeheader(FILE *fp, const char *title) "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n" "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n" "<title>", fp); - xmlencode(fp, title, strlen(title)); - if (title[0] && strippedname[0]) - fputs(" - ", fp); - xmlencode(fp, strippedname, strlen(strippedname)); + if (title) + { + xmlencode(fp, title, strlen(title)); + if (title[0] && name[0]) + fputs(" - ", fp); + } + xmlencode(fp, name, strlen(name)); if (description[0]) fputs(" - ", fp); xmlencode(fp, description, strlen(description)); @@ -520,11 +522,19 @@ writeheader(FILE *fp, const char *title) fprintf(fp, " Atom Feed (tags)\" href=\"%stags.xml\" />\n", relpath); fprintf(fp, "<link rel=\"stylesheet\" type=\"text/css\" href=\"%sstyle.css\" />\n", relpath); fputs("</head>\n<body>\n<table><tr><td>", fp); - fprintf(fp, "<a href=\"../%s\"><img src=\"%slogo.png\" alt=\"\" width=\"32\" height=\"32\" /></a>", - relpath, relpath); + fprintf(fp, "<a href=\"/\"><img src=\"%slogo.png\" alt=\"\" width=\"32\" height=\"32\" /></a>", + relpath); +#if 0 fputs("</td><td><h1>", fp); - xmlencode(fp, strippedname, strlen(strippedname)); + xmlencode(fp, name, strlen(name)); fputs("</h1><span class=\"desc\">", fp); +#else + fputs("</td><td><a id=\"title\" title=\"", fp); + xmlencode(fp, name, strlen(name)); + fprintf(fp, "\" href=\"/pub/%s\">", name); + xmlencode(fp, name, strlen(name)); + fputs("</a><span class=\"desc\">", fp); +#endif xmlencode(fp, description, strlen(description)); fputs("</span></td></tr>", fp); if (cloneurl[0]) { @@ -560,10 +570,13 @@ size_t writeblobhtml(FILE *fp, const git_blob *blob) { size_t n = 0, i, len, prev; - const char *nfmt = "<a href=\"#l%zu\" class=\"line\" id=\"l%zu\">%7zu</a> "; const char *s = git_blob_rawcontent(blob); len = git_blob_rawsize(blob); + +#if 0 + const char *nfmt = "<a href=\"#l%zu\" class=\"line\" id=\"l%zu\">%7zu</a> "; + fputs("<pre id=\"blob\">\n", fp); if (len > 0) { @@ -585,6 +598,56 @@ writeblobhtml(FILE *fp, const git_blob *blob) } fputs("</pre>\n", fp); +#else + const char *nfmt = "<a href=\"#n%zu\" class=\"line\" id=\"n%zu\">%7zu</a>"; + + fputs("<table id=\"blob\"><tbody><tr>", fp); + + if (len > 0) + { + /* Line numbers */ + fputs("<td id=\"linenumbers\"><pre>", fp); + for (i = 0, prev = 0; i < len; i++) + { + if (s[i] != '\n') + continue; + n++; + fprintf(fp, nfmt, n, n, n); + putc('\n', fp); + prev = i + 1; + } + /* trailing data */ + if ((len - prev) > 0) + { + n++; + fprintf(fp, nfmt, n, n, n); + } + fputs("</pre></td>", fp); + + n = 0; + + /* Lines */ + fputs("<td id=\"lines\"><pre>", fp); + for (i = 0, prev = 0; i < len; i++) + { + if (s[i] != '\n') + continue; + n++; + xmlencodeline(fp, &s[prev], i - prev + 1); + putc('\n', fp); + prev = i + 1; + } + /* trailing data */ + if ((len - prev) > 0) + { + n++; + xmlencodeline(fp, &s[prev], len - prev); + } + fputs("</pre></td>", fp); + } + + fputs("</tr></tbody></table>", fp); +#endif return n; } @@ -912,7 +975,7 @@ writeatom(FILE *fp, int all) fputs("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" "<feed xmlns=\"http://www.w3.org/2005/Atom\">\n<title>", fp); - xmlencode(fp, strippedname, strlen(strippedname)); + xmlencode(fp, name, strlen(name)); fputs(", branch HEAD</title>\n<subtitle>", fp); xmlencode(fp, description, strlen(description)); fputs("</subtitle>\n", fp); @@ -972,7 +1035,7 @@ writeblob(git_object *obj, const char *fpath, const char *filename, size_t files fputs("<p> ", fp); xmlencode(fp, filename, strlen(filename)); fprintf(fp, " (%zuB)", filesize); - fputs("</p><hr/>", fp); + fputs("</p>", fp); if (git_blob_is_binary((git_blob *)obj)) fputs("<p>Binary file.</p>\n", fp); @@ -1272,13 +1335,6 @@ main(int argc, char *argv[]) else name = ""; - /* strip .git suffix */ - if (!(strippedname = strdup(name))) - err(1, "strdup"); - if ((p = strrchr(strippedname, '.'))) - if (!strcmp(p, ".git")) - *p = '\0'; - /* read description or .git/description */ joinpath(path, sizeof(path), repodir, "description"); if (!(fpread = fopen(path, "r"))) { @@ -1331,7 +1387,7 @@ main(int argc, char *argv[]) fp = efopen("log.html", "w"); relpath = ""; mkdir("commit", S_IRWXU | S_IRWXG | S_IRWXO); - writeheader(fp, "Log"); + writeheader(fp, NULL); fputs("<table id=\"log\"><thead>\n<tr><td><b>Date</b></td>" "<td><b>Commit message</b></td>" "<td><b>Author</b></td><td class=\"num\" align=\"right\"><b>Files</b></td>" @@ -1385,7 +1441,7 @@ main(int argc, char *argv[]) /* files for HEAD */ fp = efopen("files.html", "w"); - writeheader(fp, "Files"); + writeheader(fp, NULL); if (head) writefiles(fp, head); writefooter(fp); @@ -1394,7 +1450,7 @@ main(int argc, char *argv[]) /* summary page with branches and tags */ fp = efopen("refs.html", "w"); - writeheader(fp, "Refs"); + writeheader(fp, NULL); writerefs(fp); writefooter(fp); checkfileerror(fp, "refs.html", 'w'); diff --git a/style.css b/style.css @@ -1,7 +1,7 @@ body { color: #000; background-color: #fff; - font-family: monospace; + font-family: serif; } h1, h2, h3, h4, h5, h6 { @@ -37,6 +37,15 @@ a.line { text-decoration: none; } +#title { + color: #000; + text-decoration: none; + font-size: 150%; +} +#title:hover { + text-decoration: underline; +} + table thead td { font-weight: bold; } @@ -81,6 +90,7 @@ hr { pre { font-family: monospace; + font-size: 12px; } pre a.h { @@ -105,6 +115,26 @@ pre a.d:hover { text-decoration: none; } +#blob { + margin-top: 0.5em; + border-collapse: collapse; + border-top: 1px solid black; +} + +#linenumbers { + margin: 0; + padding: 0 0.5em 0 0; + vertical-align: top; + text-align: right; + border-right: 1px solid grey; +} + +#lines { + margin: 0; + padding: 0 0 0 0.5em; + vertical-align: top; +} + @media (prefers-color-scheme: dark) { body { background-color: #000;