def gen_config_protect_filter(offset, extra_protects=(), extra_disables=()): collapsed_d, inc, colon = collapse_envd(pjoin(offset, "etc/env.d")) collapsed_d.setdefault("CONFIG_PROTECT", []).extend(extra_protects) collapsed_d.setdefault("CONFIG_PROTECT_MASK", []).extend(extra_disables) r = [ values.StrGlobMatch(normpath(x).rstrip("/") + "/") for x in set(stable_unique(collapsed_d["CONFIG_PROTECT"] + ["/etc"])) ] if len(r) > 1: r = values.OrRestriction(*r) else: r = r[0] neg = stable_unique(collapsed_d["CONFIG_PROTECT_MASK"]) if neg: if len(neg) == 1: r2 = values.StrGlobMatch(normpath(neg[0]).rstrip("/") + "/", negate=True) else: r2 = values.OrRestriction( negate=True, *[ values.StrGlobMatch(normpath(x).rstrip("/") + "/") for x in set(neg) ]) r = values.AndRestriction(r, r2) return r
def _identify_candidates(self, restrict, sorter): # full expansion if not isinstance(restrict, boolean.base) or isinstance(restrict, atom): return self._fast_identify_candidates(restrict, sorter) dsolutions = [ ([c.restriction for c in collect_package_restrictions(x, ("category",))], [p.restriction for p in collect_package_restrictions(x, ("package",))]) for x in restrict.iter_dnf_solutions(True)] # see if any solution state isn't dependent on cat/pkg in anyway. # if so, search whole search space. for x in dsolutions: if not x[0] and not x[1]: if sorter is iter: return self.versions return ( (c, p) for c in sorter(self.categories) for p in sorter(self.packages.get(c, ()))) # simple cases first. # if one specifies categories, and one doesn't cat_specified = bool(dsolutions[0][0]) pkg_specified = bool(dsolutions[0][1]) pgetter = self.packages.get if any(True for x in dsolutions[1:] if bool(x[0]) != cat_specified): if any(True for x in dsolutions[1:] if bool(x[1]) != pkg_specified): # merde. so we've got a mix- some specify cats, some # don't, some specify pkgs, some don't. # this may be optimizable return self.versions # ok. so... one doesn't specify a category, but they all # specify packages (or don't) pr = values.OrRestriction( *tuple(iflatten_instance( (x[1] for x in dsolutions if x[1]), values.base))) return ( (c, p) for c in sorter(self.categories) for p in sorter(pgetter(c, [])) if pr.match(p)) elif any(True for x in dsolutions[1:] if bool(x[1]) != pkg_specified): # one (or more) don't specify pkgs, but they all specify cats. cr = values.OrRestriction( *tuple(iflatten_instance( (x[0] for x in dsolutions), values.base))) cats_iter = (c for c in sorter(self.categories) if cr.match(c)) return ( (c, p) for c in cats_iter for p in sorter(pgetter(c, []))) return self._fast_identify_candidates(restrict, sorter)
def test_filtering(self): repo, vrepo = self.setup_repos() a = atom("dev-lib/fake") a2 = atom("dev-util/diffball") self.assertEqual( sorted(vrepo.itermatch(a)), sorted(repo.itermatch(a))) self.assertEqual(sorted(vrepo.itermatch(a2)), sorted([])) repo, vrepo = self.setup_repos(atom("=dev-util/diffball-1.0")) self.assertEqual( sorted(vrepo.itermatch(a)), sorted(repo.itermatch(a))) self.assertEqual( sorted(vrepo.itermatch(a2)), sorted([versioned_CPV("dev-util/diffball-0.7")])) repo, vrepo = self.setup_repos(packages.PackageRestriction( "package", values.OrRestriction( *[values.StrExactMatch(x) for x in ("diffball", "fake")]))) self.assertEqual( sorted(vrepo.itermatch(packages.AlwaysTrue)), sorted(repo.itermatch(atom("dev-util/bsdiff")))) # check sentinel value handling. vrepo = filtered.tree(repo, a2, sentinel_val=True) self.assertEqual( sorted(x.cpvstr for x in vrepo), sorted(['dev-util/diffball-0.7', 'dev-util/diffball-1.0']))
def test_iter(self): repo, vrepo = self.setup_repos( packages.PackageRestriction( "package", values.OrRestriction( *[values.StrExactMatch(x) for x in ("diffball", "fake")]))) assert sorted(vrepo) == sorted(repo.itermatch(atom("dev-util/bsdiff")))
def trigger(self, engine, existing_cset, uninstall_cset): ignore = [values.StrRegex(fnmatch.translate(x), match=True) for x in self.uninstall_ignore] ignore_filter = values.OrRestriction(*ignore).match remove = [x for x in existing_cset.iterfiles() if ignore_filter(x.location)] for x in remove: del uninstall_cset[x]
def generate_triggers(domain): domain_settings = domain.settings yield env_update() d = {} for x in ("CONFIG_PROTECT", "CONFIG_PROTECT_MASK", "COLLISION_IGNORE", "INSTALL_MASK", "UNINSTALL_IGNORE"): d[x] = domain_settings.get(x, []) if isinstance(d[x], basestring): d[x] = d[x].split() yield ConfigProtectInstall(d["CONFIG_PROTECT"], d["CONFIG_PROTECT_MASK"]) yield ConfigProtectUninstall() features = domain_settings.get("FEATURES", ()) if "collision-protect" in features: yield CollisionProtect(d["CONFIG_PROTECT"], d["CONFIG_PROTECT_MASK"], d["COLLISION_IGNORE"]) if "protect-owned" in features and "collision-protect" not in features: yield ProtectOwned(domain.vdb, d["CONFIG_PROTECT"], d["CONFIG_PROTECT_MASK"], d["COLLISION_IGNORE"]) if "multilib-strict" in features: yield register_multilib_strict_trigger(domain_settings) if "sfperms" in features: yield SFPerms() yield install_into_symdir_protect(d["CONFIG_PROTECT"], d["CONFIG_PROTECT_MASK"]) for x in ("man", "info", "doc"): if "no%s" % x in features: d["INSTALL_MASK"].append("/usr/share/%s" % x) l = [] for x in d["INSTALL_MASK"]: x = x.rstrip("/") l.append(values.StrRegex(fnmatch.translate(x))) l.append(values.StrRegex(fnmatch.translate("%s/*" % x))) install_mask = l if install_mask: if len(install_mask) == 1: install_mask = install_mask[0] else: install_mask = values.OrRestriction(*install_mask) yield triggers.PruneFiles(install_mask.match) # note that if this wipes all /usr/share/ entries, should # wipe the empty dir. yield UninstallIgnore(d["UNINSTALL_IGNORE"]) yield InfoRegen()
def gen_collision_ignore_filter(offset, extra_ignores=()): collapsed_d, inc, colon = collapse_envd(pjoin(offset, "etc/env.d")) ignored = collapsed_d.setdefault("COLLISION_IGNORE", []) ignored.extend(extra_ignores) ignored.extend(["*/.keep", "*/.keep_*"]) ignored = stable_unique(ignored) for i, x in enumerate(ignored): if not x.endswith("/*") and os.path.isdir(x): ignored[i] = ignored.rstrip("/") + "/*" ignored = [values.StrRegex(fnmatch.translate(x)) for x in stable_unique(ignored)] if len(ignored) == 1: return ignored[0] return values.OrRestriction(*ignored)
def trigger(self, engine, existing_cset, uninstall_cset, old_cset={}): ignore = [ values.StrRegex(fnmatch.translate(x), match=True) for x in self.uninstall_ignore ] ignore_filter = values.OrRestriction(*ignore).match remove = [ x for x in existing_cset.iterfiles() if ignore_filter(x.location) ] for x in remove: # don't remove matching files being uninstalled del uninstall_cset[x] # don't remove matching files being replaced old_cset.discard(x)
def __iter__(self): yield env_update() yield ConfigProtectInstall( self.opts["CONFIG_PROTECT"], self.opts["CONFIG_PROTECT_MASK"]) yield ConfigProtectUninstall() if "collision-protect" in self.domain.features: yield CollisionProtect( self.opts["CONFIG_PROTECT"], self.opts["CONFIG_PROTECT_MASK"], self.opts["COLLISION_IGNORE"]) if "protect-owned" in self.domain.features and "collision-protect" not in self.domain.features: yield ProtectOwned( self.domain.installed_repos, self.opts["CONFIG_PROTECT"], self.opts["CONFIG_PROTECT_MASK"], self.opts["COLLISION_IGNORE"]) if "multilib-strict" in self.domain.features: yield register_multilib_strict_trigger(self.opts) if "sfperms" in self.domain.features: yield SFPerms() yield install_into_symdir_protect( self.opts["CONFIG_PROTECT"], self.opts["CONFIG_PROTECT_MASK"]) # TODO: support multiple binpkg repo targets? pkgdir = self.opts.get("PKGDIR", None) if pkgdir: target_repo = self.domain.binary_repos_raw.get(pkgdir, None) else: # get the highest priority binpkg repo try: target_repo = self.domain.binary_repos_raw[0] except IndexError: target_repo = None if target_repo is not None: if 'buildpkg' in self.domain.features: yield triggers.SavePkg(pristine='no', target_repo=target_repo) elif 'pristine-buildpkg' in self.domain.features: yield triggers.SavePkg(pristine='yes', target_repo=target_repo) elif 'buildsyspkg' in self.domain.features: yield triggers.SavePkgIfInPkgset( pristine='yes', target_repo=target_repo, pkgset=self.domain.profile.system) elif 'unmerge-backup' in self.domain.features: yield triggers.SavePkgUnmerging(target_repo=target_repo) if 'save-deb' in self.domain.features: path = self.opts.get("DEB_REPO_ROOT", None) if path is None: logger.warning("disabling save-deb; DEB_REPO_ROOT is unset") else: yield ospkg.triggers.SaveDeb( basepath=normpath(path), maintainer=self.opts.get("DEB_MAINAINER", ''), platform=self.opts.get("DEB_ARCHITECTURE", "")) if 'splitdebug' in self.domain.features: yield triggers.BinaryDebug(mode='split', compress=('compressdebug' in self.domain.features)) elif 'strip' in self.domain.features or 'nostrip' not in self.domain.features: yield triggers.BinaryDebug(mode='strip') if '-fixlafiles' not in self.domain.features: yield libtool.FixLibtoolArchivesTrigger() for x in ("man", "info", "doc"): if f"no{x}" in self.domain.features: self.opts["INSTALL_MASK"].append(f"/usr/share/{x}") l = [] for x in self.opts["INSTALL_MASK"]: x = x.rstrip("/") l.append(values.StrRegex(fnmatch.translate(x))) l.append(values.StrRegex(fnmatch.translate(f"{x}/*"))) install_mask = l if install_mask: if len(install_mask) == 1: install_mask = install_mask[0] else: install_mask = values.OrRestriction(*install_mask) yield triggers.PruneFiles(install_mask.match) # note that if this wipes all /usr/share/ entries, should # wipe the empty dir. yield UninstallIgnore(self.opts["UNINSTALL_IGNORE"]) yield InfoRegen()