#!/usr/bin/env python3 from __future__ import annotations import py_compile import subprocess import sys from pathlib import Path ROOT = Path(__file__).resolve().parents[1] if hasattr(sys.stdout, "reconfigure"): sys.stdout.reconfigure(encoding="utf-8", errors="replace") if hasattr(sys.stderr, "reconfigure"): sys.stderr.reconfigure(encoding="utf-8", errors="replace") TEXT_SUFFIXES = { ".c", ".cc", ".cpp", ".h", ".hpp", ".ini", ".json", ".md", ".ps1", ".py", ".txt", ".yaml", ".yml", } SKIP_PATHS = { ".vscode/c_cpp_properties.json", ".vscode/launch.json", } def tracked_and_untracked_files() -> list[Path]: result = subprocess.run( ["git", "ls-files", "--cached", "--others", "--exclude-standard"], cwd=ROOT, text=True, encoding="utf-8", stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) if result.returncode != 0: print(result.stderr, end="") raise SystemExit(result.returncode) return [ROOT / line.strip() for line in result.stdout.splitlines() if line.strip()] def is_text_candidate(path: Path) -> bool: rel = path.relative_to(ROOT).as_posix() if rel in SKIP_PATHS: return False return path.suffix.lower() in TEXT_SUFFIXES def main() -> int: errors: list[str] = [] for path in tracked_and_untracked_files(): if not path.is_file() or not is_text_candidate(path): continue rel = path.relative_to(ROOT).as_posix() try: text = path.read_text(encoding="utf-8") except UnicodeDecodeError as exc: errors.append(f"{rel}: not valid UTF-8: {exc}") continue for line_no, line in enumerate(text.splitlines(), 1): if line.startswith(("<<<<<<<", "=======", ">>>>>>>")): errors.append(f"{rel}:{line_no}: merge conflict marker") for script in sorted((ROOT / "tools").glob("*.py")): try: py_compile.compile(str(script), doraise=True) except py_compile.PyCompileError as exc: errors.append(str(exc)) if not (ROOT / ".clang-format").exists(): print("No .clang-format found; source formatting is not reformatted by this check.") print("Checked text encodings, conflict markers, and Python syntax.") if errors: for error in errors: print(error) return 1 return 0 if __name__ == "__main__": raise SystemExit(main())