lorax: Fix dnf problems with selecting highest NEVRA from multiple repos

When using package name globs and multiple repos dnf doesn't choose the
highest NEVRA as you would expect, work around this by applying max() to
the duplicate package names in installpkg.

Resolves: rhbz#1548586
This commit is contained in:
Brian C. Lane 2018-10-25 11:15:03 -07:00
parent 32156bd349
commit 6e57bfe11d

View File

@ -534,7 +534,7 @@ class LoraxTemplateRunner(object):
pkgs = pkgs[:idx] + pkgs[idx+2:] pkgs = pkgs[:idx] + pkgs[idx+2:]
errors = False errors = False
for p in pkgs: for pkg in pkgs:
try: try:
# Start by using Subject to generate a package query, which will # Start by using Subject to generate a package query, which will
# give us a query object similar to what dbo.install would select, # give us a query object similar to what dbo.install would select,
@ -547,20 +547,27 @@ class LoraxTemplateRunner(object):
# dnf queries don't have a concept of negative globs which is why # dnf queries don't have a concept of negative globs which is why
# the filtering is done the hard way. # the filtering is done the hard way.
pkgnames = [pkg for pkg in dnf.subject.Subject(p).get_best_query(self.dbo.sack).filter(latest=True)] pkgnames = [p for p in dnf.subject.Subject(pkg).get_best_query(self.dbo.sack).filter(latest=True)]
if not pkgnames: if not pkgnames:
raise dnf.exceptions.PackageNotFoundError("no package matched", p) raise dnf.exceptions.PackageNotFoundError("no package matched", pkg)
# Apply excludes to the name only # Apply excludes to the name only
for exclude in excludes: for exclude in excludes:
pkgnames = [pkg for pkg in pkgnames if not fnmatch.fnmatch(pkg.name, exclude)] pkgnames = [p for p in pkgnames if not fnmatch.fnmatch(p.name, exclude)]
# dnf doesn't handle globs and multiple repos correctly, we need to find the highest nvr for each unique
# package name and install those. Except that we also support version pinning but in that case it
# won't be a glob so this should work.
d = {}
for p in pkgnames:
d[p.name] = max(p, d.get(p.name, p))
# Convert to a sorted NVR list for installation # Convert to a sorted NVR list for installation
pkgnvrs = sorted(["{}-{}-{}".format(pkg.name, pkg.version, pkg.release) for pkg in pkgnames]) pkgnvrs = sorted(["{}-{}-{}".format(p.name, p.version, p.release) for p in d.values()])
# If the request is a glob, expand it in the log # If the request is a glob, expand it in the log
if any(g for g in ['*','?','.'] if g in p): if any(g for g in ['*','?','.'] if g in pkg):
logger.info("installpkg: %s expands to %s", p, ",".join(pkgnvrs)) logger.info("installpkg: %s expands to %s", pkg, ",".join(pkgnvrs))
for pkgnvr in pkgnvrs: for pkgnvr in pkgnvrs:
try: try:
@ -571,7 +578,7 @@ class LoraxTemplateRunner(object):
# Not required, log it and continue processing pkgs # Not required, log it and continue processing pkgs
logger.error("installpkg %s failed: %s", pkgnvr, str(e)) logger.error("installpkg %s failed: %s", pkgnvr, str(e))
except Exception as e: # pylint: disable=broad-except except Exception as e: # pylint: disable=broad-except
logger.error("installpkg %s failed: %s", p, str(e)) logger.error("installpkg %s failed: %s", pkg, str(e))
errors = True errors = True
if errors and required: if errors and required: