Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

</div>
Expand Down Expand Up @@ -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.

Expand Down
6 changes: 6 additions & 0 deletions lib/hooks.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
34 changes: 34 additions & 0 deletions test/hooks.bats
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
Loading