git-repo

Tools for sharing git bare repositories
git clone git://git.meso-star.fr/git-repo.git
Log | Files | Refs | README | LICENSE

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:
MMakefile | 1+
Mgit-publish | 43++++++++++++++++++++++++++++++++++++++++++-
Mgit-publish.1 | 10----------
Mpost-receive.in | 45+++++++++++++++++++++++++++++++++++++++++----
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