docker/sync_helpers.py hinzugefügt
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
#!/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()
|
||||
Reference in New Issue
Block a user