"""Copies everything this tool borrows from the monorepo into ``vendor/``. The package is meant to be liftable into a repository of its own, where none of ``cc_common`` or ``persistent_storage`` exists. The copies here are what it would need to take along. They are produced by a script rather than by hand for one reason: a copy made once goes stale without saying so. Re-run this after touching anything it lists and the diff shows what drifted. python -m persistent_storage.report_generator.vendor.sync Copied under their own import paths, so ``vendor/`` on ``sys.path`` makes the package import unchanged in the new repository. """ from __future__ import annotations import shutil import sys from pathlib import Path # Where the monorepo's sources sit, relative to this file. SOURCE_ROOT = Path(__file__).resolve().parents[4] VENDOR_ROOT = Path(__file__).resolve().parent # What the tool reaches for, and nothing beyond it. A whole package is copied where the tool uses # enough of it that picking modules would only mean chasing imports on the next change. COPIED = ( # The CLI framework, the logging context and the error type every command raises. "cc_common", # The scan and artifact rows, the storage configuration, and the readers over them. "persistent_storage/__init__.py", "persistent_storage/shared.py", "persistent_storage/wrapper.py", "persistent_storage/helper.py", "persistent_storage/utils/__init__.py", "persistent_storage/utils/db_utils.py", "persistent_storage/utils/s3_utils.py", # The CVSS reader the vulnerability summariser works through. "persistent_storage/utils/cvss_utils.py", # The two summarisers the report is built from. They live in the web application today and are # written to be free of it -- no Django, no store -- which is what makes copying them honest # rather than a workaround. Wherever this package ends up, they belong beside it. "cipherverifier/__init__.py", "cipherverifier/core/__init__.py", "cipherverifier/core/services/__init__.py", "cipherverifier/core/services/sarif.py", "cipherverifier/core/services/vdr.py", ) # Never copied: caches and the compiled leftovers of whoever ran a tool over the source tree last. # They live inside the packages being copied, so leaving any of them out puts megabytes of someone # else's machine into the vendor tree. SKIPPED = shutil.ignore_patterns( "__pycache__", "*.pyc", ".DS_Store", ".mypy_cache", ".ruff_cache", ".pytest_cache", "*.egg-info" ) def sync() -> list[Path]: """Refresh every copy, replacing what is there. The copied packages are removed whole before anything is written, so that dropping an entry from :data:`COPIED` actually drops it from the tree. Replacing only what is listed leaves what used to be listed behind, and the copy then carries files nothing refers to any more -- which is the same staleness this script exists to prevent, one level up. Returns: What was written, relative to ``vendor/``. """ for root in {entry.split("/")[0] for entry in COPIED}: stale = VENDOR_ROOT / root if stale.is_dir(): shutil.rmtree(stale) elif stale.exists(): stale.unlink() written = [] for entry in COPIED: source = SOURCE_ROOT / "src" / entry target = VENDOR_ROOT / entry if not source.exists(): message = f"{source} does not exist -- the monorepo moved it, and this list has not followed." raise FileNotFoundError(message) target.parent.mkdir(parents=True, exist_ok=True) if source.is_dir(): shutil.copytree(source, target, ignore=SKIPPED) else: shutil.copy2(source, target) written.append(Path(entry)) return written if __name__ == "__main__": for path in sync(): sys.stdout.write(f"{path}\n")