* [gentoo-commits] proj/portage:master commit in: lib/portage/tests/resolver/, lib/portage/dep/, lib/_emerge/, ...
@ 2019-12-23 22:47 Zac Medico
0 siblings, 0 replies; only message in thread
From: Zac Medico @ 2019-12-23 22:47 UTC (permalink / raw
To: gentoo-commits
commit: 85f0dd173ab75bcc39c3616b5a3a967bdc88cf73
Author: Zac Medico <zmedico <AT> gentoo <DOT> org>
AuthorDate: Fri Dec 20 06:58:58 2019 +0000
Commit: Zac Medico <zmedico <AT> gentoo <DOT> org>
CommitDate: Mon Dec 23 22:23:15 2019 +0000
URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=85f0dd17
emerge --with-test-deps: allow circular deps
When USE=test is not enabled, allow circular test dependencies
by treating them like PDEPEND. When USE=test is enabled, circular
dependencies are still not allowed, as shown in unit tests.
Suggested-by: Michał Górny <mgorny <AT> gentoo.org>
Bug: https://bugs.gentoo.org/703348
Signed-off-by: Zac Medico <zmedico <AT> gentoo.org>
lib/_emerge/depgraph.py | 19 ++++--
lib/portage/dep/__init__.py | 44 +++++++++++++-
lib/portage/tests/dep/test_use_reduce.py | 72 ++++++++++++++++++++++-
lib/portage/tests/resolver/test_with_test_deps.py | 39 +++++++++++-
4 files changed, 166 insertions(+), 8 deletions(-)
diff --git a/lib/_emerge/depgraph.py b/lib/_emerge/depgraph.py
index 1a5448c8f..83631fe70 100644
--- a/lib/_emerge/depgraph.py
+++ b/lib/_emerge/depgraph.py
@@ -3325,10 +3325,6 @@ class depgraph(object):
pkg.iuse.is_valid_flag("test") and \
self._is_argument(pkg)
- if with_test_deps:
- use_enabled = set(use_enabled)
- use_enabled.add("test")
-
if not pkg.built and \
"--buildpkgonly" in self._frozen_config.myopts and \
"deep" not in self._dynamic_config.myparams:
@@ -3430,6 +3426,21 @@ class depgraph(object):
noiselevel=-1, level=logging.DEBUG)
try:
+ if (with_test_deps and 'test' not in use_enabled and
+ pkg.iuse.is_valid_flag('test')):
+ test_deps = portage.dep.use_reduce(dep_string,
+ uselist=use_enabled | {'test'},
+ is_valid_flag=pkg.iuse.is_valid_flag,
+ opconvert=True, token_class=Atom,
+ eapi=pkg.eapi,
+ subset={'test'})
+
+ if test_deps and not self._add_pkg_dep_string(
+ pkg, dep_root, self._priority(runtime_post=True),
+ test_deps,
+ allow_unsatisfied):
+ return 0
+
dep_string = portage.dep.use_reduce(dep_string,
uselist=use_enabled,
is_valid_flag=pkg.iuse.is_valid_flag,
diff --git a/lib/portage/dep/__init__.py b/lib/portage/dep/__init__.py
index f08f6ba4c..72988357a 100644
--- a/lib/portage/dep/__init__.py
+++ b/lib/portage/dep/__init__.py
@@ -405,7 +405,8 @@ def paren_enclose(mylist, unevaluated_atom=False, opconvert=False):
return " ".join(mystrparts)
def use_reduce(depstr, uselist=(), masklist=(), matchall=False, excludeall=(), is_src_uri=False, \
- eapi=None, opconvert=False, flat=False, is_valid_flag=None, token_class=None, matchnone=False):
+ eapi=None, opconvert=False, flat=False, is_valid_flag=None, token_class=None, matchnone=False,
+ subset=None):
"""
Takes a dep string and reduces the use? conditionals out, leaving an array
with subarrays. All redundant brackets are removed.
@@ -434,6 +435,8 @@ def use_reduce(depstr, uselist=(), masklist=(), matchall=False, excludeall=(), i
@type token_class: Class
@param matchnone: Treat all conditionals as inactive. Used by digestgen().
@type matchnone: Bool
+ @param subset: Select a subset of dependencies conditional on the given flags
+ @type subset: Sequence
@rtype: List
@return: The use reduced depend array
"""
@@ -491,6 +494,45 @@ def use_reduce(depstr, uselist=(), masklist=(), matchall=False, excludeall=(), i
return (flag in uselist and not is_negated) or \
(flag not in uselist and is_negated)
+ if subset:
+ def select_subset(dep_struct, disjunction, selected):
+ result = []
+ stack = list(dep_struct)
+ stack.reverse()
+ while stack:
+ token = stack.pop()
+ try:
+ conditional = token.endswith('?')
+ except AttributeError:
+ if disjunction:
+ children = select_subset(token, False, selected)
+ if children:
+ result.append(children)
+ else:
+ result.extend(select_subset(token, False, selected))
+ else:
+ if conditional:
+ children = stack.pop()
+ if is_active(token):
+ if disjunction:
+ children = select_subset(children, False, selected or token[:-1] in subset)
+ if children:
+ result.append(children)
+ else:
+ result.extend(select_subset(children, False, selected or token[:-1] in subset))
+ elif token == '||':
+ children = select_subset(stack.pop(), True, selected)
+ if children:
+ if disjunction:
+ result.extend(children)
+ else:
+ result.append(token)
+ result.append(children)
+ elif selected:
+ result.append(token)
+ return result
+ depstr = paren_enclose(select_subset(paren_reduce(depstr, _deprecation_warn=False), False, False))
+
def missing_white_space_check(token, pos):
"""
Used to generate good error messages for invalid tokens.
diff --git a/lib/portage/tests/dep/test_use_reduce.py b/lib/portage/tests/dep/test_use_reduce.py
index 4f65567cf..d9ee5a309 100644
--- a/lib/portage/tests/dep/test_use_reduce.py
+++ b/lib/portage/tests/dep/test_use_reduce.py
@@ -9,7 +9,7 @@ class UseReduceTestCase(object):
def __init__(self, deparray, uselist=[], masklist=[],
matchall=0, excludeall=[], is_src_uri=False,
eapi='0', opconvert=False, flat=False, expected_result=None,
- is_valid_flag=None, token_class=None):
+ is_valid_flag=None, token_class=None, subset=None):
self.deparray = deparray
self.uselist = uselist
self.masklist = masklist
@@ -21,13 +21,15 @@ class UseReduceTestCase(object):
self.flat = flat
self.is_valid_flag = is_valid_flag
self.token_class = token_class
+ self.subset = subset
self.expected_result = expected_result
def run(self):
try:
return use_reduce(self.deparray, self.uselist, self.masklist,
self.matchall, self.excludeall, self.is_src_uri, self.eapi,
- self.opconvert, self.flat, self.is_valid_flag, self.token_class)
+ self.opconvert, self.flat, self.is_valid_flag, self.token_class,
+ subset=self.subset)
except InvalidDependString as e:
raise InvalidDependString("%s: %s" % (e, self.deparray))
@@ -50,6 +52,72 @@ class UseReduce(TestCase):
uselist=["a", "b", "c", "d"],
expected_result=["A", "B"]
),
+ UseReduceTestCase(
+ "a? ( A ) b? ( B ) !c? ( C ) !d? ( D )",
+ uselist=["a", "b", "c", "d"],
+ subset=["b"],
+ expected_result=["B"]
+ ),
+ UseReduceTestCase(
+ "bar? ( || ( foo bar? ( baz ) ) )",
+ uselist=["bar"],
+ subset=["bar"],
+ expected_result=['||', ['foo', 'baz']]
+ ),
+ UseReduceTestCase(
+ "bar? ( foo bar? ( baz ) foo )",
+ uselist=["bar"],
+ subset=["bar"],
+ expected_result=['foo', 'baz', 'foo']
+ ),
+ UseReduceTestCase(
+ "|| ( ( a b ) ( c d ) )",
+ uselist=[],
+ subset=["bar"],
+ expected_result=[]
+ ),
+ UseReduceTestCase(
+ "|| ( ( a b ) ( bar? ( c d ) e f ) )",
+ uselist=["bar"],
+ subset=["bar"],
+ expected_result=['c', 'd']
+ ),
+ UseReduceTestCase(
+ "( a b ) ( c d bar? ( e f baz? ( g h ) ) )",
+ uselist=["bar"],
+ subset=["bar"],
+ expected_result=['e', 'f']
+ ),
+ UseReduceTestCase(
+ "( a b ) ( c d bar? ( e f baz? ( g h ) ) )",
+ uselist=["bar", "baz"],
+ subset=["bar"],
+ expected_result=['e', 'f', 'g', 'h']
+ ),
+ UseReduceTestCase(
+ "( bar? ( a b ) ( bar? ( c d ) ) ) ( e f )",
+ uselist=["bar"],
+ subset=["bar"],
+ expected_result=['a', 'b', 'c', 'd']
+ ),
+ UseReduceTestCase(
+ "|| ( foo bar? ( baz ) )",
+ uselist=["bar"],
+ subset=["bar"],
+ expected_result=["baz"]
+ ),
+ UseReduceTestCase(
+ "|| ( || ( bar? ( a || ( b c || ( d e ) ) ) ) )",
+ uselist=["bar"],
+ subset=["bar"],
+ expected_result=['a', '||', ['b', 'c', 'd', 'e']]
+ ),
+ UseReduceTestCase(
+ "|| ( || ( bar? ( a || ( ( b c ) ( d e ) ) ) ) )",
+ uselist=["bar"],
+ subset=["bar"],
+ expected_result=['a', '||', [['b', 'c'], ['d', 'e']]]
+ ),
UseReduceTestCase(
"a? ( A ) b? ( B ) !c? ( C ) !d? ( D )",
uselist=["a", "b", "c"],
diff --git a/lib/portage/tests/resolver/test_with_test_deps.py b/lib/portage/tests/resolver/test_with_test_deps.py
index 5bfc6a8a2..d88e3cb6e 100644
--- a/lib/portage/tests/resolver/test_with_test_deps.py
+++ b/lib/portage/tests/resolver/test_with_test_deps.py
@@ -21,7 +21,27 @@ class WithTestDepsTestCase(TestCase):
},
"app-misc/C-0": {
"EAPI": "5",
- }
+ },
+ "app-misc/D-0": {
+ "EAPI": "5",
+ "IUSE": "test",
+ "DEPEND": "test? ( app-misc/E )"
+ },
+ "app-misc/E-0": {
+ "EAPI": "5",
+ "IUSE": "test",
+ "DEPEND": "test? ( app-misc/D )"
+ },
+ "app-misc/F-0": {
+ "EAPI": "5",
+ "IUSE": "+test",
+ "DEPEND": "test? ( app-misc/G )"
+ },
+ "app-misc/G-0": {
+ "EAPI": "5",
+ "IUSE": "+test",
+ "DEPEND": "test? ( app-misc/F )"
+ },
}
test_cases = (
@@ -32,6 +52,23 @@ class WithTestDepsTestCase(TestCase):
success = True,
options = { "--onlydeps": True, "--with-test-deps": True },
mergelist = ["app-misc/B-0"]),
+
+ # Test that --with-test-deps allows circular dependencies.
+ ResolverPlaygroundTestCase(
+ ['app-misc/D'],
+ success = True,
+ options = {'--with-test-deps': True},
+ mergelist = [('app-misc/D-0', 'app-misc/E-0')],
+ ambiguous_merge_order=True),
+
+ # Test that --with-test-deps does not allow circular dependencies
+ # when USE=test is explicitly enabled.
+ ResolverPlaygroundTestCase(
+ ['app-misc/F'],
+ success = False,
+ options = {'--with-test-deps': True},
+ circular_dependency_solutions = {'app-misc/G-0': {frozenset({('test', False)})}, 'app-misc/F-0': {frozenset({('test', False)})}},
+ )
)
playground = ResolverPlayground(ebuilds=ebuilds, debug=False)
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2019-12-23 22:47 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-12-23 22:47 [gentoo-commits] proj/portage:master commit in: lib/portage/tests/resolver/, lib/portage/dep/, lib/_emerge/, Zac Medico
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox