#!/usr/bin/env bash # Regression matrix for git-guard.py: `bash ~/.claude/hooks/git-guard-test.sh` (exit 1 on mismatch). # Kept as a file on purpose: typed inline, the very commands under test would trip the live hook. G="$(dirname "$(readlink -f "$0")")/git-guard.py"; fail=0 # `git reset ` is allowed only for an existing path: give the matrix one to point at. tmp=$(mktemp -d) && cd "$tmp" && touch existing.py trap 'rm -rf "$tmp"' EXIT run() { printf '%s' "{\"tool_name\":\"Bash\",\"tool_input\":{\"command\":$(python3 -c 'import json,sys; print(json.dumps(sys.argv[1]))' "$2")}}" | python3 "$G" 2>/dev/null; rc=$? got=allow; [ $rc -eq 2 ] && got=block; [ "$got" = "$1" ] && mark=ok || { mark=MISMATCH; fail=1; }; printf '%-8s %-6s %-6s %s\n' "$mark" "$1" "$got" "$(printf '%s' "$2" | head -1)"; } echo "--- must block: commits / history ---" run block 'git push' run block 'git -C /home/coja/.dots push origin main' run block 'git -c user.name=x commit -m fix' run block '/usr/bin/git push' run block 'env GIT_DIR=.git git push' run block 'timeout 5 git push' run block 'sudo -u me git push' run block 'cd /tmp && git push' run block 'git status; git commit -am wip' run block 'x=1; git push' run block 'git push 2>&1 | tee log' run block "sh -c 'git push origin HEAD'" run block 'eval "git push"' run block 'git -C $(pwd) push' run block 'echo "$(git push)"' run block 'git --git-dir=/x/.git --work-tree=/x push' run block 'git commit -m "fix: grep pattern; not a command"' run block 'git revert HEAD' run block 'git cherry-pick abc123' run block 'git rebase -i HEAD~3' run block 'git rebase main' run block 'git merge feature' run block 'git merge --no-ff feature' echo "--- must block: discards working-tree changes ---" run block 'git reset --hard HEAD~1' run block 'git reset HEAD~1 --hard' run block 'git reset --soft HEAD~1' run block 'git reset --keep HEAD~2' run block 'git reset --merge' run block 'git reset' run block 'git reset -q' run block 'git reset HEAD' run block 'git reset HEAD~1' run block 'git reset abc1234' run block 'git reset 0123456789abcdef0123456789abcdef01234567' run block 'git reset origin/main' run block 'git reset @{u}' run block 'git restore --staged .' run block 'git restore --staged :/' run block 'git clean -fd' run block 'git -C . clean -n' run block 'git restore file.py' run block 'git restore --staged --worktree file.py' run block 'git restore -W file.py' run block 'git checkout -- .' run block 'git checkout -- file.py' run block 'git checkout HEAD -- file.py' run block 'git checkout .' run block 'git checkout -f main' run block 'git stash drop' run block 'git stash pop' run block 'git stash clear' run block 'git branch -D feature' run block 'git branch -f main HEAD~1' run block 'git branch -M main trunk' echo "--- must block: gh pr write ops ---" run block 'gh pr merge 12 --squash' run block 'gh -R o/r pr create --fill' run block 'gh pr edit 3 --title x' run block 'gh pr close 4' echo "--- must allow ---" run allow 'git status' run allow 'git log -1 --oneline' run allow 'git diff --cached --stat' run allow 'git add -A common/.config/claude' run allow 'git rev-parse --git-path CLAUDE_COMMIT_MSG' run allow 'git -c core.pager=cat log -3' run allow 'git reset -- file.txt' run allow 'git reset HEAD file.txt' run allow 'git reset HEAD existing.py other.py' run allow 'git reset existing.py' run allow 'git reset -p' run allow 'git reset -- .' run allow 'git restore --staged existing.py' run allow 'git restore --staged file.py' run allow 'git restore -S file.py' run allow 'git checkout main' run allow 'git checkout -b feature' run allow 'git switch main' run allow 'git merge --abort' run allow 'git stash' run allow 'git stash list' run allow 'git stash push -m wip' run allow 'git stash show -p' run allow 'git branch -d merged-branch' run allow 'git branch --list' run allow 'git branch -vv' run allow 'git commit-tree HEAD^{tree} -m x' run allow 'git worktree list' run allow 'grep -rn "git push" README.md' run allow 'grep -n "foo; git commit" file' run allow "echo 'git push'" run allow 'echo "run git push"' run allow "cat > README.md <<'EOF' Deploy with: git status; git commit -am x; git push origin main EOF echo written" run allow 'python3 - <