13508eddcSopenharmony_cifrom github import Github, Repository
23508eddcSopenharmony_cifrom gftools.utils import download_file
33508eddcSopenharmony_cifrom zipfile import ZipFile
43508eddcSopenharmony_cifrom pathlib import Path
53508eddcSopenharmony_ciimport tempfile
63508eddcSopenharmony_ciimport os
73508eddcSopenharmony_ciimport json
83508eddcSopenharmony_cifrom io import BytesIO
93508eddcSopenharmony_cifrom pybars import Compiler, strlist
103508eddcSopenharmony_ciimport re
113508eddcSopenharmony_ciimport subprocess
123508eddcSopenharmony_ci
133508eddcSopenharmony_ci
143508eddcSopenharmony_ciTESTING = False
153508eddcSopenharmony_ciSPECIAL_REPOS = [
163508eddcSopenharmony_ci    "notofonts.github.io",
173508eddcSopenharmony_ci    "overview",
183508eddcSopenharmony_ci    ".github",
193508eddcSopenharmony_ci    ".allstar",
203508eddcSopenharmony_ci    "notobuilder",
213508eddcSopenharmony_ci    "noto-data-dev",
223508eddcSopenharmony_ci    "noto-docs",
233508eddcSopenharmony_ci    "noto-project-template",
243508eddcSopenharmony_ci    "notoglot-mini",
253508eddcSopenharmony_ci]
263508eddcSopenharmony_ci
273508eddcSopenharmony_ci
283508eddcSopenharmony_cidef fonts_from_zip(zipfile, dst=None):
293508eddcSopenharmony_ci    """Unzip fonts. If not dst is given unzip as BytesIO objects"""
303508eddcSopenharmony_ci    fonts = []
313508eddcSopenharmony_ci    for filename in zipfile.namelist():
323508eddcSopenharmony_ci        if filename.endswith(".ttf") or filename.endswith(".otf"):
333508eddcSopenharmony_ci            if dst:
343508eddcSopenharmony_ci                target = os.path.join(dst, filename)
353508eddcSopenharmony_ci                zipfile.extract(filename, dst)
363508eddcSopenharmony_ci                fonts.append(target)
373508eddcSopenharmony_ci            else:
383508eddcSopenharmony_ci                fonts.append(BytesIO(zipfile.read(filename)))
393508eddcSopenharmony_ci    return fonts
403508eddcSopenharmony_ci
413508eddcSopenharmony_ci
423508eddcSopenharmony_cidef tree_has_new_files():
433508eddcSopenharmony_ci    ls = subprocess.run(["git", "ls-files", "--others"], capture_output=True)
443508eddcSopenharmony_ci    return ls.stdout
453508eddcSopenharmony_ci
463508eddcSopenharmony_ci
473508eddcSopenharmony_ciprint("Fetching existing repos")
483508eddcSopenharmony_cig = Github(os.environ["GITHUB_TOKEN"])
493508eddcSopenharmony_ciorg = g.get_organization("notofonts")
503508eddcSopenharmony_ciorg_repos = org.get_repos()
513508eddcSopenharmony_ciorg_names = [r.name for r in org_repos]
523508eddcSopenharmony_ci
533508eddcSopenharmony_cisubprocess.run(["git", "config", "user.name", "actions-user"])
543508eddcSopenharmony_cisubprocess.run(["git", "config", "user.email", "actions-user@users.noreply.github.com"])
553508eddcSopenharmony_ci
563508eddcSopenharmony_cito_push = []
573508eddcSopenharmony_ci
583508eddcSopenharmony_cifontrepos = json.load(open("fontrepos.json"))
593508eddcSopenharmony_ciif os.path.exists("state.json"):
603508eddcSopenharmony_ci    state = json.load(open("state.json"))
613508eddcSopenharmony_cielse:
623508eddcSopenharmony_ci    state = {}
633508eddcSopenharmony_ci
643508eddcSopenharmony_ciresults = {}
653508eddcSopenharmony_ci
663508eddcSopenharmony_cifor repo_name in org_names:
673508eddcSopenharmony_ci    if repo_name in SPECIAL_REPOS:
683508eddcSopenharmony_ci        continue
693508eddcSopenharmony_ci    repo = g.get_repo("notofonts/" + repo_name)
703508eddcSopenharmony_ci    if repo.archived:
713508eddcSopenharmony_ci        continue
723508eddcSopenharmony_ci    if repo_name not in fontrepos:
733508eddcSopenharmony_ci        print("Unknown repo %s; is it missing from fontrepos?" % repo_name)
743508eddcSopenharmony_ci        continue
753508eddcSopenharmony_ci
763508eddcSopenharmony_ci    print(f"Gathering data for {repo_name}")
773508eddcSopenharmony_ci
783508eddcSopenharmony_ci    repo = g.get_repo("notofonts/" + repo_name)
793508eddcSopenharmony_ci    results[repo_name] = {
803508eddcSopenharmony_ci        "title": repo.description,
813508eddcSopenharmony_ci        "tier": fontrepos[repo_name].get("tier", 3),
823508eddcSopenharmony_ci        "gh_url": "https://notofonts.github.io/" + repo_name,
833508eddcSopenharmony_ci        "repo_url": "https://www.github.com/notofonts/" + repo_name,
843508eddcSopenharmony_ci    }
853508eddcSopenharmony_ci
863508eddcSopenharmony_ci    # Get issues
873508eddcSopenharmony_ci    results[repo_name]["issues"] = []
883508eddcSopenharmony_ci    for issue in repo.get_issues():
893508eddcSopenharmony_ci        results[repo_name]["issues"].append(
903508eddcSopenharmony_ci            {"title": issue.title, "number": issue.number, "url": issue.html_url}
913508eddcSopenharmony_ci        )
923508eddcSopenharmony_ci
933508eddcSopenharmony_ci    if repo_name not in state:
943508eddcSopenharmony_ci        state[repo_name] = {}
953508eddcSopenharmony_ci
963508eddcSopenharmony_ci    # Check for new releases
973508eddcSopenharmony_ci    releases = repo.get_releases()
983508eddcSopenharmony_ci    for release in sorted(
993508eddcSopenharmony_ci        releases, key=lambda r: r.published_at.isoformat() if r.published_at else ""
1003508eddcSopenharmony_ci    ):
1013508eddcSopenharmony_ci        m = re.match(r"^(.*)-(v[\d.]+)", release.tag_name)
1023508eddcSopenharmony_ci        if not m:
1033508eddcSopenharmony_ci            print(f"Unparsable release {release.tag_name} in {repo_name}")
1043508eddcSopenharmony_ci            continue
1053508eddcSopenharmony_ci        if release.draft:
1063508eddcSopenharmony_ci            continue
1073508eddcSopenharmony_ci        family, version = m[1], m[2]
1083508eddcSopenharmony_ci        family = re.sub(r"([a-z])([A-Z])", r"\1 \2", family)
1093508eddcSopenharmony_ci        if release.tag_name in state[repo_name].get("known_releases", []):
1103508eddcSopenharmony_ci            continue
1113508eddcSopenharmony_ci        assets = release.get_assets()
1123508eddcSopenharmony_ci        if not assets:
1133508eddcSopenharmony_ci            continue
1143508eddcSopenharmony_ci        latest_asset = assets[0]
1153508eddcSopenharmony_ci        state[repo_name].setdefault("known_releases", []).append(release.tag_name)
1163508eddcSopenharmony_ci        family_thing = (
1173508eddcSopenharmony_ci            state[repo_name].setdefault("families", {}).setdefault(family, {})
1183508eddcSopenharmony_ci        )
1193508eddcSopenharmony_ci
1203508eddcSopenharmony_ci        body = release.body
1213508eddcSopenharmony_ci        if not body:
1223508eddcSopenharmony_ci            tag_sha = repo.get_git_ref("tags/" + release.tag_name).object.sha
1233508eddcSopenharmony_ci            try:
1243508eddcSopenharmony_ci                body = repo.get_git_tag(tag_sha).message
1253508eddcSopenharmony_ci            except Exception as e:
1263508eddcSopenharmony_ci                print("Couldn't retrieve release message for %s" % release.tag_name)
1273508eddcSopenharmony_ci
1283508eddcSopenharmony_ci        family_thing["latest_release"] = {
1293508eddcSopenharmony_ci            "url": release.html_url,
1303508eddcSopenharmony_ci            "version": version,
1313508eddcSopenharmony_ci            "notes": body,
1323508eddcSopenharmony_ci        }
1333508eddcSopenharmony_ci
1343508eddcSopenharmony_ci        if release.published_at:
1353508eddcSopenharmony_ci            family_thing["latest_release"][
1363508eddcSopenharmony_ci                "published"
1373508eddcSopenharmony_ci            ] = release.published_at.isoformat()
1383508eddcSopenharmony_ci
1393508eddcSopenharmony_ci        try:
1403508eddcSopenharmony_ci            z = ZipFile(download_file(latest_asset.browser_download_url))
1413508eddcSopenharmony_ci            family_thing["files"] = []
1423508eddcSopenharmony_ci            with tempfile.TemporaryDirectory() as tmpdir:
1433508eddcSopenharmony_ci                fonts = fonts_from_zip(z, tmpdir)
1443508eddcSopenharmony_ci                for font in fonts:
1453508eddcSopenharmony_ci                    newpath = Path("fonts/") / Path(font).relative_to(tmpdir)
1463508eddcSopenharmony_ci                    os.makedirs(newpath.parent, exist_ok=True)
1473508eddcSopenharmony_ci                    family_thing["files"].append(str(newpath))
1483508eddcSopenharmony_ci                    os.rename(font, newpath)
1493508eddcSopenharmony_ci                if tree_has_new_files() and not TESTING:
1503508eddcSopenharmony_ci                    # Add it and tag it
1513508eddcSopenharmony_ci                    subprocess.run(["git", "add", "."])
1523508eddcSopenharmony_ci                    subprocess.run(["git", "commit", "-m", "Add " + release.tag_name])
1533508eddcSopenharmony_ci                    subprocess.run(["git", "tag", release.tag_name])
1543508eddcSopenharmony_ci                    to_push.append(release.tag_name)
1553508eddcSopenharmony_ci        except Exception as e:
1563508eddcSopenharmony_ci            print("Couldn't fetch download for %s" % latest_asset.browser_download_url)
1573508eddcSopenharmony_ci
1583508eddcSopenharmony_ci            # Tweet about the new release or something
1593508eddcSopenharmony_ci    results[repo_name]["families"] = state[repo_name].get("families", {})
1603508eddcSopenharmony_ci
1613508eddcSopenharmony_cisubprocess.run(["git", "push"])
1623508eddcSopenharmony_cifor tag in to_push:
1633508eddcSopenharmony_ci    subprocess.run(["git", "push", "origin", tag])
1643508eddcSopenharmony_ci
1653508eddcSopenharmony_ci# Save state
1663508eddcSopenharmony_cijson.dump(state, open("state.json", "w"), indent=True, sort_keys=True)
1673508eddcSopenharmony_ci
1683508eddcSopenharmony_cifor result in results.values():
1693508eddcSopenharmony_ci    for family in result.get("families", {}).values():
1703508eddcSopenharmony_ci        newfiles = {"unhinted": [], "hinted": [], "full": []}
1713508eddcSopenharmony_ci        for file in sorted(family.get("files", [])):
1723508eddcSopenharmony_ci            if "unhinted" in file:
1733508eddcSopenharmony_ci                newfiles["unhinted"].append(file)
1743508eddcSopenharmony_ci            elif "hinted" in file:
1753508eddcSopenharmony_ci                newfiles["hinted"].append(file)
1763508eddcSopenharmony_ci            elif "full" in file:
1773508eddcSopenharmony_ci                newfiles["full"].append(file)
1783508eddcSopenharmony_ci        family["files"] = newfiles
1793508eddcSopenharmony_ci
1803508eddcSopenharmony_cijson.dump(results, open("docs/noto.json", "w"), indent=True, sort_keys=True)
181