[prev in list] [next in list] [prev in thread] [next in thread] 

List:       gentoo-commits
Subject:    [gentoo-commits] proj/pkgcore/pkgcheck:master commit in: testdata/repos/python/stub/ruby-dep-old/, .
From:       "Arthur Zamarin" <arthurzam () gentoo ! org>
Date:       2023-06-30 21:00:54
Message-ID: 1688150193.839a1f4a9a723e642ac4a1b26154bbb8f49e488a.arthurzam () gentoo
[Download RAW message or body]

commit:     839a1f4a9a723e642ac4a1b26154bbb8f49e488a
Author:     Arthur Zamarin <arthurzam <AT> gentoo <DOT> org>
AuthorDate: Thu Jun 29 18:27:16 2023 +0000
Commit:     Arthur Zamarin <arthurzam <AT> gentoo <DOT> org>
CommitDate: Fri Jun 30 18:36:33 2023 +0000
URL:        https://gitweb.gentoo.org/proj/pkgcore/pkgcheck.git/commit/?id=839a1f4a

RubyCompatCheck: new check for new USE_RUBY compatible values

Resolves: https://github.com/pkgcore/pkgcheck/issues/304
Signed-off-by: Arthur Zamarin <arthurzam <AT> gentoo.org>

 src/pkgcheck/checks/ruby.py                        | 109 +++++++++++++++++++++
 .../RubyCompatCheck/RubyCompatUpdate/expected.json |   2 +
 .../RubyCompatUpdate/RubyCompatUpdate-0.ebuild     |  17 ++++
 .../RubyCompatUpdate/RubyCompatUpdate-1.ebuild     |  17 ++++
 .../RubyCompatUpdate/RubyCompatUpdate-2.ebuild     |  17 ++++
 .../repos/python/dev-lang/ruby/ruby-2.7.ebuild     |   6 ++
 .../repos/python/dev-lang/ruby/ruby-3.0.ebuild     |   6 ++
 .../repos/python/dev-lang/ruby/ruby-3.1.ebuild     |   6 ++
 .../repos/python/dev-lang/ruby/ruby-3.2.ebuild     |   6 ++
 testdata/repos/python/eclass/ruby-ng.eclass        |  83 ++++++++++++++++
 .../repos/python/profiles/desc/ruby_targets.desc   |   5 +
 .../python/stub/ruby-dep-old/ruby-dep-old-0.ebuild |  14 +++
 .../repos/python/stub/ruby-dep/ruby-dep-0.ebuild   |  14 +++
 13 files changed, 302 insertions(+)

diff --git a/src/pkgcheck/checks/ruby.py b/src/pkgcheck/checks/ruby.py
new file mode 100644
index 00000000..d7cbb914
--- /dev/null
+++ b/src/pkgcheck/checks/ruby.py
@@ -0,0 +1,109 @@
+import itertools
+
+from pkgcore.ebuild.atom import atom
+from snakeoil.sequences import iflatten_instance
+from snakeoil.strings import pluralism
+
+from .. import results
+from . import Check
+
+
+IUSE_PREFIX = "ruby_targets_"
+
+
+class RubyCompatUpdate(results.VersionResult, results.Info):
+    """``USE_RUBY`` can be updated to support newer ruby version(s)."""
+
+    def __init__(self, updates, **kwargs):
+        super().__init__(**kwargs)
+        self.updates = tuple(updates)
+
+    @property
+    def desc(self):
+        s = pluralism(self.updates)
+        updates = ", ".join(self.updates)
+        return f"USE_RUBY update{s} available: {updates}"
+
+
+class RubyCompatCheck(Check):
+    """Check ruby ebuilds for possible ``USE_RUBY`` updates.
+
+    Supports ebuilds inheriting ``ruby-ng``.
+    """
+
+    known_results = frozenset({RubyCompatUpdate})
+
+    whitelist_categories = frozenset({"virtual"})
+
+    def __init__(self, *args):
+        super().__init__(*args)
+        repo = self.options.target_repo
+        # sorter for ruby targets leveraging USE_EXPAND flag ordering from repo
+        self.sorter = repo.use_expand_sorter("ruby_targets")
+
+        # determine available USE_RUBY use flags
+        targets = []
+        for target, _desc in repo.use_expand_desc.get(IUSE_PREFIX[:-1], ()):
+            if target[len(IUSE_PREFIX) :].startswith("ruby"):
+                targets.append(target[len(IUSE_PREFIX) :])
+        self.multi_targets = tuple(sorted(targets, key=self.sorter))
+
+    def ruby_deps(self, deps, prefix):
+        for dep in (x for x in deps if x.use):
+            for x in dep.use:
+                if x.startswith(("-", "!")):
+                    continue
+                if x.startswith(prefix):
+                    yield dep.no_usedeps
+                    break
+
+    def deps(self, pkg):
+        """Set of dependencies for a given package's attributes."""
+        return {
+            p
+            for attr in (x.lower() for x in pkg.eapi.dep_keys)
+            for p in iflatten_instance(getattr(pkg, attr), atom)
+            if not p.blocks
+        }
+
+    def feed(self, pkg):
+        if pkg.category in self.whitelist_categories or "ruby-ng" not in \
pkg.inherited: +            return
+
+        deps = self.deps(pkg)
+
+        try:
+            # determine the latest supported ruby version
+            latest_target = sorted(
+                (
+                    f"ruby{x.slot.replace('.', '')}"
+                    for x in deps
+                    if x.key == "dev-lang/ruby" and x.slot is not None
+                ),
+                key=self.sorter,
+            )[-1]
+        except IndexError:
+            return
+
+        # determine ruby impls to target
+        targets = set(
+            itertools.takewhile(lambda x: x != latest_target, \
reversed(self.multi_targets)) +        )
+
+        if targets:
+            try:
+                # determine if deps support missing ruby targets
+                for dep in self.ruby_deps(deps, IUSE_PREFIX):
+                    # TODO: use query caching for repo matching?
+                    latest = sorted(self.options.search_repo.match(dep))[-1]
+                    targets.intersection_update(
+                        f"ruby{x.rsplit('ruby', 1)[-1]}"
+                        for x in latest.iuse_stripped
+                        if x.startswith(IUSE_PREFIX)
+                    )
+                    if not targets:
+                        return
+            except IndexError:
+                return
+
+            yield RubyCompatUpdate(sorted(targets, key=self.sorter), pkg=pkg)

diff --git a/testdata/data/repos/python/RubyCompatCheck/RubyCompatUpdate/expected.json \
b/testdata/data/repos/python/RubyCompatCheck/RubyCompatUpdate/expected.json new file \
mode 100644 index 00000000..b5253f79
--- /dev/null
+++ b/testdata/data/repos/python/RubyCompatCheck/RubyCompatUpdate/expected.json
@@ -0,0 +1,2 @@
+{"__class__": "RubyCompatUpdate", "category": "RubyCompatCheck", "package": \
"RubyCompatUpdate", "version": "0", "updates": ["ruby31", "ruby32"]} +{"__class__": \
"RubyCompatUpdate", "category": "RubyCompatCheck", "package": "RubyCompatUpdate", \
"version": "1", "updates": ["ruby32"]}

diff --git a/testdata/repos/python/RubyCompatCheck/RubyCompatUpdate/RubyCompatUpdate-0.ebuild \
b/testdata/repos/python/RubyCompatCheck/RubyCompatUpdate/RubyCompatUpdate-0.ebuild \
new file mode 100644 index 00000000..8f6f1da4
--- /dev/null
+++ b/testdata/repos/python/RubyCompatCheck/RubyCompatUpdate/RubyCompatUpdate-0.ebuild
 @@ -0,0 +1,17 @@
+EAPI=7
+
+USE_RUBY="ruby27 ruby30"
+inherit ruby-ng
+
+DESCRIPTION="Ebuild with potential USE_RUBY updates"
+HOMEPAGE="https://github.com/pkgcore/pkgcheck"
+LICENSE="BSD"
+SLOT="0"
+
+RDEPEND="
+	stub/stub2
+"
+
+ruby_add_rdepend "
+	stub/ruby-dep
+"

diff --git a/testdata/repos/python/RubyCompatCheck/RubyCompatUpdate/RubyCompatUpdate-1.ebuild \
b/testdata/repos/python/RubyCompatCheck/RubyCompatUpdate/RubyCompatUpdate-1.ebuild \
new file mode 100644 index 00000000..8af80e69
--- /dev/null
+++ b/testdata/repos/python/RubyCompatCheck/RubyCompatUpdate/RubyCompatUpdate-1.ebuild
 @@ -0,0 +1,17 @@
+EAPI=7
+
+USE_RUBY="ruby27 ruby30 ruby31"
+inherit ruby-ng
+
+DESCRIPTION="Ebuild with potential USE_RUBY updates"
+HOMEPAGE="https://github.com/pkgcore/pkgcheck"
+LICENSE="BSD"
+SLOT="0"
+
+RDEPEND="
+	stub/stub2
+"
+
+ruby_add_depend "
+	stub/ruby-dep
+"

diff --git a/testdata/repos/python/RubyCompatCheck/RubyCompatUpdate/RubyCompatUpdate-2.ebuild \
b/testdata/repos/python/RubyCompatCheck/RubyCompatUpdate/RubyCompatUpdate-2.ebuild \
new file mode 100644 index 00000000..bb2e95d3
--- /dev/null
+++ b/testdata/repos/python/RubyCompatCheck/RubyCompatUpdate/RubyCompatUpdate-2.ebuild
 @@ -0,0 +1,17 @@
+EAPI=7
+
+USE_RUBY="ruby27 ruby30"
+inherit ruby-ng
+
+DESCRIPTION="Ebuild without potential USE_RUBY updates"
+HOMEPAGE="https://github.com/pkgcore/pkgcheck"
+LICENSE="BSD"
+SLOT="0"
+
+RDEPEND="
+	stub/stub2
+"
+
+ruby_add_rdepend "
+	stub/ruby-dep-old
+"

diff --git a/testdata/repos/python/dev-lang/ruby/ruby-2.7.ebuild \
b/testdata/repos/python/dev-lang/ruby/ruby-2.7.ebuild new file mode 100644
index 00000000..6192e625
--- /dev/null
+++ b/testdata/repos/python/dev-lang/ruby/ruby-2.7.ebuild
@@ -0,0 +1,6 @@
+EAPI=7
+
+DESCRIPTION="Stub ebuild for ruby interpreter"
+HOMEPAGE="https://github.com/pkgcore/pkgcheck"
+LICENSE="BSD"
+SLOT="2.7"

diff --git a/testdata/repos/python/dev-lang/ruby/ruby-3.0.ebuild \
b/testdata/repos/python/dev-lang/ruby/ruby-3.0.ebuild new file mode 100644
index 00000000..452b04e7
--- /dev/null
+++ b/testdata/repos/python/dev-lang/ruby/ruby-3.0.ebuild
@@ -0,0 +1,6 @@
+EAPI=7
+
+DESCRIPTION="Stub ebuild for ruby interpreter"
+HOMEPAGE="https://github.com/pkgcore/pkgcheck"
+LICENSE="BSD"
+SLOT="3.0"

diff --git a/testdata/repos/python/dev-lang/ruby/ruby-3.1.ebuild \
b/testdata/repos/python/dev-lang/ruby/ruby-3.1.ebuild new file mode 100644
index 00000000..570b1709
--- /dev/null
+++ b/testdata/repos/python/dev-lang/ruby/ruby-3.1.ebuild
@@ -0,0 +1,6 @@
+EAPI=7
+
+DESCRIPTION="Stub ebuild for ruby interpreter"
+HOMEPAGE="https://github.com/pkgcore/pkgcheck"
+LICENSE="BSD"
+SLOT="3.1"

diff --git a/testdata/repos/python/dev-lang/ruby/ruby-3.2.ebuild \
b/testdata/repos/python/dev-lang/ruby/ruby-3.2.ebuild new file mode 100644
index 00000000..9bbb0f65
--- /dev/null
+++ b/testdata/repos/python/dev-lang/ruby/ruby-3.2.ebuild
@@ -0,0 +1,6 @@
+EAPI=7
+
+DESCRIPTION="Stub ebuild for ruby interpreter"
+HOMEPAGE="https://github.com/pkgcore/pkgcheck"
+LICENSE="BSD"
+SLOT="3.2"

diff --git a/testdata/repos/python/eclass/ruby-ng.eclass \
b/testdata/repos/python/eclass/ruby-ng.eclass new file mode 100644
index 00000000..082c98f0
--- /dev/null
+++ b/testdata/repos/python/eclass/ruby-ng.eclass
@@ -0,0 +1,83 @@
+_ruby_implementation_depend() {
+	local rubypn= rubyslot=
+
+	case $1 in
+		ruby27) rubypn="dev-lang/ruby" rubyslot=":2.7" ;;
+		ruby30) rubypn="dev-lang/ruby" rubyslot=":3.0" ;;
+		ruby31) rubypn="dev-lang/ruby" rubyslot=":3.1" ;;
+		ruby32) rubypn="dev-lang/ruby" rubyslot=":3.2" ;;
+		*) die "$1: unknown Ruby implementation"
+	esac
+
+	echo "$2${rubypn}$3${rubyslot}"
+}
+
+_ruby_implementations_depend() {
+	local depend _ruby_implementation
+	for _ruby_implementation in "${_RUBY_GET_ALL_IMPLS[@]}"; do
+		depend="${depend}${depend+ }ruby_targets_${_ruby_implementation}? ( \
$(_ruby_implementation_depend $_ruby_implementation) )" +	done
+	DEPEND="${depend}"
+	IUSE="${_RUBY_GET_ALL_IMPLS[*]/#/ruby_targets_}"
+	REQUIRED_USE="|| ( ${IUSE} )"
+}
+
+_ruby_atoms_samelib_generic() {
+	local shopt_save=$(shopt -p -o noglob)
+	echo "RUBYTARGET? ("
+	for token in $*; do
+		case "$token" in
+			"||" | "(" | ")" | *"?")
+				echo "${token}" ;;
+			*])
+				echo "${token%[*}[RUBYTARGET(-),${token/*[}" ;;
+			*)
+				echo "${token}[RUBYTARGET(-)]" ;;
+		esac
+	done
+	echo ")"
+	${shopt_save}
+}
+
+_ruby_atoms_samelib() {
+	local atoms=$(_ruby_atoms_samelib_generic "$*")
+    for _ruby_implementation in "${_RUBY_GET_ALL_IMPLS[@]}"; do
+        echo "${atoms//RUBYTARGET/ruby_targets_${_ruby_implementation}}"
+    done
+}
+
+_ruby_get_all_impls() {
+	_RUBY_GET_ALL_IMPLS=()
+
+	local i found_valid_impl
+	for i in ${USE_RUBY}; do
+		case ${i} in
+			# removed implementations
+			ruby19|ruby2[0-7]|jruby)
+				;;
+			*)
+				found_valid_impl=1
+				_RUBY_GET_ALL_IMPLS+=( ${i} )
+				;;
+		esac
+	done
+
+	if [[ -z ${found_valid_impl} ]] ; then
+		die "No supported implementation in USE_RUBY."
+	fi
+}
+
+ruby_add_depend() {
+	DEPEND+=" $(_ruby_atoms_samelib "$1")"
+}
+
+ruby_add_bdepend() {
+	BDEPEND+=" $(_ruby_atoms_samelib "$1")"
+}
+
+ruby_add_rdepend() {
+	RDEPEND+=" $(_ruby_atoms_samelib "$1")"
+}
+
+_ruby_get_all_impls
+_ruby_implementations_depend

diff --git a/testdata/repos/python/profiles/desc/ruby_targets.desc \
b/testdata/repos/python/profiles/desc/ruby_targets.desc new file mode 100644
index 00000000..59c3dec7
--- /dev/null
+++ b/testdata/repos/python/profiles/desc/ruby_targets.desc
@@ -0,0 +1,5 @@
+# available RUBY_TARGETS USE_EXPAND flags
+ruby27 - Build with MRI Ruby 2.7.x
+ruby30 - Build with MRI Ruby 3.0.x
+ruby31 - Build with MRI Ruby 3.1.x
+ruby32 - Build with MRI Ruby 3.2.x

diff --git a/testdata/repos/python/stub/ruby-dep-old/ruby-dep-old-0.ebuild \
b/testdata/repos/python/stub/ruby-dep-old/ruby-dep-old-0.ebuild new file mode 100644
index 00000000..ec9071c3
--- /dev/null
+++ b/testdata/repos/python/stub/ruby-dep-old/ruby-dep-old-0.ebuild
@@ -0,0 +1,14 @@
+EAPI=7
+
+USE_RUBY="ruby27 ruby30"
+
+inherit ruby-ng
+
+DESCRIPTION="Stub ebuild with old USE_RUBY support"
+HOMEPAGE="https://github.com/pkgcore/pkgcheck"
+LICENSE="BSD"
+SLOT="0"
+
+RDEPEND="
+	stub/stub2
+"

diff --git a/testdata/repos/python/stub/ruby-dep/ruby-dep-0.ebuild \
b/testdata/repos/python/stub/ruby-dep/ruby-dep-0.ebuild new file mode 100644
index 00000000..abc2efee
--- /dev/null
+++ b/testdata/repos/python/stub/ruby-dep/ruby-dep-0.ebuild
@@ -0,0 +1,14 @@
+EAPI=7
+
+USE_RUBY="ruby27 ruby30 ruby31 ruby32"
+
+inherit ruby-ng
+
+DESCRIPTION="Stub ebuild with complete USE_RUBY support"
+HOMEPAGE="https://github.com/pkgcore/pkgcheck"
+LICENSE="BSD"
+SLOT="0"
+
+RDEPEND="
+	stub/stub1
+"


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic