58 lines
1.5 KiB
Bash
58 lines
1.5 KiB
Bash
#!/usr/bin/env bash
|
|
# scope-check.sh — Validate that git diff only touches declared files.
|
|
# Usage: ./scripts/scope-check.sh "file1.cs" "file2.cs" ...
|
|
# Exit 0 if all changed files are in scope, 1 if any are outside.
|
|
#
|
|
# Checks staged, unstaged, and untracked changes against the allowed list.
|
|
# Supports glob patterns in the allowed list (e.g. "ytLive.Tests/*").
|
|
|
|
set -euo pipefail
|
|
|
|
if [ $# -eq 0 ]; then
|
|
echo "Usage: $0 \"file1.cs\" \"file2.cs\" ..."
|
|
echo " Pass the declared file list as arguments."
|
|
exit 1
|
|
fi
|
|
|
|
# Collect allowed patterns into an array
|
|
allowed=("$@")
|
|
|
|
# Gather all changed files: working tree vs HEAD (tracked) + staged + untracked
|
|
changed=$({
|
|
git diff --name-only HEAD 2>/dev/null || true
|
|
git diff --name-only --cached 2>/dev/null || true
|
|
git ls-files --others --exclude-standard 2>/dev/null || true
|
|
} | sort -u)
|
|
|
|
if [ -z "$changed" ]; then
|
|
echo "✓ No changes detected."
|
|
exit 0
|
|
fi
|
|
|
|
violations=()
|
|
while IFS= read -r file; do
|
|
matched=false
|
|
for pattern in "${allowed[@]}"; do
|
|
if [[ "$file" == $pattern ]]; then
|
|
matched=true
|
|
break
|
|
fi
|
|
done
|
|
if [ "$matched" = false ]; then
|
|
violations+=("$file")
|
|
fi
|
|
done <<< "$changed"
|
|
|
|
if [ ${#violations[@]} -eq 0 ]; then
|
|
echo "✓ Scope check passed — all changed files are in scope."
|
|
exit 0
|
|
fi
|
|
|
|
echo "✗ SCOPE VIOLATION — the following files are outside the declared scope:"
|
|
for f in "${violations[@]}"; do
|
|
echo " - $f"
|
|
done
|
|
echo ""
|
|
echo "Either justify the edit or revert the change."
|
|
exit 1
|