kingfisher/scripts/install-kingfisher-pre-commit.sh
2025-12-12 17:21:17 -08:00

154 lines
3.3 KiB
Bash
Executable file

#!/usr/bin/env bash
set -euo pipefail
usage() {
cat <<'USAGE'
Usage: install-kingfisher-pre-commit.sh [--global] [--hooks-path PATH] [--uninstall]
Installs a Git pre-commit hook that runs Kingfisher.
Modes:
(default) Install in the current repo.
--global Install in the global Git hooks directory.
--hooks-path Override hooks directory (repo only).
--uninstall Remove the installed hook.
USAGE
}
GLOBAL=false
UNINSTALL=false
HOOKS_PATH=""
while [[ $# -gt 0 ]]; do
case "$1" in
--global)
GLOBAL=true
shift
;;
--hooks-path)
HOOKS_PATH="$2"
shift 2
;;
--uninstall)
UNINSTALL=true
shift
;;
-h|--help)
usage
exit 0
;;
*)
echo "Unknown option: $1" >&2
usage
exit 1
;;
esac
done
# ------------------------------
# Determine hooks directory
# ------------------------------
if $GLOBAL; then
GLOBAL_PATH="$(git config --global core.hooksPath || true)"
if [[ -z "$GLOBAL_PATH" ]]; then
GLOBAL_PATH="$HOME/.git-hooks"
git config --global core.hooksPath "$GLOBAL_PATH"
echo "Configured global Git hooks at $GLOBAL_PATH"
fi
HOOKS_PATH="$GLOBAL_PATH"
else
if [[ -z "$HOOKS_PATH" ]]; then
if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
HOOKS_PATH="$(git rev-parse --git-path hooks)"
else
HOOKS_PATH="$PWD/.git/hooks"
echo "Git repository not detected; using fallback hooks path $HOOKS_PATH"
fi
fi
fi
mkdir -p "$HOOKS_PATH"
PRE_COMMIT="$HOOKS_PATH/pre-commit"
LEGACY="$HOOKS_PATH/pre-commit.legacy.kingfisher"
KF_HOOK="$HOOKS_PATH/kingfisher-pre-commit"
MARKER="# Kingfisher pre-commit wrapper"
# ------------------------------
# Uninstall
# ------------------------------
uninstall() {
if [[ -f "$PRE_COMMIT" ]] && grep -q "$MARKER" "$PRE_COMMIT"; then
if [[ -f "$LEGACY" ]]; then
mv "$LEGACY" "$PRE_COMMIT"
chmod +x "$PRE_COMMIT"
echo "Restored previous pre-commit hook from $LEGACY"
else
rm -f "$PRE_COMMIT"
echo "Removed Kingfisher pre-commit wrapper."
fi
fi
rm -f "$KF_HOOK" "$LEGACY"
echo "Kingfisher pre-commit hook uninstalled."
}
if $UNINSTALL; then
uninstall
exit 0
fi
# ------------------------------
# Create Kingfisher hook
# ------------------------------
cat > "$KF_HOOK" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
if ! command -v kingfisher >/dev/null 2>&1; then
echo "Kingfisher is not on PATH; skipping scan." >&2
exit 0
fi
repo_root="$(git rev-parse --show-toplevel)"
cd "$repo_root"
kingfisher scan . --staged --quiet --no-update-check
EOF
chmod +x "$KF_HOOK"
# ------------------------------
# Preserve existing hook only if it exists
# ------------------------------
if [[ -f "$PRE_COMMIT" ]]; then
if ! grep -q "$MARKER" "$PRE_COMMIT"; then
mv "$PRE_COMMIT" "$LEGACY"
chmod +x "$LEGACY"
echo "Existing pre-commit hook preserved at $LEGACY"
fi
fi
# ------------------------------
# Install wrapper
# ------------------------------
cat > "$PRE_COMMIT" <<EOF
#!/usr/bin/env bash
$MARKER
set -euo pipefail
legacy_hook="$LEGACY"
kf_hook="$KF_HOOK"
if [[ -f "\$legacy_hook" && -x "\$legacy_hook" ]]; then
"\$legacy_hook" "\$@"
fi
"\$kf_hook" "\$@"
EOF
chmod +x "$PRE_COMMIT"
echo "Kingfisher pre-commit hook installed at $PRE_COMMIT"
if [[ -f "$LEGACY" ]]; then
echo "Existing hook will run first from $LEGACY"
fi