stagit
Fork of stagit for GNUfault.org
Log | Files | Refs | README | LICENSE
commit 87dbcb84cc44b5f34cf1d423bd8282650c541f83
parent 519cae2fcab6f2427dc8f2805d6a5d1eee4bdb05
Author: Connor Thomson <connor@gnufault.org>
Date: Wed, 11 Nov 2026 17:09:07 -0800
Add GNUfault.org specifc stuff
Diffstat:
9 files changed, 18 insertions(+), 504 deletions(-)
diff --git a/Makefile b/Makefile
@@ -57,8 +57,6 @@ dist:
rm -rf ${NAME}-${VERSION}
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} | \
@@ -83,12 +81,7 @@ install: all
for f in ${BIN}; do chmod 755 ${DESTDIR}${PREFIX}/bin/$$f; done
# installing example files.
mkdir -p ${DESTDIR}${DOCPREFIX}
- cp -f style.css\
- favicon.png\
- logo.png\
- example_create.sh\
- example_post-receive.sh\
- README\
+ cp -f README.md\
${DESTDIR}${DOCPREFIX}
# installing manual pages.
mkdir -p ${DESTDIR}${MANPREFIX}/man1
@@ -100,12 +93,7 @@ uninstall:
for f in ${BIN}; do rm -f ${DESTDIR}${PREFIX}/bin/$$f; done
# removing example files.
rm -f \
- ${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
+ ${DESTDIR}${DOCPREFIX}/README.md
-rmdir ${DESTDIR}${DOCPREFIX}
# removing manual pages.
for m in ${MAN1}; do rm -f ${DESTDIR}${MANPREFIX}/man1/$$m; done
diff --git a/README b/README
@@ -1,186 +1 @@
-stagit
-------
-
-static git page generator.
-
-It generates static HTML pages for a git repository.
-
-
-Usage
------
-
-Make files per repository:
-
- $ mkdir -p htmlroot/htmlrepo1 && cd htmlroot/htmlrepo1
- $ stagit path/to/gitrepo1
- repeat for other repositories
- $ ...
-
-Make index file for repositories:
-
- $ cd htmlroot
- $ stagit-index path/to/gitrepo1 \
- path/to/gitrepo2 \
- path/to/gitrepo3 > index.html
-
-
-Build and install
------------------
-
-$ make
-# make install
-
-
-Dependencies
-------------
-
-- C compiler (C99).
-- libc (tested with OpenBSD, FreeBSD, NetBSD, Linux: glibc and musl).
-- libgit2 (v0.22+).
-- POSIX make (optional).
-
-
-Documentation
--------------
-
-See man pages: stagit(1) and stagit-index(1).
-
-
-Building a static binary
-------------------------
-
-It may be useful to build static binaries, for example to run in a chroot.
-
-It can be done like this at the time of writing (v0.24):
-
-cd libgit2-src
-
-# change the options in the CMake file: CMakeLists.txt
-BUILD_SHARED_LIBS to OFF (static)
-CURL to OFF (not needed)
-USE_SSH OFF (not needed)
-THREADSAFE OFF (not needed)
-USE_OPENSSL OFF (not needed, use builtin)
-
-mkdir -p build && cd build
-cmake ../
-make
-make install
-
-
-Extract owner field from git config
------------------------------------
-
-A way to extract the gitweb owner for example in the format:
-
- [gitweb]
- owner = Name here
-
-Script:
-
- #!/bin/sh
- awk '/^[ ]*owner[ ]=/ {
- sub(/^[^=]*=[ ]*/, "");
- print $0;
- }'
-
-
-Set clone URL for a directory of repos
---------------------------------------
- #!/bin/sh
- cd "$dir"
- for i in *; do
- test -d "$i" && echo "git://git.codemadness.org/$i" > "$i/url"
- done
-
-
-Update files on git push
-------------------------
-
-Using a post-receive hook the static files can be automatically updated.
-Keep in mind git push -f can change the history and the commits may need
-to be recreated. This is because stagit checks if a commit file already
-exists. It also has a cache (-c) option which can conflict with the new
-history. See stagit(1).
-
-git post-receive hook (repo/.git/hooks/post-receive):
-
- #!/bin/sh
- # detect git push -f
- force=0
- while read -r old new ref; do
- hasrevs=$(git rev-list "$old" "^$new" | sed 1q)
- if test -n "$hasrevs"; then
- force=1
- break
- fi
- done
-
- # remove commits and .cache on git push -f
- #if test "$force" = "1"; then
- # ...
- #fi
-
- # see example_create.sh for normal creation of the files.
-
-
-Create .tar.gz archives by tag
-------------------------------
- #!/bin/sh
- name="stagit"
- mkdir -p archives
- git tag -l | while read -r t; do
- f="archives/${name}-$(echo "${t}" | tr '/' '_').tar.gz"
- test -f "${f}" && continue
- git archive \
- --format tar.gz \
- --prefix "${t}/" \
- -o "${f}" \
- -- \
- "${t}"
- done
-
-
-Features
---------
-
-- Log of all commits from HEAD.
-- Log and diffstat per commit.
-- Show file tree with linkable line numbers.
-- Show references: local branches and tags.
-- Detect README and LICENSE file from HEAD and link it as a webpage.
-- Detect submodules (.gitmodules file) from HEAD and link it as a webpage.
-- Atom feed of the commit log (atom.xml).
-- Atom feed of the tags/refs (tags.xml).
-- Make index page for multiple repositories with stagit-index.
-- After generating the pages (relatively slow) serving the files is very fast,
- simple and requires little resources (because the content is static), only
- a HTTP file server is required.
-- Usable with text-browsers such as dillo, links, lynx and w3m.
-
-
-Cons
-----
-
-- Not suitable for large repositories (2000+ commits), because diffstats are
- an expensive operation, the cache (-c flag) is a workaround for this in
- some cases.
-- Not suitable for large repositories with many files, because all files are
- written for each execution of stagit. This is because stagit shows the lines
- of textfiles and there is no "cache" for file metadata (this would add more
- complexity to the code).
-- Not suitable for repositories with many branches, a quite linear history is
- assumed (from HEAD).
-
- In these cases it is better to just use cgit or possibly change stagit to
- run as a CGI program.
-
-- Relatively slow to run the first time (about 3 seconds for sbase,
- 1500+ commits), incremental updates are faster.
-- Does not support some of the dynamic features cgit has, like:
- - Snapshot tarballs per commit.
- - File tree per commit.
- - History log of branches diverged from HEAD.
- - Stats (git shortlog -s).
-
- This is by design, just use git locally.
+This is a fork of stagit v1.3 for GNUfault.org
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/favicon.png b/favicon.png
Binary files differ.
diff --git a/logo.png b/logo.png
Binary files differ.
diff --git a/stagit-index.c b/stagit-index.c
@@ -95,30 +95,25 @@ printtimeshort(FILE *fp, const git_time *intime)
void
writeheader(FILE *fp)
{
- fputs("<!DOCTYPE html>\n"
+ fputs("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n"
"<html>\n<head>\n"
- "<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, description, strlen(description));
- fprintf(fp, "</title>\n<link rel=\"icon\" type=\"image/png\" href=\"%sfavicon.png\" />\n", relpath);
- fprintf(fp, "<link rel=\"stylesheet\" type=\"text/css\" href=\"%sstyle.css\" />\n", relpath);
fputs("</head>\n<body>\n", fp);
- fprintf(fp, "<table>\n<tr><td><img src=\"%slogo.png\" alt=\"\" width=\"32\" height=\"32\" /></td>\n"
+ fprintf(fp, "<table>\n<tr><td></td>\n"
"<td><span class=\"desc\">", relpath);
xmlencode(fp, description, strlen(description));
fputs("</span></td></tr><tr><td></td><td>\n"
- "</td></tr>\n</table>\n<hr/>\n<div id=\"content\">\n"
- "<table id=\"index\"><thead>\n"
+ "</td></tr>\n</table>\n<hr/>\n"
+ "<table id=\"index\">\n"
"<tr><td><b>Name</b></td><td><b>Description</b></td><td><b>Owner</b></td>"
- "<td><b>Last commit</b></td></tr>"
- "</thead><tbody>\n", fp);
+ "<td><b>Last commit</b></td></tr>", fp);
}
void
writefooter(FILE *fp)
{
- fputs("</tbody>\n</table>\n</div>\n</body>\n</html>\n", fp);
+ fputs("</table>\n</body>\n</html>\n", fp);
}
int
diff --git a/stagit.c b/stagit.c
@@ -499,10 +499,8 @@ printtimeshort(FILE *fp, const git_time *intime)
void
writeheader(FILE *fp, const char *title)
{
- fputs("<!DOCTYPE html>\n"
+ fputs("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n"
"<html>\n<head>\n"
- "<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])
@@ -511,30 +509,18 @@ writeheader(FILE *fp, const char *title)
if (description[0])
fputs(" - ", fp);
xmlencode(fp, description, strlen(description));
- fprintf(fp, "</title>\n<link rel=\"icon\" type=\"image/png\" href=\"%sfavicon.png\" />\n", relpath);
- fputs("<link rel=\"alternate\" type=\"application/atom+xml\" title=\"", fp);
- xmlencode(fp, name, strlen(name));
- fprintf(fp, " Atom Feed\" href=\"%satom.xml\" />\n", relpath);
- fputs("<link rel=\"alternate\" type=\"application/atom+xml\" title=\"", fp);
- xmlencode(fp, name, strlen(name));
- 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);
- fputs("</td><td><h1>", fp);
- xmlencode(fp, strippedname, strlen(strippedname));
- fputs("</h1><span class=\"desc\">", fp);
+ fputs("</title>\n</head>\n<body>\n", fp);
+ fprintf(fp, "<b>%s</b><br/>\n", strippedname);
xmlencode(fp, description, strlen(description));
- fputs("</span></td></tr>", fp);
+ fputs("<br/>\n", fp);
+
if (cloneurl[0]) {
- fputs("<tr class=\"url\"><td></td><td>git clone <a href=\"", fp);
- xmlencode(fp, cloneurl, strlen(cloneurl)); /* not percent-encoded */
+ fputs("git clone <a href=\"", fp);
+ xmlencode(fp, cloneurl, strlen(cloneurl));
fputs("\">", fp);
xmlencode(fp, cloneurl, strlen(cloneurl));
- fputs("</a></td></tr>", fp);
+ fputs("</a><br/>\n", fp);
}
- fputs("<tr><td></td><td>\n", fp);
fprintf(fp, "<a href=\"%slog.html\">Log</a> | ", relpath);
fprintf(fp, "<a href=\"%sfiles.html\">Files</a> | ", relpath);
fprintf(fp, "<a href=\"%srefs.html\">Refs</a>", relpath);
@@ -547,7 +533,7 @@ writeheader(FILE *fp, const char *title)
if (license)
fprintf(fp, " | <a href=\"%sfile/%s.html\">LICENSE</a>",
relpath, license);
- fputs("</td></tr></table>\n<hr/>\n<div id=\"content\">\n", fp);
+ fputs("<hr/>\n", fp);
}
void
diff --git a/style.css b/style.css
@@ -1,154 +0,0 @@
-body {
- color: #000;
- background-color: #fff;
- font-family: monospace;
-}
-
-h1, h2, h3, h4, h5, h6 {
- font-size: 1em;
- margin: 0;
-}
-
-img, h1, h2 {
- vertical-align: middle;
-}
-
-img {
- border: 0;
-}
-
-a:target {
- background-color: #ccc;
-}
-
-a.d,
-a.h,
-a.i,
-a.line {
- text-decoration: none;
-}
-
-#blob a {
- color: #555;
-}
-
-#blob a:hover {
- color: blue;
- text-decoration: none;
-}
-
-table thead td {
- font-weight: bold;
-}
-
-table td {
- padding: 0 0.4em;
-}
-
-#content table td {
- vertical-align: top;
- white-space: nowrap;
-}
-
-#branches tr:hover td,
-#tags tr:hover td,
-#index tr:hover td,
-#log tr:hover td,
-#files tr:hover td {
- background-color: #eee;
-}
-
-#index tr td:nth-child(2),
-#tags tr td:nth-child(3),
-#branches tr td:nth-child(3),
-#log tr td:nth-child(2) {
- white-space: normal;
-}
-
-td.num {
- text-align: right;
-}
-
-.desc {
- color: #555;
-}
-
-hr {
- border: 0;
- border-top: 1px solid #555;
- height: 1px;
-}
-
-pre {
- font-family: monospace;
-}
-
-pre a.h {
- color: #00a;
-}
-
-.A,
-span.i,
-pre a.i {
- color: #070;
-}
-
-.D,
-span.d,
-pre a.d {
- color: #e00;
-}
-
-pre a.h:hover,
-pre a.i:hover,
-pre a.d:hover {
- text-decoration: none;
-}
-
-@media (prefers-color-scheme: dark) {
- body {
- background-color: #000;
- color: #bdbdbd;
- }
- hr {
- border-color: #222;
- }
- a {
- color: #56c8ff;
- }
- a:target {
- background-color: #222;
- }
- .desc {
- color: #aaa;
- }
- #blob a {
- color: #555;
- }
- #blob a:target {
- color: #eee;
- }
- #blob a:hover {
- color: #56c8ff;
- }
- pre a.h {
- color: #00cdcd;
- }
- .A,
- span.i,
- pre a.i {
- color: #00cd00;
- }
- .D,
- span.d,
- pre a.d {
- color: #cd0000;
- }
- #branches tr:hover td,
- #tags tr:hover td,
- #index tr:hover td,
- #log tr:hover td,
- #files tr:hover td {
- background-color: #111;
- }
-}