Files
2026-07-13 12:49:17 +08:00

85 lines
2.0 KiB
Bash
Executable File

#!/usr/bin/env bash
# Installs the repo's git hooks into .git/hooks/.
#
# Usage:
# tools/install-hooks.sh # install missing hooks (preserves existing ones)
# tools/install-hooks.sh --force # overwrite any existing hooks
# tools/install-hooks.sh --uninstall # remove hooks that match the ones we installed
set -euo pipefail
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
SRC_DIR="${REPO_ROOT}/tools/hooks"
DST_DIR="${REPO_ROOT}/.git/hooks"
if [[ ! -d "$DST_DIR" ]]; then
echo "error: $DST_DIR not found — is this a git checkout?" >&2
exit 2
fi
if [[ ! -d "$SRC_DIR" ]]; then
echo "error: $SRC_DIR missing" >&2
exit 2
fi
FORCE=0
UNINSTALL=0
for arg in "$@"; do
case "$arg" in
--force) FORCE=1 ;;
--uninstall) UNINSTALL=1 ;;
-h|--help)
sed -n '2,7p' "$0" | sed 's/^# \{0,1\}//'
exit 0 ;;
*) echo "Unknown argument: $arg" >&2; exit 2 ;;
esac
done
installed=0
skipped=0
removed=0
for src in "$SRC_DIR"/*; do
[[ -e "$src" ]] || continue
name="$(basename "$src")"
dst="$DST_DIR/$name"
if [[ $UNINSTALL -eq 1 ]]; then
if [[ -e "$dst" ]] && cmp -s "$src" "$dst"; then
rm -f "$dst"
echo " removed $dst"
removed=$((removed + 1))
else
echo " skipped $dst (not our hook, or absent)"
fi
continue
fi
if [[ -e "$dst" && $FORCE -ne 1 ]]; then
if cmp -s "$src" "$dst"; then
echo " ok $dst (already up to date)"
skipped=$((skipped + 1))
else
echo " skipped $dst (exists and differs — use --force to overwrite)"
skipped=$((skipped + 1))
fi
continue
fi
cp "$src" "$dst"
chmod +x "$dst"
echo " installed $dst"
installed=$((installed + 1))
done
if [[ $UNINSTALL -eq 1 ]]; then
echo
echo "Summary: $removed hook(s) removed"
else
echo
echo "Summary: $installed installed, $skipped skipped"
if [[ $installed -gt 0 ]]; then
echo
echo "Hooks are active. To bypass for a single push: git push --no-verify"
fi
fi