From 9612f9e16f230fff24e911d322b150f13e92b66d Mon Sep 17 00:00:00 2001 From: David Shea Date: Wed, 16 Mar 2016 11:27:58 -0400 Subject: [PATCH] Add a means of excluding packages from a glob This makes package selection a little more roundabout, but it allows for unused packages (and their dependencies) to be removed from globs during the install phase. dnf.subject.Subject is the class used by dnf's Base.install to select packages, so the behavior of installpkg without --except options is the same as it was before. --- src/pylorax/ltmpl.py | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/pylorax/ltmpl.py b/src/pylorax/ltmpl.py index c369c410..521c2cf7 100644 --- a/src/pylorax/ltmpl.py +++ b/src/pylorax/ltmpl.py @@ -493,7 +493,7 @@ class LoraxTemplateRunner(object): def installpkg(self, *pkgs): ''' - installpkg [--required] PKGGLOB [PKGGLOB ...] + installpkg [--required] [--except PKGGLOB [--except PKGGLOB ...]] PKGGLOB [PKGGLOB ...] Request installation of all packages matching the given globs. Note that this is just a *request* - nothing is *actually* installed until the 'run_pkg_transaction' command is given. @@ -503,9 +503,35 @@ class LoraxTemplateRunner(object): pkgs = pkgs[1:] required = True + excludes = [] + while '--except' in pkgs: + idx = pkgs.index('--except') + if len(pkgs) == idx+1: + raise ValueError("installpkg needs an argument after --except") + + excludes.append(pkgs[idx+1]) + pkgs = pkgs[:idx] + pkgs[idx+2:] + for p in pkgs: try: - self.dbo.install(p) + # Start by using Subject to generate a package query, which will + # give us a query object similar to what dbo.install would select, + # minus the handling for multilib. This query may contain + # multiple arches. Pull the package names out of that, filter any + # that match the excludes patterns, and pass those names back to + # dbo.install to do the actual, arch and version and multilib + # aware, package selction. + + # dnf queries don't have a concept of negative globs which is why + # the filtering is done the hard way. + + pkgnames = {pkg.name for pkg in dnf.subject.Subject(p).get_best_query(self.dbo.sack)} + + for exclude in excludes: + pkgnames = {pkgname for pkgname in pkgnames if not fnmatch.fnmatch(pkgname, exclude)} + + for pkgname in pkgnames: + self.dbo.install(pkgname) except Exception as e: # pylint: disable=broad-except # FIXME: save exception and re-raise after the loop finishes logger.error("installpkg %s failed: %s", p, str(e))