From c526e5726bd154c208d521d824ef42c38fa7a412 Mon Sep 17 00:00:00 2001 From: olavostauros Date: Fri, 26 Jun 2026 13:52:14 -0300 Subject: [PATCH] fix(hooks): warn when preserved pre-commit hook does not dispatch pre-commit.d (#52) --- README.md | 4 ++-- lib/hooks.sh | 6 ++++++ test/hooks.bats | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7e7c766..ebf91ec 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Manage repo-level dependencies with an encrypted manifest and a gitignored clone A public observer sees only 'this repo uses modules' — no names, no pinned commits, no count. ![lang: bash](https://img.shields.io/badge/lang-bash-4EAA25?style=flat&logo=gnubash&logoColor=white) -[![tests: 136 passing](https://img.shields.io/badge/tests-136%20passing-brightgreen?style=flat)](test/) +[![tests: 138 passing](https://img.shields.io/badge/tests-138%20passing-brightgreen?style=flat)](test/) ![License: MIT](https://img.shields.io/badge/License-MIT-blue?style=flat) @@ -122,7 +122,7 @@ cd modules && mise trust && mise install mise run test ``` -**136 tests** across 13 suites, using [BATS](https://github.com/bats-core/bats-core). All tests use local git repos in temp directories — no network, no external dependencies. +**138 tests** across 13 suites, using [BATS](https://github.com/bats-core/bats-core). All tests use local git repos in temp directories — no network, no external dependencies. The `git-mechanics` suite verifies git's behavior around gitignored nested repos. The `merge-driver` suite simulates concurrent pin bumps to validate the manifest merge logic. The `roundtrip` suite drives the full setup → add → lock → fresh-clone → unlock → init path end-to-end with git-crypt. diff --git a/lib/hooks.sh b/lib/hooks.sh index f9cada6..6b4e9e0 100644 --- a/lib/hooks.sh +++ b/lib/hooks.sh @@ -21,6 +21,12 @@ install_pre_commit_hooks() { mkdir -p "$hooks_dst" cp "$hooks_src/dispatcher" "$hooks_dst/pre-commit" chmod +x "$hooks_dst/pre-commit" + elif ! grep -q 'pre-commit\.d' "$hooks_dst/pre-commit" 2>/dev/null; then + echo "Warning: existing pre-commit hook at $hooks_dst/pre-commit" >&2 + echo " does not dispatch pre-commit.d/. The modules guards were" >&2 + echo " installed but may not run until this hook invokes them." >&2 + echo " To use the default dispatcher: rm $hooks_dst/pre-commit && mise run install-hooks" >&2 + echo " To keep your hook: update it to iterate files in ${hooks_dst}/pre-commit.d/" >&2 fi mkdir -p "$hooks_dst/pre-commit.d" diff --git a/test/hooks.bats b/test/hooks.bats index eaf0e2d..89e9908 100644 --- a/test/hooks.bats +++ b/test/hooks.bats @@ -58,6 +58,40 @@ HOOK [ ! -e "$PARENT/.git/hooks/pre-commit.d/path-obfuscation" ] } +@test "setup warns when preserved pre-commit does not dispatch pre-commit.d" { + local fresh="$BATS_TEST_TMPDIR/no-dispatch" + create_parent_repo "$fresh" + cat > "$fresh/.git/hooks/pre-commit" <<'EOF' +#!/usr/bin/env bash +echo "my custom hook" +EOF + chmod +x "$fresh/.git/hooks/pre-commit" + + export MODULES_CALLER_PWD="$fresh" + run modules setup + + [ "$status" -eq 0 ] + echo "$output" | grep -q "does not dispatch pre-commit.d" +} + +@test "setup quiet when preserved pre-commit dispatches pre-commit.d" { + local fresh="$BATS_TEST_TMPDIR/dispatches" + create_parent_repo "$fresh" + cat > "$fresh/.git/hooks/pre-commit" <<'DISPATCH' +#!/usr/bin/env bash +for hook in "$(dirname "$0")/pre-commit.d"/*; do + [ -x "$hook" ] && "$hook" || exit $? +done +DISPATCH + chmod +x "$fresh/.git/hooks/pre-commit" + + export MODULES_CALLER_PWD="$fresh" + run modules setup + + [ "$status" -eq 0 ] + ! echo "$output" | grep -q "does not dispatch pre-commit.d" +} + @test "setup removes obsolete path-obfuscation hook if present" { # Simulate upgrading from an old layout where path-obfuscation was installed cat > "$PARENT/.git/hooks/pre-commit.d/path-obfuscation" <<'EOF'