rpmmd: Add error reporting support to dnf-json

Previously dnf-json hasn't been able to report any reports. This commit
tries to fix it with introduction of somewhat flexible error format.
This commit is contained in:
Ondřej Budai 2019-11-12 20:17:28 +01:00 committed by Tom Gundersen
parent 495f5b558b
commit 9076f68f7b
2 changed files with 54 additions and 4 deletions

View file

@ -5,6 +5,8 @@ import dnf
import json
import sys
DNF_ERROR_EXIT_CODE = 10
def timestamp_to_rfc3339(timestamp):
d = datetime.datetime.utcfromtimestamp(package.buildtime)
@ -39,6 +41,11 @@ def create_base(repos):
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", {})
@ -63,8 +70,21 @@ if command == "dump":
elif command == "depsolve":
base = create_base(arguments.get("repos", {}))
base.install_specs(arguments["package-specs"])
base.resolve()
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({

View file

@ -2,6 +2,8 @@ package rpmmd
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"os/exec"
"sort"
@ -44,6 +46,15 @@ type RPMMD interface {
Depsolve(specs []string, repos []RepoConfig) ([]PackageSpec, error)
}
type DNFError struct {
Kind string `json:"kind"`
Reason string `json:"reason"`
}
func (err *DNFError) Error() string {
return fmt.Sprintf("DNF error occured: %s: %s", err.Kind, err.Reason)
}
func runDNF(command string, arguments interface{}, result interface{}) error {
var call = struct {
Command string `json:"command"`
@ -77,12 +88,31 @@ func runDNF(command string, arguments interface{}, result interface{}) error {
}
stdin.Close()
err = json.NewDecoder(stdout).Decode(result)
output, err := ioutil.ReadAll(stdout)
if err != nil {
return err
}
return cmd.Wait()
err = cmd.Wait()
const DnfErrorExitCode = 10
if runError, ok := err.(*exec.ExitError); ok && runError.ExitCode() == DnfErrorExitCode {
var dnfError DNFError
err = json.Unmarshal(output, &dnfError)
if err != nil {
return err
}
return &dnfError
}
err = json.Unmarshal(output, result)
if err != nil {
return err
}
return nil
}
type rpmmdImpl struct{}