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}")
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
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"])
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)
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)
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
def _parse_cpv(s): try: return cpv.VersionedCPV(s) except cpv.InvalidCPV: logger.error(f'invalid package.provided entry: {s!r}')
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)
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}")