#!/usr/bin/env bash # scripts/quality/clang-format.sh # # Verify every source file under code/{include,src,tests} matches the # project's `.clang-format` policy. Runs in dry-run mode by default — # only reports diffs; never edits files. # # Pass `--fix` to apply the suggested formatting in place. # # Local-only. Promotion to CI is intended once the existing tree is # 100 %-conformant; today we report drift but don't fail (the script # exits non-zero only with `--strict`). # # Usage: # bash scripts/quality/clang-format.sh # dry-run, exit 0 always # bash scripts/quality/clang-format.sh --strict # dry-run, exit 1 on drift # bash scripts/quality/clang-format.sh --fix # apply changes # # Exit codes: # 0 no drift, or drift but --strict not set # 1 drift detected AND --strict (or fixes applied AND --fix) # 2 prerequisite missing set -uo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" cd "$ROOT" || exit 2 command -v clang-format >/dev/null 2>&1 || { echo "FAIL: clang-format not in PATH." >&2 echo " macOS: brew install clang-format" >&2 echo " Linux: sudo apt install clang-format" >&2 exit 2 } STRICT=0 FIX=0 for arg in "$@"; do case "$arg" in --strict) STRICT=1 ;; --fix) FIX=1 ;; *) echo "Unknown arg: $arg" >&2; exit 2 ;; esac done FILES_LIST="$(find code/include code/src code/tests \ \( -name "*.h" -o -name "*.hpp" -o -name "*.cpp" \) \ -type f 2>/dev/null \ | grep -v "^code/deps/" \ | grep -v " 2\." \ | sort)" n_total=0 n_drift=0 drift_list="" while IFS= read -r f; do [ -z "$f" ] && continue n_total=$((n_total + 1)) if [ "$FIX" -eq 1 ]; then clang-format -i "$f" else # --dry-run + -Werror sets non-zero exit when changes would be made. if ! clang-format --dry-run -Werror "$f" >/dev/null 2>&1; then n_drift=$((n_drift + 1)) drift_list="$drift_list $f " fi fi done <