homebrew-fonts/.fontfoldercleanup/create_homebrew_formula.py
Matt Troutman 91d5ffad9d
Update Gitea URL from port 3002 to 8085 and add sha256 to formulae
All formulae were failing to download because the archive URL pointed to
the old Gitea port (3002). Updated to port 8085 and computed the correct
sha256 hash for the archive.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 21:18:58 -06:00

167 lines
No EOL
5.8 KiB
Python
Executable file

#!/usr/bin/env python3
import re
from pathlib import Path
def formula_name_to_class(formula_name: str) -> str:
"""Convert formula name (e.g. 'acrylic-hand', 'graham_hand') to valid Ruby PascalCase."""
# Split on hyphens and underscores, capitalize each segment, join (no separators)
parts = re.split(r"[-_]+", formula_name)
return "".join(p.capitalize() for p in parts if p)
class HomebrewFormulaGenerator:
def __init__(self, fonts_dir):
self.fonts_dir = Path(fonts_dir)
self.formula_dir = self.fonts_dir.parent / "Formula"
self.formula_dir.mkdir(exist_ok=True)
self.web_extensions = (".woff", ".woff2", ".eot", ".svg")
def _font_has_files(self, font_dir: Path) -> tuple[bool, bool, bool, bool]:
"""Return (has_ttf, has_otf, has_web, has_other) for the font folder."""
has_ttf = any((font_dir / "ttf").glob("*.ttf"))
has_otf = any((font_dir / "otf").glob("*.otf"))
web_dir = font_dir / "web"
has_web = any(
f.suffix.lower() in self.web_extensions for f in web_dir.glob("*") if f.is_file()
)
other_dir = font_dir / "other_files"
has_other = any(other_dir.iterdir()) if other_dir.exists() else False
return (has_ttf, has_otf, has_web, has_other)
def _generate_test_block(
self, formula_name: str, has_ttf: bool, has_otf: bool, has_web: bool, has_other: bool
) -> str:
"""Generate test block that asserts at least one install path has files for this formula."""
assertions = []
if has_ttf:
assertions.append('assert (share/"fonts/truetype").glob("*.ttf").any?, "No TTF fonts installed"')
if has_otf:
assertions.append('assert (share/"fonts/opentype").glob("*.otf").any?, "No OTF fonts installed"')
if has_web:
assertions.append(
'assert (share/"fonts/webfonts").glob("*").any?, "No web fonts installed"'
)
if has_other:
assertions.append(
f'assert_predicate share/"{formula_name}", :directory?, "Other files dir missing"'
)
if not assertions:
assertions.append(
f'assert_predicate share/"{formula_name}", :directory?, "Formula share dir missing"'
)
return "\n ".join(assertions)
def generate_formula_content(
self,
font_name: str,
formula_name: str,
has_ttf: bool,
has_otf: bool,
has_web: bool,
has_other: bool,
) -> str:
"""Generate the Ruby formula content for a font."""
class_name = formula_name_to_class(formula_name)
extensions = []
if has_ttf:
extensions.append("TTF")
if has_otf:
extensions.append("OTF")
if has_web:
extensions.append("web")
ext_comment = " ".join(extensions) if extensions else "other_files only"
test_block = self._generate_test_block(
formula_name, has_ttf, has_otf, has_web, has_other
)
return f"""# typed: false
# frozen_string_literal: true
# This file was generated by the font folder cleanup script
# Do not edit this file directly
# Installs: {ext_comment}
class Font{class_name} < Formula
desc "Font: {formula_name}"
homepage "http://clancy.genet-godzilla.ts.net:8085/Fonts/homebrew-fonts"
url "http://clancy.genet-godzilla.ts.net:8085/Fonts/homebrew-fonts/archive/main.tar.gz"
version "1.0.0"
sha256 "bac980fd4ed38cb23e2dd9a7fc282d4e25f83b71a620f2822f7da73349375444"
def install
# Create font directories
(share/"fonts").mkpath
(share/"fonts/truetype").mkpath
(share/"fonts/opentype").mkpath
(share/"fonts/webfonts").mkpath
# Install TTF fonts
Dir.glob("homebrew-fonts-main/font_files/{font_name}/ttf/*.ttf").each do |font|
system "cp", font, share/"fonts/truetype"
end
# Install OTF fonts
Dir.glob("homebrew-fonts-main/font_files/{font_name}/otf/*.otf").each do |font|
system "cp", font, share/"fonts/opentype"
end
# Install web fonts
Dir.glob("homebrew-fonts-main/font_files/{font_name}/web/*.{{woff,woff2,eot,svg}}").each do |font|
system "cp", font, share/"fonts/webfonts"
end
# Install documentation and other files
(share/"{formula_name}").mkpath
Dir.glob("homebrew-fonts-main/font_files/{font_name}/other_files/*").each do |file|
system "cp", "-r", file, share/"{formula_name}"
end
end
def caveats
<<~EOS
Fonts have been installed to:
#{{share}}/fonts/truetype
#{{share}}/fonts/opentype
#{{share}}/fonts/webfonts
Additional files are available in:
#{{share}}/{formula_name}
EOS
end
test do
{test_block}
end
end
"""
def generate_formulas(self):
"""Generate Homebrew formulas for all font folders."""
for font_dir in sorted(self.fonts_dir.glob("font-*")):
if not font_dir.is_dir():
continue
font_name = font_dir.name
formula_name = font_name.replace("font-", "", 1)
has_ttf, has_otf, has_web, has_other = self._font_has_files(font_dir)
formula_content = self.generate_formula_content(
font_name, formula_name, has_ttf, has_otf, has_web, has_other
)
formula_path = self.formula_dir / f"font-{formula_name}.rb"
formula_path.write_text(formula_content)
print(f"Generated formula for font-{formula_name}")
def main():
# Get the absolute path to the font_files directory
script_dir = Path(__file__).parent
fonts_dir = script_dir.parent / 'font_files'
if not fonts_dir.exists():
print(f"Error: Font directory not found: {fonts_dir}")
return
generator = HomebrewFormulaGenerator(fonts_dir)
generator.generate_formulas()
if __name__ == "__main__":
main()