#!/bin/sh set -eu ROOT_DIR=$(git rev-parse --show-toplevel) cd "$ROOT_DIR" TMP_DIR=${TMPDIR:-/tmp}/nex-hooks-test.$$ mkdir -p "$TMP_DIR" cleanup() { rm -f \ backend/pkg/buildinfo/hook_bad_test_fixture.go \ frontend/src/hook_bad_fixture.ts \ frontend/src/hook_format_fixture.ts \ docs/hook-doc-fixture.md \ docs/hook-conflict-fixture.md \ docs/hook-large-fixture.txt rm -rf "$TMP_DIR" } trap cleanup EXIT HUP INT TERM pass() { printf 'OK: %s\n' "$1" } fail() { printf 'FAIL: %s\n' "$1" >&2 exit 1 } write_msg() { file=$1 shift printf '%s\n' "$*" > "$file" } expect_success() { name=$1 shift if "$@" > "$TMP_DIR/out" 2>&1; then pass "$name" else cat "$TMP_DIR/out" >&2 fail "$name" fi } expect_failure() { name=$1 shift if "$@" > "$TMP_DIR/out" 2>&1; then cat "$TMP_DIR/out" >&2 fail "$name" fi pass "$name" } run_precommit_for() { index=$TMP_DIR/index rm -f "$index" GIT_INDEX_FILE=$index git read-tree HEAD for file in "$@"; do GIT_INDEX_FILE=$index git add -f "$file" done GIT_INDEX_FILE=$index make _hooks-pre-commit } MSG_FILE=$TMP_DIR/commit-msg.txt write_msg "$MSG_FILE" 'feat: 添加 hook 测试' expect_success 'commit-msg accepts Chinese description' scripts/git-hooks/commit-msg "$MSG_FILE" write_msg "$MSG_FILE" 'feat: add hook tests' expect_failure 'commit-msg rejects English-only description' scripts/git-hooks/commit-msg "$MSG_FILE" write_msg "$MSG_FILE" 'update: 添加 hook 测试' expect_failure 'commit-msg rejects invalid type' scripts/git-hooks/commit-msg "$MSG_FILE" write_msg "$MSG_FILE" 'Merge branch feature' expect_success 'commit-msg accepts merge commits' scripts/git-hooks/commit-msg "$MSG_FILE" cat > backend/pkg/buildinfo/hook_bad_test_fixture.go <<'EOF' package buildinfo import "fmt" func hookBadTestFixture() { fmt.Println("bad") } EOF expect_failure 'pre-commit rejects Go lint errors' run_precommit_for backend/pkg/buildinfo/hook_bad_test_fixture.go rm -f backend/pkg/buildinfo/hook_bad_test_fixture.go cat > frontend/src/hook_bad_fixture.ts <<'EOF' console.log('bad') EOF expect_failure 'pre-commit rejects frontend lint errors' run_precommit_for frontend/src/hook_bad_fixture.ts rm -f frontend/src/hook_bad_fixture.ts cat > frontend/src/hook_format_fixture.ts <<'EOF' const hookFormatFixture={foo:"bar"} export { hookFormatFixture } EOF expect_failure 'pre-commit rejects frontend format errors' run_precommit_for frontend/src/hook_format_fixture.ts rm -f frontend/src/hook_format_fixture.ts cat > docs/hook-doc-fixture.md <<'EOF' hook doc fixture EOF expect_success 'pre-commit skips non-code staged files' run_precommit_for docs/hook-doc-fixture.md rm -f docs/hook-doc-fixture.md cat > docs/hook-conflict-fixture.md <<'EOF' <<<<<<< HEAD conflict ======= other >>>>>>> branch EOF expect_failure 'pre-commit rejects conflict markers' run_precommit_for docs/hook-conflict-fixture.md rm -f docs/hook-conflict-fixture.md i=0 while [ "$i" -lt 40000 ]; do printf 'large hook fixture line\n' i=$((i + 1)) done > docs/hook-large-fixture.txt if run_precommit_for docs/hook-large-fixture.txt > "$TMP_DIR/out" 2>&1 && grep -q 'Warning: large staged text file' "$TMP_DIR/out"; then pass 'pre-commit warns for large text files' else cat "$TMP_DIR/out" >&2 fail 'pre-commit warns for large text files' fi rm -f docs/hook-large-fixture.txt