commit: e9a8c4094584ae23fd5921098105a94a1a81d60e Author: Arthur Zamarin <arthurzam <AT> gentoo <DOT> org> AuthorDate: Wed Aug 30 17:23:06 2023 +0000 Commit: Arthur Zamarin <arthurzam <AT> gentoo <DOT> org> CommitDate: Fri Sep 1 08:18:36 2023 +0000 URL: https://gitweb.gentoo.org/proj/pkgcore/pkgcheck.git/commit/?id=e9a8c409
EclassManualDepsCheck: add check for missing manual deps When in special modes of eclasses (for example CARGO_OPTIONAL=1), verify specific dependencies are listed somehow in one of the dependencies var. Resolves: https://github.com/pkgcore/pkgcheck/issues/615 Signed-off-by: Arthur Zamarin <arthurzam <AT> gentoo.org> src/pkgcheck/checks/eclass.py | 92 ++++++++++++++++++++++ .../GoMissingDeps/expected.json | 1 + .../RubyMissingDeps/expected.json | 1 + .../RubyMissingDeps/fix.patch | 9 +++ .../RustMissingDeps/expected.json | 1 + .../RustMissingDeps/fix.patch | 9 +++ .../RubyMissingDeps/RubyMissingDeps-0.ebuild | 12 +++ .../RubyMissingDeps/RubyMissingDeps-1.ebuild | 8 ++ .../RubyMissingDeps/RubyMissingDeps-2.ebuild | 14 ++++ .../RustMissingDeps/RustMissingDeps-0.ebuild | 6 ++ .../RustMissingDeps/RustMissingDeps-1.ebuild | 10 +++ .../repos/standalone/dev-lang/ruby/ruby-0.ebuild | 4 + .../repos/standalone/dev-ruby/stub/stub-0.ebuild | 4 + testdata/repos/standalone/eclass/ruby-ng.eclass | 1 + .../standalone/virtual/rubygems/rubygems-0.ebuild | 2 + .../repos/standalone/virtual/rust/rust-0.ebuild | 2 + 16 files changed, 176 insertions(+) diff --git a/src/pkgcheck/checks/eclass.py b/src/pkgcheck/checks/eclass.py index 935ed960..394ef192 100644 --- a/src/pkgcheck/checks/eclass.py +++ b/src/pkgcheck/checks/eclass.py @@ -3,8 +3,10 @@ import subprocess from collections import defaultdict from functools import partial +from pkgcore.ebuild.atom import atom as atom_cls from pkgcore.ebuild.eapi import EAPI from pkgcore.ebuild.eclass import EclassDoc +from snakeoil.sequences import iflatten_instance from snakeoil.strings import pluralism from .. import addons, bash, results, sources @@ -498,3 +500,93 @@ class EclassCheck(Check): ) if vars_missing_docs: yield EclassDocMissingVar(sorted(vars_missing_docs), eclass=eclass) + + +class GoMissingDeps(results.VersionResult, results.Warning): + """Package sets ``GO_OPTIONAL`` but does not depend on ``dev-lang/go``.""" + + desc = "sets GO_OPTIONAL but does not depend on dev-lang/go" + + +class RubyMissingDeps(results.VersionResult, results.Warning): + """Package sets ``RUBY_OPTIONAL`` but does not depend on ``dev-lang/ruby`` + or ``virtual/rubygems``.""" + + desc = "sets RUBY_OPTIONAL but does not depend on dev-lang/ruby or virtual/rubygems" + + +class RustMissingDeps(results.VersionResult, results.Warning): + """Package sets ``CARGO_OPTIONAL`` but does not depend on ``virtual/rust``.""" + + desc = "sets CARGO_OPTIONAL but does not depend on virtual/rust" + + +class TmpfilesMissingDeps(results.VersionResult, results.Warning): + """Package sets ``TMPFILES_OPTIONAL`` but does not depend on ``virtual/tmpfiles``.""" + + desc = "sets TMPFILES_OPTIONAL but does not depend on virtual/tmpfiles" + + +class EclassManualDepsCheck(Check): + """Check for missing deps when inheriting eclasses in special mode.""" + + _source = sources.EbuildParseRepoSource + known_results = frozenset( + { + GoMissingDeps, + RustMissingDeps, + RubyMissingDeps, + TmpfilesMissingDeps, + } + ) + + dependencies = ( + # eclass, variable, one of deps, class + ("cargo", "CARGO_OPTIONAL", {"virtual/rust"}, RustMissingDeps), + ("go-module", "GO_OPTIONAL", {"dev-lang/go"}, GoMissingDeps), + ( + "ruby-ng", + "RUBY_OPTIONAL", + {"dev-lang/ruby", "virtual/rubygems", "dev-ruby"}, + RubyMissingDeps, + ), + ("tmpfiles", "TMPFILES_OPTIONAL", {"virtual/tmpfiles"}, TmpfilesMissingDeps), + ) + + def __init__(self, options, **kwargs): + super().__init__(options, **kwargs) + + self.queries_by_eclass = defaultdict(list) + for eclass, variable, deps, cls in self.dependencies: + pkgs = frozenset({x for x in deps if "/" in x}) + categories = frozenset({x for x in deps if "/" not in x}) + self.queries_by_eclass[eclass].append( + ( + bash.query( + # has variable assignment to a variable named + f'(variable_assignment name: (variable_name) @name (.eq? @name "{variable}"))' + ), + pkgs, + categories, + cls, + ) + ) + + def feed(self, pkg: bash.ParseTree): + for eclass, queries in self.queries_by_eclass.items(): + if eclass not in pkg.inherited: + continue + for query, pkgs, categories, cls in queries: + # is the variable assigned in global scope + try: + next(pkg.global_query(query)) + except StopIteration: + continue + + # does any dep attr have any of the deps + if all( + atom.key not in pkgs and atom.category not in categories + for attr in pkg.eapi.dep_keys + for atom in iflatten_instance(getattr(pkg, attr.lower()), atom_cls) + ): + yield cls(pkg) diff --git a/testdata/data/repos/standalone/EclassManualDepsCheck/GoMissingDeps/expected.json b/testdata/data/repos/standalone/EclassManualDepsCheck/GoMissingDeps/expected.json new file mode 100644 index 00000000..a2e61bca --- /dev/null +++ b/testdata/data/repos/standalone/EclassManualDepsCheck/GoMissingDeps/expected.json @@ -0,0 +1 @@ +{"__class__": "GoMissingDeps", "category": "EclassUsageCheck", "package": "DeprecatedEclassVariable", "version": "0"} diff --git a/testdata/data/repos/standalone/EclassManualDepsCheck/RubyMissingDeps/expected.json b/testdata/data/repos/standalone/EclassManualDepsCheck/RubyMissingDeps/expected.json new file mode 100644 index 00000000..94c44a0e --- /dev/null +++ b/testdata/data/repos/standalone/EclassManualDepsCheck/RubyMissingDeps/expected.json @@ -0,0 +1 @@ +{"__class__": "RubyMissingDeps", "category": "EclassManualDepsCheck", "package": "RubyMissingDeps", "version": "1"} diff --git a/testdata/data/repos/standalone/EclassManualDepsCheck/RubyMissingDeps/fix.patch b/testdata/data/repos/standalone/EclassManualDepsCheck/RubyMissingDeps/fix.patch new file mode 100644 index 00000000..40c816d3 --- /dev/null +++ b/testdata/data/repos/standalone/EclassManualDepsCheck/RubyMissingDeps/fix.patch @@ -0,0 +1,9 @@ +diff -Naur standalone/EclassManualDepsCheck/RubyMissingDeps/RubyMissingDeps-1.ebuild fixed/EclassManualDepsCheck/RubyMissingDeps/RubyMissingDeps-1.ebuild +--- standalone/EclassManualDepsCheck/RubyMissingDeps/RubyMissingDeps-1.ebuild ++++ fixed/EclassManualDepsCheck/RubyMissingDeps/RubyMissingDeps-1.ebuild +@@ -6,3 +6,5 @@ DESCRIPTION="Optional inherit without dep" + HOMEPAGE="https://github.com/pkgcore/pkgcheck" + SLOT="0" + LICENSE="BSD" ++ ++DEPEND="virtual/rubygems" diff --git a/testdata/data/repos/standalone/EclassManualDepsCheck/RustMissingDeps/expected.json b/testdata/data/repos/standalone/EclassManualDepsCheck/RustMissingDeps/expected.json new file mode 100644 index 00000000..43be8d93 --- /dev/null +++ b/testdata/data/repos/standalone/EclassManualDepsCheck/RustMissingDeps/expected.json @@ -0,0 +1 @@ +{"__class__": "RustMissingDeps", "category": "EclassManualDepsCheck", "package": "RustMissingDeps", "version": "1"} diff --git a/testdata/data/repos/standalone/EclassManualDepsCheck/RustMissingDeps/fix.patch b/testdata/data/repos/standalone/EclassManualDepsCheck/RustMissingDeps/fix.patch new file mode 100644 index 00000000..a62eb390 --- /dev/null +++ b/testdata/data/repos/standalone/EclassManualDepsCheck/RustMissingDeps/fix.patch @@ -0,0 +1,9 @@ +diff -Naur standalone/EclassManualDepsCheck/RustMissingDeps/RustMissingDeps-1.ebuild fixed/EclassManualDepsCheck/RustMissingDeps/RustMissingDeps-1.ebuild +--- standalone/EclassManualDepsCheck/RustMissingDeps/RustMissingDeps-1.ebuild ++++ fixed/EclassManualDepsCheck/RustMissingDeps/RustMissingDeps-1.ebuild +@@ -8,3 +8,5 @@ DESCRIPTION="Optional inherit without deps" + HOMEPAGE="https://github.com/pkgcore/pkgcheck" + SLOT="0" + LICENSE="BSD" ++ ++BDEPEND="virtual/rust" diff --git a/testdata/repos/standalone/EclassManualDepsCheck/RubyMissingDeps/RubyMissingDeps-0.ebuild b/testdata/repos/standalone/EclassManualDepsCheck/RubyMissingDeps/RubyMissingDeps-0.ebuild new file mode 100644 index 00000000..aaf1acd0 --- /dev/null +++ b/testdata/repos/standalone/EclassManualDepsCheck/RubyMissingDeps/RubyMissingDeps-0.ebuild @@ -0,0 +1,12 @@ +EAPI=8 + +RUBY_OPTIONAL=1 + +inherit ruby-ng + +DESCRIPTION="Optional inherit with one dep" +HOMEPAGE="https://github.com/pkgcore/pkgcheck" +SLOT="0" +LICENSE="BSD" + +IDEPEND="dev-lang/ruby" diff --git a/testdata/repos/standalone/EclassManualDepsCheck/RubyMissingDeps/RubyMissingDeps-1.ebuild b/testdata/repos/standalone/EclassManualDepsCheck/RubyMissingDeps/RubyMissingDeps-1.ebuild new file mode 100644 index 00000000..aba69b0b --- /dev/null +++ b/testdata/repos/standalone/EclassManualDepsCheck/RubyMissingDeps/RubyMissingDeps-1.ebuild @@ -0,0 +1,8 @@ +RUBY_OPTIONAL=1 + +inherit ruby-ng + +DESCRIPTION="Optional inherit without dep" +HOMEPAGE="https://github.com/pkgcore/pkgcheck" +SLOT="0" +LICENSE="BSD" diff --git a/testdata/repos/standalone/EclassManualDepsCheck/RubyMissingDeps/RubyMissingDeps-2.ebuild b/testdata/repos/standalone/EclassManualDepsCheck/RubyMissingDeps/RubyMissingDeps-2.ebuild new file mode 100644 index 00000000..04bab5d8 --- /dev/null +++ b/testdata/repos/standalone/EclassManualDepsCheck/RubyMissingDeps/RubyMissingDeps-2.ebuild @@ -0,0 +1,14 @@ +EAPI=8 + +RUBY_OPTIONAL=1 + +inherit ruby-ng + +DESCRIPTION="Optional inherit with category whitelist" +HOMEPAGE="https://github.com/pkgcore/pkgcheck" +SLOT="0" +LICENSE="BSD" + +IUSE="test" +RESTRICT="!test? ( test )" +BDEPEND="test? ( dev-ruby/stub )" diff --git a/testdata/repos/standalone/EclassManualDepsCheck/RustMissingDeps/RustMissingDeps-0.ebuild b/testdata/repos/standalone/EclassManualDepsCheck/RustMissingDeps/RustMissingDeps-0.ebuild new file mode 100644 index 00000000..2b453030 --- /dev/null +++ b/testdata/repos/standalone/EclassManualDepsCheck/RustMissingDeps/RustMissingDeps-0.ebuild @@ -0,0 +1,6 @@ +inherit cargo + +DESCRIPTION="Normal non-optional inherit" +HOMEPAGE="https://github.com/pkgcore/pkgcheck" +SLOT="0" +LICENSE="BSD" diff --git a/testdata/repos/standalone/EclassManualDepsCheck/RustMissingDeps/RustMissingDeps-1.ebuild b/testdata/repos/standalone/EclassManualDepsCheck/RustMissingDeps/RustMissingDeps-1.ebuild new file mode 100644 index 00000000..b43ff1b4 --- /dev/null +++ b/testdata/repos/standalone/EclassManualDepsCheck/RustMissingDeps/RustMissingDeps-1.ebuild @@ -0,0 +1,10 @@ +EAPI=7 + +CARGO_OPTIONAL=1 + +inherit cargo + +DESCRIPTION="Optional inherit without deps" +HOMEPAGE="https://github.com/pkgcore/pkgcheck" +SLOT="0" +LICENSE="BSD" diff --git a/testdata/repos/standalone/dev-lang/ruby/ruby-0.ebuild b/testdata/repos/standalone/dev-lang/ruby/ruby-0.ebuild new file mode 100644 index 00000000..ba6aebb4 --- /dev/null +++ b/testdata/repos/standalone/dev-lang/ruby/ruby-0.ebuild @@ -0,0 +1,4 @@ +DESCRIPTION="Stub ebuild" +HOMEPAGE="https://github.com/pkgcore/pkgcheck" +SLOT="0" +LICENSE="BSD" diff --git a/testdata/repos/standalone/dev-ruby/stub/stub-0.ebuild b/testdata/repos/standalone/dev-ruby/stub/stub-0.ebuild new file mode 100644 index 00000000..ba6aebb4 --- /dev/null +++ b/testdata/repos/standalone/dev-ruby/stub/stub-0.ebuild @@ -0,0 +1,4 @@ +DESCRIPTION="Stub ebuild" +HOMEPAGE="https://github.com/pkgcore/pkgcheck" +SLOT="0" +LICENSE="BSD" diff --git a/testdata/repos/standalone/eclass/ruby-ng.eclass b/testdata/repos/standalone/eclass/ruby-ng.eclass new file mode 100644 index 00000000..5b2b9973 --- /dev/null +++ b/testdata/repos/standalone/eclass/ruby-ng.eclass @@ -0,0 +1 @@ +# ruby-ng eclass diff --git a/testdata/repos/standalone/virtual/rubygems/rubygems-0.ebuild b/testdata/repos/standalone/virtual/rubygems/rubygems-0.ebuild new file mode 100644 index 00000000..9c2ce2e9 --- /dev/null +++ b/testdata/repos/standalone/virtual/rubygems/rubygems-0.ebuild @@ -0,0 +1,2 @@ +DESCRIPTION="Stub ebuild" +SLOT="0" diff --git a/testdata/repos/standalone/virtual/rust/rust-0.ebuild b/testdata/repos/standalone/virtual/rust/rust-0.ebuild new file mode 100644 index 00000000..9c2ce2e9 --- /dev/null +++ b/testdata/repos/standalone/virtual/rust/rust-0.ebuild @@ -0,0 +1,2 @@ +DESCRIPTION="Stub ebuild" +SLOT="0"