[gentoo-commits] proj/portage:master commit in: lib/_emerge/, lib/portage/tests/resolver/

2024-05-26 Thread Zac Medico
commit: 96e4f95cc8c0d544d375b28394dafe8809c4bc9b
Author: Zac Medico  gentoo  org>
AuthorDate: Sun May 26 18:23:27 2024 +
Commit: Zac Medico  gentoo  org>
CommitDate: Sun May 26 18:34:04 2024 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=96e4f95c

Revert "find_smallest_cycle: Optimize to traverse fewer nodes"

This reverts commit 49e01d041c74680a81860b819daff812d83df02f
in order to fix bug 922629. Later we can try to optimize it
again but without breaking testTarMergeOrder.

Bug: https://bugs.gentoo.org/922629
Signed-off-by: Zac Medico  gentoo.org>

 lib/_emerge/depgraph.py| 36 ++
 .../tests/resolver/test_rebuild_ghostscript.py |  2 +-
 .../resolver/test_runtime_cycle_merge_order.py |  7 ++---
 lib/portage/tests/resolver/test_tar_merge_order.py |  4 ++-
 4 files changed, 9 insertions(+), 40 deletions(-)

diff --git a/lib/_emerge/depgraph.py b/lib/_emerge/depgraph.py
index 6b91d5c42d..3adc04bcfb 100644
--- a/lib/_emerge/depgraph.py
+++ b/lib/_emerge/depgraph.py
@@ -9313,14 +9313,7 @@ class depgraph:
 
 asap_nodes.extend(libc_pkgs)
 
-def gather_deps(
-ignore_priority,
-mergeable_nodes,
-selected_nodes,
-node,
-smallest_cycle=None,
-traversed_nodes=None,
-):
+def gather_deps(ignore_priority, mergeable_nodes, selected_nodes, 
node):
 """
 Recursively gather a group of nodes that RDEPEND on
 eachother. This ensures that they are merged as a group
@@ -9340,24 +9333,10 @@ class depgraph:
 # RDEPENDs installed first, but ignore uninstalls
 # (these occur when new portage blocks an older package 
version).
 return False
-if traversed_nodes is not None:
-if node in traversed_nodes:
-# Identical to a previously traversed cycle.
-return False
-traversed_nodes.add(node)
 selected_nodes.add(node)
-if smallest_cycle is not None and len(selected_nodes) >= len(
-smallest_cycle
-):
-return False
 for child in mygraph.child_nodes(node, 
ignore_priority=ignore_priority):
 if not gather_deps(
-ignore_priority,
-mergeable_nodes,
-selected_nodes,
-child,
-smallest_cycle=smallest_cycle,
-traversed_nodes=traversed_nodes,
+ignore_priority, mergeable_nodes, selected_nodes, child
 ):
 return False
 return True
@@ -9515,21 +9494,12 @@ class depgraph:
 local_priority_range.MEDIUM_SOFT + 1,
 )
 ):
-# Traversed nodes for current priority
-traversed_nodes = set()
 for node in nodes:
 if not mygraph.parent_nodes(node):
 continue
-if node in traversed_nodes:
-continue
 selected_nodes = set()
 if gather_deps(
-priority,
-mergeable_nodes,
-selected_nodes,
-node,
-smallest_cycle=smallest_cycle,
-traversed_nodes=traversed_nodes,
+priority, mergeable_nodes, selected_nodes, node
 ):
 if smallest_cycle is None or 
len(selected_nodes) < len(
 smallest_cycle

diff --git a/lib/portage/tests/resolver/test_rebuild_ghostscript.py 
b/lib/portage/tests/resolver/test_rebuild_ghostscript.py
index 8ee3349d6f..dad6a21322 100644
--- a/lib/portage/tests/resolver/test_rebuild_ghostscript.py
+++ b/lib/portage/tests/resolver/test_rebuild_ghostscript.py
@@ -137,9 +137,9 @@ class RebuildGhostscriptTestCase(TestCase):
 mergelist=[
 "sys-apps/dbus-1.15.6",
 "x11-libs/gtk+-3.24.38",
-"app-text/ghostscript-gpl-10.01.2",
 "net-dns/avahi-0.8-r7",
 "net-print/cups-2.4.6",
+"app-text/ghostscript-gpl-10.01.2",
 "app-text/libspectre-0.2.12",
 "x11-libs/goffice-0.10.55",
 ],

diff --git a/lib/portage/tests/resolver/test_runtime_cycle_merge_order.py 
b/lib/portage/tests/resolver/test_runtime_cycle_merge_order.py
index ed329aa097..a695b25198 100644
--- 

[gentoo-commits] proj/portage:master commit in: lib/_emerge/, lib/portage/tests/resolver/

2023-12-24 Thread Zac Medico
commit: bf3d091de8702f0c95e5530d03c6e925008ee80a
Author: Zac Medico  gentoo  org>
AuthorDate: Sun Dec 24 05:12:55 2023 +
Commit: Zac Medico  gentoo  org>
CommitDate: Sun Dec 24 19:29:25 2023 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=bf3d091d

depclean: drop direct circular deps in merge order calculation

Drop direct circular deps in the depclean merge order calculation,
since it does not handle them well as shown by the test case
for bug 916135.

Bug: https://bugs.gentoo.org/916135
Signed-off-by: Zac Medico  gentoo.org>

 lib/_emerge/actions.py|  8 ++--
 lib/portage/tests/resolver/test_depclean_order.py | 10 ++
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/lib/_emerge/actions.py b/lib/_emerge/actions.py
index 86ba7f77a5..13bb75931c 100644
--- a/lib/_emerge/actions.py
+++ b/lib/_emerge/actions.py
@@ -1,4 +1,4 @@
-# Copyright 1999-2021 Gentoo Authors
+# Copyright 1999-2023 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 import collections
@@ -1642,7 +1642,11 @@ def _calc_depclean(settings, trees, ldpath_mtimes, 
myopts, action, args_set, spi
 if mypriority.runtime:
 mypriority.runtime_slot_op = True
 
-graph.add(child_node, node, priority=mypriority)
+# Drop direct circular deps because the unmerge 
order
+# calculation does not handle them well as 
demonstrated
+# by the test case for bug 916135.
+if child_node is not node:
+graph.add(child_node, node, 
priority=mypriority)
 
 if debug:
 writemsg_level("\nunmerge digraph:\n\n", noiselevel=-1, 
level=logging.DEBUG)

diff --git a/lib/portage/tests/resolver/test_depclean_order.py 
b/lib/portage/tests/resolver/test_depclean_order.py
index 867b1a54ca..23b5e755c3 100644
--- a/lib/portage/tests/resolver/test_depclean_order.py
+++ b/lib/portage/tests/resolver/test_depclean_order.py
@@ -1,8 +1,6 @@
-# Copyright 2013 Gentoo Foundation
+# Copyright 2013-2023 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
-import pytest
-
 from portage.tests import TestCase
 from portage.tests.resolver.ResolverPlayground import (
 ResolverPlayground,
@@ -60,8 +58,12 @@ class SimpleDepcleanTestCase(TestCase):
 finally:
 playground.cleanup()
 
-@pytest.mark.xfail()
 def testIDEPENDDepclean(self):
+"""
+Test for bug 916135, where a direct circular dependency caused
+the unmerge order to fail to account for IDEPEND.
+"""
+
 ebuilds = {
 "dev-util/A-1": {},
 "dev-libs/B-1": {



[gentoo-commits] proj/portage:master commit in: lib/_emerge/, lib/portage/tests/resolver/

2023-12-06 Thread Zac Medico
commit: 1d856747ada48f8d32c033091b1156cc655efed3
Author: Zac Medico  gentoo  org>
AuthorDate: Wed Dec  6 06:05:46 2023 +
Commit: Zac Medico  gentoo  org>
CommitDate: Wed Dec  6 20:23:14 2023 +
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  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 

[gentoo-commits] proj/portage:master commit in: lib/_emerge/, lib/portage/tests/resolver/

2023-11-28 Thread Zac Medico
commit: 3487594cd8f46a5c83caaab3a9425321443e5efc
Author: Zac Medico  gentoo  org>
AuthorDate: Tue Nov 28 04:58:07 2023 +
Commit: Zac Medico  gentoo  org>
CommitDate: Tue Nov 28 22:41:45 2023 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=3487594c

Increase ignore_priority during topological sort for runtime cycle

Fix AlternativesGzipTestCase by increasing ignore_priority in
order to find smaller groups of leaf nodes during topological
sort for runtime cycles. This causes some changes in merge
order for MergeOrderTestCase, but they appear to be acceptable
since they prevent temporarily unsatisfied RDEPEND by relying
on satisfied installed build-time dependencies.

Bug: https://bugs.gentoo.org/917259
Signed-off-by: Zac Medico  gentoo.org>

 lib/_emerge/depgraph.py| 27 --
 .../tests/resolver/test_alternatives_gzip.py   |  8 +++
 lib/portage/tests/resolver/test_merge_order.py | 20 
 .../tests/resolver/test_rebuild_ghostscript.py |  2 +-
 4 files changed, 35 insertions(+), 22 deletions(-)

diff --git a/lib/_emerge/depgraph.py b/lib/_emerge/depgraph.py
index 29eadba3d1..da37f980ad 100644
--- a/lib/_emerge/depgraph.py
+++ b/lib/_emerge/depgraph.py
@@ -9478,17 +9478,30 @@ class depgraph:
 )
 selected_nodes = []
 while cycle_digraph:
+# Increase ignore_priority in order to find
+# smaller groups of leaf nodes. This solves
+# bug 917259 which happened because too many
+# leaves were selected at once.
+smallest_leaves = None
 for ignore_priority in ignore_priorities:
 leaves = cycle_digraph.leaf_nodes(
 ignore_priority=ignore_priority
 )
-if leaves:
-cycle_digraph.difference_update(leaves)
-selected_nodes.extend(leaves)
-break
-else:
-selected_nodes.extend(cycle_digraph)
-break
+if leaves and (
+smallest_leaves is None
+or len(leaves) < len(smallest_leaves)
+):
+smallest_leaves = leaves
+if len(smallest_leaves) == 1:
+break
+
+if smallest_leaves is None:
+smallest_leaves = [cycle_digraph.order[-1]]
+
+# Only harvest one node at a time, in order to
+# minimize the number of ignored dependencies.
+cycle_digraph.remove(smallest_leaves[0])
+selected_nodes.append(smallest_leaves[0])
 
 if not selected_nodes and myblocker_uninstalls:
 # An Uninstall task needs to be executed in order to

diff --git a/lib/portage/tests/resolver/test_alternatives_gzip.py 
b/lib/portage/tests/resolver/test_alternatives_gzip.py
index 602ed1756f..e763e84640 100644
--- a/lib/portage/tests/resolver/test_alternatives_gzip.py
+++ b/lib/portage/tests/resolver/test_alternatives_gzip.py
@@ -1,8 +1,6 @@
 # Copyright 2023 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
-import pytest
-
 from portage.tests import TestCase
 from portage.tests.resolver.ResolverPlayground import (
 ResolverPlayground,
@@ -10,7 +8,6 @@ from portage.tests.resolver.ResolverPlayground import (
 )
 
 
-@pytest.mark.xfail()
 class AlternativesGzipTestCase(TestCase):
 def testAlternativesGzip(self):
 """
@@ -19,8 +16,9 @@ class AlternativesGzipTestCase(TestCase):
 find_smallest_cycle selects a large cycle and the topological
 sort produces poor results when leaf_nodes returns
 app-alternatives/gzip as part of a large group of nodes.
-This problem might be solved by implementing a finer-grained
-ignore_priority for leaf_nodes calls.
+This problem was solved by changing the topological sort to
+increase ignore_priority in order to select a smaller number
+of leaf nodes at a time.
 """
 ebuilds = {
 "app-alternatives/gzip-1": {

diff --git a/lib/portage/tests/resolver/test_merge_order.py 
b/lib/portage/tests/resolver/test_merge_order.py
index 940eb3bbbe..e6d45c847b 100644
--- a/lib/portage/tests/resolver/test_merge_order.py
+++ b/lib/portage/tests/resolver/test_merge_order.py
@@ -1,4 +1,4 @@
-# Copyright 2011-2020 Gentoo Authors
+# Copyright 2011-2023 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 from portage.tests import TestCase
@@ -382,10 +382,12 @@ class MergeOrderTestCase(TestCase):
 ambiguous_merge_order=True,
 

[gentoo-commits] proj/portage:master commit in: lib/_emerge/, lib/portage/tests/resolver/

2023-11-28 Thread Sam James
commit: 2e298ea7ba36801a1cfba6e4cbfc16a7c05ee73d
Author: Sam James  gentoo  org>
AuthorDate: Tue Nov 28 06:22:44 2023 +
Commit: Sam James  gentoo  org>
CommitDate: Tue Nov 28 22:07:46 2023 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=2e298ea7

DepPriority{Normal,Satisfied}Range: strengthen _ignore_runtime for runtime slot 
operators

In the reported bug, net-misc/curl gets merged (binary), then dev-util/cmake 
gets
bulit (from source) which fails because one of the built curl's dependencies
(net-libs/nghttp2) is missing:
```
[binary   R] net-misc/curl-8.4.0::test_repo  USE="http2%*" 0 KiB
[ebuild U  ] dev-util/cmake-3.27.8::test_repo [3.26.5-r2::test_repo] 0 KiB
[ebuild  N ] net-libs/nghttp2-1.57.0::test_repo  0 KiB
```

Zac had the idea [0] of strengthening _ignore_runtime to consider runtime slot 
deps
as well, so we now get:
```
[ebuild U  ] dev-util/cmake-3.27.8::test_repo [3.26.5-r2::test_repo] 0 KiB
[ebuild  N ] net-libs/nghttp2-1.57.0::test_repo  0 KiB
[binary   R] net-misc/curl-8.4.0::test_repo  USE="http2%*" 0 KiB
```

For DepPrioritySatisfiedRange, we now allow ignoring the dep if:
* it's either a satisfied runtime slot dep, or it's not a runtime slot dep at 
all, and
* the dep is satisfied or it's optional/not a build time dep.

(i.e. we now prevent ignoring the slot dep unless it's satisfied.)

For DepPriorityNormalRange, we now allow ignoring the dep if:
* it's not a runtime slot dep, and
* it's optional, or
* it's not a buildtime dep.

(i.e. we now prevent ignoring the slot dep.)

We then realise we can't ignore curl's dep on nghttp2 and come up with a better 
order.

[0] https://github.com/gentoo/portage/pull/1193#issuecomment-1829178126

Bug: https://bugs.gentoo.org/918683
Thanks-to: Zac Medico  gentoo.org>
Signed-off-by: Sam James  gentoo.org>

 lib/_emerge/DepPriorityNormalRange.py   |  8 +++-
 lib/_emerge/DepPrioritySatisfiedRange.py| 13 +++--
 .../tests/resolver/test_runtime_cycle_merge_order.py|  9 -
 3 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/lib/_emerge/DepPriorityNormalRange.py 
b/lib/_emerge/DepPriorityNormalRange.py
index a85e1b9c14..d7e4381b47 100644
--- a/lib/_emerge/DepPriorityNormalRange.py
+++ b/lib/_emerge/DepPriorityNormalRange.py
@@ -37,7 +37,13 @@ class DepPriorityNormalRange:
 def _ignore_runtime(cls, priority):
 if priority.__class__ is not DepPriority:
 return False
-return bool(priority.optional or not priority.buildtime)
+# If we ever allow "optional" runtime_slot_op, we'll need
+# 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
+and (priority.optional or not priority.buildtime)
+)
 
 ignore_medium = _ignore_runtime
 ignore_medium_soft = _ignore_runtime_post

diff --git a/lib/_emerge/DepPrioritySatisfiedRange.py 
b/lib/_emerge/DepPrioritySatisfiedRange.py
index 0633a5e1c2..0d42e7613d 100644
--- a/lib/_emerge/DepPrioritySatisfiedRange.py
+++ b/lib/_emerge/DepPrioritySatisfiedRange.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.DepPriority import DepPriority
@@ -89,7 +89,16 @@ class DepPrioritySatisfiedRange:
 def _ignore_runtime(cls, priority):
 if priority.__class__ is not DepPriority:
 return False
-return bool(priority.satisfied or priority.optional or not 
priority.buildtime)
+# We could split this up into 2 variants (ignoring satisfied
+# runtime_slot_op, and not) if we need more granularity for 
ignore_priority
+# in future.
+return bool(
+(
+(not priority.runtime_slot_op)
+or (priority.satisfied and priority.runtime_slot_op)
+)
+and (priority.satisfied or priority.optional or not 
priority.buildtime)
+)
 
 ignore_medium = _ignore_runtime
 ignore_medium_soft = _ignore_satisfied_buildtime_slot_op

diff --git a/lib/portage/tests/resolver/test_runtime_cycle_merge_order.py 
b/lib/portage/tests/resolver/test_runtime_cycle_merge_order.py
index 26850ccad2..ed329aa097 100644
--- a/lib/portage/tests/resolver/test_runtime_cycle_merge_order.py
+++ b/lib/portage/tests/resolver/test_runtime_cycle_merge_order.py
@@ -1,4 +1,4 @@
-# Copyright 2016 Gentoo Foundation
+# Copyright 2016-2023 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 from portage.tests import TestCase
@@ -7,8 +7,6 @@ from portage.tests.resolver.ResolverPlayground import (
 ResolverPlaygroundTestCase,
 )
 
-import pytest
-
 
 class RuntimeCycleMergeOrderTestCase(TestCase):
 def testRuntimeCycleMergeOrder(self):
@@ -77,7 

[gentoo-commits] proj/portage:master commit in: lib/_emerge/, lib/portage/tests/resolver/

2023-11-27 Thread Zac Medico
commit: 49e01d041c74680a81860b819daff812d83df02f
Author: Zac Medico  gentoo  org>
AuthorDate: Tue Nov 28 03:42:17 2023 +
Commit: Zac Medico  gentoo  org>
CommitDate: Tue Nov 28 03:42:17 2023 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=49e01d04

find_smallest_cycle: Optimize to traverse fewer nodes

If gather_deps is traversing a cycle that is greater than
or equal to the size of the current smallest_cycle, then
abort early. Also abort early if we traverse a node
encountered in a previous cycle for the same ignore_priority,
since that means the two cycles are identical.

On my laptop, this brings the emerge -pe @world time down
to 3m28.884s, compared to 10m44.268s with portage-3.0.55.

Bug: https://bugs.gentoo.org/918682
Signed-off-by: Zac Medico  gentoo.org>

 lib/_emerge/depgraph.py| 36 --
 .../tests/resolver/test_rebuild_ghostscript.py |  2 +-
 .../resolver/test_runtime_cycle_merge_order.py |  7 +++--
 3 files changed, 39 insertions(+), 6 deletions(-)

diff --git a/lib/_emerge/depgraph.py b/lib/_emerge/depgraph.py
index e4305c18c9..29eadba3d1 100644
--- a/lib/_emerge/depgraph.py
+++ b/lib/_emerge/depgraph.py
@@ -9151,7 +9151,14 @@ class depgraph:
 
 asap_nodes.extend(libc_pkgs)
 
-def gather_deps(ignore_priority, mergeable_nodes, selected_nodes, 
node):
+def gather_deps(
+ignore_priority,
+mergeable_nodes,
+selected_nodes,
+node,
+smallest_cycle=None,
+traversed_nodes=None,
+):
 """
 Recursively gather a group of nodes that RDEPEND on
 eachother. This ensures that they are merged as a group
@@ -9171,10 +9178,24 @@ class depgraph:
 # RDEPENDs installed first, but ignore uninstalls
 # (these occur when new portage blocks an older package 
version).
 return False
+if traversed_nodes is not None:
+if node in traversed_nodes:
+# Identical to a previously traversed cycle.
+return False
+traversed_nodes.add(node)
 selected_nodes.add(node)
+if smallest_cycle is not None and len(selected_nodes) >= len(
+smallest_cycle
+):
+return False
 for child in mygraph.child_nodes(node, 
ignore_priority=ignore_priority):
 if not gather_deps(
-ignore_priority, mergeable_nodes, selected_nodes, child
+ignore_priority,
+mergeable_nodes,
+selected_nodes,
+child,
+smallest_cycle=smallest_cycle,
+traversed_nodes=traversed_nodes,
 ):
 return False
 return True
@@ -9332,12 +9353,21 @@ class depgraph:
 local_priority_range.MEDIUM_SOFT + 1,
 )
 ):
+# Traversed nodes for current priority
+traversed_nodes = set()
 for node in nodes:
 if not mygraph.parent_nodes(node):
 continue
+if node in traversed_nodes:
+continue
 selected_nodes = set()
 if gather_deps(
-priority, mergeable_nodes, selected_nodes, node
+priority,
+mergeable_nodes,
+selected_nodes,
+node,
+smallest_cycle=smallest_cycle,
+traversed_nodes=traversed_nodes,
 ):
 if smallest_cycle is None or 
len(selected_nodes) < len(
 smallest_cycle

diff --git a/lib/portage/tests/resolver/test_rebuild_ghostscript.py 
b/lib/portage/tests/resolver/test_rebuild_ghostscript.py
index 8d7cbb1f92..88dc2b5fc3 100644
--- a/lib/portage/tests/resolver/test_rebuild_ghostscript.py
+++ b/lib/portage/tests/resolver/test_rebuild_ghostscript.py
@@ -137,9 +137,9 @@ class RebuildGhostscriptTestCase(TestCase):
 mergelist=[
 "sys-apps/dbus-1.15.6",
 "x11-libs/gtk+-3.24.38",
+"app-text/ghostscript-gpl-10.01.2",
 "net-print/cups-2.4.6",
 "net-dns/avahi-0.8-r7",
-"app-text/ghostscript-gpl-10.01.2",
 "app-text/libspectre-0.2.12",
 "x11-libs/goffice-0.10.55",
 ],

diff --git a/lib/portage/tests/resolver/test_runtime_cycle_merge_order.py 

[gentoo-commits] proj/portage:master commit in: lib/_emerge/, lib/portage/tests/resolver/

2023-11-19 Thread Zac Medico
commit: 9206d5a75ecd2d9ae0fe63e57d28aa8061b5927e
Author: Zac Medico  gentoo  org>
AuthorDate: Sat Nov 18 17:07:59 2023 +
Commit: Zac Medico  gentoo  org>
CommitDate: Sun Nov 19 04:15:22 2023 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=9206d5a7

find_smallest_cycle: Increase ignore_priority to find smaller cycles

Fix AlternativesGzipTestCase by increasing ignore_priority in
order to find smaller cycles. This causes some changes in merge
order for MergeOrderTestCase, but they appear to be acceptable
since they prevent temporarily unsatisfied RDEPEND by relying
on satisfied installed build-time dependencies.

Add a test case for bug 690436, since the change to merge order
in MergeOrderTestCase is related (see commit 680276cc4d4f).

Bug: https://bugs.gentoo.org/690436
Bug: https://bugs.gentoo.org/917259
Signed-off-by: Zac Medico  gentoo.org>

 lib/_emerge/depgraph.py|   7 +-
 lib/portage/tests/resolver/meson.build |   1 +
 .../tests/resolver/test_alternatives_gzip.py   |   7 +-
 lib/portage/tests/resolver/test_merge_order.py |  24 ++--
 .../tests/resolver/test_rebuild_ghostscript.py | 160 +
 5 files changed, 180 insertions(+), 19 deletions(-)

diff --git a/lib/_emerge/depgraph.py b/lib/_emerge/depgraph.py
index e4305c18c9..0d3b37c698 100644
--- a/lib/_emerge/depgraph.py
+++ b/lib/_emerge/depgraph.py
@@ -9345,9 +9345,10 @@ class depgraph:
 smallest_cycle = selected_nodes
 ignore_priority = priority
 
-# Exit this loop with the lowest possible priority, 
which
-# minimizes the use of installed packages to break 
cycles.
-if smallest_cycle is not None:
+if smallest_cycle is not None and len(smallest_cycle) 
== 1:
+# The cycle can't get any smaller than this,
+# so there is no need to search further since
+# we try to minimize ignore_priority.
 break
 
 return smallest_cycle, ignore_priority

diff --git a/lib/portage/tests/resolver/meson.build 
b/lib/portage/tests/resolver/meson.build
index 7d2bd367d4..770027ac47 100644
--- a/lib/portage/tests/resolver/meson.build
+++ b/lib/portage/tests/resolver/meson.build
@@ -49,6 +49,7 @@ py.install_sources(
 'test_profile_default_eapi.py',
 'test_profile_package_set.py',
 'test_rebuild.py',
+'test_rebuild_ghostscript.py',
 'test_regular_slot_change_without_revbump.py',
 'test_required_use.py',
 'test_runtime_cycle_merge_order.py',

diff --git a/lib/portage/tests/resolver/test_alternatives_gzip.py 
b/lib/portage/tests/resolver/test_alternatives_gzip.py
index 602ed1756f..7cd1da25f1 100644
--- a/lib/portage/tests/resolver/test_alternatives_gzip.py
+++ b/lib/portage/tests/resolver/test_alternatives_gzip.py
@@ -1,8 +1,6 @@
 # Copyright 2023 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
-import pytest
-
 from portage.tests import TestCase
 from portage.tests.resolver.ResolverPlayground import (
 ResolverPlayground,
@@ -10,7 +8,6 @@ from portage.tests.resolver.ResolverPlayground import (
 )
 
 
-@pytest.mark.xfail()
 class AlternativesGzipTestCase(TestCase):
 def testAlternativesGzip(self):
 """
@@ -19,8 +16,8 @@ class AlternativesGzipTestCase(TestCase):
 find_smallest_cycle selects a large cycle and the topological
 sort produces poor results when leaf_nodes returns
 app-alternatives/gzip as part of a large group of nodes.
-This problem might be solved by implementing a finer-grained
-ignore_priority for leaf_nodes calls.
+This problem was solved by increasing ignore_priority in order
+to find a smaller cycle.
 """
 ebuilds = {
 "app-alternatives/gzip-1": {

diff --git a/lib/portage/tests/resolver/test_merge_order.py 
b/lib/portage/tests/resolver/test_merge_order.py
index 940eb3bbbe..671543ca29 100644
--- a/lib/portage/tests/resolver/test_merge_order.py
+++ b/lib/portage/tests/resolver/test_merge_order.py
@@ -382,10 +382,12 @@ class MergeOrderTestCase(TestCase):
 ambiguous_merge_order=True,
 # The following merge order assertion reflects optimal order 
for
 # a circular relationship which is DEPEND in one direction and
-# RDEPEND in the other.
-merge_order_assertions=(
-("app-misc/circ-buildtime-a-1", 
"app-misc/circ-buildtime-c-1"),
-),
+# RDEPEND in the other. However, it is not respected because
+# it would result in a temporarily broken RDEPEND, so we 
instead
+# rely on satisfied installed build-time dependencies.

[gentoo-commits] proj/portage:master commit in: lib/_emerge/, lib/portage/tests/resolver/, /

2023-11-06 Thread Sam James
commit: c56ca69564452198039e17b3a07f24f5b87a6852
Author: Sam James  gentoo  org>
AuthorDate: Mon Nov  6 15:03:10 2023 +
Commit: Sam James  gentoo  org>
CommitDate: Mon Nov  6 15:57:56 2023 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=c56ca695

emerge: fix _show_ignored_binaries_respect_use with incomplete depgraph

I've gone for the simpler solution of just using an empty tuple where the
merge list is empty to preserve prior behaviour with what we do (or do not)
display wrt skipped binaries.

Bug: https://bugs.gentoo.org/916614
Signed-off-by: Sam James  gentoo.org>

 NEWS|  2 +
 lib/_emerge/depgraph.py |  4 +-
 lib/portage/tests/resolver/test_useflags.py | 89 +
 3 files changed, 94 insertions(+), 1 deletion(-)

diff --git a/NEWS b/NEWS
index 4a33559a33..89d9335275 100644
--- a/NEWS
+++ b/NEWS
@@ -15,6 +15,8 @@ Bug fixes:
 
 * Avoid crash with incomplete depgraph for binpkg-respect-use notice (bug 
#916614).
 
+* Avoid crash with blockers in depgraph for binpkg-respect-use notice (bug 
#916336).
+
 portage-3.0.54 (2023-10-25)
 --
 

diff --git a/lib/_emerge/depgraph.py b/lib/_emerge/depgraph.py
index d1fed0d652..e4305c18c9 100644
--- a/lib/_emerge/depgraph.py
+++ b/lib/_emerge/depgraph.py
@@ -1234,11 +1234,13 @@ class depgraph:
 def _show_ignored_binaries_respect_use(self, respect_use):
 seen = {}
 messages = []
+
 merging = {
 (pkg.root, pkg.cpv)
-for pkg in self._dynamic_config._displayed_list
+for pkg in self._dynamic_config._displayed_list or ()
 if isinstance(pkg, Package)
 }
+
 for pkg, flags in respect_use.items():
 # Don't include recursive deps which aren't in the merge list 
anyway.
 if (pkg.root, pkg.cpv) not in merging:

diff --git a/lib/portage/tests/resolver/test_useflags.py 
b/lib/portage/tests/resolver/test_useflags.py
index ee9f4f2763..86684f7f28 100644
--- a/lib/portage/tests/resolver/test_useflags.py
+++ b/lib/portage/tests/resolver/test_useflags.py
@@ -229,3 +229,92 @@ class UseFlagsTestCase(TestCase):
 )
 finally:
 playground.cleanup()
+
+def testNoMergeBinpkgRespectUse(self):
+"""
+Testcase for bug #916614 where an incomplete depgraph may be fed into
+_show_ignored_binaries_respect_use.
+
+We use a mix of +/-abi_x86_32 to trigger the binpkg-respect-use notice
+and depend on a non-existent package in one of the available ebuilds we
+queue to reinstall to trigger an aborted calculation.
+"""
+ebuilds = {
+"dev-libs/A-2": {
+"EAPI": "7",
+"IUSE": "abi_x86_32",
+},
+"dev-libs/B-1": {
+"IUSE": "abi_x86_32",
+"RDEPEND": "=dev-libs/A-1",
+},
+}
+
+installed = {
+"dev-libs/B-1": {
+"IUSE": "abi_x86_32",
+"USE": "abi_x86_32",
+},
+"dev-libs/A-1": {
+"IUSE": "abi_x86_32",
+"USE": "abi_x86_32",
+},
+}
+
+binpkgs = {
+"dev-libs/A-2": {
+"IUSE": "abi_x86_32",
+"USE": "abi_x86_32",
+},
+"dev-libs/B-1": {
+"IUSE": "abi_x86_32",
+"USE": "",
+"BUILD_ID": "2",
+"BUILD_TIME": "2",
+},
+}
+
+user_config = {
+"make.conf": (
+'FEATURES="binpkg-multi-instance"',
+'USE="abi_x86_32 abi_x86_32"',
+),
+}
+
+world = ("dev-libs/A",)
+
+test_cases = (
+ResolverPlaygroundTestCase(
+["@installed"],
+options={
+"--verbose": "y",
+"--emptytree": True,
+"--usepkg": True,
+},
+success=False,
+mergelist=["[binary]dev-libs/A-2", "dev-libs/B-1"],
+slot_collision_solutions=[],
+),
+)
+
+for binpkg_format in SUPPORTED_GENTOO_BINPKG_FORMATS:
+with self.subTest(binpkg_format=binpkg_format):
+print(colorize("HILITE", binpkg_format), end=" ... ")
+sys.stdout.flush()
+user_config["make.conf"] += 
(f'BINPKG_FORMAT="{binpkg_format}"',)
+playground = ResolverPlayground(
+ebuilds=ebuilds,
+binpkgs=binpkgs,
+installed=installed,
+user_config=user_config,
+world=world,
+)
+
+try:
+for test_case in test_cases:
+

[gentoo-commits] proj/portage:master commit in: lib/_emerge/, lib/portage/tests/resolver/, /

2023-11-06 Thread Sam James
commit: 262b8c9213c6698be4a7e2ce88536568899e6c2a
Author: Sam James  gentoo  org>
AuthorDate: Mon Oct 30 05:30:04 2023 +
Commit: Sam James  gentoo  org>
CommitDate: Mon Nov  6 15:57:56 2023 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=262b8c92

emerge: fix binpkg-respect-use notice with blockers

Items in _dynamic_config._displayed_list might be blockers, so filter those out.

Bug: https://bugs.gentoo.org/916336
Fixes: bb82666b48e18f448661a1a8bf6a39b773cc4b1c
Signed-off-by: Sam James  gentoo.org>

 NEWS|  2 +
 lib/_emerge/depgraph.py |  6 +-
 lib/portage/tests/resolver/test_useflags.py | 87 +
 3 files changed, 94 insertions(+), 1 deletion(-)

diff --git a/NEWS b/NEWS
index be551de33d..4a33559a33 100644
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,8 @@ Bug fixes:
 * Convert portageq helper to a function to avoid breaking external callers
   (bug #916287, bug #916296).
 
+* Avoid crash with incomplete depgraph for binpkg-respect-use notice (bug 
#916614).
+
 portage-3.0.54 (2023-10-25)
 --
 

diff --git a/lib/_emerge/depgraph.py b/lib/_emerge/depgraph.py
index 85845dc1e2..0717e0429f 100644
--- a/lib/_emerge/depgraph.py
+++ b/lib/_emerge/depgraph.py
@@ -1234,7 +1234,11 @@ class depgraph:
 def _show_ignored_binaries_respect_use(self, respect_use):
 seen = {}
 messages = []
-merging = {pkg.cpv for pkg in self._dynamic_config._displayed_list}
+merging = {
+pkg.cpv
+for pkg in self._dynamic_config._displayed_list
+if isinstance(pkg, Package)
+}
 for pkg, flags in respect_use.items():
 # Don't include recursive deps which aren't in the merge list 
anyway.
 if pkg.cpv not in merging:

diff --git a/lib/portage/tests/resolver/test_useflags.py 
b/lib/portage/tests/resolver/test_useflags.py
index 0af1cb5585..ee9f4f2763 100644
--- a/lib/portage/tests/resolver/test_useflags.py
+++ b/lib/portage/tests/resolver/test_useflags.py
@@ -142,3 +142,90 @@ class UseFlagsTestCase(TestCase):
 )
 finally:
 playground.cleanup()
+
+def testBlockerBinpkgRespectUse(self):
+"""
+Test for bug #916336 where we tried to check properties of a blocker
+object which isn't a Package to be merged.
+"""
+
+ebuilds = {
+"dev-libs/A-1": {
+"EAPI": "7",
+"IUSE": "abi_x86_32",
+"RDEPEND": "dev-libs/B",
+},
+"dev-libs/B-1": {
+"EAPI": "7",
+"IUSE": "abi_x86_32",
+},
+"dev-libs/A-2": {
+"EAPI": "7",
+"IUSE": "abi_x86_32",
+"RDEPEND": "!

[gentoo-commits] proj/portage:master commit in: lib/_emerge/, lib/portage/tests/resolver/

2023-06-15 Thread Sam James
commit: 224207c7d1988a354d004507bb7ecfb90b4ef097
Author: YiFei Zhu  gmail  com>
AuthorDate: Tue Jun 13 00:47:52 2023 +
Commit: Sam James  gentoo  org>
CommitDate: Fri Jun 16 03:34:46 2023 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=224207c7

depgraph: Do not allow slotted deps to be satisfied by wrong slots

This may be part of what caused the "perl rebuild bug". The
"priority" of perl, when seen by perl modules, may have "satisfied"
set to an installed perl of a wrong slot. Compounding this factor
with bug #756199 where find_smallest_cycle would select a single
node, in this case because the dependency of perl is satisfied and
the priority then gets ignored, the "cycle" becomes a perl module
alone and gets rebuilt early.

I also updated the test from the previous patch to account for
this change. No other tests seems affected.

For a larger scale test, I reproduced this initially with a stage3
chroot from a Jan 1 2022 stage3 snapshot, and testing in an
equivalent dockerfile would work too:

  FROM gentoo/stage3:amd64-openrc-20220101
  RUN emerge-webrsync
  COPY . /portage

Before this patch (USE flags omitted):

  # cd /portage && bin/emerge -puDN @world 2>&1 | grep -i perl
  [ebuild U  ] app-admin/perl-cleaner-2.30-r1 [2.30]
  [ebuild  rR] virtual/perl-File-Temp-0.231.100
  [ebuild  rR] dev-perl/Locale-gettext-1.70.0-r1
  [ebuild  rR] dev-perl/MIME-Charset-1.12.2-r1
  [ebuild  rR] dev-perl/Module-Build-0.423.100
  [ebuild  rR] dev-perl/Text-CharWidth-0.40.0-r2
  [ebuild U  ] dev-lang/perl-5.36.0-r2 [5.34.0-r3]
  [ebuild  N ] virtual/perl-CPAN-2.330.0
  [ebuild U  ] virtual/perl-ExtUtils-MakeMaker-7.640.0 [7.620.0]
  [ebuild U  ] virtual/perl-File-Spec-3.840.0 [3.800.0]
  [...]

After this patch:

  # cd /portage && bin/emerge -puDN @world 2>&1 | grep -i perl
  [ebuild U  ] app-admin/perl-cleaner-2.30-r1 [2.30]
  [ebuild U  ] dev-lang/perl-5.36.0-r2:0/5.36 [5.34.0-r3:0/5.34]
  [ebuild  N ] virtual/perl-CPAN-2.330.0
  [ebuild U  ] virtual/perl-ExtUtils-MakeMaker-7.640.0 [7.620.0]
  [ebuild U  ] virtual/perl-Data-Dumper-2.184.0 [2.179.0]
  [ebuild U  ] virtual/perl-File-Spec-3.840.0 [3.800.0]
  [ebuild U  ] virtual/perl-Test-Harness-3.440.0-r1 [3.430.0]
  [ebuild  rR] dev-perl/Pod-Parser-1.630.0-r1
  [ebuild  rR] dev-perl/Text-CharWidth-0.40.0-r2
  [ebuild  rR] dev-perl/Text-WrapI18N-0.60.0-r2
  [...]

Bug: https://bugs.gentoo.org/463976
Bug: https://bugs.gentoo.org/592880
Bug: https://bugs.gentoo.org/596664
Bug: https://bugs.gentoo.org/631490
Bug: https://bugs.gentoo.org/764365
Bug: https://bugs.gentoo.org/793992
Signed-off-by: YiFei Zhu  gmail.com>
Closes: https://github.com/gentoo/portage/pull/1055
Signed-off-by: Sam James  gentoo.org>

 lib/_emerge/depgraph.py | 18 ++
 lib/portage/tests/resolver/test_perl_rebuild_bug.py |  4 ++--
 2 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/lib/_emerge/depgraph.py b/lib/_emerge/depgraph.py
index 60e57b226..28acfed9d 100644
--- a/lib/_emerge/depgraph.py
+++ b/lib/_emerge/depgraph.py
@@ -4042,6 +4042,16 @@ class depgraph:
 inst_pkg, modified_use=self._pkg_use_enabled(inst_pkg)
 )
 ]
+# Do not allow slotted deps to be satisfied by wrong slots.
+# Otherwise, slot-operator-dependent packages may rebuild
+# before the slotted package they are dependent on.
+if child and atom.slot_operator == "=":
+inst_pkgs = [
+inst_pkg
+for inst_pkg in inst_pkgs
+if inst_pkg.slot == child.slot
+and inst_pkg.sub_slot == child.sub_slot
+]
 if inst_pkgs:
 for inst_pkg in inst_pkgs:
 if self._pkg_visibility_check(inst_pkg):
@@ -4161,6 +4171,14 @@ class depgraph:
 inst_pkg, 
modified_use=self._pkg_use_enabled(inst_pkg)
 )
 ]
+# Do not allow slotted deps to be satisfied by wrong slots.
+if child and atom.slot_operator == "=":
+inst_pkgs = [
+inst_pkg
+for inst_pkg in inst_pkgs
+if inst_pkg.slot == child.slot
+and inst_pkg.sub_slot == child.sub_slot
+]
 if inst_pkgs:
 for inst_pkg in inst_pkgs:
 if self._pkg_visibility_check(inst_pkg):

diff --git a/lib/portage/tests/resolver/test_perl_rebuild_bug.py 
b/lib/portage/tests/resolver/test_perl_rebuild_bug.py
index 928fd47d7..7e376f396 100644
--- a/lib/portage/tests/resolver/test_perl_rebuild_bug.py
+++ 

[gentoo-commits] proj/portage:master commit in: lib/_emerge/, lib/portage/tests/resolver/

2023-06-15 Thread Sam James
commit: 44afa8445dc46464200fe46c1e09e0c7475067bf
Author: YiFei Zhu  gmail  com>
AuthorDate: Mon Jun 12 02:23:09 2023 +
Commit: Sam James  gentoo  org>
CommitDate: Fri Jun 16 03:34:46 2023 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=44afa844

depgraph: Don't ignore downgrades as missed_updates

Missed updates can also come in the form of package downgrades,
when, for example, there are keyword changes. They can cause
rebuilds, and these rebuilds may be not possible due to reasons such
as keywords or masks. In this case, prior to this patch, portage
would cancel the downgrade, but the rebuilds would be requested
endlessly, because bug 439688's backtrack code does not trigger.

To reproduce, on an ACCEPT_KEYWORDS=~amd64 machine, emerge
=dev-libs/openssl=3.0.9, dev-util/rustup, and something else that
depends on openssl. Then un-accept ~amd64 for openssl and rustup.
Prior to this patch, a @world upgrade would cause:

  These are the packages that would be merged, in order:

  Calculating dependencies... done!

  [ebuild  rR] dev-libs/libevent-2.1.12-r1:0/2.1-7::gentoo
  [ebuild  rR] net-misc/rsync-3.2.7-r2::gentoo
  [...]

  Total: 71 packages (71 reinstalls), Size of downloads: 0 KiB

There are no packages marked "R", only "rR". There are no section
labeled "The following packages are causing rebuilds:" either.

After this patch, we have:

  These are the packages that would be merged, in order:

  Calculating dependencies... done!

  Total: 0 packages, Size of downloads: 0 KiB

  WARNING: One or more updates/rebuilds have been skipped due to a dependency 
conflict:

  dev-libs/openssl:0

(dev-libs/openssl-1.1.1u:0/1.1::gentoo, ebuild scheduled for merge)
  dev-libs/openssl:0/3= required by (dev-util/rustup-1.25.2:0/0::gentoo, 
installed)

I also updated the test from the previous patch to account for
this change. No other tests seems affected.

Bug: https://bugs.gentoo.org/439688
Bug: https://bugs.gentoo.org/622270
Signed-off-by: YiFei Zhu  gmail.com>
Closes: https://github.com/gentoo/portage/pull/1053
Signed-off-by: Sam James  gentoo.org>

 lib/_emerge/depgraph.py| 4 +---
 lib/portage/tests/resolver/test_slot_conflict_blocked_prune.py | 2 +-
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/lib/_emerge/depgraph.py b/lib/_emerge/depgraph.py
index 77133e99c..60e57b226 100644
--- a/lib/_emerge/depgraph.py
+++ b/lib/_emerge/depgraph.py
@@ -1287,9 +1287,7 @@ class depgraph:
 pkg.root, pkg.slot_atom
 ):
 any_selected = True
-if chosen_pkg > pkg or (
-not chosen_pkg.installed and chosen_pkg.version == 
pkg.version
-):
+if not chosen_pkg.installed and chosen_pkg.version == 
pkg.version:
 missed_update = False
 break
 if any_selected and missed_update:

diff --git a/lib/portage/tests/resolver/test_slot_conflict_blocked_prune.py 
b/lib/portage/tests/resolver/test_slot_conflict_blocked_prune.py
index 14e98cd00..b23126d5f 100644
--- a/lib/portage/tests/resolver/test_slot_conflict_blocked_prune.py
+++ b/lib/portage/tests/resolver/test_slot_conflict_blocked_prune.py
@@ -63,7 +63,7 @@ class SlotConflictBlockedPruneTestCase(TestCase):
 ["@world"],
 options={"--deep": True, "--update": True, "--verbose": True},
 success=True,
-mergelist=["x11-base/xwayland-23.1.1"],
+mergelist=[],
 ),
 )
 



[gentoo-commits] proj/portage:master commit in: lib/_emerge/, lib/portage/tests/resolver/, /, man/

2023-02-20 Thread Sam James
commit: 75a4f2c2e07c128fef4d9faf3a8fb9d67565239e
Author: Sam James  gentoo  org>
AuthorDate: Thu Feb 16 06:26:07 2023 +
Commit: Sam James  gentoo  org>
CommitDate: Tue Feb 21 07:16:27 2023 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=75a4f2c2

emerge: add --update-if-installed

This adds a new emerge option '--update-if-installed'.

The use case for such an option is as follows:
- User finds out libfoo-1.2 is buggy.
- They want to upgrade all their systems if libfoo is installed.
- They don't want to install libfoo if it's not already installed.

  Unfortunately, --update fails this last point, hence
  the need for a new option.

Closes: https://github.com/gentoo/portage/pull/988
Signed-off-by: Sam James  gentoo.org>

 NEWS  |   4 ++
 lib/_emerge/create_depgraph_params.py |   6 ++
 lib/_emerge/depgraph.py   |  17 -
 lib/_emerge/main.py   |   3 +-
 lib/portage/tests/resolver/test_update.py | 106 ++
 man/emerge.1  |   6 ++
 6 files changed, 140 insertions(+), 2 deletions(-)

diff --git a/NEWS b/NEWS
index 29e9de038..9389d2c09 100644
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,10 @@ Features:
 
 * emerge: add --onlydeps-with-ideps= option (bug #890777)
 
+* emerge: add --update-if-installed option. This is useful for one-shot
+  emerge commands to be run across several machines to upgrade packages
+  only if they're installed.
+
 * install-qa-check.d: 60pkgconfig: add opt-in QA_PKGCONFIG_VERSION check
 
 * emerge: Log completion of package installs.

diff --git a/lib/_emerge/create_depgraph_params.py 
b/lib/_emerge/create_depgraph_params.py
index 531230402..1bbca5de9 100644
--- a/lib/_emerge/create_depgraph_params.py
+++ b/lib/_emerge/create_depgraph_params.py
@@ -129,6 +129,12 @@ def create_depgraph_params(myopts, myaction):
 if changed_slot:
 myparams["changed_slot"] = True
 
+# --update-if-installed implies --update
+update_if_installed = myopts.get("--update-if-installed")
+if update_if_installed is not None:
+myparams["update_if_installed"] = update_if_installed
+myopts["--update"] = True
+
 if (
 "--update" in myopts
 or "--newrepo" in myopts

diff --git a/lib/_emerge/depgraph.py b/lib/_emerge/depgraph.py
index 1631ed126..412dc7b6f 100644
--- a/lib/_emerge/depgraph.py
+++ b/lib/_emerge/depgraph.py
@@ -1,4 +1,4 @@
-# Copyright 1999-2021 Gentoo Authors
+# Copyright 1999-2023 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 import errno
@@ -5019,6 +5019,21 @@ class depgraph:
 pkg, existing_node = self._select_package(
 myroot, atom, onlydeps=onlydeps
 )
+
+# Is the package installed (at any version)?
+if pkg and "update_if_installed" in 
self._dynamic_config.myparams:
+package_is_installed = any(
+self._iter_match_pkgs(
+self._frozen_config.roots[myroot], 
"installed", atom
+)
+)
+
+# This package isn't eligible for selection in the
+# merge list as the user passed --update-if-installed
+# and it isn't installed.
+if not package_is_installed:
+continue
+
 if not pkg:
 pprovided_match = False
 for virt_choice in virtuals.get(atom.cp, []):

diff --git a/lib/_emerge/main.py b/lib/_emerge/main.py
index 38233e05c..850487d36 100644
--- a/lib/_emerge/main.py
+++ b/lib/_emerge/main.py
@@ -1,4 +1,4 @@
-# Copyright 1999-2020 Gentoo Authors
+# Copyright 1999-2023 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 import argparse
@@ -52,6 +52,7 @@ options = [
 "--tree",
 "--unordered-display",
 "--update",
+"--update-if-installed",
 ]
 
 shortmapping = {

diff --git a/lib/portage/tests/resolver/test_update.py 
b/lib/portage/tests/resolver/test_update.py
new file mode 100644
index 0..e67013f9f
--- /dev/null
+++ b/lib/portage/tests/resolver/test_update.py
@@ -0,0 +1,106 @@
+# Copyright 2022-2023 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+from portage.tests import TestCase
+from portage.tests.resolver.ResolverPlayground import (
+ResolverPlayground,
+ResolverPlaygroundTestCase,
+)
+
+
+class UpdateIfInstalledTestCase(TestCase):
+def testUpdateIfInstalledEmerge(self):
+installed = {
+"dev-lang/ghc-4": {},
+"dev-libs/larryware-3": {},
+"dev-libs/larryware-ng-3": {},
+"virtual/libc-1": {},
+}
+
+ebuilds = installed.copy()
+ebuilds.update(
+

[gentoo-commits] proj/portage:master commit in: lib/_emerge/, lib/portage/tests/resolver/

2020-11-21 Thread Zac Medico
commit: 5095c2023595a75e2848f1ad3dbe25b5fb451a44
Author: Zac Medico  gentoo  org>
AuthorDate: Mon Nov 16 05:55:54 2020 +
Commit: Zac Medico  gentoo  org>
CommitDate: Sun Nov 22 03:19:29 2020 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=5095c202

find_smallest_cycle: enhance search prioritization

Enhance the find_smallest_cycle function to prioritize its
search so that it will minimize the use of installed packages
to break cycles. When installed packages must be used to
break cycles, it will now prefer to do this for runtime
dependencies over buildtime dependencies, since it's
preferable to build against latest versions of buildtime
dependencies whenever possible. This should solve some cases
of bug 199856 which have been triggered by unsafe reliance
on installed packages to break cycles.

The included unit test case demonstrates correct merge order
for a dependency calculation involving 6 independent cycles.
This test case fails with the master branch, due to a buildtime
dependency cycle of 3 packages being merged earlier than cycles
of 2 packages. We can generalize this to say that the master
branch may use an installed package to break an arbitrarily
sized cycle in a somewhat random location, even though that
cycle may be composed of smaller independent cycles which
would be safer to break individually.

Bug: https://bugs.gentoo.org/754903
Signed-off-by: Zac Medico  gentoo.org>

 lib/_emerge/DepPriorityNormalRange.py  |  2 +
 lib/_emerge/DepPrioritySatisfiedRange.py   | 53 --
 lib/_emerge/depgraph.py| 43 -
 lib/portage/tests/resolver/test_merge_order.py | 10 +
 4 files changed, 70 insertions(+), 38 deletions(-)

diff --git a/lib/_emerge/DepPriorityNormalRange.py 
b/lib/_emerge/DepPriorityNormalRange.py
index 5f3f3da70..10f205a3b 100644
--- a/lib/_emerge/DepPriorityNormalRange.py
+++ b/lib/_emerge/DepPriorityNormalRange.py
@@ -14,6 +14,7 @@ class DepPriorityNormalRange:
"""
MEDIUM  = 3
MEDIUM_SOFT = 2
+   MEDIUM_POST = 2
SOFT= 1
NONE= 0
 
@@ -37,6 +38,7 @@ class DepPriorityNormalRange:
 
ignore_medium  = _ignore_runtime
ignore_medium_soft = _ignore_runtime_post
+   ignore_medium_post = _ignore_runtime_post
ignore_soft= _ignore_optional
 
 DepPriorityNormalRange.ignore_priority = (

diff --git a/lib/_emerge/DepPrioritySatisfiedRange.py 
b/lib/_emerge/DepPrioritySatisfiedRange.py
index e056e676f..fb0d7db4e 100644
--- a/lib/_emerge/DepPrioritySatisfiedRange.py
+++ b/lib/_emerge/DepPrioritySatisfiedRange.py
@@ -8,17 +8,18 @@ class DepPrioritySatisfiedRange:
 
not satisfied and buildtimeHARD
not satisfied and runtime  7   MEDIUM
-   not satisfied and runtime_post 6   MEDIUM_SOFT
-   satisfied and buildtime_slot_op5   SOFT
-   satisfied and buildtime4   SOFT
-   satisfied and runtime  3   SOFT
-   satisfied and runtime_post 2   SOFT
+   satisfied and buildtime_slot_op6   MEDIUM_SOFT
+   satisfied and buildtime5   MEDIUM_SOFT
+   satisfied and runtime  4   MEDIUM_SOFT
+   runtime_post   3   MEDIUM_POST
+   satisfied and runtime_post 2   MEDIUM_POST
optional   1   SOFT
(none of the above)0   NONE
"""
MEDIUM  = 7
MEDIUM_SOFT = 6
-   SOFT= 5
+   MEDIUM_POST = 3
+   SOFT= 1
NONE= 0
 
@classmethod
@@ -35,42 +36,51 @@ class DepPrioritySatisfiedRange:
return True
if not priority.satisfied:
return False
+   if priority.buildtime or priority.runtime:
+   return False
return bool(priority.runtime_post)
 
@classmethod
-   def _ignore_satisfied_runtime(cls, priority):
+   def _ignore_runtime_post(cls, priority):
if priority.__class__ is not DepPriority:
return False
if priority.optional:
return True
-   if not priority.satisfied:
+   if priority.buildtime or priority.runtime:
return False
-   return not priority.buildtime
+   return bool(priority.runtime_post)
 
@classmethod
-   def _ignore_satisfied_buildtime(cls, priority):
+   def _ignore_satisfied_runtime(cls, priority):
if priority.__class__ is not DepPriority:
return False
if priority.optional:
return True
-   if priority.buildtime_slot_op:
+ 

[gentoo-commits] proj/portage:master commit in: lib/_emerge/, lib/portage/tests/resolver/

2020-09-20 Thread Zac Medico
commit: f64310749f176f8921b72ce282b4294efe81c3f0
Author: Zac Medico  gentoo  org>
AuthorDate: Sat Sep 19 21:32:41 2020 +
Commit: Zac Medico  gentoo  org>
CommitDate: Sun Sep 20 22:27:32 2020 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=f6431074

_slot_confict_backtrack: minimize conflict atoms (bug 743631)

Prefer choices that minimize conflict atoms, so that choices
which satisfy all parents are preferred. This reduces the
minimum necessary backtrack tries from 21 to 7 for the unit
test related to bug 743115.

Bug: https://bugs.gentoo.org/743115
Bug: https://bugs.gentoo.org/743631
Signed-off-by: Zac Medico  gentoo.org>

 lib/_emerge/depgraph.py| 6 ++
 lib/portage/tests/resolver/test_slot_operator_missed_update.py | 2 +-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/lib/_emerge/depgraph.py b/lib/_emerge/depgraph.py
index 3f864aefc..7281d8692 100644
--- a/lib/_emerge/depgraph.py
+++ b/lib/_emerge/depgraph.py
@@ -1797,6 +1797,12 @@ class depgraph:
if parent_atom not in parent_atoms)
backtrack_data.append((to_be_masked, conflict_atoms))
 
+   # Prefer choices that minimize conflict atoms. This is intended
+   # to take precedence over the earlier package version sort. The
+   # package version sort is still needed or else choices for the
+   # testOverlapSlotConflict method of 
VirtualMinimizeChildrenTestCase
+   # become non-deterministic.
+   backtrack_data.sort(key=lambda item: len(item[1]))
to_be_masked = backtrack_data[-1][0]
 
self._dynamic_config._backtrack_infos.setdefault(

diff --git a/lib/portage/tests/resolver/test_slot_operator_missed_update.py 
b/lib/portage/tests/resolver/test_slot_operator_missed_update.py
index fce012f62..1ea701003 100644
--- a/lib/portage/tests/resolver/test_slot_operator_missed_update.py
+++ b/lib/portage/tests/resolver/test_slot_operator_missed_update.py
@@ -90,7 +90,7 @@ class BacktrackMissedUpdateTestCase(TestCase):
# Bug 743115: missed updates trigger excessive 
backtracking
ResolverPlaygroundTestCase(
[">=dev-python/pypy3-7.3.2_rc", "@world"],
-   options={"--update": True, "--deep": True, 
"--backtrack": 25},
+   options={"--update": True, "--deep": True, 
"--backtrack": 10},
success=True,
mergelist=[
"dev-python/pypy3-7.3.2_rc2_p37-r1",



[gentoo-commits] proj/portage:master commit in: lib/_emerge/, lib/portage/tests/resolver/

2020-02-14 Thread Zac Medico
commit: 079f8c4a36ccc2ef5e25e7a57cd0707640f82592
Author: Zac Medico  gentoo  org>
AuthorDate: Fri Feb 14 19:21:28 2020 +
Commit: Zac Medico  gentoo  org>
CommitDate: Fri Feb 14 23:10:37 2020 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=079f8c4a

depclean: ensure consistency with update actions (bug 649622)

Make depclean traverse dependencies in the same order as update
actions, in order to ensure consistency in decisions which are
dependent on the order of dependency evaluation due to inconsistent
use of || preferences in different packages.

In unit tests, update test_virtual_w3m_realistic to assert that
the order of graph traversal is deterministic and consistent
between update and removal (depclean) actions.

Bug: https://bugs.gentoo.org/649622
Signed-off-by: Zac Medico  gentoo.org>

 lib/_emerge/actions.py   | 33 +++---
 lib/_emerge/depgraph.py  | 21 +--
 lib/portage/tests/resolver/ResolverPlayground.py | 77 +++-
 lib/portage/tests/resolver/test_or_choices.py| 12 +++-
 4 files changed, 96 insertions(+), 47 deletions(-)

diff --git a/lib/_emerge/actions.py b/lib/_emerge/actions.py
index 31252af16..4bf9ce425 100644
--- a/lib/_emerge/actions.py
+++ b/lib/_emerge/actions.py
@@ -1,8 +1,9 @@
-# Copyright 1999-2019 Gentoo Authors
+# Copyright 1999-2020 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 from __future__ import division, print_function, unicode_literals
 
+import collections
 import errno
 import logging
 import operator
@@ -741,7 +742,19 @@ def action_depclean(settings, trees, ldpath_mtimes,
 
return rval
 
+
 def calc_depclean(settings, trees, ldpath_mtimes,
+   myopts, action, args_set, spinner):
+   result = _calc_depclean(settings, trees, ldpath_mtimes,
+   myopts, action, args_set, spinner)
+   return result.returncode, result.cleanlist, result.ordered, 
result.req_pkg_count
+
+
+_depclean_result = collections.namedtuple('_depclean_result',
+   ('returncode', 'cleanlist', 'ordered', 'req_pkg_count', 'depgraph'))
+
+
+def _calc_depclean(settings, trees, ldpath_mtimes,
myopts, action, args_set, spinner):
allow_missing_deps = bool(args_set)
 
@@ -805,7 +818,7 @@ def calc_depclean(settings, trees, ldpath_mtimes,
writemsg_level(_("!!! Aborting due to set configuration "
"errors displayed above.\n"),
level=logging.ERROR, noiselevel=-1)
-   return 1, [], False, 0
+   return _depclean_result(1, [], False, 0, None)
 
if action == "depclean":
emergelog(xterm_titles, " >>> depclean")
@@ -920,7 +933,7 @@ def calc_depclean(settings, trees, ldpath_mtimes,
resolver.display_problems()
 
if not success:
-   return 1, [], False, 0
+   return _depclean_result(1, [], False, 0, resolver)
 
def unresolved_deps():
 
@@ -1020,7 +1033,7 @@ def calc_depclean(settings, trees, ldpath_mtimes,
return False
 
if unresolved_deps():
-   return 1, [], False, 0
+   return _depclean_result(1, [], False, 0, resolver)
 
graph = resolver._dynamic_config.digraph.copy()
required_pkgs_total = 0
@@ -1321,7 +1334,7 @@ def calc_depclean(settings, trees, ldpath_mtimes,
runtime_slot_op=True),
root=pkg.root)):
resolver.display_problems()
-   return 1, [], False, 0
+   return _depclean_result(1, [], 
False, 0, resolver)
 
writemsg_level("\nCalculating dependencies  ")
success = resolver._complete_graph(
@@ -1329,9 +1342,9 @@ def calc_depclean(settings, trees, ldpath_mtimes,
writemsg_level("\b\b... done!\n")
resolver.display_problems()
if not success:
-   return 1, [], False, 0
+   return _depclean_result(1, [], False, 0, 
resolver)
if unresolved_deps():
-   return 1, [], False, 0
+   return _depclean_result(1, [], False, 0, 
resolver)
 
graph = resolver._dynamic_config.digraph.copy()
required_pkgs_total = 0
@@ -1340,7 +1353,7 @@ def calc_depclean(settings, trees, ldpath_mtimes,
required_pkgs_total += 1
cleanlist = create_cleanlist()
if not cleanlist:
-   return 0, [], False, required_pkgs_total
+   return _depclean_result(0, [], False, 

[gentoo-commits] proj/portage:master commit in: lib/_emerge/, lib/portage/tests/resolver/

2019-09-11 Thread Zac Medico
commit: 1e61c439143b12d079e1fc344bbc0c192a84cbe0
Author: Zac Medico  gentoo  org>
AuthorDate: Wed Sep 11 02:54:51 2019 +
Commit: Zac Medico  gentoo  org>
CommitDate: Thu Sep 12 01:31:21 2019 +
URL:https://gitweb.gentoo.org/proj/portage.git/commit/?id=1e61c439

_add_dep: less aggressive backtracking (bug 693836)

In order to suppress the sort of aggressive backtracking that can
trigger undesirable downgrades as in bug 693836, do not backtrack
for an unsatisfied dependency if there's an available package in
the runtime package mask which was involved in a slot conflict and
satisfied all involved parent atoms. Instead, discard the current
depgraph in favor of other backtracking configurations that may
exist. This case would not have been encountered prior to the fix
for bug 692746 which enabled backtracking for the type of slot
conflict that is detected here.

Fixes: 994ac00aa764 ("_slot_confict_backtrack: consider masking a package 
matched by all parent atoms (bug 692746)")
Bug: https://bugs.gentoo.org/693836
Signed-off-by: Zac Medico  gentoo.org>

 lib/_emerge/depgraph.py| 13 
 .../test_aggressive_backtrack_downgrade.py | 91 ++
 2 files changed, 104 insertions(+)

diff --git a/lib/_emerge/depgraph.py b/lib/_emerge/depgraph.py
index 6be1b3ec7..51614fc14 100644
--- a/lib/_emerge/depgraph.py
+++ b/lib/_emerge/depgraph.py
@@ -2888,6 +2888,19 @@ class depgraph(object):
dep.atom.without_use if 
dep.atom.package
else dep.atom, 
onlydeps=dep.onlydeps)
if dep_pkg is None:
+
+   # In order to suppress the sort 
of aggressive
+   # backtracking that can trigger 
undesirable downgrades
+   # as in bug 693836, do not 
backtrack if there's an
+   # available package which was 
involved in a slot
+   # conflict and satisfied all 
involved parent atoms.
+   for dep_pkg, reasons in 
self._dynamic_config._runtime_pkg_mask.items():
+   if 
(dep.atom.match(dep_pkg) and
+   len(reasons) == 
1 and
+   not 
reasons.get("slot conflict", True)):
+   
self._dynamic_config._skip_restart = True
+   return 0
+

self._dynamic_config._backtrack_infos["missing dependency"] = dep

self._dynamic_config._need_restart = True
if debug:

diff --git a/lib/portage/tests/resolver/test_aggressive_backtrack_downgrade.py 
b/lib/portage/tests/resolver/test_aggressive_backtrack_downgrade.py
new file mode 100644
index 0..fbe85dc89
--- /dev/null
+++ b/lib/portage/tests/resolver/test_aggressive_backtrack_downgrade.py
@@ -0,0 +1,91 @@
+# Copyright 2019 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+from portage.tests import TestCase
+from portage.tests.resolver.ResolverPlayground import (ResolverPlayground,
+   ResolverPlaygroundTestCase)
+
+class AgressiveBacktrackDowngradeTestCase(TestCase):
+
+   def testAgressiveBacktrackDowngrade(self):
+
+   ebuilds = {
+   'www-client/firefox-69.0' : {
+   'EAPI': '7',
+   'RDEPEND': 
'=media-libs/libvpx-1.7*:0=[postproc] media-video/ffmpeg'
+   },
+
+   'www-client/firefox-60.9.0' : {
+   'EAPI': '7',
+   'RDEPEND': ''
+   },
+
+   'media-libs/libvpx-1.8.0' : {
+   'EAPI': '7',
+   'SLOT' : '0/6',
+   'IUSE': 'postproc',
+   },
+
+   'media-libs/libvpx-1.7.0' : {
+   'EAPI': '7',
+   'SLOT' : '0/5',
+   'IUSE': '+postproc',
+   },
+
+   'media-libs/libvpx-1.6.0' : {
+   'EAPI': '7',
+   'SLOT' : '0/4',
+   'IUSE': 'postproc',
+   },
+
+   'media-video/ffmpeg-4.2' : {
+   'EAPI': '7',
+   'RDEPEND':