the static git browser that builds this site
git clone https://git.lucas.co/gitsite.git
post-commit hook: a commit pushes itself to GitHub
post-commit-push pushes the committed branch to origin, never forcing,
and reports a rejected push rather than hiding it; it stays quiet on a
detached HEAD or mid-rebase. install-hooks.sh symlinks it into every repo
in repos.conf so there is one copy to edit, and the readme's publishing
model says that a plain commit is now the publishing step.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
install-hooks.sh | 44 ++++++++++++++++++++++++++++++++++++++++++++
post-commit-push | 27 +++++++++++++++++++++++++++
readme.txt | 15 ++++++++++++++-
3 files changed, 85 insertions(+), 1 deletion(-)
diff --git a/install-hooks.sh b/install-hooks.sh
new file mode 100755
index 0000000..45f4d8d
--- /dev/null
+++ b/install-hooks.sh
@@ -0,0 +1,44 @@
+#!/bin/sh
+# Symlink post-commit-push into every repo listed in repos.conf, as its
+# post-commit hook. Safe to re-run: an existing symlink is refreshed, and a
+# hook that is a real file (someone's own) is left alone and reported.
+#
+# Work trees are found by NAME under $GIT_WORK_ROOTS, since repos.conf records
+# only where a repo is mirrored from. A name that resolves to nothing fails
+# the run rather than being skipped.
+set -eu
+
+BASE=$(dirname "$(readlink -f "$0")")
+HOOK="$BASE/post-commit-push"
+WORK_ROOTS="${GIT_WORK_ROOTS:-$HOME/projects/cce $HOME/projects}"
+FAILED=""
+
+names=$(grep -v '^#' "$BASE/repos.conf" | grep -v '^[[:space:]]*$' | cut -d'|' -f1)
+for name in $names; do
+ wt=""
+ for root in $WORK_ROOTS; do
+ if [ -d "$root/$name/.git" ]; then wt="$root/$name"; break; fi
+ done
+ if [ -z "$wt" ]; then
+ echo "!! $name: no work tree under $WORK_ROOTS"
+ FAILED="$FAILED $name"
+ continue
+ fi
+ hooks=$(git -C "$wt" rev-parse --path-format=absolute --git-path hooks)
+ dest="$hooks/post-commit"
+ if [ -e "$dest" ] && [ ! -L "$dest" ]; then
+ echo "!! $name: $dest exists and is not a symlink -- left alone"
+ FAILED="$FAILED $name"
+ continue
+ fi
+ mkdir -p "$hooks"
+ ln -sfn "$HOOK" "$dest"
+ echo " $name"
+done
+
+echo
+if [ -n "$FAILED" ]; then
+ echo "done, with failures:$FAILED"
+ exit 1
+fi
+echo "done: post-commit hook installed in every repo"
diff --git a/post-commit-push b/post-commit-push
new file mode 100755
index 0000000..758db53
--- /dev/null
+++ b/post-commit-push
@@ -0,0 +1,27 @@
+#!/bin/sh
+# post-commit hook: push the branch just committed to origin (GitHub).
+#
+# Installed into every repo in repos.conf by install-hooks.sh, as a symlink to
+# this file, so there is one copy to edit. It makes a commit also the
+# publishing step: without it, committing is local only and nothing reaches
+# GitHub (or git.lucas.co, which mirrors GitHub hourly) until a manual push.
+#
+# It never forces. If the push is rejected -- the branch moved on GitHub, the
+# network is down -- the commit stands and the message below says so; fix it
+# with an ordinary git pull / git push. Nothing is pushed on a detached HEAD
+# or while a rebase is replaying commits.
+
+branch=$(git symbolic-ref --quiet --short HEAD) || exit 0
+git_dir=$(git rev-parse --git-dir)
+if [ -d "$git_dir/rebase-merge" ] || [ -d "$git_dir/rebase-apply" ]; then
+ exit 0
+fi
+git remote get-url origin >/dev/null 2>&1 || exit 0
+
+if out=$(git push --quiet --set-upstream origin "$branch" 2>&1); then
+ echo "pushed $branch to origin"
+else
+ echo "post-commit: push of $branch FAILED -- the commit is local only:" >&2
+ printf '%s\n' "$out" | sed 's/^/ /' >&2
+fi
+exit 0
diff --git a/readme.txt b/readme.txt
index be78746..b029ced 100644
--- a/readme.txt
+++ b/readme.txt
@@ -20,6 +20,11 @@ autodeploy.sh
gitsite.service, gitsite.timer
systemd user units that run autodeploy.sh hourly — see
"Automatic publishing" below; nothing here installs them
+post-commit-push
+ git post-commit hook: pushes the committed branch to origin,
+ so committing is publishing -- see "Publishing model" below
+install-hooks.sh
+ symlinks post-commit-push into every repo in repos.conf
style.css matches lucas.co (black, white, blue links, Circe)
Workflow
@@ -59,6 +64,13 @@ GitHub (git ls-remote) whether any HEAD moved. So:
git push # the publishing step
# gitsite.timer then deploys it
+Every repo in repos.conf has post-commit-push installed as its post-commit
+hook (install-hooks.sh does that; re-run it after cloning a repo fresh or
+adding one), so in practice the push happens on commit and a plain commit
+IS the publishing step. The hook never forces: a rejected push leaves the
+commit local and says so, and you resolve it with git pull / git push as
+usual. It does nothing on a detached HEAD or mid-rebase.
+
The 27 crates pinned to https://git.lucas.co/<name>.git?rev=... keep
working because the dumb-http clone dirs are built from the same mirrors;
a rev exists here as long as it is reachable on GitHub.
@@ -97,4 +109,5 @@ Notes
(Cloudflare rejects files over 25MB). Delete a mirror dir to force a
fresh re-mirror.
- To add a repo: create it on GitHub (gh repo create lsgalante/<name>
- --public), push, add a line to repos.conf, run build.sh + deploy.sh.
+ --public), push, add a line to repos.conf, run install-hooks.sh, then
+ build.sh + deploy.sh.