commit 574532787a9a7fba1ce8174d418f997d35cec8f9 parent cfc8cccf25f73f933a86f23b30ba928accd506ef Author: Fred Großkopf <fred@kuandu.systems> Date: Wed, 15 Apr 2026 13:05:34 +0200 Adds symlink-git-hook.sh A helper script to symlink a git hook file to a directory of git repositories. Diffstat:
| A | symlink-git-hook.sh | | | 74 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 74 insertions(+), 0 deletions(-)
diff --git a/symlink-git-hook.sh b/symlink-git-hook.sh @@ -0,0 +1,74 @@ +#!/bin/sh + +set -eu + +usage() { + cat << EOF >&2 +Usage: $0 HOOK_FILE GIT_DIR +EOF + exit 1 +} + +error() { + printf 'error: %s\n' "$1" >&2 + exit 1 +} + +info() { + printf 'info: %s\n' "$1" +} + +check_args() { + [ $# -eq 2 ] || usage + HOOK_FILE="$1" + GIT_DIR="$2" +} + +check_hook_file() { + [ -f "$HOOK_FILE" ] || error "hook missing: $HOOK_FILE" + [ -x "$HOOK_FILE" ] || error "hook not executable: $HOOK_FILE" +} + +check_git_dir() { + [ -d "$GIT_DIR" ] || error "Git directory not found: $GIT_DIR" + [ -n "$(ls "$GIT_DIR"/*.git 2> /dev/null)" ] || error "no *.git repos in $GIT_DIR" +} + +install_hook() { + repo="$1" + hook_name="$2" + hook_file="$3" + target="$repo/hooks/$hook_name" + + if [ -L "$target" ] && [ "$(readlink "$target")" = "$hook_file" ]; then + info "$(basename "$repo")/$hook_name: up-to-date" + return 1 + fi + + rm -f "$target" + ln -sf "$hook_file" "$target" + info "$(basename "$repo")/$hook_name: deployed" + return 0 +} + +main() { + check_args "$@" + check_hook_file + check_git_dir + + hook_name="$(basename "$HOOK_FILE")" + changed=0 + + for repo in "$GIT_DIR"/*.git; do + [ -d "$repo" ] || continue + install_hook "$repo" "$hook_name" "$HOOK_FILE" && changed=$((changed + 1)) + done + + if [ "$changed" -eq 0 ]; then + info "All repositories up-to-date" + else + info "Deployed/updated $changed repositories" + fi +} + +main "$@"