"""Check one edited repository file without executing its contents.""" import json import subprocess import sys from pathlib import Path PROJECT_ROOT = Path(__file__).resolve().parents[2] CHECK_TIMEOUT = 10 def check_file(file_path: str, project_dir: Path) -> None: project_dir = project_dir.resolve() path = Path(file_path) if not path.is_absolute(): path = project_dir / path path = path.resolve() try: relative = path.relative_to(project_dir) except ValueError: return if path.suffix == ".py": compile(path.read_bytes(), str(path), "exec") return if path.suffix == ".sh" and relative.parts[:2] == ("scripts", "server"): command = ["bash", "-n", str(path)] elif path.suffix == ".sh" and ( relative.parts[:2] == ("scripts", "router") or relative == Path("build_router_package.sh") ): command = ["sh", "-n", str(path)] elif path.suffix == ".js" and relative.parts[:1] == ("substore",): command = ["node", "--check", str(path)] else: return result = subprocess.run( command, cwd=str(project_dir), capture_output=True, text=True, timeout=CHECK_TIMEOUT, ) if result.returncode: detail = result.stderr.strip() or result.stdout.strip() raise RuntimeError(detail or f"{command[0]} exited with status {result.returncode}") def main() -> int: try: payload = json.load(sys.stdin) if not isinstance(payload, dict): raise ValueError("Hook payload must be a JSON object") if payload.get("tool_name") not in ("Write", "Edit"): return 0 tool_input = payload.get("tool_input") if not isinstance(tool_input, dict): raise ValueError("Write/Edit payload must contain tool_input") file_path = tool_input.get("file_path") if not isinstance(file_path, str) or not file_path: raise ValueError("Write/Edit payload must contain a nonempty file_path") check_file(file_path, PROJECT_ROOT) except (OSError, SyntaxError, ValueError, RuntimeError, subprocess.TimeoutExpired) as exc: print(f"[syntax-check] {exc}", file=sys.stderr) return 2 return 0 if __name__ == "__main__": sys.exit(main())