"""Relocate explicitly named capture roots and join CI/focused LCOV inputs.""" import argparse from pathlib import Path, PurePosixPath parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("ci_directory", type=Path) parser.add_argument("focused_file", type=Path) parser.add_argument("output_directory", type=Path) parser.add_argument("checkout", type=Path) parser.add_argument("source_roots", nargs="+", help="Captured POSIX checkout roots") args = parser.parse_args() source_roots = sorted( {str(PurePosixPath(root)).rstrip("/") for root in args.source_roots}, key=len, reverse=True, ) if any(not root.startswith("/") for root in source_roots): parser.error("Captured source roots must be absolute POSIX paths") checkout = args.checkout.resolve() def normalize(text): lines = [] for line in text.splitlines(): if line.startswith("SF:"): source = line[3:] for root in source_roots: prefix = root + "/" if source.startswith(prefix): relative = PurePosixPath(source[len(prefix):]) if relative.is_absolute() or ".." in relative.parts: raise ValueError(f"Source path escapes its capture root: {source}") line = "SF:" + str(checkout / Path(*relative.parts)) break lines.append(line) return "\n".join(lines) + "\n" reports = [ normalize(path.read_text(encoding="utf-8")) for path in sorted(args.ci_directory.rglob("*.lcov")) ] if not reports: raise ValueError("No CI LCOV files found") focused = normalize(args.focused_file.read_text(encoding="utf-8")) args.output_directory.mkdir(parents=True, exist_ok=True) (args.output_directory / "ci-normalized.lcov").write_text( "\n".join(reports), encoding="utf-8" ) reports.append(focused) (args.output_directory / "ci-plus-controls.lcov").write_text( "\n".join(reports), encoding="utf-8" )