Skip to content

Commit 839a1f4

Browse files
committed
RubyCompatCheck: new check for new USE_RUBY compatible values
Resolves: #304 Signed-off-by: Arthur Zamarin <arthurzam@gentoo.org>
1 parent c41771d commit 839a1f4

13 files changed

Lines changed: 302 additions & 0 deletions

File tree

src/pkgcheck/checks/ruby.py

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import itertools
2+
3+
from pkgcore.ebuild.atom import atom
4+
from snakeoil.sequences import iflatten_instance
5+
from snakeoil.strings import pluralism
6+
7+
from .. import results
8+
from . import Check
9+
10+
11+
IUSE_PREFIX = "ruby_targets_"
12+
13+
14+
class RubyCompatUpdate(results.VersionResult, results.Info):
15+
"""``USE_RUBY`` can be updated to support newer ruby version(s)."""
16+
17+
def __init__(self, updates, **kwargs):
18+
super().__init__(**kwargs)
19+
self.updates = tuple(updates)
20+
21+
@property
22+
def desc(self):
23+
s = pluralism(self.updates)
24+
updates = ", ".join(self.updates)
25+
return f"USE_RUBY update{s} available: {updates}"
26+
27+
28+
class RubyCompatCheck(Check):
29+
"""Check ruby ebuilds for possible ``USE_RUBY`` updates.
30+
31+
Supports ebuilds inheriting ``ruby-ng``.
32+
"""
33+
34+
known_results = frozenset({RubyCompatUpdate})
35+
36+
whitelist_categories = frozenset({"virtual"})
37+
38+
def __init__(self, *args):
39+
super().__init__(*args)
40+
repo = self.options.target_repo
41+
# sorter for ruby targets leveraging USE_EXPAND flag ordering from repo
42+
self.sorter = repo.use_expand_sorter("ruby_targets")
43+
44+
# determine available USE_RUBY use flags
45+
targets = []
46+
for target, _desc in repo.use_expand_desc.get(IUSE_PREFIX[:-1], ()):
47+
if target[len(IUSE_PREFIX) :].startswith("ruby"):
48+
targets.append(target[len(IUSE_PREFIX) :])
49+
self.multi_targets = tuple(sorted(targets, key=self.sorter))
50+
51+
def ruby_deps(self, deps, prefix):
52+
for dep in (x for x in deps if x.use):
53+
for x in dep.use:
54+
if x.startswith(("-", "!")):
55+
continue
56+
if x.startswith(prefix):
57+
yield dep.no_usedeps
58+
break
59+
60+
def deps(self, pkg):
61+
"""Set of dependencies for a given package's attributes."""
62+
return {
63+
p
64+
for attr in (x.lower() for x in pkg.eapi.dep_keys)
65+
for p in iflatten_instance(getattr(pkg, attr), atom)
66+
if not p.blocks
67+
}
68+
69+
def feed(self, pkg):
70+
if pkg.category in self.whitelist_categories or "ruby-ng" not in pkg.inherited:
71+
return
72+
73+
deps = self.deps(pkg)
74+
75+
try:
76+
# determine the latest supported ruby version
77+
latest_target = sorted(
78+
(
79+
f"ruby{x.slot.replace('.', '')}"
80+
for x in deps
81+
if x.key == "dev-lang/ruby" and x.slot is not None
82+
),
83+
key=self.sorter,
84+
)[-1]
85+
except IndexError:
86+
return
87+
88+
# determine ruby impls to target
89+
targets = set(
90+
itertools.takewhile(lambda x: x != latest_target, reversed(self.multi_targets))
91+
)
92+
93+
if targets:
94+
try:
95+
# determine if deps support missing ruby targets
96+
for dep in self.ruby_deps(deps, IUSE_PREFIX):
97+
# TODO: use query caching for repo matching?
98+
latest = sorted(self.options.search_repo.match(dep))[-1]
99+
targets.intersection_update(
100+
f"ruby{x.rsplit('ruby', 1)[-1]}"
101+
for x in latest.iuse_stripped
102+
if x.startswith(IUSE_PREFIX)
103+
)
104+
if not targets:
105+
return
106+
except IndexError:
107+
return
108+
109+
yield RubyCompatUpdate(sorted(targets, key=self.sorter), pkg=pkg)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
{"__class__": "RubyCompatUpdate", "category": "RubyCompatCheck", "package": "RubyCompatUpdate", "version": "0", "updates": ["ruby31", "ruby32"]}
2+
{"__class__": "RubyCompatUpdate", "category": "RubyCompatCheck", "package": "RubyCompatUpdate", "version": "1", "updates": ["ruby32"]}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
EAPI=7
2+
3+
USE_RUBY="ruby27 ruby30"
4+
inherit ruby-ng
5+
6+
DESCRIPTION="Ebuild with potential USE_RUBY updates"
7+
HOMEPAGE="https://github.com/pkgcore/pkgcheck"
8+
LICENSE="BSD"
9+
SLOT="0"
10+
11+
RDEPEND="
12+
stub/stub2
13+
"
14+
15+
ruby_add_rdepend "
16+
stub/ruby-dep
17+
"
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
EAPI=7
2+
3+
USE_RUBY="ruby27 ruby30 ruby31"
4+
inherit ruby-ng
5+
6+
DESCRIPTION="Ebuild with potential USE_RUBY updates"
7+
HOMEPAGE="https://github.com/pkgcore/pkgcheck"
8+
LICENSE="BSD"
9+
SLOT="0"
10+
11+
RDEPEND="
12+
stub/stub2
13+
"
14+
15+
ruby_add_depend "
16+
stub/ruby-dep
17+
"
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
EAPI=7
2+
3+
USE_RUBY="ruby27 ruby30"
4+
inherit ruby-ng
5+
6+
DESCRIPTION="Ebuild without potential USE_RUBY updates"
7+
HOMEPAGE="https://github.com/pkgcore/pkgcheck"
8+
LICENSE="BSD"
9+
SLOT="0"
10+
11+
RDEPEND="
12+
stub/stub2
13+
"
14+
15+
ruby_add_rdepend "
16+
stub/ruby-dep-old
17+
"
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
EAPI=7
2+
3+
DESCRIPTION="Stub ebuild for ruby interpreter"
4+
HOMEPAGE="https://github.com/pkgcore/pkgcheck"
5+
LICENSE="BSD"
6+
SLOT="2.7"
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
EAPI=7
2+
3+
DESCRIPTION="Stub ebuild for ruby interpreter"
4+
HOMEPAGE="https://github.com/pkgcore/pkgcheck"
5+
LICENSE="BSD"
6+
SLOT="3.0"
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
EAPI=7
2+
3+
DESCRIPTION="Stub ebuild for ruby interpreter"
4+
HOMEPAGE="https://github.com/pkgcore/pkgcheck"
5+
LICENSE="BSD"
6+
SLOT="3.1"
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
EAPI=7
2+
3+
DESCRIPTION="Stub ebuild for ruby interpreter"
4+
HOMEPAGE="https://github.com/pkgcore/pkgcheck"
5+
LICENSE="BSD"
6+
SLOT="3.2"
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
_ruby_implementation_depend() {
2+
local rubypn= rubyslot=
3+
4+
case $1 in
5+
ruby27) rubypn="dev-lang/ruby" rubyslot=":2.7" ;;
6+
ruby30) rubypn="dev-lang/ruby" rubyslot=":3.0" ;;
7+
ruby31) rubypn="dev-lang/ruby" rubyslot=":3.1" ;;
8+
ruby32) rubypn="dev-lang/ruby" rubyslot=":3.2" ;;
9+
*) die "$1: unknown Ruby implementation"
10+
esac
11+
12+
echo "$2${rubypn}$3${rubyslot}"
13+
}
14+
15+
_ruby_implementations_depend() {
16+
local depend _ruby_implementation
17+
for _ruby_implementation in "${_RUBY_GET_ALL_IMPLS[@]}"; do
18+
depend="${depend}${depend+ }ruby_targets_${_ruby_implementation}? ( $(_ruby_implementation_depend $_ruby_implementation) )"
19+
done
20+
DEPEND="${depend}"
21+
IUSE="${_RUBY_GET_ALL_IMPLS[*]/#/ruby_targets_}"
22+
REQUIRED_USE="|| ( ${IUSE} )"
23+
}
24+
25+
_ruby_atoms_samelib_generic() {
26+
local shopt_save=$(shopt -p -o noglob)
27+
echo "RUBYTARGET? ("
28+
for token in $*; do
29+
case "$token" in
30+
"||" | "(" | ")" | *"?")
31+
echo "${token}" ;;
32+
*])
33+
echo "${token%[*}[RUBYTARGET(-),${token/*[}" ;;
34+
*)
35+
echo "${token}[RUBYTARGET(-)]" ;;
36+
esac
37+
done
38+
echo ")"
39+
${shopt_save}
40+
}
41+
42+
_ruby_atoms_samelib() {
43+
local atoms=$(_ruby_atoms_samelib_generic "$*")
44+
for _ruby_implementation in "${_RUBY_GET_ALL_IMPLS[@]}"; do
45+
echo "${atoms//RUBYTARGET/ruby_targets_${_ruby_implementation}}"
46+
done
47+
}
48+
49+
_ruby_get_all_impls() {
50+
_RUBY_GET_ALL_IMPLS=()
51+
52+
local i found_valid_impl
53+
for i in ${USE_RUBY}; do
54+
case ${i} in
55+
# removed implementations
56+
ruby19|ruby2[0-7]|jruby)
57+
;;
58+
*)
59+
found_valid_impl=1
60+
_RUBY_GET_ALL_IMPLS+=( ${i} )
61+
;;
62+
esac
63+
done
64+
65+
if [[ -z ${found_valid_impl} ]] ; then
66+
die "No supported implementation in USE_RUBY."
67+
fi
68+
}
69+
70+
ruby_add_depend() {
71+
DEPEND+=" $(_ruby_atoms_samelib "$1")"
72+
}
73+
74+
ruby_add_bdepend() {
75+
BDEPEND+=" $(_ruby_atoms_samelib "$1")"
76+
}
77+
78+
ruby_add_rdepend() {
79+
RDEPEND+=" $(_ruby_atoms_samelib "$1")"
80+
}
81+
82+
_ruby_get_all_impls
83+
_ruby_implementations_depend

0 commit comments

Comments
 (0)