91 lines
2.4 KiB
Python
91 lines
2.4 KiB
Python
#!/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())
|