#!/usr/bin/env python3 """Git pre-commit: validate headers on new files; refresh Updated/Digest on staged edits.""" from __future__ import annotations import subprocess import sys from pathlib import Path from header_lib import ( REPO_ROOT, SOURCE_SUFFIXES, apply_header_to_content, has_valid_header, header_needs_identity_refresh, is_excluded_path, resolve_header_contributor, update_header_timestamps, ) def staged_files() -> list[Path]: out = subprocess.check_output( ["git", "diff", "--cached", "--name-only", "--diff-filter=ACMR"], cwd=REPO_ROOT, text=True, ) files = [] for line in out.splitlines(): p = REPO_ROOT / line.strip() if not p.is_file() or p.suffix.lower() not in SOURCE_SUFFIXES: continue if is_excluded_path(p): continue files.append(p) return files def is_new_file(path: Path) -> bool: rel = path.relative_to(REPO_ROOT).as_posix() try: subprocess.check_call( ["git", "diff", "--cached", "--diff-filter=A", "--quiet", "--", rel], cwd=REPO_ROOT, ) return False except subprocess.CalledProcessError: return True def main() -> int: errors = [] contributor = resolve_header_contributor() for path in staged_files(): text = path.read_text(encoding="utf-8", errors="replace") if is_new_file(path): if not has_valid_header(text): errors.append( f"{path.relative_to(REPO_ROOT)}: new file must include HEADER.txt block" ) text = apply_header_to_content(path, text) text = update_header_timestamps(text, path, contributor) else: if has_valid_header(text): if header_needs_identity_refresh(text, path): text = apply_header_to_content(path, text) text = update_header_timestamps(text, path, contributor) else: text = apply_header_to_content(path, text) text = update_header_timestamps(text, path, contributor) path.write_text(text, encoding="utf-8", newline="\n") rel = path.relative_to(REPO_ROOT).as_posix() subprocess.check_call(["git", "add", "--", rel], cwd=REPO_ROOT) if errors: for e in errors: print(e, file=sys.stderr) print( "Run: python3 scripts/apply-project-headers.py", file=sys.stderr, ) return 1 return 0 if __name__ == "__main__": sys.exit(main())