fix(git): push-guard — resolve re-review blockers; mutation table now generated
ci/woodpecker/pr/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
Authored by installer-7; committed by mos-claude (no credential for this remote). BLOCKER 1 — verify-clean-clone.sh had B1's own defect: it copied WORKING-TREE files into a scratch repo and asserted the SCRATCH index, so a stale local exec bit was laundered in and it reported success while the committed artifact was still 100644. v2 reads mode from 'git ls-tree' of the SOURCE COMMIT and runs from 'git clone --no-local --no-hardlinks' of that commit; there is no 'cp' in the file. Proven by A/B against one laundered repo: v1 EXIT=0, v2 EXIT=1 (both observed, not asserted). New test-verify-clean-clone.sh 6/6, incl. a fixture that first proves it really is git=100644 disk=755 before testing it. BLOCKER 2 — empty-merge needle + non-empty-merge control, both asserting on OUTPUT; the fixture first proves it IS a merge with a tree identical to both parents. The 'non-blocking' README item was not documentation: regenerating its mutation table (now generated by mutate-push-guard.sh, not hand-numbered) found TWO genuinely surviving mutants against a 46/46 green suite — staged-but-uncommitted opt-out honoured, and unparseable committed config ignored. Both still exit 6 under mutation because control falls to a SIBLING refusal, so an exit-code-only assertion would have been satisfied by the wrong branch. It also found a live instance of the substring-anchor defect already in the suite: three branches print 'OPT-OUT IS NOT REVIEWABLE', so deleting one let the needle RE-POINT to a sibling instead of failing. Re-anchored. Suite 44 -> 46. Verifier 6/6. 13 mutants, 0 survived. Also: README reformatted to satisfy 'pnpm format:check' (prettier), which was failing CI at both prior heads — a gate neither author nor reviewer had exercised. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01YKj59Qadrb2WBLaePvkM7H
This commit is contained in:
co-authored by
Claude Opus 5
parent
b0fb208b89
commit
8310075d33
@@ -0,0 +1,95 @@
|
||||
#!/usr/bin/env bash
|
||||
# test-verify-clean-clone.sh -- needles for the verifier itself.
|
||||
#
|
||||
# v1 of the verifier passed while the real repository recorded 100644, because it
|
||||
# asserted a SCRATCH repo built by cp. There was no needle that could have caught
|
||||
# that: every case ran against a tree whose modes came off my filesystem.
|
||||
# So the load-bearing needle here is w2 -- SOURCE GIT MODE 100644, DISK MODE 755.
|
||||
# That is the exact contaminated state, and v1 exits 0 on it while v2 must refuse.
|
||||
# A verifier without this needle is the same shape as the defect it verifies.
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
VERIFY="$HERE/verify-clean-clone.sh"
|
||||
ARTIFACTS=(push-guard.sh test-push-guard.sh verify-clean-clone.sh mutate-push-guard.sh)
|
||||
|
||||
PASS=0; FAIL=0
|
||||
TMP="$(mktemp -d)"; trap 'rm -rf "$TMP"' EXIT
|
||||
|
||||
# Build a source repo whose COMMITTED modes are 100755 and whose disk modes are
|
||||
# executable -- the honest state.
|
||||
mkrepo() {
|
||||
local d="$1"
|
||||
mkdir -p "$d"
|
||||
local f
|
||||
for f in "${ARTIFACTS[@]}"; do
|
||||
install -m 755 "$HERE/$f" "$d/$f"
|
||||
done
|
||||
git -C "$d" init -q .
|
||||
git -C "$d" config user.email "[email protected]"
|
||||
git -C "$d" config user.name "Verifier Needles"
|
||||
git -C "$d" add -A
|
||||
git -C "$d" commit -q -m "artifacts"
|
||||
}
|
||||
|
||||
run_case() {
|
||||
local name="$1" want_rc="$2" want_txt="$3" repo="$4"
|
||||
local out rc
|
||||
out="$("$VERIFY" --repo "$repo" 2>&1)"; rc=$?
|
||||
if (( rc == want_rc )) && [[ "$out" == *"$want_txt"* ]]; then
|
||||
printf ' ok [%-14s]\n' "$name"; PASS=$(( PASS + 1 ))
|
||||
else
|
||||
printf ' FAIL [%-14s] wanted rc=%d containing %q; got rc=%d\n%s\n' \
|
||||
"$name" "$want_rc" "$want_txt" "$rc" "$out"; FAIL=$(( FAIL + 1 ))
|
||||
fi
|
||||
}
|
||||
|
||||
echo "== POSITIVE CONTROL: an honestly-committed artifact must PASS =="
|
||||
# Without this, every case below could be passing because the verifier always
|
||||
# refuses -- a wall, not a gate.
|
||||
mkrepo "$TMP/good"
|
||||
run_case w1-honest 0 "the COMMITTED artifact ran and passed" "$TMP/good"
|
||||
|
||||
echo
|
||||
echo "== THE B1 NEEDLE: source git mode 100644, DISK MODE STILL 755 =="
|
||||
# This is the reviewer's exact reproduction. v1 of the verifier exits 0 here.
|
||||
mkrepo "$TMP/laundered"
|
||||
git -C "$TMP/laundered" update-index --chmod=-x push-guard.sh test-push-guard.sh
|
||||
git -C "$TMP/laundered" commit -q -m "drop exec bit in git only"
|
||||
# PROVE THE FIXTURE IS THE CONTAMINATED STATE, not merely a broken repo: git must
|
||||
# say 100644 while the filesystem still says executable. If the disk bit were
|
||||
# gone too, the needle would be testing something easier than the real defect.
|
||||
src_mode="$(git -C "$TMP/laundered" ls-tree HEAD -- push-guard.sh | awk '{print $1}')"
|
||||
disk_mode="$(stat -c '%a' "$TMP/laundered/push-guard.sh")"
|
||||
if [[ "$src_mode" == "100644" && "$disk_mode" == "755" ]]; then
|
||||
printf ' ok [%-14s] fixture is git=%s disk=%s\n' "w2-fixture" "$src_mode" "$disk_mode"; PASS=$(( PASS + 1 ))
|
||||
else
|
||||
printf ' FAIL [%-14s] fixture wrong: git=%s disk=%s -- needle would not test the defect\n' \
|
||||
"w2-fixture" "$src_mode" "$disk_mode"; FAIL=$(( FAIL + 1 ))
|
||||
fi
|
||||
run_case w2-laundered 1 "committed 100644, needs 100755" "$TMP/laundered"
|
||||
|
||||
echo
|
||||
echo "== the artifact must be COMMITTED, or there is no mode to verify =="
|
||||
mkrepo "$TMP/untracked"
|
||||
git -C "$TMP/untracked" rm -q --cached push-guard.sh
|
||||
git -C "$TMP/untracked" commit -q -m "untrack the guard"
|
||||
run_case w3-untracked 1 "NOT TRACKED" "$TMP/untracked"
|
||||
|
||||
echo
|
||||
echo "== a committed SYMLINK is a path, not the reviewed code =="
|
||||
mkrepo "$TMP/symlink"
|
||||
( cd "$TMP/symlink" && rm -f push-guard.sh && ln -s /dev/null push-guard.sh \
|
||||
&& git add push-guard.sh && git commit -q -m "symlink the guard" )
|
||||
run_case w4-symlink 1 "SYMLINK" "$TMP/symlink"
|
||||
|
||||
echo
|
||||
echo "== not a repository at all: REFUSE, never pass =="
|
||||
mkdir -p "$TMP/bare"
|
||||
for f in "${ARTIFACTS[@]}"; do install -m 755 "$HERE/$f" "$TMP/bare/$f"; done
|
||||
run_case w5-norepo 1 "not inside a git repository" "$TMP/bare"
|
||||
|
||||
echo
|
||||
printf '%d passed, %d failed\n' "$PASS" "$FAIL"
|
||||
(( FAIL == 0 ))
|
||||
Reference in New Issue
Block a user