1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677 | #!/bin/sh
# post-receive hook for Repo Renderer. contrib/new-repo links each
# repository's hooks/post-receive to this one file.
#
# A push does two things, each only if the repository's git config asks
# for it:
#
# repo-render.config the renderer's config: queue a job for each branch
# and tag pushed, and start repo-render kick, which
# renders them
# repo-render.program the repo-render to run (default: repo-render on
# PATH)
# repo-render.mirror a git URL to push to, one per mirror: the default
# branch, forced, and every tag. Never --mirror,
# which would delete what only the mirror has.
# ssh runs as core.sshCommand says, if set, and
# otherwise never prompts, gives up on a
# connection that hangs, and checks host keys
# against ssh's known_hosts files.
#
# It must return in milliseconds, so the render and the mirror pushes run
# in the background. Nothing from the client is trusted except ref names
# and SHAs, which enqueue and the renderer both validate. Mirror failures
# go to syslog (logger -t repo-render-mirror), and the next push retries.
# The repository's name comes from its directory on disk, which the
# client can't influence.
repo=$(basename "$(cd "${GIT_DIR:-.}" && pwd -P)" .git)
case "$repo" in
""|.*|*[!A-Za-z0-9._-]*) exit 0 ;;
esac
# Run in the background below, as "post-receive mirror".
if [ "${1-}" = mirror ]; then
branch=$(git symbolic-ref --short HEAD) || exit 1
if [ -z "$(git config core.sshCommand)" ]; then
GIT_SSH_COMMAND="ssh -o BatchMode=yes -o StrictHostKeyChecking=yes -o ConnectTimeout=30 -o ServerAliveInterval=15 -o ServerAliveCountMax=4"
export GIT_SSH_COMMAND
fi
git config --get-all repo-render.mirror | while read -r url; do
if git push --no-verify --quiet -- "$url" "+refs/heads/$branch:refs/heads/$branch" "refs/tags/*:refs/tags/*" </dev/null 2>&1; then
echo "$repo: mirrored to $url"
else
echo "$repo: mirror to $url failed (the next push retries)"
fi
done
exit 0
fi
program=$(git config repo-render.program) || program="repo-render"
config=$(git config repo-render.config) || config=""
pushed=""
while read -r old new ref; do
case "$ref" in
refs/heads/*|refs/tags/*)
pushed=1
# enqueue locks against the renderer claiming the queue, so
# no job is lost to a push that races a running kick.
if [ -n "$config" ]; then
"$program" --config "$config" enqueue "$repo" "$ref" "$old" "$new"
fi
;;
esac
done
[ -n "$pushed" ] || exit 0
if [ -n "$config" ]; then
nohup "$program" --config "$config" kick </dev/null >/dev/null 2>&1 &
fi
if git config --get-all repo-render.mirror >/dev/null; then
# nohup on the shell, so that both ends of the pipe ignore hangups.
# shellcheck disable=SC2016 # $0 expands in that shell
nohup sh -c 'if command -v logger >/dev/null 2>&1; then "$0" mirror 2>&1 | logger -t repo-render-mirror; else "$0" mirror; fi' "$0" \
</dev/null >/dev/null 2>&1 &
fi
exit 0
|