`scripts/reindent.sh` and `scripts/hooks/pre-commit` each carried their own copy of the directory list, and neither included `tools` or `examples`. Both hold ordinary hand-written C, so `--check` reported a clean tree without having looked at them and the hook let them through unformatted -- which defeats the one thing that keeps this tree a fixed point of `indent-region`. The comment in `reindent.sh` already said the scope is "directories whose C sources are hand-maintained", so this is the list catching up with the stated intent rather than a new policy. The two copies are now marked as being two copies of one decision, because they have already disagreed once and nothing detects it when they do. `scripts/reindent.sh --check` is clean with the wider scope. Co-Authored-By: Claude Code <noreply@anthropic.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
103 lines
3.2 KiB
Bash
Executable File
103 lines
3.2 KiB
Bash
Executable File
#!/bin/sh
|
|
#
|
|
# Reindent staged C sources to the canonical style before the commit is made.
|
|
# See AGENTS.md -> "Coding Style".
|
|
#
|
|
# Enable with:
|
|
# git config core.hooksPath scripts/hooks
|
|
# Bypass a single commit with `git commit --no-verify`.
|
|
#
|
|
# The hook checks the *staged* content, not the working tree, so what gets
|
|
# committed is what was verified. When a file needs reindenting it is fixed in
|
|
# the working tree and re-staged -- but only when the working tree and the index
|
|
# agree for that file. If they disagree (a partial `git add -p`), re-staging
|
|
# would sweep unstaged work into the commit, so the hook stops and asks you to
|
|
# do it yourself.
|
|
|
|
set -eu
|
|
|
|
root=$(git rev-parse --show-toplevel)
|
|
reindent="$root/scripts/reindent.sh"
|
|
|
|
# Leave conflict resolution alone.
|
|
if [ -e "$root/.git/MERGE_HEAD" ]; then
|
|
exit 0
|
|
fi
|
|
|
|
if [ ! -x "$reindent" ]; then
|
|
echo "pre-commit: $reindent missing or not executable; skipping style check" >&2
|
|
exit 0
|
|
fi
|
|
|
|
# Without Emacs the canonical style cannot be applied or even checked. Warn
|
|
# rather than block: a hook that fails closed on a missing optional tool just
|
|
# teaches everyone to pass --no-verify.
|
|
if ! command -v emacs >/dev/null 2>&1; then
|
|
echo "pre-commit: emacs not found; skipping reindent (see AGENTS.md)" >&2
|
|
exit 0
|
|
fi
|
|
|
|
# Keep this list in step with SCOPE in scripts/reindent.sh. They are two copies
|
|
# of one decision, and they have already disagreed once: `tools` and `examples`
|
|
# arrived with the documentation harness and were reindentable by hand while
|
|
# neither this hook nor `--check` could see them.
|
|
staged=$(git diff --cached --name-only --diff-filter=ACMR \
|
|
| grep -E '^(src|include|tests|util|tools|examples)/.*\.[ch]$' \
|
|
| grep -v -x -F 'include/akgl/SDL_GameControllerDB.h' || true)
|
|
|
|
if [ -z "$staged" ]; then
|
|
exit 0
|
|
fi
|
|
|
|
tmp=$(mktemp -d)
|
|
trap 'rm -rf "$tmp"' EXIT INT TERM
|
|
|
|
# Reindent a copy of each file's staged content and see whether it moves.
|
|
needs=''
|
|
for f in $staged; do
|
|
copy="$tmp/$(printf '%s' "$f" | tr '/' '_')"
|
|
git show ":$f" >"$copy"
|
|
cp "$copy" "$copy.orig"
|
|
if ! "$reindent" "$copy" >/dev/null 2>&1; then
|
|
echo "pre-commit: reindent failed on $f; commit aborted" >&2
|
|
exit 1
|
|
fi
|
|
if ! cmp -s "$copy" "$copy.orig"; then
|
|
needs="$needs $f"
|
|
fi
|
|
done
|
|
|
|
if [ -z "$needs" ]; then
|
|
exit 0
|
|
fi
|
|
|
|
# Refuse to touch anything if even one file is partially staged.
|
|
blocked=''
|
|
for f in $needs; do
|
|
if ! git diff --quiet -- "$f"; then
|
|
blocked="$blocked $f"
|
|
fi
|
|
done
|
|
|
|
if [ -n "$blocked" ]; then
|
|
echo "pre-commit: these files need reindenting but have unstaged changes," >&2
|
|
echo "so re-staging them would pull unstaged work into the commit:" >&2
|
|
for f in $blocked; do echo " $f" >&2; done
|
|
echo >&2
|
|
echo "Reindent and stage them yourself, then commit again:" >&2
|
|
echo " scripts/reindent.sh$(for f in $blocked; do printf ' %s' "$f"; done)" >&2
|
|
echo " git add$(for f in $blocked; do printf ' %s' "$f"; done)" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Safe: for every file needing work, the index and working tree agree.
|
|
# shellcheck disable=SC2086
|
|
"$reindent" $needs
|
|
# shellcheck disable=SC2086
|
|
git add $needs
|
|
|
|
echo "pre-commit: reindented and re-staged:" >&2
|
|
for f in $needs; do echo " $f" >&2; done
|
|
|
|
exit 0
|