"""add-font CLI: add or update a font in the tap, then run cleanup, generator, and tests.""" import re import shutil import subprocess import sys from pathlib import Path def _repo_root() -> Path: """Repository root (directory containing font_files/ and Formula/).""" root = Path(__file__).resolve().parent.parent assert (root / "font_files").exists(), f"Repo root not found: {root}" return root def _normalize_to_font_name(name: str) -> str: """Return font- with lowercase, spaces/hyphens normalized.""" name = name.strip().lower().replace(" ", "-") # Collapse multiple hyphens name = re.sub(r"-+", "-", name).strip("-") if not name.startswith("font-"): name = f"font-{name}" return name def _infer_font_name_from_path(path: Path) -> str: """Infer font- from a folder or archive path.""" name = path.name # Strip common suffixes for suf in (".zip", ".tar.gz", ".tgz", ".tar"): if name.endswith(suf): name = name[: -len(suf)] break return _normalize_to_font_name(name.replace("font-", "", 1) if name.lower().startswith("font-") else name) def _run(cmd: list[str], cwd: Path | None = None) -> int: """Run command; return exit code.""" r = subprocess.run(cmd, cwd=cwd or _repo_root()) return r.returncode def main() -> None: import argparse parser = argparse.ArgumentParser( description="Add or update a font in the tap: run cleanup, generate formula, run tests." ) parser.add_argument( "path_or_name", help="Path to an unpacked font folder (or archive) or font name (e.g. font-acrylic-hand or acrylic-hand)", ) parser.add_argument( "--no-test", action="store_true", help="Skip running the test suite after changes", ) parser.add_argument( "--no-audit", action="store_true", help="Skip brew audit (default: run audit for touched formula)", ) args = parser.parse_args() root = _repo_root() font_files_dir = root / "font_files" script_dir = root / ".fontfoldercleanup" path_arg = Path(args.path_or_name) if path_arg.exists() and path_arg.is_dir(): # Add from path: copy into font_files/font- font_name = _infer_font_name_from_path(path_arg) dest = font_files_dir / font_name if dest.resolve() == path_arg.resolve(): # Already in place pass else: if dest.exists(): print(f"Destination exists: {dest}; merging by copying new files.") for item in path_arg.iterdir(): dest_item = dest / item.name if item.is_dir(): if dest_item.exists(): shutil.copytree(item, dest_item, dirs_exist_ok=True) else: shutil.copytree(item, dest_item) else: shutil.copy2(item, dest_item) else: shutil.copytree(path_arg, dest) print(f"Copied to {dest}") else: # Treat as font name font_name = _normalize_to_font_name(args.path_or_name) dest = font_files_dir / font_name if not dest.is_dir(): print(f"Error: no folder at {dest}", file=sys.stderr) sys.exit(1) # Run cleanup on font_files cleanup_script = script_dir / "cleanup_font_folders.py" font_files_abs = str(font_files_dir.resolve()) if _run([sys.executable, str(cleanup_script), "--path", font_files_abs]) != 0: sys.exit(1) # Run formula generator formula_script = script_dir / "create_homebrew_formula.py" if _run([sys.executable, str(formula_script)]) != 0: sys.exit(1) if not args.no_test: # Run pytest if _run([sys.executable, "-m", "pytest", "tests/", "-v", "--tb=short"]) != 0: print("Tests failed.", file=sys.stderr) sys.exit(1) if not args.no_audit: formula_path = root / "Formula" / f"{font_name}.rb" if formula_path.exists(): code = _run(["brew", "audit", "--formula", str(formula_path)]) if code != 0: print("brew audit reported issues (non-fatal).", file=sys.stderr) print(f"Done: {font_name}")