homebrew-fonts/tap_cli/main.py

123 lines
4.3 KiB
Python

"""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-<name> 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-<name> 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-<name>
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}")