commit: 9fefb10f2b5ca6dc3e595e1d318956252f396ed0 Author: Arthur Zamarin <arthurzam <AT> gentoo <DOT> org> AuthorDate: Thu Oct 27 19:07:12 2022 +0000 Commit: Arthur Zamarin <arthurzam <AT> gentoo <DOT> org> CommitDate: Fri Nov 4 12:57:44 2022 +0000 URL: https://gitweb.gentoo.org/proj/pkgcore/pkgcheck.git/commit/?id=9fefb10f
VirtualProvidersCheck: new check for providers issues - check for virtual package defining DEPEND or BDEPEND - check for virtual package with a single provider across versions Closes: https://bugs.gentoo.org/744784 Signed-off-by: Arthur Zamarin <arthurzam <AT> gentoo.org> src/pkgcheck/checks/metadata.py | 80 +++++++++++++++++++++- .../VirtualWithBdepend/expected.json | 2 + .../VirtualWithDepend/expected.json | 2 + .../VirtualWithSingleProvider/expected.json | 1 + testdata/repos/standalone/profiles/desc/elibc.desc | 1 + .../repos/standalone/profiles/package.deprecated | 1 + .../VirtualWithBdepend/VirtualWithBdepend-0.ebuild | 6 ++ .../VirtualWithBdepend/VirtualWithBdepend-1.ebuild | 11 +++ .../VirtualWithDepend/VirtualWithDepend-0.ebuild | 6 ++ .../VirtualWithDepend/VirtualWithDepend-1.ebuild | 11 +++ .../VirtualWithSingleProvider1-0.ebuild | 10 +++ .../VirtualWithSingleProvider2-0.ebuild | 10 +++ .../VirtualWithSingleProvider3-0.ebuild | 8 +++ .../VirtualWithSingleProvider3-1.ebuild | 8 +++ .../VirtualWithSingleProvider4-0.ebuild | 8 +++ .../VirtualWithSingleProvider4-1.ebuild | 8 +++ .../VirtualWithSingleProvider5-0.ebuild | 8 +++ .../VirtualWithSingleProvider6-0.ebuild | 9 +++ 18 files changed, 189 insertions(+), 1 deletion(-) diff --git a/src/pkgcheck/checks/metadata.py b/src/pkgcheck/checks/metadata.py index 7980942d..6e087c5f 100644 --- a/src/pkgcheck/checks/metadata.py +++ b/src/pkgcheck/checks/metadata.py @@ -7,7 +7,7 @@ from difflib import SequenceMatcher from functools import partial from operator import attrgetter -from pkgcore.ebuild import atom as atom_mod +from pkgcore.ebuild import atom as atom_mod, restricts from pkgcore.ebuild.atom import atom as atom_cls from pkgcore.ebuild.eapi import get_eapi from pkgcore.ebuild.misc import sort_keywords @@ -1627,3 +1627,81 @@ class MissingUnpackerDepCheck(Check): for unpackers, filenames in missing_unpackers.items(): yield MissingUnpackerDep( str(pkg.eapi), sorted(filenames), sorted(unpackers), pkg=pkg) + + +class VirtualWithSingleProvider(results.PackageResult, results.Warning): + """Virtual package with a single remaining provider. + + Virtual packages are used to provide a common interface for multiple + implementations of a given functionality. However, if there is only a + single implementation, there is no need for a virtual package. In such + case, consider adding the package to package.deprecated and removing the + virtual package. + """ + + def __init__(self, provider, **kwargs): + super().__init__(**kwargs) + self.provider = str(provider) + + @property + def desc(self): + return f'virtual package with a single provider: {self.provider}' + + +class VirtualWithBdepend(results.VersionResult, results.Warning): + """Virtual package with a BDEPEND defined.""" + + desc = 'virtual package with a BDEPEND defined' + + +class VirtualWithDepend(results.VersionResult, results.Warning): + """Virtual package with a BDEPEND defined.""" + + desc = 'virtual package with a DEPEND defined' + + +class VirtualProvidersCheck(Check): + """Check providers of virtual packages.""" + + _restricted_source = (sources.RestrictionRepoSource, (restricts.CategoryDep('virtual'), )) + _source = (sources.PackageRepoSource, (), (('source', _restricted_source),)) + known_results = frozenset([VirtualWithSingleProvider, + VirtualWithBdepend, VirtualWithDepend]) + + useless_depends = ( + ('depend', VirtualWithDepend), + ('bdepend', VirtualWithBdepend), + ) + + def __init__(self, options, **kwargs): + super().__init__(options, **kwargs) + + self.deprecated = self.options.target_repo.deprecated + + def pkg_has_conditional_exception(self, pkgs): + return any(use.startswith(('elibc', 'kernel')) + for pkg in pkgs + for dep in iflatten_instance(pkg.rdepend, (atom_cls, packages.Conditional)) + if isinstance(dep, packages.Conditional) and dep.attr == 'use' and isinstance(dep.restriction, values.ContainmentMatch) + for use in dep.restriction.vals + ) + + def feed(self, pkgs): + for pkg in pkgs: + for attr, cls in self.useless_depends: + if getattr(pkg, attr): + yield cls(pkg=pkg) + + if not any(self.deprecated.match(pkg) for pkg in pkgs): + pkgs_rdepends = tuple( + tuple(iflatten_instance(pkg.rdepend, atom_cls)) + for pkg in pkgs + ) + if max(map(len, pkgs_rdepends)) == 1: + unversioned_rdepends = { + deps[0].unversioned_atom + for deps in pkgs_rdepends + if len(deps) == 1 + } + if len(unversioned_rdepends) == 1 and not self.pkg_has_conditional_exception(pkgs): + yield VirtualWithSingleProvider(unversioned_rdepends.pop(), pkg=pkgs[0]) diff --git a/testdata/data/repos/standalone/VirtualProvidersCheck/VirtualWithBdepend/expected.json b/testdata/data/repos/standalone/VirtualProvidersCheck/VirtualWithBdepend/expected.json new file mode 100644 index 00000000..67f8c375 --- /dev/null +++ b/testdata/data/repos/standalone/VirtualProvidersCheck/VirtualWithBdepend/expected.json @@ -0,0 +1,2 @@ +{"__class__": "VirtualWithBdepend", "category": "virtual", "package": "VirtualWithBdepend", "version": "0"} +{"__class__": "VirtualWithBdepend", "category": "virtual", "package": "VirtualWithBdepend", "version": "1"} diff --git a/testdata/data/repos/standalone/VirtualProvidersCheck/VirtualWithDepend/expected.json b/testdata/data/repos/standalone/VirtualProvidersCheck/VirtualWithDepend/expected.json new file mode 100644 index 00000000..05edb413 --- /dev/null +++ b/testdata/data/repos/standalone/VirtualProvidersCheck/VirtualWithDepend/expected.json @@ -0,0 +1,2 @@ +{"__class__": "VirtualWithDepend", "category": "virtual", "package": "VirtualWithDepend", "version": "0"} +{"__class__": "VirtualWithDepend", "category": "virtual", "package": "VirtualWithDepend", "version": "1"} diff --git a/testdata/data/repos/standalone/VirtualProvidersCheck/VirtualWithSingleProvider/expected.json b/testdata/data/repos/standalone/VirtualProvidersCheck/VirtualWithSingleProvider/expected.json new file mode 100644 index 00000000..898cdb35 --- /dev/null +++ b/testdata/data/repos/standalone/VirtualProvidersCheck/VirtualWithSingleProvider/expected.json @@ -0,0 +1 @@ +{"__class__": "VirtualWithSingleProvider", "category": "virtual", "package": "VirtualWithSingleProvider4", "provider": "stub/slotted"} diff --git a/testdata/repos/standalone/profiles/desc/elibc.desc b/testdata/repos/standalone/profiles/desc/elibc.desc new file mode 100644 index 00000000..82a26e2b --- /dev/null +++ b/testdata/repos/standalone/profiles/desc/elibc.desc @@ -0,0 +1 @@ +glibc - ELIBC setting for systems that use the GNU C library diff --git a/testdata/repos/standalone/profiles/package.deprecated b/testdata/repos/standalone/profiles/package.deprecated new file mode 100644 index 00000000..f3b49d01 --- /dev/null +++ b/testdata/repos/standalone/profiles/package.deprecated @@ -0,0 +1 @@ +virtual/VirtualWithSingleProvider5 diff --git a/testdata/repos/standalone/virtual/VirtualWithBdepend/VirtualWithBdepend-0.ebuild b/testdata/repos/standalone/virtual/VirtualWithBdepend/VirtualWithBdepend-0.ebuild new file mode 100644 index 00000000..a34781c9 --- /dev/null +++ b/testdata/repos/standalone/virtual/VirtualWithBdepend/VirtualWithBdepend-0.ebuild @@ -0,0 +1,6 @@ +EAPI=7 + +DESCRIPTION="Ebuild with unnecessary DEPEND" +SLOT="0" + +BDEPEND="stub/stub1" diff --git a/testdata/repos/standalone/virtual/VirtualWithBdepend/VirtualWithBdepend-1.ebuild b/testdata/repos/standalone/virtual/VirtualWithBdepend/VirtualWithBdepend-1.ebuild new file mode 100644 index 00000000..f9f7f891 --- /dev/null +++ b/testdata/repos/standalone/virtual/VirtualWithBdepend/VirtualWithBdepend-1.ebuild @@ -0,0 +1,11 @@ +EAPI=7 + +DESCRIPTION="Ebuild with unnecessary DEPEND" +SLOT="0" + +RDEPEND="|| ( + stub/stub1 + stub/stub2 +) +" +BDEPEND="${RDEPEND}" diff --git a/testdata/repos/standalone/virtual/VirtualWithDepend/VirtualWithDepend-0.ebuild b/testdata/repos/standalone/virtual/VirtualWithDepend/VirtualWithDepend-0.ebuild new file mode 100644 index 00000000..bc9f2162 --- /dev/null +++ b/testdata/repos/standalone/virtual/VirtualWithDepend/VirtualWithDepend-0.ebuild @@ -0,0 +1,6 @@ +EAPI=7 + +DESCRIPTION="Ebuild with unnecessary DEPEND" +SLOT="0" + +DEPEND="stub/stub1" diff --git a/testdata/repos/standalone/virtual/VirtualWithDepend/VirtualWithDepend-1.ebuild b/testdata/repos/standalone/virtual/VirtualWithDepend/VirtualWithDepend-1.ebuild new file mode 100644 index 00000000..d29f3b42 --- /dev/null +++ b/testdata/repos/standalone/virtual/VirtualWithDepend/VirtualWithDepend-1.ebuild @@ -0,0 +1,11 @@ +EAPI=7 + +DESCRIPTION="Ebuild with unnecessary DEPEND" +SLOT="0" + +RDEPEND="|| ( + stub/stub1 + stub/stub2 +) +" +DEPEND="${RDEPEND}" diff --git a/testdata/repos/standalone/virtual/VirtualWithSingleProvider1/VirtualWithSingleProvider1-0.ebuild b/testdata/repos/standalone/virtual/VirtualWithSingleProvider1/VirtualWithSingleProvider1-0.ebuild new file mode 100644 index 00000000..7a9a8f34 --- /dev/null +++ b/testdata/repos/standalone/virtual/VirtualWithSingleProvider1/VirtualWithSingleProvider1-0.ebuild @@ -0,0 +1,10 @@ +EAPI=7 + +DESCRIPTION="Good virtual with 2 providers" +SLOT="0" + +RDEPEND="|| ( + stub/stub1 + stub/stub2 +) +" diff --git a/testdata/repos/standalone/virtual/VirtualWithSingleProvider2/VirtualWithSingleProvider2-0.ebuild b/testdata/repos/standalone/virtual/VirtualWithSingleProvider2/VirtualWithSingleProvider2-0.ebuild new file mode 100644 index 00000000..2891a52e --- /dev/null +++ b/testdata/repos/standalone/virtual/VirtualWithSingleProvider2/VirtualWithSingleProvider2-0.ebuild @@ -0,0 +1,10 @@ +EAPI=7 + +DESCRIPTION="Good virtual with 1 provider but different use combinations" +SLOT="0" + +RDEPEND="|| ( + stub/stub1[matching] + stub/stub1[probable] +) +" diff --git a/testdata/repos/standalone/virtual/VirtualWithSingleProvider3/VirtualWithSingleProvider3-0.ebuild b/testdata/repos/standalone/virtual/VirtualWithSingleProvider3/VirtualWithSingleProvider3-0.ebuild new file mode 100644 index 00000000..85b8d702 --- /dev/null +++ b/testdata/repos/standalone/virtual/VirtualWithSingleProvider3/VirtualWithSingleProvider3-0.ebuild @@ -0,0 +1,8 @@ +EAPI=7 + +DESCRIPTION="Good virtual with 1 different provider across versions" +SLOT="0" + +RDEPEND=" + stub/stub1 +" diff --git a/testdata/repos/standalone/virtual/VirtualWithSingleProvider3/VirtualWithSingleProvider3-1.ebuild b/testdata/repos/standalone/virtual/VirtualWithSingleProvider3/VirtualWithSingleProvider3-1.ebuild new file mode 100644 index 00000000..5655b1ff --- /dev/null +++ b/testdata/repos/standalone/virtual/VirtualWithSingleProvider3/VirtualWithSingleProvider3-1.ebuild @@ -0,0 +1,8 @@ +EAPI=7 + +DESCRIPTION="Good virtual with 1 different provider across versions" +SLOT="0" + +RDEPEND=" + stub/stub2 +" diff --git a/testdata/repos/standalone/virtual/VirtualWithSingleProvider4/VirtualWithSingleProvider4-0.ebuild b/testdata/repos/standalone/virtual/VirtualWithSingleProvider4/VirtualWithSingleProvider4-0.ebuild new file mode 100644 index 00000000..e3469bf8 --- /dev/null +++ b/testdata/repos/standalone/virtual/VirtualWithSingleProvider4/VirtualWithSingleProvider4-0.ebuild @@ -0,0 +1,8 @@ +EAPI=7 + +DESCRIPTION="Redundant virtual with 1 provider" +SLOT="1" + +RDEPEND=" + stub/slotted:${SLOT} +" diff --git a/testdata/repos/standalone/virtual/VirtualWithSingleProvider4/VirtualWithSingleProvider4-1.ebuild b/testdata/repos/standalone/virtual/VirtualWithSingleProvider4/VirtualWithSingleProvider4-1.ebuild new file mode 100644 index 00000000..e3469bf8 --- /dev/null +++ b/testdata/repos/standalone/virtual/VirtualWithSingleProvider4/VirtualWithSingleProvider4-1.ebuild @@ -0,0 +1,8 @@ +EAPI=7 + +DESCRIPTION="Redundant virtual with 1 provider" +SLOT="1" + +RDEPEND=" + stub/slotted:${SLOT} +" diff --git a/testdata/repos/standalone/virtual/VirtualWithSingleProvider5/VirtualWithSingleProvider5-0.ebuild b/testdata/repos/standalone/virtual/VirtualWithSingleProvider5/VirtualWithSingleProvider5-0.ebuild new file mode 100644 index 00000000..e7c2db6b --- /dev/null +++ b/testdata/repos/standalone/virtual/VirtualWithSingleProvider5/VirtualWithSingleProvider5-0.ebuild @@ -0,0 +1,8 @@ +EAPI=7 + +DESCRIPTION="Good virtual with 2 providers" +SLOT="0" + +RDEPEND=" + stub/stub1 +" diff --git a/testdata/repos/standalone/virtual/VirtualWithSingleProvider6/VirtualWithSingleProvider6-0.ebuild b/testdata/repos/standalone/virtual/VirtualWithSingleProvider6/VirtualWithSingleProvider6-0.ebuild new file mode 100644 index 00000000..0f874ab4 --- /dev/null +++ b/testdata/repos/standalone/virtual/VirtualWithSingleProvider6/VirtualWithSingleProvider6-0.ebuild @@ -0,0 +1,9 @@ +EAPI=7 + +DESCRIPTION="virtual with 1 provider, but behind special use flags" +SLOT="0" +IUSE="elibc_glibc" + +RDEPEND=" + !elibc_glibc? ( stub/stub1 ) +"
