#!/usr/bin/env python3 """Turn build-info.json into a ready-to-publish PKGBUILD. pkgrel is derived from what is currently on the AUR: same pkgver means this is a rebuild (against a new R/Qt6), so pkgrel increments; a new pkgver resets it to 1. """ import argparse import json import re import sys import urllib.request AUR_RPC = "https://aur.archlinux.org/rpc/v5/info?arg[]={}" def next_minor(version: str) -> str: """4.6 -> 4.7, 6.11 -> 6.12 — the upper bound of the compatible range.""" major, minor = version.split(".")[:2] return f"{major}.{int(minor) + 1}" def current_aur_version(pkgname: str) -> tuple[str, int] | None: """(pkgver, pkgrel) currently published on the AUR, or None if absent.""" try: with urllib.request.urlopen(AUR_RPC.format(pkgname), timeout=30) as r: results = json.load(r).get("results", []) except Exception as exc: # network trouble must not silently reset pkgrel print(f"warning: could not query AUR: {exc}", file=sys.stderr) return None if not results: return None full = results[0]["Version"] # e.g. "0.98.1-2" ver, _, rel = full.rpartition("-") return ver, int(rel) if rel.isdigit() else 1 def main() -> int: ap = argparse.ArgumentParser() ap.add_argument("--build-info", required=True) ap.add_argument("--template", required=True) ap.add_argument("--out", required=True) ap.add_argument("--base-url", required=True, help="public directory the tarball is served from") ap.add_argument("--maintainer", required=True) ap.add_argument("--pkgname", default="jasp-desktop-bin") args = ap.parse_args() info = json.loads(open(args.build_info).read()) jasp_version = info["jasp_version"] published = current_aur_version(args.pkgname) if published and published[0] == jasp_version: pkgrel = published[1] + 1 print(f"rebuild of {jasp_version}: pkgrel {published[1]} -> {pkgrel}") else: pkgrel = 1 print(f"new version {jasp_version}: pkgrel 1") tag = f"v{jasp_version}-{pkgrel}" download_url = f"{args.base_url.rstrip('/')}/{info['tarball']}" qt_minor = info["qt6_minor"] substitutions = { "@MAINTAINER@": args.maintainer, "@JASP_VERSION@": jasp_version, "@JASP_TAG@": info["jasp_tag"], "@JASP_COMMIT@": info["jasp_commit"], "@PKGREL@": str(pkgrel), "@BUNDLED_R@": info["bundled_r_version"], "@QT_MINOR@": qt_minor, "@DOWNLOAD_URL@": download_url, "@SHA256@": info["sha256"], } text = open(args.template).read() for key, value in substitutions.items(): text = text.replace(key, value) leftover = re.findall(r"@[A-Z0-9_]+@", text) if leftover: print(f"error: unsubstituted placeholders: {sorted(set(leftover))}", file=sys.stderr) return 1 with open(args.out, "w") as fh: fh.write(text) # Consumed by the release + AUR-push steps of the workflow. with open("release-meta.json", "w") as fh: json.dump({"tag": tag, "pkgrel": pkgrel, "download_url": download_url, **info}, fh, indent=2) print(f"wrote {args.out} ({args.pkgname} {jasp_version}-{pkgrel})") print(f" R bundled at {info['bundled_r_version']}; built against Qt {qt_minor}") print(" depends are unpinned - everything volatile is bundled") return 0 if __name__ == "__main__": sys.exit(main())