Previously dnf-json hasn't been able to report any reports. This commit tries to fix it with introduction of somewhat flexible error format.
97 lines
2.7 KiB
Python
97 lines
2.7 KiB
Python
#!/usr/bin/python3
|
|
|
|
import datetime
|
|
import dnf
|
|
import json
|
|
import sys
|
|
|
|
DNF_ERROR_EXIT_CODE = 10
|
|
|
|
|
|
def timestamp_to_rfc3339(timestamp):
|
|
d = datetime.datetime.utcfromtimestamp(package.buildtime)
|
|
return d.strftime('%Y-%m-%dT%H:%M:%SZ')
|
|
|
|
|
|
def dnfrepo(desc, parent_conf=None):
|
|
"""Makes a dnf.repo.Repo out of a JSON repository description"""
|
|
|
|
repo = dnf.repo.Repo(desc["id"], parent_conf)
|
|
repo.name = desc["name"]
|
|
|
|
if "baseurl" in desc:
|
|
repo.baseurl = desc["baseurl"]
|
|
elif "metalink" in desc:
|
|
repo.metalink = desc["metalink"]
|
|
elif "mirrorlist" in desc:
|
|
repo.metalink = desc["mirrorlist"]
|
|
else:
|
|
assert False
|
|
|
|
return repo
|
|
|
|
|
|
def create_base(repos):
|
|
base = dnf.Base()
|
|
|
|
for repo in repos:
|
|
base.repos.add(dnfrepo(repo, base.conf))
|
|
|
|
base.fill_sack(load_system_repo=False)
|
|
return base
|
|
|
|
|
|
def exit_with_dnf_error(kind: str, reason: str):
|
|
json.dump({"kind": kind, "reason": reason}, sys.stdout)
|
|
sys.exit(DNF_ERROR_EXIT_CODE)
|
|
|
|
|
|
call = json.load(sys.stdin)
|
|
command = call["command"]
|
|
arguments = call.get("arguments", {})
|
|
|
|
if command == "dump":
|
|
base = create_base(arguments.get("repos", {}))
|
|
packages = []
|
|
for package in base.sack.query().available():
|
|
packages.append({
|
|
"name": package.name,
|
|
"summary": package.summary,
|
|
"description": package.description,
|
|
"url": package.url,
|
|
"epoch": package.epoch,
|
|
"version": package.version,
|
|
"release": package.release,
|
|
"arch": package.arch,
|
|
"buildtime": timestamp_to_rfc3339(package.buildtime),
|
|
"license": package.license
|
|
})
|
|
json.dump(packages, sys.stdout)
|
|
|
|
elif command == "depsolve":
|
|
base = create_base(arguments.get("repos", {}))
|
|
errors = []
|
|
for pkgspec in arguments["package-specs"]:
|
|
try:
|
|
base.install_specs([pkgspec])
|
|
except dnf.exceptions.MarkingError as e:
|
|
errors.append((pkgspec, str(e)))
|
|
if errors:
|
|
formatted_errors = ", ".join((f"{package} ({err})" for package, err in errors))
|
|
exit_with_dnf_error("MarkingError", f"The following package(s) had problems: {formatted_errors}")
|
|
|
|
try:
|
|
base.resolve()
|
|
except dnf.exceptions.DepsolveError as e:
|
|
exit_with_dnf_error("DepsolveError", f"There was a problem depsolving {arguments['package-specs']}: {e}")
|
|
|
|
packages = []
|
|
for package in base.transaction.install_set:
|
|
packages.append({
|
|
"name": package.name,
|
|
"epoch": package.epoch,
|
|
"version": package.version,
|
|
"release": package.release,
|
|
"arch": package.arch
|
|
})
|
|
json.dump(packages, sys.stdout)
|