diff options
author | Arthur Zamarin <arthurzam@gentoo.org> | 2024-01-13 11:16:10 +0200 |
---|---|---|
committer | Arthur Zamarin <arthurzam@gentoo.org> | 2024-01-13 11:16:10 +0200 |
commit | f2d4e371da2bfa834644973d4dd0bede50deafb4 (patch) | |
tree | b01862d2cd0d1c25a6af0417080bf6b7b18bdcd2 | |
parent | DeprecatedDep: fix mishandling of slotted deprecates (diff) | |
download | pkgcheck-f2d4e371da2bfa834644973d4dd0bede50deafb4.tar.gz pkgcheck-f2d4e371da2bfa834644973d4dd0bede50deafb4.tar.bz2 pkgcheck-f2d4e371da2bfa834644973d4dd0bede50deafb4.zip |
UnstatedIuse: check for unstated IUSE in "?" dependencies
Check for cases where a dependency uses conditional use dependency
with unknown USE flag. PMS states:
It is an error for an ebuild to use a conditional use dependency when
that ebuild does not have the flag in IUSE_EFFECTIVE.
Bug: https://bugs.gentoo.org/921841
Requested-by: Sam James <sam@gentoo.org>
Signed-off-by: Arthur Zamarin <arthurzam@gentoo.org>
8 files changed, 37 insertions, 15 deletions
diff --git a/src/pkgcheck/checks/metadata.py b/src/pkgcheck/checks/metadata.py index 2aba62f0..2cbb8985 100644 --- a/src/pkgcheck/checks/metadata.py +++ b/src/pkgcheck/checks/metadata.py @@ -7,8 +7,8 @@ from difflib import SequenceMatcher from functools import partial from operator import attrgetter -from pkgcore.ebuild import atom as atom_mod, restricts -from pkgcore.ebuild.atom import atom as atom_cls +from pkgcore.ebuild import restricts +from pkgcore.ebuild.atom import atom as atom_cls, transitive_use_atom from pkgcore.ebuild.eapi import get_eapi from pkgcore.ebuild.misc import sort_keywords from pkgcore.fetch import fetchable, unknown_mirror @@ -871,7 +871,7 @@ class DependencyCheck(Check): required_addons = (addons.UseAddon,) known_results = frozenset( - [ + { BadDependency, MissingPackageRevision, MissingUseDepDefault, @@ -883,7 +883,7 @@ class DependencyCheck(Check): InvalidBdepend, InvalidIdepend, MisplacedWeakBlocker, - ] + } ) def __init__(self, *args, use_addon): @@ -929,12 +929,9 @@ class DependencyCheck(Check): ) yield from unstated + unknowns_useflags = set() for node in nodes: - if isinstance(node, boolean.OrRestriction): - in_or_restriction = True - else: - in_or_restriction = False - + in_or_restriction = isinstance(node, boolean.OrRestriction) for atom in iflatten_instance(node, (atom_cls,)): # Skip reporting blockers on deprecated packages; the primary # purpose of deprecations is to get rid of dependencies @@ -959,6 +956,15 @@ class DependencyCheck(Check): if atom.op == "=" and not atom.revision: yield MissingPackageRevision(attr, str(atom), pkg=pkg) + if isinstance(atom, transitive_use_atom) and atom.use is not None: + for useflag in atom.use: + if useflag[-1] == "?": + useflag = useflag[:-1].removeprefix("!") + if useflag[-1] == ")": + useflag = useflag[:-3] + if useflag not in pkg.iuse_stripped: + unknowns_useflags.add(useflag) + if atom.blocks: if atom.match(pkg): yield BadDependency(attr, atom, "package blocks itself", pkg=pkg) @@ -969,6 +975,9 @@ class DependencyCheck(Check): elif not atom.blocks_strongly: weak_blocks[attr].add(atom) + if unknowns_useflags: + yield UnstatedIuse(attr, sorted(unknowns_useflags), pkg=pkg) + for attr in ("depend", "bdepend"): weak_blocks[attr].difference_update(weak_blocks["rdepend"]) weak_blocks["idepend"].difference_update(weak_blocks["rdepend"], weak_blocks["depend"]) @@ -1597,7 +1606,7 @@ class InvalidProperties(results.MetadataError, results.VersionResult): class _RestrictPropertiesCheck(Check): """Generic check for RESTRICT and PROPERTIES.""" - _attr = None + _attr: str = None _unknown_result_cls = None required_addons = (addons.UseAddon,) @@ -1606,9 +1615,9 @@ class _RestrictPropertiesCheck(Check): self.filter = use_addon.get_filter(self._attr) # pull allowed values from a repo and its masters - allowed = [] + allowed = set() for repo in self.options.target_repo.trees: - allowed.extend(getattr(repo.config, f"{self._attr}_allowed")) + allowed.update(getattr(repo.config, f"{self._attr}_allowed")) self.allowed = frozenset(allowed) def feed(self, pkg): diff --git a/testdata/data/repos/standalone/DependencyCheck/MissingUseDepDefault/fix.patch b/testdata/data/repos/standalone/DependencyCheck/MissingUseDepDefault/fix.patch index c86bbe16..c1cd3750 100644 --- a/testdata/data/repos/standalone/DependencyCheck/MissingUseDepDefault/fix.patch +++ b/testdata/data/repos/standalone/DependencyCheck/MissingUseDepDefault/fix.patch @@ -1,10 +1,10 @@ diff -Naur standalone/DependencyCheck/MissingUseDepDefault/MissingUseDepDefault-0.ebuild fixed/DependencyCheck/MissingUseDepDefault/MissingUseDepDefault-0.ebuild --- standalone/DependencyCheck/MissingUseDepDefault/MissingUseDepDefault-0.ebuild 2019-12-02 21:50:34.617257001 -0700 +++ fixed/DependencyCheck/MissingUseDepDefault/MissingUseDepDefault-0.ebuild 2019-12-02 21:52:56.547749364 -0700 -@@ -3,7 +3,7 @@ - HOMEPAGE="https://github.com/pkgcore/pkgcheck" +@@ -4,7 +4,7 @@ SLOT="0" LICENSE="BSD" + IUSE="foo" -DEPEND="stub/stub1[foo]" -RDEPEND="|| ( stub/stub2[used] stub/stub2[-foo] )" -BDEPEND="stub/stub3[foo?]" diff --git a/testdata/data/repos/standalone/DependencyCheck/UnstatedIuse/expected-verbose.json b/testdata/data/repos/standalone/DependencyCheck/UnstatedIuse/expected-verbose.json index 799fec6f..12e2f462 100644 --- a/testdata/data/repos/standalone/DependencyCheck/UnstatedIuse/expected-verbose.json +++ b/testdata/data/repos/standalone/DependencyCheck/UnstatedIuse/expected-verbose.json @@ -1,2 +1,3 @@ +{"__class__": "UnstatedIuse", "category": "DependencyCheck", "package": "UnstatedIuse", "version": "0", "attr": "depend", "flags": ["used"], "profile": null, "num_profiles": null} {"__class__": "UnstatedIuse", "category": "DependencyCheck", "package": "UnstatedIuse", "version": "0", "attr": "rdepend", "flags": ["used"], "profile": "default/amd64", "num_profiles": null} {"__class__": "UnstatedIuse", "category": "DependencyCheck", "package": "UnstatedIuse", "version": "0", "attr": "rdepend", "flags": ["used"], "profile": "default/x86", "num_profiles": null} diff --git a/testdata/data/repos/standalone/DependencyCheck/UnstatedIuse/expected.json b/testdata/data/repos/standalone/DependencyCheck/UnstatedIuse/expected.json index 512b0afa..0950d1f3 100644 --- a/testdata/data/repos/standalone/DependencyCheck/UnstatedIuse/expected.json +++ b/testdata/data/repos/standalone/DependencyCheck/UnstatedIuse/expected.json @@ -1 +1,2 @@ +{"__class__": "UnstatedIuse", "category": "DependencyCheck", "package": "UnstatedIuse", "version": "0", "attr": "depend", "flags": ["used"], "profile": null, "num_profiles": null} {"__class__": "UnstatedIuse", "category": "DependencyCheck", "package": "UnstatedIuse", "version": "0", "attr": "rdepend", "flags": ["used"], "profile": "default/amd64", "num_profiles": 2} diff --git a/testdata/repos/standalone/DependencyCheck/MissingUseDepDefault/MissingUseDepDefault-0.ebuild b/testdata/repos/standalone/DependencyCheck/MissingUseDepDefault/MissingUseDepDefault-0.ebuild index 53992988..f03b475b 100644 --- a/testdata/repos/standalone/DependencyCheck/MissingUseDepDefault/MissingUseDepDefault-0.ebuild +++ b/testdata/repos/standalone/DependencyCheck/MissingUseDepDefault/MissingUseDepDefault-0.ebuild @@ -4,6 +4,7 @@ DESCRIPTION="Ebuild missing USE dependency default" HOMEPAGE="https://github.com/pkgcore/pkgcheck" SLOT="0" LICENSE="BSD" +IUSE="foo" DEPEND="stub/stub1[foo]" RDEPEND="|| ( stub/stub2[used] stub/stub2[-foo] )" BDEPEND="stub/stub3[foo?]" diff --git a/testdata/repos/standalone/DependencyCheck/MissingUseDepDefault/metadata.xml b/testdata/repos/standalone/DependencyCheck/MissingUseDepDefault/metadata.xml new file mode 100644 index 00000000..bd802a63 --- /dev/null +++ b/testdata/repos/standalone/DependencyCheck/MissingUseDepDefault/metadata.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE pkgmetadata SYSTEM "https://www.gentoo.org/dtd/metadata.dtd"> +<pkgmetadata> + <use> + <flag name="foo">stub</flag> + </use> +</pkgmetadata> diff --git a/testdata/repos/standalone/DependencyCheck/UnstatedIuse/UnstatedIuse-0.ebuild b/testdata/repos/standalone/DependencyCheck/UnstatedIuse/UnstatedIuse-0.ebuild index b7438aaa..1179764b 100644 --- a/testdata/repos/standalone/DependencyCheck/UnstatedIuse/UnstatedIuse-0.ebuild +++ b/testdata/repos/standalone/DependencyCheck/UnstatedIuse/UnstatedIuse-0.ebuild @@ -1,5 +1,8 @@ +EAPI=7 + DESCRIPTION="Ebuild with unstated IUSE in depsets" HOMEPAGE="https://github.com/pkgcore/pkgcheck" SLOT="0" LICENSE="BSD" RDEPEND="used? ( stub/stub1 )" +DEPEND="stub/stub4[used?]" diff --git a/tests/checks/test_metadata.py b/tests/checks/test_metadata.py index 77c062c6..f6c2f00b 100644 --- a/tests/checks/test_metadata.py +++ b/tests/checks/test_metadata.py @@ -953,7 +953,7 @@ class TestDependencyCheck(use_based(), misc.ReportTestCase): @pytest.mark.parametrize("attr", dep_attrs) def test_depset_missing_usedep_default(self, attr): chk = self.mk_check() - mk_pkg = partial(self.mk_pkg, attr) + mk_pkg = partial(self.mk_pkg, attr, iuse="foo bar baz blah") # USE flag exists on all matching pkgs self.assertNoReport(chk, mk_pkg(eapi="4", depset="dev-libs/foo[bar?]")) |