set -euo pipefail
if ! command -v git-format-staged >/dev/null 2>&1; then
echo "error: git-format-staged is required for the pre-commit hook" >&2
echo "install it or bypass with git commit --no-verify" >&2
exit 1
fi
stash_created=0
install_companion_hooks() {
local repo_root
repo_root="$(git rev-parse --show-toplevel)"
"$repo_root/scripts/install-git-hook-shims" commit-msg pre-push
}
staged_paths_are_docs_or_media_only() {
local path
local found=0
while IFS= read -r path; do
found=1
case "${path,,}" in
docs/*|*.md|*.markdown|*.avif|*.gif|*.jpeg|*.jpg|*.png|*.svg|*.webp) ;;
*) return 1 ;;
esac
done < <(git diff --cached --name-only --diff-filter=ACMRD)
[[ "$found" -eq 1 ]]
}
restore_unstaged() {
local status=$?
if [[ "$stash_created" -eq 1 ]]; then
if ! git stash pop --quiet; then
echo "error: failed to restore unstaged changes after pre-commit checks" >&2
echo "resolve the stash conflict, then run git stash drop when finished" >&2
status=1
fi
fi
exit "$status"
}
trap restore_unstaged EXIT
hide_unstaged_changes() {
if git diff --quiet --ignore-submodules -- && [[ -z "$(git ls-files --others --exclude-standard)" ]]; then
return 0
fi
git stash push --quiet --keep-index --include-untracked -m "pre-commit unstaged changes"
stash_created=1
}
install_companion_hooks
git-format-staged
hide_unstaged_changes
if staged_paths_are_docs_or_media_only; then
echo "skip pre-commit checks: only documentation or media files staged"
exit 0
fi
if ! just pre-commit; then
echo "pre-commit checks failed" >&2
echo "if clippy reported fixable lints, run: just clippy-fix" >&2
echo "review and stage any fixes, then commit again" >&2
exit 1
fi