Example #1
0
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
Example #2
0
    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)
Example #3
0
    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']))
Example #4
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")))
Example #5
0
    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]
Example #6
0
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()
Example #7
0
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)
Example #8
0
    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)
Example #9
0
    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()