106 lines
3.5 KiB
Python
106 lines
3.5 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
sync_helpers.py - small helper used by sync.sh
|
|
|
|
Two jobs, on purpose kept out of bash because reliable YAML parsing and XML
|
|
escaping in pure bash/sed is a losing game:
|
|
|
|
parse-yaml <file>
|
|
Reads the "sources:" list from the YAML file and prints it as JSON
|
|
on stdout, so sync.sh can loop over it safely (no word-splitting
|
|
issues, handles quoting etc.).
|
|
|
|
gen-appstream <origin> <entries_json>
|
|
entries_json is a JSON array of {"name":..., "summary":...} objects
|
|
(only the *explicitly requested* top-level packages, never pulled-in
|
|
dependencies). Prints a minimal AppStream "generic component" catalog
|
|
on stdout, which sync.sh gzips and injects into the repo metadata via
|
|
modifyrepo_c.
|
|
|
|
NOTE: "generic" components (no icon/screenshots/.desktop file) make a
|
|
package installable from GNOME Software / Discover and show up in
|
|
search, but will NOT appear on the curated "Explore" front page -
|
|
that's a GNOME Software behaviour for non-desktop-app components, not
|
|
something fixable at the repo-metadata level.
|
|
"""
|
|
import sys
|
|
import json
|
|
import argparse
|
|
from xml.sax.saxutils import escape
|
|
|
|
|
|
def cmd_parse_yaml(path: str) -> None:
|
|
try:
|
|
import yaml
|
|
except ImportError:
|
|
sys.stderr.write(
|
|
"ERROR: python3-pyyaml (PyYAML) is not installed.\n"
|
|
"Install it with: dnf install -y python3-pyyaml\n"
|
|
)
|
|
sys.exit(1)
|
|
|
|
with open(path, "r", encoding="utf-8") as fh:
|
|
data = yaml.safe_load(fh) or {}
|
|
|
|
sources = data.get("sources") or []
|
|
if not isinstance(sources, list):
|
|
sys.stderr.write("ERROR: 'sources' in YAML is not a list\n")
|
|
sys.exit(1)
|
|
|
|
for i, src in enumerate(sources):
|
|
for field in ("name", "baseurl", "packages"):
|
|
if field not in src:
|
|
sys.stderr.write(
|
|
f"ERROR: source #{i} is missing required field '{field}'\n"
|
|
)
|
|
sys.exit(1)
|
|
if not isinstance(src["packages"], list) or not src["packages"]:
|
|
sys.stderr.write(
|
|
f"ERROR: source '{src.get('name')}' has an empty/invalid packages list\n"
|
|
)
|
|
sys.exit(1)
|
|
|
|
json.dump(sources, sys.stdout)
|
|
|
|
|
|
def cmd_gen_appstream(origin: str, entries_json: str) -> None:
|
|
entries = json.loads(entries_json)
|
|
print('<?xml version="1.0" encoding="UTF-8"?>')
|
|
print(f'<components version="0.14" origin="{escape(origin)}">')
|
|
for e in entries:
|
|
name = e.get("name", "")
|
|
summary = e.get("summary") or f"{name} (mirrored package)"
|
|
cid = f"{name}.generic"
|
|
print(' <component type="generic">')
|
|
print(f" <id>{escape(cid)}</id>")
|
|
print(f" <pkgname>{escape(name)}</pkgname>")
|
|
print(f" <name>{escape(name)}</name>")
|
|
print(f" <summary>{escape(summary)}</summary>")
|
|
print(" <metadata_license>CC0-1.0</metadata_license>")
|
|
print(" <project_license>unknown</project_license>")
|
|
print(" </component>")
|
|
print("</components>")
|
|
|
|
|
|
def main() -> None:
|
|
ap = argparse.ArgumentParser()
|
|
sub = ap.add_subparsers(dest="cmd", required=True)
|
|
|
|
p1 = sub.add_parser("parse-yaml")
|
|
p1.add_argument("path")
|
|
|
|
p2 = sub.add_parser("gen-appstream")
|
|
p2.add_argument("origin")
|
|
p2.add_argument("entries_json")
|
|
|
|
args = ap.parse_args()
|
|
|
|
if args.cmd == "parse-yaml":
|
|
cmd_parse_yaml(args.path)
|
|
elif args.cmd == "gen-appstream":
|
|
cmd_gen_appstream(args.origin, args.entries_json)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|