()
| 292 | |
| 293 | |
| 294 | def main() -> int: |
| 295 | parser = argparse.ArgumentParser( |
| 296 | description="Add or check SPDX license headers on source files.", |
| 297 | ) |
| 298 | parser.add_argument( |
| 299 | "--check", |
| 300 | action="store_true", |
| 301 | help="Check mode: exit 1 if any file is missing a header.", |
| 302 | ) |
| 303 | parser.add_argument( |
| 304 | "--verbose", |
| 305 | "-v", |
| 306 | action="store_true", |
| 307 | help="Print status for every file processed.", |
| 308 | ) |
| 309 | parser.add_argument( |
| 310 | "paths", |
| 311 | nargs="*", |
| 312 | type=Path, |
| 313 | help="Specific files to process (default: all files under repo root).", |
| 314 | ) |
| 315 | args = parser.parse_args() |
| 316 | |
| 317 | root = find_repo_root() |
| 318 | |
| 319 | if args.paths: |
| 320 | # Resolve relative paths and filter to supported + non-excluded files. |
| 321 | files = [] |
| 322 | for p in args.paths: |
| 323 | p = p.resolve() |
| 324 | if not p.is_file(): |
| 325 | continue |
| 326 | try: |
| 327 | rel = p.relative_to(root) |
| 328 | except ValueError: |
| 329 | continue |
| 330 | if is_excluded(rel) or is_git_ignored(root, rel): |
| 331 | continue |
| 332 | if get_comment_style(rel) is not None: |
| 333 | files.append(p) |
| 334 | else: |
| 335 | files = discover_files(root) |
| 336 | |
| 337 | if args.check: |
| 338 | print(f"Checking {len(files)} files for SPDX headers...") |
| 339 | else: |
| 340 | print(f"Processing {len(files)} files...") |
| 341 | |
| 342 | missing = [] |
| 343 | for f in files: |
| 344 | if not process_file(f, root, check=args.check, verbose=args.verbose): |
| 345 | missing.append(f) |
| 346 | |
| 347 | if args.check: |
| 348 | if missing: |
| 349 | print(f"\n{len(missing)} file(s) missing SPDX headers.") |
| 350 | return 1 |
| 351 | print("All files have SPDX headers.") |
no test coverage detected