예제 #1
0
    def check_range(self, vuln_range, ver_matches, ver_nonmatches):
        self.mk_glsa([("dev-util/diffball", ([], [vuln_range]))])
        restrict = list(OrRestriction(*tuple(glsa.GlsaDirSet(self.dir))))
        if len(restrict) == 0:  # exception thrown
            restrict.append(AlwaysBool(negate=False))
        self.assertEqual(len(restrict), 1)
        restrict = restrict[0]
        for ver in ver_matches:
            pkg = cpv.VersionedCPV(f"dev-util/diffball-{ver}")
            self.assertTrue(
                restrict.match(pkg),
                msg=f"pkg {pkg} must match for {vuln_range!r}: {restrict}")

        for ver in ver_nonmatches:
            pkg = cpv.VersionedCPV(f"dev-util/diffball-{ver}")
            self.assertFalse(
                restrict.match(pkg),
                msg="pkg {pkg} must not match for {vuln_range!r}: {restrict}")
예제 #2
0
 def test_attribute_errors(self):
     obj = cpv.VersionedCPV("foo/bar-0")
     assert not obj == 0
     assert obj != 0
     with pytest.raises(TypeError):
         assert obj < 0
     with pytest.raises(TypeError):
         assert obj <= 0
     with pytest.raises(TypeError):
         assert obj > 0
     with pytest.raises(TypeError):
         assert obj >= 0
예제 #3
0
 def test_pkg_grouped_iter(self):
     self.mk_glsa(pkgs_set + (("dev-util/bsdiff", ([], ["~>=2-r1"])), ))
     g = glsa.GlsaDirSet(self.dir)
     l = list(g.pkg_grouped_iter(sorter=sorted))
     self.assertEqual(set(x.key for x in l),
                      set(['dev-util/diffball', 'dev-util/bsdiff']))
     # main interest is dev-util/bsdiff
     r = l[0]
     pkgs = [
         cpv.VersionedCPV(f"dev-util/bsdiff-{ver}")
         for ver in ("0", "1", "1.1", "2", "2-r1")
     ]
     self.assertEqual([x.fullver for x in pkgs if r.match(x)],
                      ["1.1", "2-r1"])
예제 #4
0
    def generate_restrict_from_range(self, node, negate=False):
        op = str(node.get("range").strip())
        slot = str(node.get("slot", "").strip())

        try:
            restrict = self.op_translate[op.lstrip("r")]
        except KeyError:
            raise ValueError(f'unknown operator: {op!r}')
        if node.text is None:
            raise ValueError(f"{op!r} node missing version")

        base = str(node.text.strip())
        glob = base.endswith("*")
        if glob:
            base = base[:-1]
        base = cpv.VersionedCPV(f"cat/pkg-{base}")

        if glob:
            if op != "eq":
                raise ValueError(f"glob cannot be used with {op} ops")
            return packages.PackageRestriction(
                "fullver", values.StrGlobMatch(base.fullver))
        restrictions = []
        if op.startswith("r"):
            if not base.revision:
                if op == "rlt":  # rlt -r0 can never match
                    # this is a non-range.
                    raise ValueError(
                        "range %s version %s is a guaranteed empty set" %
                        (op, str(node.text.strip())))
                elif op == "rle":  # rle -r0 -> = -r0
                    return atom_restricts.VersionMatch("=",
                                                       base.version,
                                                       negate=negate)
                elif op == "rge":  # rge -r0 -> ~
                    return atom_restricts.VersionMatch("~",
                                                       base.version,
                                                       negate=negate)
            # rgt -r0 passes through to regular ~ + >
            restrictions.append(atom_restricts.VersionMatch("~", base.version))
        restrictions.append(
            atom_restricts.VersionMatch(restrict,
                                        base.version,
                                        rev=base.revision), )
        if slot:
            restrictions.append(atom_restricts.SlotDep(slot))
        return packages.AndRestriction(*restrictions, negate=negate)
예제 #5
0
    def path_restrict(self, path):
        """Return a restriction from a given path in a repo.

        :param path: full or partial path to an ebuild
        :return: a package restriction matching the given path if possible
        :raises ValueError: if the repo doesn't contain the given path, the
            path relates to a file that isn't an ebuild, or the ebuild isn't in the
            proper directory layout
        """
        if path not in self:
            raise ValueError(
                f"{self.repo_id!r} repo doesn't contain: {path!r}")

        if not path.startswith(os.sep) and os.path.exists(
                pjoin(self.location, path)):
            path_chunks = path.split(os.path.sep)
        else:
            path = os.path.realpath(os.path.abspath(path))
            relpath = path[len(os.path.realpath(self.location)):].strip('/')
            path_chunks = relpath.split(os.path.sep)

        if os.path.isfile(path):
            if not path.endswith('.ebuild'):
                raise ValueError(f"file is not an ebuild: {path!r}")
            elif len(path_chunks) != 3:
                # ebuild isn't in a category/PN directory
                raise ValueError(
                    f"ebuild not in the correct directory layout: {path!r}")

        restrictions = []

        # add restrictions until path components run out
        try:
            restrictions.append(restricts.RepositoryDep(self.repo_id))
            if path_chunks[0] in self.categories:
                restrictions.append(restricts.CategoryDep(path_chunks[0]))
                restrictions.append(restricts.PackageDep(path_chunks[1]))
                base = cpv.VersionedCPV(
                    f"{path_chunks[0]}/{os.path.splitext(path_chunks[2])[0]}")
                restrictions.append(
                    restricts.VersionMatch('=',
                                           base.version,
                                           rev=base.revision))
        except IndexError:
            pass
        return packages.AndRestriction(*restrictions)
예제 #6
0
    def create_ebuild(self, cpvstr, data=None, **kwargs):
        from pkgcore.ebuild import cpv as cpv_mod
        cpv = cpv_mod.VersionedCPV(cpvstr)
        self._repo.notify_add_package(cpv)
        ebuild_dir = pjoin(self.path, cpv.category, cpv.package)
        os.makedirs(ebuild_dir, exist_ok=True)

        # use defaults for some ebuild metadata if unset
        eapi = kwargs.pop('eapi', '7')
        slot = kwargs.pop('slot', '0')
        desc = kwargs.pop('description', 'stub package description')
        homepage = kwargs.pop('homepage', 'https://github.com/pkgcore/pkgcheck')
        license = kwargs.pop('license', 'blank')

        ebuild_path = pjoin(ebuild_dir, f'{cpv.package}-{cpv.fullver}.ebuild')
        with open(ebuild_path, 'w') as f:
            if self.repo_id == 'gentoo':
                f.write(textwrap.dedent(f"""\
                    # Copyright 1999-{self._today.year} Gentoo Authors
                    # Distributed under the terms of the GNU General Public License v2
                """))
            f.write(f'EAPI="{eapi}"\n')
            f.write(f'DESCRIPTION="{desc}"\n')
            f.write(f'HOMEPAGE="{homepage}"\n')
            f.write(f'SLOT="{slot}"\n')

            if license:
                f.write(f'LICENSE="{license}"\n')
                # create a fake license
                os.makedirs(pjoin(self.path, 'licenses'), exist_ok=True)
                touch(pjoin(self.path, 'licenses', license))

            for k, v in kwargs.items():
                # handle sequences such as KEYWORDS and IUSE
                if isinstance(v, (tuple, list)):
                    v = ' '.join(v)
                f.write(f'{k.upper()}="{v}"\n')
            if data:
                f.write(data.strip() + '\n')

        return ebuild_path
예제 #7
0
 def _parse_cpv(s):
     try:
         return cpv.VersionedCPV(s)
     except cpv.InvalidCPV:
         logger.error(f'invalid package.provided entry: {s!r}')
예제 #8
0
 def test_init(self):
     cpv.CPV("dev-util", "diffball", "0.7.1")
     cpv.CPV("dev-util", "diffball")
     cpv.CPV("dev-util/diffball-0.7.1", versioned=True)
     with pytest.raises(TypeError):
         cpv.VersionedCPV("dev-util", "diffball", None)
예제 #9
0
 def make_inst(self, cat, pkg, fullver=""):
     if self.testing_secondary_args:
         return cpv.CPV(cat, pkg, fullver, versioned=bool(fullver))
     if fullver:
         return cpv.VersionedCPV(f"{cat}/{pkg}-{fullver}")
     return cpv.UnversionedCPV(f"{cat}/{pkg}")