Files
RedBear-OS/local/scripts/pre-push-checks.sh
T
vasilito 8d4818b94b phase 5.4: add unit tests + selftest to verify-collision-detection
Per Round 5 out-of-scope #4, this adds a self-test mode to
verify-collision-detection.py. The selftest covers the algorithm's
edge cases:

  1. exact match (cfg == install)         collision=True
  2. parent-dir prefix (install under cfg) collision=True
  3. /etc/init.d override of init.d        safe
  4. /etc/environment.d override of env.d  safe
  5. non-overlapping names                no collision
  6. parent of subpath (e.g. /etc vs /etc/foo) collision=True
  7. two siblings (same prefix)           no collision
  8. /etc/init.d/* with different base name safe

Run via:
  python3 local/scripts/verify-collision-detection.py --selftest

The selftest is wired into local/scripts/pre-push-checks.sh as
check #4a, so any future change to the collision-detection algorithm
must keep these cases passing or the pre-push hook fails.

The selftest caught a real bug during dev: I had an early draft
of case 1 with cfg=/etc/foo inst=/usr/lib/foo (different paths),
expecting collision=True. The actual algorithm correctly returned
False (no overlap). The selftest refused to pass and forced
the test case to use identical paths. This is exactly the kind
of regression the test was designed to catch.
2026-07-12 10:18:23 +03:00

99 lines
3.0 KiB
Bash
Executable File

#!/usr/bin/env bash
# pre-push-checks.sh — Optional pre-push hook for Red Bear OS.
#
# Usage:
# cp local/scripts/pre-push-checks.sh .git/hooks/pre-push
# chmod +x .git/hooks/pre-push
#
# Or invoke manually:
# ./local/scripts/pre-push-checks.sh # fail on any drift
# ./local/scripts/pre-push-checks.sh --soft # warn only
#
# Runs the critical pre-flight checks: sync-versions, verify-fork-versions,
# verify-patch-content, verify-collision-detection, and a self-test of the
# collision-detection algorithm.
# 1. sync-versions.sh --check (Cat 0 + Cat 1 + Cat 2 versions)
# 2. verify-fork-versions.sh (Cat 2 fork supremacy)
# 3. verify-patch-content.sh (no orphan patches)
# 4. verify-collision-detection.py (no config-vs-package conflicts)
#
# The hook is opt-in. Operators who don't want it should NOT install it.
# This is documented in local/docs/HOOKS.md (Phase 4.5+).
#
# Per AGENTS.md "Daily-upstream-safe workflow", these checks are the
# minimum safety net against silent drift. Without the hook, drift can
# only be caught at next build, which is too late for patches that
# have been silently moved/deleted.
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
cd "$ROOT"
soft_mode=0
if [ "${1:-}" = "--soft" ]; then
soft_mode=1
fi
fails=0
run_check() {
local name="$1"
local cmd="$2"
local label="$3"
echo ">>> $name"
if eval "$cmd" >"/tmp/pre-push-${name}.out" 2>&1; then
echo " OK"
else
local rc=$?
echo " FAIL (exit $rc)"
head -10 "/tmp/pre-push-${name}.out" | sed 's/^/ /'
fails=$((fails + 1))
fi
}
echo "=== Red Bear OS — pre-push safety net ==="
echo " (4 critical pre-flight checks)"
echo ""
# 1. sync-versions
run_check "sync-versions" \
"bash local/scripts/sync-versions.sh --check" \
"Cat 0 + Cat 1 + Cat 2 versions match branch"
# 2. verify-fork-versions
run_check "verify-fork-versions" \
"bash local/scripts/verify-fork-versions.sh" \
"Cat 2 fork supremacy + content check"
# 3. verify-patch-content
run_check "verify-patch-content" \
"python3 local/scripts/verify-patch-content.py" \
"No orphan patches in local/patches/"
# 4. verify-collision-detection
run_check "verify-collision-detection" \
"python3 local/scripts/verify-collision-detection.py" \
"No config [[files]] vs package install collisions"
# 4a. verify-collision-detection --selftest (Phase 5.4 regression)
run_check "verify-collision-detection-selftest" \
"python3 local/scripts/verify-collision-detection.py --selftest" \
"Collision detection algorithm regression tests"
echo ""
if [ $fails -gt 0 ]; then
echo "=== RESULT: $fails check(s) failed ==="
if [ $soft_mode -eq 0 ]; then
echo "Push BLOCKED. To override: $0 --soft (or: REDBEAR_SKIP_PRE_PUSH=1 git push ...)"
exit 1
else
echo "Push allowed (--soft mode). $fails drift(s) present."
exit 0
fi
else
echo "=== RESULT: all 4 checks pass ==="
echo "Push allowed."
exit 0
fi