Skip to content

Commit ee679e7

Browse files
committed
chore: harden pre-commit hook (tracked .githooks/ + core.hooksPath)
Replace the dev-shell installer that wrote .git/hooks/pre-commit with a tracked .githooks/pre-commit wired via `git config core.hooksPath .githooks`. Fixes three issues with the old hook: it gated on `[ -d .git ]` (false in worktrees/submodules where .git is a file), it clobbered any existing .git/hooks/pre-commit on every `nix develop`, and `nix fmt … || exit 0` swallowed real formatter failures. The new hook skips only when `nix` is absent (CI is the authoritative gate) and otherwise blocks on a `nix fmt` failure or reformat.
1 parent 10838df commit ee679e7

3 files changed

Lines changed: 23 additions & 17 deletions

File tree

.githooks/pre-commit

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/usr/bin/env bash
2+
# Content-based format gate. CI's `nix fmt && git diff --exit-code` is
3+
# authoritative; this hook is just a local convenience.
4+
#
5+
# Tracked under .githooks/ and wired via `git config core.hooksPath .githooks`
6+
# in the dev-shell shellHook — robust across git worktrees and submodules
7+
# (where .git is a file) and it never clobbers a developer's .git/hooks.
8+
set -u
9+
command -v nix >/dev/null 2>&1 || exit 0 # no nix here → skip; CI still gates
10+
11+
before=$(git diff)
12+
if ! nix fmt >/dev/null 2>&1; then
13+
echo "pre-commit: 'nix fmt' failed — fix the formatter error, then commit." >&2
14+
exit 1
15+
fi
16+
if [ "$before" != "$(git diff)" ]; then
17+
echo "pre-commit: 'nix fmt' reformatted files — re-stage them, then commit." >&2
18+
exit 1
19+
fi

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@
33
!/.github/
44
!/.tidyrc.json
55
!/.lua-format
6+
!/.githooks/
67
/output/

flake.nix

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -48,23 +48,9 @@
4848
spago-bin.spago-0_21_0
4949
treefmt
5050
];
51-
# Install a content-based pre-commit hook. It compares the working
52-
# tree diff before and after `nix fmt`, so it only objects to changes
53-
# the formatter itself introduces (not the developer's existing
54-
# unstaged work) and is not fooled by formatters that only bump mtime.
55-
# Rewritten each shell entry to stay in sync with this flake.
56-
shellHook = ''
57-
hook=.git/hooks/pre-commit
58-
if [ -d .git ]; then
59-
printf '%s\n' \
60-
'#!/usr/bin/env bash' \
61-
'before=$(git diff)' \
62-
'nix fmt >/dev/null 2>&1 || exit 0' \
63-
'[ "$before" = "$(git diff)" ] || { echo "nix fmt changed files; re-stage them, then commit." >&2; exit 1; }' \
64-
> "$hook"
65-
chmod +x "$hook"
66-
fi
67-
'';
51+
# Robust pre-commit hook: point git at the tracked .githooks/ dir
52+
# (worktree/submodule-safe; never clobbers an existing .git/hooks).
53+
shellHook = "git config core.hooksPath .githooks";
6854
};
6955
}
7056
);

0 commit comments

Comments
 (0)