From: "Zac Medico" <zmedico@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Subject: [gentoo-commits] proj/portage:master commit in: lib/_emerge/, lib/portage/tests/resolver/
Date: Wed, 6 Dec 2023 20:29:49 +0000 (UTC) [thread overview]
Message-ID: <1701894194.1d856747ada48f8d32c033091b1156cc655efed3.zmedico@gentoo> (raw)
commit: 1d856747ada48f8d32c033091b1156cc655efed3
Author: Zac Medico <zmedico <AT> gentoo <DOT> org>
AuthorDate: Wed Dec 6 06:05:46 2023 +0000
Commit: Zac Medico <zmedico <AT> gentoo <DOT> org>
CommitDate: Wed Dec 6 20:23:14 2023 +0000
URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=1d856747
DepPriority{Normal,Satisfied}Range: weaken _ignore_runtime for cross root
When the dependency parent is for a cross root (ROOT != /) package,
weaken _ignore_runtime in order to tolerate runtime cycles that are
less problematic for cross root packages.
The included test case fails with this error without the fix:
* Error: circular dependencies:
(dev-libs/gmp-6.3.0:0/10.4::test_repo, binary scheduled for merge to '/tmp/tmp25nwdjn7/cross_root/') depends on
(sys-devel/gcc-13.2.1_p20230826:0/0::test_repo, binary scheduled for merge to '/tmp/tmp25nwdjn7/cross_root/') (runtime)
(dev-libs/gmp-6.3.0:0/10.4::test_repo, binary scheduled for merge to '/tmp/tmp25nwdjn7/cross_root/') (runtime_slot_op)
It might be possible to break this cycle
by applying the following change:
- dev-libs/gmp-6.3.0 (Change USE: -cxx)
Bug: https://bugs.gentoo.org/919174
Signed-off-by: Zac Medico <zmedico <AT> gentoo.org>
lib/_emerge/DepPriority.py | 4 +-
lib/_emerge/DepPriorityNormalRange.py | 4 +-
lib/_emerge/DepPrioritySatisfiedRange.py | 1 +
lib/_emerge/UnmergeDepPriority.py | 3 +-
lib/_emerge/depgraph.py | 46 ++++--
lib/portage/tests/resolver/meson.build | 1 +
.../tests/resolver/test_cross_dep_priority.py | 164 +++++++++++++++++++++
7 files changed, 208 insertions(+), 15 deletions(-)
diff --git a/lib/_emerge/DepPriority.py b/lib/_emerge/DepPriority.py
index 99d38477e2..8d282b937a 100644
--- a/lib/_emerge/DepPriority.py
+++ b/lib/_emerge/DepPriority.py
@@ -1,11 +1,11 @@
-# Copyright 1999-2013 Gentoo Foundation
+# Copyright 1999-2023 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
from _emerge.AbstractDepPriority import AbstractDepPriority
class DepPriority(AbstractDepPriority):
- __slots__ = ("satisfied", "optional", "ignored")
+ __slots__ = ("cross", "ignored", "optional", "satisfied")
def __int__(self):
"""
diff --git a/lib/_emerge/DepPriorityNormalRange.py b/lib/_emerge/DepPriorityNormalRange.py
index d7e4381b47..cb0e6c26b1 100644
--- a/lib/_emerge/DepPriorityNormalRange.py
+++ b/lib/_emerge/DepPriorityNormalRange.py
@@ -1,4 +1,4 @@
-# Copyright 1999-2011 Gentoo Foundation
+# Copyright 1999-2023 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
from _emerge.DepPriority import DepPriority
@@ -41,7 +41,7 @@ class DepPriorityNormalRange:
# to adjust this appropriately. But only build time dependencies
# are optional right now, so it's not an issue as-is.
return bool(
- not priority.runtime_slot_op
+ not (priority.runtime_slot_op and not priority.cross)
and (priority.optional or not priority.buildtime)
)
diff --git a/lib/_emerge/DepPrioritySatisfiedRange.py b/lib/_emerge/DepPrioritySatisfiedRange.py
index 0d42e7613d..b3bc90c2ff 100644
--- a/lib/_emerge/DepPrioritySatisfiedRange.py
+++ b/lib/_emerge/DepPrioritySatisfiedRange.py
@@ -96,6 +96,7 @@ class DepPrioritySatisfiedRange:
(
(not priority.runtime_slot_op)
or (priority.satisfied and priority.runtime_slot_op)
+ or priority.cross
)
and (priority.satisfied or priority.optional or not priority.buildtime)
)
diff --git a/lib/_emerge/UnmergeDepPriority.py b/lib/_emerge/UnmergeDepPriority.py
index ff81eff46f..d818bad1b8 100644
--- a/lib/_emerge/UnmergeDepPriority.py
+++ b/lib/_emerge/UnmergeDepPriority.py
@@ -1,4 +1,4 @@
-# Copyright 1999-2013 Gentoo Foundation
+# Copyright 1999-2023 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
from _emerge.AbstractDepPriority import AbstractDepPriority
@@ -6,6 +6,7 @@ from _emerge.AbstractDepPriority import AbstractDepPriority
class UnmergeDepPriority(AbstractDepPriority):
__slots__ = (
+ "cross",
"ignored",
"optional",
"satisfied",
diff --git a/lib/_emerge/depgraph.py b/lib/_emerge/depgraph.py
index 9b09701021..59c78c7354 100644
--- a/lib/_emerge/depgraph.py
+++ b/lib/_emerge/depgraph.py
@@ -3630,7 +3630,7 @@ class depgraph:
blocker=False,
depth=depth,
parent=pkg,
- priority=self._priority(runtime=True),
+ priority=self._priority(cross=self._cross(pkg.root), runtime=True),
root=pkg.root,
)
if not self._add_dep(dep, allow_unsatisfied=allow_unsatisfied):
@@ -3968,17 +3968,26 @@ class depgraph:
# _dep_disjunctive_stack first, so that choices for build-time
# deps influence choices for run-time deps (bug 639346).
deps = (
- (myroot, edepend["RDEPEND"], self._priority(runtime=True)),
+ (
+ myroot,
+ edepend["RDEPEND"],
+ self._priority(cross=self._cross(pkg.root), runtime=True),
+ ),
(
self._frozen_config._running_root.root,
edepend["IDEPEND"],
- self._priority(runtime=True),
+ self._priority(cross=self._cross(pkg.root), runtime=True),
+ ),
+ (
+ myroot,
+ edepend["PDEPEND"],
+ self._priority(cross=self._cross(pkg.root), runtime_post=True),
),
- (myroot, edepend["PDEPEND"], self._priority(runtime_post=True)),
(
depend_root,
edepend["DEPEND"],
self._priority(
+ cross=self._cross(pkg.root),
buildtime=True,
optional=(pkg.built or ignore_depend_deps),
ignored=ignore_depend_deps,
@@ -3988,6 +3997,7 @@ class depgraph:
self._frozen_config._running_root.root,
edepend["BDEPEND"],
self._priority(
+ cross=self._cross(pkg.root),
buildtime=True,
optional=(pkg.built or ignore_bdepend_deps),
ignored=ignore_bdepend_deps,
@@ -4036,7 +4046,9 @@ class depgraph:
self._queue_disjunctive_deps(
pkg,
dep_root,
- self._priority(runtime_post=True),
+ self._priority(
+ cross=self._cross(pkg.root), runtime_post=True
+ ),
test_deps,
)
)
@@ -4044,7 +4056,9 @@ class depgraph:
if test_deps and not self._add_pkg_dep_string(
pkg,
dep_root,
- self._priority(runtime_post=True),
+ self._priority(
+ cross=self._cross(pkg.root), runtime_post=True
+ ),
test_deps,
allow_unsatisfied,
):
@@ -4359,7 +4373,10 @@ class depgraph:
return 0
for atom, child in self._minimize_children(
- pkg, self._priority(runtime=True), root_config, atoms
+ pkg,
+ self._priority(cross=self._cross(pkg.root), runtime=True),
+ root_config,
+ atoms,
):
# If this was a specially generated virtual atom
# from dep_check, map it back to the original, in
@@ -4369,7 +4386,7 @@ class depgraph:
atom = getattr(atom, "_orig_atom", atom)
# This is a GLEP 37 virtual, so its deps are all runtime.
- mypriority = self._priority(runtime=True)
+ mypriority = self._priority(cross=self._cross(pkg.root), runtime=True)
if not atom.blocker:
inst_pkgs = [
inst_pkg
@@ -4616,6 +4633,13 @@ class depgraph:
priority_constructor = DepPriority
return priority_constructor(**kwargs)
+ def _cross(self, eroot):
+ """
+ Returns True if the ROOT for the given EROOT is not /,
+ or EROOT is cross-prefix.
+ """
+ return eroot != self._frozen_config._running_root.root
+
def _dep_expand(self, root_config, atom_without_category):
"""
@param root_config: a root config instance
@@ -5788,7 +5812,9 @@ class depgraph:
node_priority = priority.copy()
else:
# virtuals only have runtime deps
- node_priority = self._priority(runtime=True)
+ node_priority = self._priority(
+ cross=self._cross(node_parent.root), runtime=True
+ )
k = Dependency(
atom=parent_atom,
@@ -5874,7 +5900,7 @@ class depgraph:
pkg._metadata.get("RDEPEND", ""),
myuse=self._pkg_use_enabled(pkg),
parent=pkg,
- priority=self._priority(runtime=True),
+ priority=self._priority(cross=self._cross(pkg.root), runtime=True),
)
except InvalidDependString as e:
if not pkg.installed:
diff --git a/lib/portage/tests/resolver/meson.build b/lib/portage/tests/resolver/meson.build
index 770027ac47..77c65a511e 100644
--- a/lib/portage/tests/resolver/meson.build
+++ b/lib/portage/tests/resolver/meson.build
@@ -21,6 +21,7 @@ py.install_sources(
'test_circular_dependencies.py',
'test_complete_graph.py',
'test_complete_if_new_subslot_without_revbump.py',
+ 'test_cross_dep_priority.py',
'test_depclean.py',
'test_depclean_order.py',
'test_depclean_slot_unavailable.py',
diff --git a/lib/portage/tests/resolver/test_cross_dep_priority.py b/lib/portage/tests/resolver/test_cross_dep_priority.py
new file mode 100644
index 0000000000..10f2eb36e2
--- /dev/null
+++ b/lib/portage/tests/resolver/test_cross_dep_priority.py
@@ -0,0 +1,164 @@
+# Copyright 2023 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+import shutil
+import subprocess
+import os
+
+import portage
+from portage.tests import TestCase
+from portage.tests.resolver.ResolverPlayground import (
+ ResolverPlayground,
+ ResolverPlaygroundTestCase,
+)
+
+
+class CrossDepPriorityTestCase(TestCase):
+ def testCrossDepPriority(self):
+ """
+ Test bug 919174, where cross-root merge to an empty root
+ failed due to circular dependencies.
+ """
+ ebuilds = {
+ "dev-lang/python-3.11.6": {
+ "EAPI": "8",
+ "DEPEND": "sys-apps/util-linux:=",
+ "RDEPEND": "sys-apps/util-linux:=",
+ },
+ "sys-apps/util-linux-2.38.1-r2": {
+ "EAPI": "8",
+ "DEPEND": "selinux? ( >=sys-libs/libselinux-2.2.2-r4 )",
+ "RDEPEND": "selinux? ( >=sys-libs/libselinux-2.2.2-r4 )",
+ "IUSE": "selinux",
+ },
+ "sys-libs/libselinux-3.5-r1": {
+ "EAPI": "8",
+ "DEPEND": "python? ( dev-lang/python )",
+ "RDEPEND": "python? ( dev-lang/python )",
+ "IUSE": "python",
+ },
+ "dev-libs/gmp-6.3.0": {
+ "EAPI": "8",
+ "SLOT": "0/10.4",
+ "DEPEND": "cxx? ( sys-devel/gcc )",
+ "RDEPEND": "cxx? ( sys-devel/gcc )",
+ "IUSE": "cxx",
+ },
+ "sys-devel/gcc-13.2.1_p20230826": {
+ "EAPI": "8",
+ "DEPEND": ">=dev-libs/gmp-4.3.2:0=",
+ "RDEPEND": ">=dev-libs/gmp-4.3.2:0=",
+ },
+ }
+
+ installed = {
+ "dev-lang/python-3.11.6": {
+ "EAPI": "8",
+ "KEYWORDS": "x86",
+ "DEPEND": "sys-apps/util-linux:0/0=",
+ "RDEPEND": "sys-apps/util-linux:0/0=",
+ },
+ "sys-apps/util-linux-2.38.1-r2": {
+ "EAPI": "8",
+ "KEYWORDS": "x86",
+ "DEPEND": "selinux? ( >=sys-libs/libselinux-2.2.2-r4 )",
+ "RDEPEND": "selinux? ( >=sys-libs/libselinux-2.2.2-r4 )",
+ "IUSE": "selinux",
+ "USE": "selinux",
+ },
+ "sys-libs/libselinux-3.5-r1": {
+ "EAPI": "8",
+ "KEYWORDS": "x86",
+ "DEPEND": "python? ( dev-lang/python )",
+ "RDEPEND": "python? ( dev-lang/python )",
+ "IUSE": "python",
+ "USE": "python",
+ },
+ "dev-libs/gmp-6.3.0": {
+ "EAPI": "8",
+ "KEYWORDS": "x86",
+ "SLOT": "0/10.4",
+ "DEPEND": "cxx? ( sys-devel/gcc )",
+ "RDEPEND": "cxx? ( sys-devel/gcc )",
+ "IUSE": "cxx",
+ "USE": "cxx",
+ },
+ "sys-devel/gcc-13.2.1_p20230826": {
+ "EAPI": "8",
+ "KEYWORDS": "x86",
+ "DEPEND": ">=dev-libs/gmp-4.3.2:0/10.4=",
+ "RDEPEND": ">=dev-libs/gmp-4.3.2:0/10.4=",
+ },
+ }
+
+ world = [
+ "sys-apps/util-linux",
+ "sys-devel/gcc",
+ ]
+
+ user_config = {
+ "make.conf": ('USE="cxx python selinux"',),
+ }
+
+ test_cases = (
+ ResolverPlaygroundTestCase(
+ ["@world"],
+ options={"--emptytree": True},
+ success=True,
+ mergelist=[
+ "dev-libs/gmp-6.3.0",
+ "sys-devel/gcc-13.2.1_p20230826",
+ "sys-apps/util-linux-2.38.1-r2",
+ "dev-lang/python-3.11.6",
+ "sys-libs/libselinux-3.5-r1",
+ ],
+ ),
+ )
+
+ playground = ResolverPlayground(
+ ebuilds=ebuilds,
+ installed=installed,
+ world=world,
+ user_config=user_config,
+ )
+ try:
+ for test_case in test_cases:
+ playground.run_TestCase(test_case)
+ self.assertEqual(test_case.test_success, True, test_case.fail_msg)
+
+ # Since ResolverPlayground does not internally support
+ # cross-root, test with emerge.
+ cross_root = os.path.join(playground.settings["EPREFIX"], "cross_root")
+ world_file = os.path.join(
+ cross_root,
+ playground.settings["EPREFIX"].lstrip(os.sep),
+ portage.const.WORLD_FILE,
+ )
+ os.makedirs(os.path.dirname(world_file))
+ shutil.copy(
+ os.path.join(playground.settings["EPREFIX"], portage.const.WORLD_FILE),
+ world_file,
+ )
+ result = subprocess.run(
+ [
+ "emerge",
+ f"--root={cross_root}",
+ "--pretend",
+ "--verbose",
+ "--usepkgonly",
+ "--quickpkg-direct=y",
+ "@world",
+ ],
+ env=playground.settings.environ(),
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ )
+ output = result.stdout.decode(errors="replace")
+ try:
+ self.assertTrue("5 packages (5 new, 5 binaries)" in output)
+ self.assertEqual(result.returncode, os.EX_OK)
+ except Exception:
+ print(output)
+ raise
+ finally:
+ playground.cleanup()
next reply other threads:[~2023-12-06 20:29 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-12-06 20:29 Zac Medico [this message]
-- strict thread matches above, loose matches on Subject: below --
2024-05-26 18:48 [gentoo-commits] proj/portage:master commit in: lib/_emerge/, lib/portage/tests/resolver/ Zac Medico
2023-12-24 19:30 Zac Medico
2023-11-28 22:42 Zac Medico
2023-11-28 22:26 Sam James
2023-11-28 4:20 Zac Medico
2023-11-19 17:56 Zac Medico
2023-06-16 3:34 Sam James
2023-06-16 3:34 Sam James
2020-11-22 6:13 Zac Medico
2020-09-21 5:39 Zac Medico
2020-02-15 0:05 Zac Medico
2019-09-12 1:51 Zac Medico
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1701894194.1d856747ada48f8d32c033091b1156cc655efed3.zmedico@gentoo \
--to=zmedico@gentoo.org \
--cc=gentoo-commits@lists.gentoo.org \
--cc=gentoo-dev@lists.gentoo.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox