Handle excludes during depsolving.

Prefiously, packages were excluded from the initial package list,
but could have been pulled in during depsolving. This patch excludes
selected packages for good. Supported syntax is -$name or -%name.%arch
including wildchars.
This commit is contained in:
Daniel Mach 2012-03-05 06:10:17 -05:00 committed by Dennis Gilmore
parent 8ccc24e106
commit 9d7f82d91a
1 changed files with 31 additions and 30 deletions

View File

@ -25,6 +25,8 @@ import subprocess
import createrepo import createrepo
import ConfigParser import ConfigParser
import pylorax import pylorax
from fnmatch import fnmatch
class MyConfigParser(ConfigParser.ConfigParser): class MyConfigParser(ConfigParser.ConfigParser):
"""A subclass of ConfigParser which does not lowercase options""" """A subclass of ConfigParser which does not lowercase options"""
@ -139,6 +141,7 @@ class Pungi(pypungi.PungiBase):
self.srpms_fulltree = [] self.srpms_fulltree = []
self.last_po = 0 self.last_po = 0
self.resolved_deps = {} # list the deps we've already resolved, short circuit. self.resolved_deps = {} # list the deps we've already resolved, short circuit.
self.excluded_pkgs = {} # list the packages we've already excluded.
def _add_yum_repo(self, name, url, mirrorlist=False, groups=True, def _add_yum_repo(self, name, url, mirrorlist=False, groups=True,
cost=1000, includepkgs=[], excludepkgs=[], cost=1000, includepkgs=[], excludepkgs=[],
@ -306,6 +309,30 @@ class Pungi(pypungi.PungiBase):
return True return True
def excludePackages(self, pkg_sack):
"""exclude packages according to config file"""
if not pkg_sack:
return pkg_sack
excludes = [] # list of (name, arch, pattern)
for i in self.ksparser.handler.packages.excludedList:
if "." in i:
excludes.append(i.rsplit(".", 1) + [i])
else:
excludes.append((i, None, i))
for pkg in pkg_sack[:]:
for name, arch, exclude_pattern in excludes:
if fnmatch(pkg.name, name):
if not arch or fnmatch(pkg.arch, arch):
if pkg.nvra not in self.excluded_pkgs:
self.logger.info("Excluding %s.%s (pattern: %s)" % (pkg.name, pkg.arch, exclude_pattern))
self.excluded_pkgs[pkg.nvra] = pkg
pkg_sack.remove(pkg)
break
return pkg_sack
def getPackageDeps(self, po): def getPackageDeps(self, po):
"""Add the dependencies for a given package to the """Add the dependencies for a given package to the
transaction info""" transaction info"""
@ -328,6 +355,7 @@ class Pungi(pypungi.PungiBase):
if self.config.getboolean('pungi', 'alldeps'): if self.config.getboolean('pungi', 'alldeps'):
# greedy # greedy
deps = self.ayum.whatProvides(r, f, v).returnPackages() deps = self.ayum.whatProvides(r, f, v).returnPackages()
deps = self.excludePackages(deps)
if not deps: if not deps:
self.logger.warn("Unresolvable dependency %s in %s.%s" % (r, po.name, po.arch)) self.logger.warn("Unresolvable dependency %s in %s.%s" % (r, po.name, po.arch))
continue continue
@ -342,6 +370,7 @@ class Pungi(pypungi.PungiBase):
# nogreedy # nogreedy
try: try:
pkg_sack = self.ayum.whatProvides(r, f, v).returnPackages() pkg_sack = self.ayum.whatProvides(r, f, v).returnPackages()
pkg_sack = self.excludePackages(pkg_sack)
if not pkg_sack: if not pkg_sack:
self.logger.warn("Unresolvable dependency %s in %s.%s" % (r, po.name, po.arch)) self.logger.warn("Unresolvable dependency %s in %s.%s" % (r, po.name, po.arch))
continue continue
@ -413,33 +442,6 @@ class Pungi(pypungi.PungiBase):
self.logger.debug('Add default groups %s' % groups) self.logger.debug('Add default groups %s' % groups)
return groups return groups
def _deselectPackage(self, pkg, *args):
"""Stolen from anaconda; Remove a package from the transaction set"""
sp = pkg.rsplit(".", 2)
txmbrs = []
if len(sp) == 2:
txmbrs = self.ayum.tsInfo.matchNaevr(name=sp[0], arch=sp[1])
if len(txmbrs) == 0:
exact, match, unmatch = yum.packages.parsePackages(self.ayum.pkgSack.returnPackages(), [pkg], casematch=1)
for p in exact + match:
txmbrs.append(p)
if len(txmbrs) > 0:
for x in txmbrs:
self.ayum.tsInfo.remove(x.pkgtup)
# we also need to remove from the conditionals
# dict so that things don't get pulled back in as a result
# of them. yes, this is ugly. conditionals should die.
for req, pkgs in self.ayum.tsInfo.conditionals.iteritems():
if x in pkgs:
pkgs.remove(x)
self.ayum.tsInfo.conditionals[req] = pkgs
return len(txmbrs)
else:
self.logger.debug("no such package %s to remove" %(pkg,))
return 0
def getPackageObjects(self): def getPackageObjects(self):
"""Cycle through the list of packages, get package object """Cycle through the list of packages, get package object
matches, and resolve deps. matches, and resolve deps.
@ -485,6 +487,7 @@ class Pungi(pypungi.PungiBase):
# Search repos for things in our searchlist, supports globs # Search repos for things in our searchlist, supports globs
(exactmatched, matched, unmatched) = yum.packages.parsePackages(self.ayum.pkgSack.returnPackages(), searchlist, casematch=1) (exactmatched, matched, unmatched) = yum.packages.parsePackages(self.ayum.pkgSack.returnPackages(), searchlist, casematch=1)
matches = filter(self._filtersrcdebug, exactmatched + matched) matches = filter(self._filtersrcdebug, exactmatched + matched)
matches = self.excludePackages(matches)
# Populate a dict of package objects to their names # Populate a dict of package objects to their names
for match in matches: for match in matches:
@ -509,6 +512,7 @@ class Pungi(pypungi.PungiBase):
pkg_sack = self.ayum.pkgSack.searchNevra(name=name, arch=arch) pkg_sack = self.ayum.pkgSack.searchNevra(name=name, arch=arch)
# filter sources out of the package sack # filter sources out of the package sack
pkg_sack = [ i for i in pkg_sack if i.arch not in ("src", "nosrc") ] pkg_sack = [ i for i in pkg_sack if i.arch not in ("src", "nosrc") ]
pkg_sack = self.excludePackages(pkg_sack)
match = self.ayum._bestPackageFromList(pkg_sack) match = self.ayum._bestPackageFromList(pkg_sack)
if not match: if not match:
@ -521,9 +525,6 @@ class Pungi(pypungi.PungiBase):
if len(self.ayum.tsInfo) == 0: if len(self.ayum.tsInfo) == 0:
raise yum.Errors.MiscError, 'No packages found to download.' raise yum.Errors.MiscError, 'No packages found to download.'
# Deselect things we don't want from the ks
map(self._deselectPackage, self.ksparser.handler.packages.excludedList)
moretoprocess = True moretoprocess = True
while moretoprocess: # Our fun loop while moretoprocess: # Our fun loop
moretoprocess = False moretoprocess = False