| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869 |
- #!/usr/bin/env bash
- # Check git index modes, not filesystem permissions (Git Bash can fake those).
- # Root tests/*.sh and scripts/*.sh are excluded because tracked 100644 files
- # there are legitimate today; this gate covers skill-bundled scripts only.
- set -u
- usage() {
- cat <<'EOF'
- Usage: tests/check-exec-bits.sh [--help]
- Print tracked skill scripts whose git mode is not 100755, one per line.
- EXAMPLES
- bash tests/check-exec-bits.sh
- bash tests/check-exec-bits.sh --help
- Exit codes: 0 clean, 1 findings, 2 usage error.
- EOF
- }
- case "${1-}" in
- "") ;;
- -h|--help) usage; exit 0 ;;
- *) echo "check-exec-bits: unknown argument: $1" >&2; usage >&2; exit 2 ;;
- esac
- [ "$#" -le 1 ] || { echo "check-exec-bits: too many arguments" >&2; usage >&2; exit 2; }
- ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
- cd "$ROOT" || exit 2
- findings=0
- candidates=0
- while read -r mode object stage path; do
- case "$path" in
- skills/*/scripts/*)
- # A "script" is: known script extension, OR extensionless with a
- # shebang (e.g. introspect/scripts/cc-session). Data/doc files and
- # .gitkeep placeholders are not scripts.
- base="${path##*/}"
- is_script=0
- case "$base" in
- *.sh|*.py|*.mjs|*.js) is_script=1 ;;
- *.*|.*) ;; # other extensions / dotfiles: not gated
- *) head -c 2 -- "$path" 2>/dev/null | grep -q '^#!' && is_script=1 ;;
- esac
- [ "$is_script" -eq 1 ] || continue
- candidates=$((candidates + 1))
- if [ "$mode" != "100755" ]; then
- echo "$path"
- findings=$((findings + 1))
- fi
- ;;
- esac
- done < <(git ls-files -s -- skills)
- # Empty candidate list means the scan itself is broken (not in a repo, path
- # typo, git missing) — a gate that checked nothing must not report clean.
- if [ "$candidates" -eq 0 ]; then
- echo "check-exec-bits: self-check failed — zero candidate scripts found (broken scan?)" >&2
- exit 2
- fi
- if [ "$findings" -eq 0 ]; then
- echo "check-exec-bits: clean ($candidates scripts checked)" >&2
- exit 0
- fi
- echo "check-exec-bits: $findings file(s) are not tracked as 100755" >&2
- exit 1
|