commit 133fe0206b9aacba626f632b0cb3663a81949e62
parent 2c898721c6a63b2b104e08588ee402882afea357
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Fri, 30 May 2025 17:39:17 +0200
git-publish: ensures HTML index consistency
Until now, all bare repositories served publicly by git were assumed to
have their own HTML pages. This commit removes this assumption: the
index lists only those repositories that are publicly exposed by both
git and the web server.
Diffstat:
4 files changed, 84 insertions(+), 15 deletions(-)
diff --git a/Makefile b/Makefile
@@ -57,5 +57,6 @@ uninstall:
lint:
shellcheck -o all git-publish
shellcheck -o all git-repo
+ shellcheck -o all post-receive.in
mandoc -Wbase -Tlint git-publish.1 || [ $$? -le 1 ];
mandoc -Wbase -Tlint git-repo.1
diff --git a/git-publish b/git-publish
@@ -150,6 +150,47 @@ setup_post_receive_hook()
chmod 755 "${repo}/hooks/post-receive"
}
+# Create an index from the list of directories in 'dir_www' that
+# correspond to the list of bare repositories in 'dir_git'.
+#
+# Inputs:
+# - dir_git: directory where to publish the git repository
+# - dir_www: directory where to publish the git repository's HTML pages
+make_index()
+{
+ tmpfile="${TMPDIR:-/tmp}/git-publish-index.txt"
+
+ # Removes trailing slashes. This allows you to write the following
+ # regular expressions for find directives
+ dir=$(dirname "${dir_www}")
+ www=$(basename "${dir_www}")
+ dir_www="${dir}/${www}"
+ dir=$(dirname "${dir_git}")
+ git=$(basename "${dir_git}")
+ dir_git="${dir}/${git}"
+
+ # Build list of candidate git repositories from the directories of the
+ # publicly exposed WWW directory
+ find "${dir_www}" -type d -path "${dir_www}/*" -prune \
+ -exec sh -c "
+ printf '%s\n' \"\$@\" \
+ | sed 's;${dir_www}/\(.\{1,\}\)$;${dir_git}/\1.git;' \
+ | sort" \
+ -- {} + > "${tmpfile}"
+
+ # Compare the candidate list to the list of publicly exposed git
+ # repositories. The intersection corresponds to the repositories to
+ # exposed in the HTML index
+ repo_list=$(find "${dir_git}" -path "${dir_git}/*.git" -prune | sort \
+ | join - "${tmpfile}" | tr '\n' ' ')
+
+ # Generate the index
+ # shellcheck disable=SC2086
+ stagit-index ${repo_list} > "${dir_www}/index.html"
+
+ rm -f "${tmpfile}"
+}
+
########################################################################
# The script
########################################################################
@@ -192,6 +233,6 @@ printf '%s\n' "$@" | while read -r repo; do
done
# [Re]generate index of publicly exposed repositories
-stagit-index "${dir_git}/"*/ > "${dir_www}/index.html"
+make_index
die 0
diff --git a/git-publish.1 b/git-publish.1
@@ -44,16 +44,6 @@ To make sure they're up to date, a post-receipt hook is added to
published repositories to update HTML pages on new commits
.Pq see Xr githooks 5
.Pp
-.Nm
-assumes that all publicly accessible repositories also have their own
-set of HTML pages.
-In other words, they have been made public via
-.Nm .
-The HTML index is therefore generated from all publicly accessible git
-repositories.
-If this constraint is not met, some entries in the index will refer to
-an invalid URL.
-.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl f
diff --git a/post-receive.in b/post-receive.in
@@ -1,6 +1,7 @@
#!/bin/sh
# Copyright (c) 2015-2024 Hiltjo Posthuma <hiltjo@codemadness.org>
+# Copyright (c) 2025 |Méso|Star> <contact@meso-star.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
@@ -33,7 +34,7 @@ export LC_CTYPE="en_US.UTF-8"
name="$1"
if test "${name}" = ""; then
- name=$(basename "$(pwd)")
+ name=$(basename "${PWD}")
fi
# config
@@ -46,6 +47,42 @@ destdir="${htmldir}${stagitdir}"
cachefile=".cache"
# /config
+# Create an index from the list of directories in 'destdir' that correspond to
+# the list of bare repositories in 'reposdir'.
+make_index()
+{
+ tmpfile="${TMPDIR:-/tmp}/git-publish-index.txt"
+
+ # Removes trailing slashes. This allows you to write the following
+ # regular expressions for find directives
+ dir__=$(dirname "${reposdir}")
+ git__=$(basename "${reposdir}")
+ reposdir="${dir__}/${www__}"
+ dir__=$(dirname "${destdir}")
+ www__=$(basename "${destdir}")
+ destdir="${dir__}/${git__}"
+
+ # Build list of candidate git repositories from the directories
+ # of the publicly exposed WWW directory
+ find "${destdir}" -type d -path "${destdir}/*" -prune \
+ -exec sh -c "
+ printf '%s\n' \"\$@\" \
+ | sed 's;${destdir}/\(.\{1,\}\)$;${reposdir}/\1.git;' \
+ | sort" -- {} + > "${tmpfile}"
+
+ # Compare the candidate list to the list of publicly exposed git
+ # repositories. The intersection corresponds to the repositories
+ # to exposed in the HTML index
+ repo_list=$(find "${reposdir}" -path "${reposdir}/*.git" -prune | sort \
+ | join - "${tmpfile}" | tr '\n' ' ')
+
+ # Generate the index
+ # shellcheck disable=SC2086
+ stagit-index ${repo_list} > "${destdir}/index.html"
+
+ rm -f "${tmpfile}"
+}
+
if ! test -d "${dir}"; then
echo "${dir} does not exist" >&2
exit 1
@@ -54,6 +91,7 @@ cd "${dir}" || exit 1
# detect git push -f
force=0
+# shellcheck disable=SC2034
while read -r old new ref; do
test "${old}" = "0000000000000000000000000000000000000000" && continue
test "${new}" = "0000000000000000000000000000000000000000" && continue
@@ -79,11 +117,10 @@ if test "${force}" = "1"; then
rm -rf "commit"
fi
-# make index.
-stagit-index "${reposdir}/"*/ > "${destdir}/index.html"
+make_index
# make pages.
-stagit -c "${cachefile}" -u "@BASE_URL@/$d/" "${reposdir}/${r}"
+stagit -c "${cachefile}" -u "@BASE_URL@/${d}/" "${reposdir}/${r}"
ln -sf './log.html' ./index.html
ln -sf '../style.css' ./style.css