From a128b27aabc246c74fc407c93fc8b696f8f1bd92 Mon Sep 17 00:00:00 2001 From: Alexander Sulfrian Date: Thu, 1 Nov 2012 02:25:57 +0100 Subject: Packages: ability to overwrite recommended flag per package --- src/lib/Server/Plugins/Packages/Apt.py | 49 ++++++++++++++++++++++++--- src/lib/Server/Plugins/Packages/Collection.py | 12 ++++--- src/lib/Server/Plugins/Packages/Source.py | 2 +- src/lib/Server/Plugins/Packages/Yum.py | 8 ++--- src/lib/Server/Plugins/Packages/__init__.py | 5 ++- 5 files changed, 61 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/lib/Server/Plugins/Packages/Apt.py b/src/lib/Server/Plugins/Packages/Apt.py index d999e21c8..0c0c95e70 100644 --- a/src/lib/Server/Plugins/Packages/Apt.py +++ b/src/lib/Server/Plugins/Packages/Apt.py @@ -17,6 +17,7 @@ class AptSource(Source): Source.__init__(self, basepath, xsource, config) self.pkgnames = set() self.versions = dict() + self.recommends = dict() self.url_map = [{'rawurl': self.rawurl, 'url': self.url, 'version': self.version, @@ -25,13 +26,13 @@ class AptSource(Source): def save_state(self): cache = file(self.cachefile, 'wb') cPickle.dump((self.pkgnames, self.deps, self.provides, - self.versions), + self.versions, self.recommends), cache, 2) cache.close() def load_state(self): data = file(self.cachefile) - self.pkgnames, self.deps, self.provides, self.versions = cPickle.load(data) + self.pkgnames, self.deps, self.provides, self.versions, self.recommends = cPickle.load(data) def filter_unknown(self, unknown): filtered = set([u for u in unknown if u.startswith('choice')]) @@ -51,6 +52,7 @@ class AptSource(Source): def read_files(self): bdeps = dict() + brecs = dict() bprov = dict() self.versions = dict() if self.recommended: @@ -68,6 +70,7 @@ class AptSource(Source): barch = self.arches[0] if barch not in bdeps: bdeps[barch] = dict() + brecs[barch] = dict() bprov[barch] = dict() self.versions[barch] = dict() try: @@ -81,7 +84,8 @@ class AptSource(Source): pkgname = words[1].strip().rstrip() self.pkgnames.add(pkgname) bdeps[barch][pkgname] = [] - elif words[0] in depfnames: + brecs[barch][pkgname] = [] + elif words[0] in ['Depends', 'Pre-Depends', 'Recommends']: vindex = 0 for dep in words[1].split(','): if '|' in dep: @@ -92,12 +96,19 @@ class AptSource(Source): barch, vindex) vindex += 1 - bdeps[barch][pkgname].append(dyn_dname) + + if words[0] == 'Recommends': + brecs[barch][pkgname].append(dyn_dname) + else: + bdeps[barch][pkgname].append(dyn_dname) bprov[barch][dyn_dname] = set(cdeps) else: raw_dep = re.sub('\(.*\)', '', dep) raw_dep = raw_dep.rstrip().strip() - bdeps[barch][pkgname].append(raw_dep) + if words[0] == 'Recommends': + brecs[barch][pkgname].append(raw_dep) + else: + bdeps[barch][pkgname].append(raw_dep) elif words[0] == 'Provides': for pkg in words[1].split(','): dname = pkg.rstrip().strip() @@ -108,12 +119,15 @@ class AptSource(Source): self.versions[barch][pkgname] = words[1].rstrip().strip() self.deps['global'] = dict() + self.recommends['global'] = dict() self.provides['global'] = dict() for barch in bdeps: self.deps[barch] = dict() + self.recommends[barch] = dict() self.provides[barch] = dict() for pkgname in self.pkgnames: pset = set() + rset = set() for barch in bdeps: if pkgname not in bdeps[barch]: bdeps[barch][pkgname] = [] @@ -123,6 +137,17 @@ class AptSource(Source): else: for barch in bdeps: self.deps[barch][pkgname] = bdeps[barch][pkgname] + + for barch in brecs: + if pkgname not in brecs[barch]: + brecs[barch][pkgname] = [] + rset.add(tuple(brecs[barch][pkgname])) + if len(rset) == 1: + self.recommends['global'][pkgname] = rset.pop() + else: + for barch in brecs: + self.recommends[barch][pkgname] = brecs[barch][pkgname] + provided = set() for bprovided in list(bprov.values()): provided.update(set(bprovided)) @@ -139,6 +164,20 @@ class AptSource(Source): self.provides[barch][prov] = bprov[barch].get(prov, ()) self.save_state() + def get_deps(self, metadata, pkgname, recommended=None): + recs = [] + if ((recommended is None and self.recommended) or + (recommended and recommended.lower() == 'true')): + for arch in self.get_arches(metadata): + if pkgname in self.recommends[arch]: + recs.extend(self.recommends[arch][pkgname]) + + for arch in self.get_arches(metadata): + if pkgname in self.deps[arch]: + recs.extend(self.deps[arch][pkgname]) + + return recs + def is_package(self, _, pkg): return (pkg in self.pkgnames and pkg not in self.blacklist and diff --git a/src/lib/Server/Plugins/Packages/Collection.py b/src/lib/Server/Plugins/Packages/Collection.py index e0c7e338f..d2d8a015d 100644 --- a/src/lib/Server/Plugins/Packages/Collection.py +++ b/src/lib/Server/Plugins/Packages/Collection.py @@ -91,20 +91,24 @@ class Collection(Bcfg2.Server.Plugin.Debuggable): return True return False - def get_deps(self, package, pinnings=None): + def get_deps(self, package, pinnings=None, recs=None): pin_found = False pin_source = None if pinnings and package in pinnings: pin_source = pinnings[package] + recommended = None + if recs and package in recs: + recommended = recs[package] + for source in self.sources: if pin_source and pin_source != source.name: continue pin_found = True if source.is_package(self.metadata, package): - return source.get_deps(self.metadata, package) + return source.get_deps(self.metadata, package, recommended) if not pin_found: self.logger.error("Packages: Source '%s' for package '%s' not found" % @@ -152,7 +156,7 @@ class Collection(Bcfg2.Server.Plugin.Debuggable): """ do any collection-level data setup tasks """ pass - def complete(self, packagelist, pinnings=None): + def complete(self, packagelist, pinnings=None, recommended=None): '''Build the transitive closure of all package dependencies Arguments: @@ -213,7 +217,7 @@ class Collection(Bcfg2.Server.Plugin.Debuggable): self.debug_log("Packages: handling package requirement %s" % current) packages.add(current) - deps = self.get_deps(current, pinnings) + deps = self.get_deps(current, pinnings, recommended) newdeps = set(deps).difference(examined) if newdeps: self.debug_log("Packages: Package %s added requirements %s" diff --git a/src/lib/Server/Plugins/Packages/Source.py b/src/lib/Server/Plugins/Packages/Source.py index d94bcca14..d19d23442 100644 --- a/src/lib/Server/Plugins/Packages/Source.py +++ b/src/lib/Server/Plugins/Packages/Source.py @@ -250,7 +250,7 @@ class Source(Bcfg2.Server.Plugin.Debuggable): def get_arches(self, metadata): return ['global'] + [a for a in self.arches if a in metadata.groups] - def get_deps(self, metadata, pkgname): + def get_deps(self, metadata, pkgname, recommended=None): for arch in self.get_arches(metadata): if pkgname in self.deps[arch]: return self.deps[arch][pkgname] diff --git a/src/lib/Server/Plugins/Packages/Yum.py b/src/lib/Server/Plugins/Packages/Yum.py index 8543b44e4..74eee2662 100644 --- a/src/lib/Server/Plugins/Packages/Yum.py +++ b/src/lib/Server/Plugins/Packages/Yum.py @@ -355,9 +355,9 @@ class YumCollection(Collection): # for API completeness return self.call_helper("is_virtual_package", package) - def get_deps(self, package, pinnings): + def get_deps(self, package, pinnings=None, recommended=None): if not self.use_yum: - return Collection.get_deps(self, package, pinnings) + return Collection.get_deps(self, package, pinnings, recommended) else: # this should really never get called; it's just provided # for API completeness @@ -383,9 +383,9 @@ class YumCollection(Collection): pkgs = self.call_helper("get_group", dict(group=group, type=ptype)) return pkgs - def complete(self, packagelist, pinnings): + def complete(self, packagelist, pinnings=None, recommended=None): if not self.use_yum: - return Collection.complete(self, packagelist, pinnings) + return Collection.complete(self, packagelist, pinnings, recommended) packages = set() unknown = set(packagelist) diff --git a/src/lib/Server/Plugins/Packages/__init__.py b/src/lib/Server/Plugins/Packages/__init__.py index 637560de5..e94b79c6d 100644 --- a/src/lib/Server/Plugins/Packages/__init__.py +++ b/src/lib/Server/Plugins/Packages/__init__.py @@ -150,6 +150,7 @@ class Packages(Bcfg2.Server.Plugin.Plugin, # base is the set of initial packages with groups expanded base = set() pinned_src = dict() + recommended = dict() to_remove = [] for struct in structures: for pkg in struct.xpath('//Package | //BoundPackage'): @@ -158,6 +159,8 @@ class Packages(Bcfg2.Server.Plugin.Plugin, if pkg.get("src"): pinned_src[pkg.get("name")] = pkg.get("src") + if pkg.get("recommended"): + recommended[pkg.get("name")] = pkg.get("recommended") elif pkg.get("group"): try: if pkg.get("type"): @@ -178,7 +181,7 @@ class Packages(Bcfg2.Server.Plugin.Plugin, for el in to_remove: el.getparent().remove(el) - packages, unknown = collection.complete(base, pinned_src) + packages, unknown = collection.complete(base, pinned_src, recommended) if unknown: self.logger.info("Packages: Got %d unknown entries" % len(unknown)) self.logger.info("Packages: %s" % list(unknown)) -- cgit v1.2.3-1-g7c22