Skip to content
File

Blob: scripts/format_c.py

python83 lines
1#!/usr/bin/env python3
2"""Install, run, or check the pinned formatter for the maintained C adapters."""
3import argparse
4import subprocess
5import sys
6 
7from project import CLANG_FORMAT_VERSION, ROOT
8 
9ENVIRONMENT = ROOT / ".tools/clang-format"
10FORMATTER = ENVIRONMENT / "bin/clang-format"
11EXPECTED_VERSION = f"clang-format version {CLANG_FORMAT_VERSION}"
12 
13 
14def installed_version():
15 try:
16 result = subprocess.run(
17 [str(FORMATTER), "--version"], capture_output=True, text=True
18 )
19 except OSError:
20 return None
21 return result.stdout.strip() if result.returncode == 0 else None
22 
23 
24def require_formatter():
25 if installed_version() != EXPECTED_VERSION:
26 raise SystemExit(
27 f"Expected clang-format {CLANG_FORMAT_VERSION}. Run make setup-c-format."
28 )
29 
30 
31def setup():
32 if installed_version() != EXPECTED_VERSION:
33 python = ENVIRONMENT / "bin/python"
34 if not python.exists():
35 subprocess.run(
36 [sys.executable, "-m", "venv", str(ENVIRONMENT)], check=True
37 )
38 subprocess.run(
39 [
40 str(python), "-m", "pip", "install", "--disable-pip-version-check",
41 "--only-binary=:all:", "--no-deps",
42 f"clang-format=={CLANG_FORMAT_VERSION}",
43 ],
44 check=True,
45 )
46 require_formatter()
47 print(f"{EXPECTED_VERSION} is ready in .tools/clang-format.")
48 
49 
50def main():
51 parser = argparse.ArgumentParser(description=__doc__)
52 action = parser.add_mutually_exclusive_group()
53 action.add_argument("--setup", action="store_true", help="Install the pinned formatter")
54 action.add_argument("--check", action="store_true", help="Check formatting without editing")
55 action.add_argument("--version", action="store_true", help="Verify and print the installed version")
56 args = parser.parse_args()
57 if args.setup:
58 setup()
59 return 0
60 require_formatter()
61 if args.version:
62 print(EXPECTED_VERSION)
63 return 0
64 sources = sorted(
65 path for path in (ROOT / "firmware/platform").rglob("*")
66 if path.is_file() and path.suffix in {".c", ".h"}
67 )
68 if not sources:
69 raise SystemExit("No maintained C sources found in firmware/platform.")
70 return subprocess.run(
71 [
72 str(FORMATTER), f"--style=file:{ROOT / 'firmware/.clang-format'}",
73 "--fail-on-incomplete-format",
74 *(["--dry-run", "--Werror"] if args.check else ["-i"]),
75 *map(str, sources),
76 ],
77 cwd=ROOT,
78 ).returncode
79 
80 
81if __name__ == "__main__":
82 raise SystemExit(main())