120 lines
3.9 KiB
Python
120 lines
3.9 KiB
Python
#!/usr/bin/env python3
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import shutil
|
|
from pathlib import Path
|
|
|
|
|
|
ROOT_DIR = Path(__file__).resolve().parent.parent
|
|
CELLAR_DIR = Path("/opt/homebrew/Cellar")
|
|
LICENSE_ROOT = ROOT_DIR / "src-tauri" / "vendor" / "licenses" / "homebrew"
|
|
LICENSE_BUNDLE_ROOT = ROOT_DIR / "src-tauri" / "vendor" / "licenses_bundle"
|
|
FFMPEG_RECEIPT = sorted(CELLAR_DIR.glob("ffmpeg/*/INSTALL_RECEIPT.json"))[-1]
|
|
LICENSE_PATTERNS = [
|
|
"LICENSE*",
|
|
"LICENCE*",
|
|
"COPYING*",
|
|
"COPYRIGHT*",
|
|
"NOTICE*",
|
|
]
|
|
|
|
|
|
def load_runtime_formulas() -> list[tuple[str, str | None]]:
|
|
data = json.loads(FFMPEG_RECEIPT.read_text())
|
|
formulas: list[tuple[str, str | None]] = [("ffmpeg", None)]
|
|
for item in data.get("runtime_dependencies", []):
|
|
full_name = item.get("full_name")
|
|
version = item.get("version")
|
|
if full_name:
|
|
formulas.append((full_name, version))
|
|
return formulas
|
|
|
|
|
|
def resolve_formula_dir(name: str, version: str | None) -> Path | None:
|
|
if version:
|
|
exact = CELLAR_DIR / name / version
|
|
if exact.exists():
|
|
return exact
|
|
matches = sorted((CELLAR_DIR / name).glob("*"))
|
|
return matches[-1] if matches else None
|
|
|
|
|
|
def collect_license_files(formula_dir: Path) -> list[Path]:
|
|
found: list[Path] = []
|
|
seen: set[Path] = set()
|
|
for pattern in LICENSE_PATTERNS:
|
|
for path in sorted(formula_dir.rglob(pattern)):
|
|
if path.is_file() and path not in seen:
|
|
seen.add(path)
|
|
found.append(path)
|
|
return found
|
|
|
|
|
|
def main() -> None:
|
|
if LICENSE_ROOT.exists():
|
|
shutil.rmtree(LICENSE_ROOT)
|
|
LICENSE_ROOT.mkdir(parents=True, exist_ok=True)
|
|
LICENSE_BUNDLE_ROOT.mkdir(parents=True, exist_ok=True)
|
|
|
|
manifest_lines = [
|
|
"CrossSubtitle-AI Third-Party Notices",
|
|
"",
|
|
"This directory contains license files collected from Homebrew formulas",
|
|
"used by the bundled ffmpeg binary and its runtime dependencies.",
|
|
"",
|
|
]
|
|
|
|
for formula_name, version in load_runtime_formulas():
|
|
formula_dir = resolve_formula_dir(formula_name, version)
|
|
target_dir = LICENSE_ROOT / formula_name.replace("@", "_at_")
|
|
target_dir.mkdir(parents=True, exist_ok=True)
|
|
target_dir.chmod(0o755)
|
|
|
|
if formula_dir is None:
|
|
manifest_lines.append(f"- {formula_name}: formula directory not found")
|
|
continue
|
|
|
|
copied: list[str] = []
|
|
for license_file in collect_license_files(formula_dir):
|
|
destination = target_dir / license_file.name
|
|
if destination.exists():
|
|
destination.chmod(0o644)
|
|
shutil.copy2(license_file, destination)
|
|
destination.chmod(0o644)
|
|
copied.append(license_file.name)
|
|
|
|
actual_version = formula_dir.name
|
|
if copied:
|
|
manifest_lines.append(
|
|
f"- {formula_name} ({actual_version}): {', '.join(sorted(copied))}"
|
|
)
|
|
else:
|
|
note = target_dir / "MISSING_LICENSE.txt"
|
|
note.write_text(
|
|
f"No license file matching common patterns was found in {formula_dir}\n"
|
|
)
|
|
manifest_lines.append(
|
|
f"- {formula_name} ({actual_version}): no matching license file found"
|
|
)
|
|
|
|
manifest_path = LICENSE_ROOT / "THIRD_PARTY_NOTICES.txt"
|
|
manifest_path.write_text("\n".join(manifest_lines) + "\n")
|
|
manifest_path.chmod(0o644)
|
|
|
|
bundle_manifest = LICENSE_BUNDLE_ROOT / "THIRD_PARTY_NOTICES.txt"
|
|
shutil.copy2(manifest_path, bundle_manifest)
|
|
bundle_manifest.chmod(0o644)
|
|
|
|
archive_base = LICENSE_BUNDLE_ROOT / "homebrew-licenses"
|
|
archive_path = shutil.make_archive(str(archive_base), "zip", LICENSE_ROOT)
|
|
Path(archive_path).chmod(0o644)
|
|
|
|
print(f"Prepared bundled licenses at: {LICENSE_ROOT}")
|
|
print(f"Prepared bundled license archive at: {archive_path}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|