Gentoo Archives: gentoo-portage-dev

From: Zac Medico <zmedico@g.o>
To: gentoo-portage-dev@l.g.o
Cc: Zac Medico <zmedico@g.o>
Subject: [gentoo-portage-dev] [PATCH] depgraph: avoid missed update with slot operator and circ dep (bug 612874)
Date: Fri, 17 Mar 2017 08:18:41
Message-Id: 20170317081819.30654-1-zmedico@gentoo.org
1 Fix check_reverse_dependencies to ignore direct circular dependencies,
2 since these dependencies tend to prevent updates of packages. This
3 solves a missed update from llvm:0 to llvm:4 when clang is not in the
4 world file, as demonstrated by the included test case.
5
6 X-Gentoo-bug: 612874
7 X-Gentoo-bug-url: https://bugs.gentoo.org/show_bug.cgi?id=612874
8 ---
9 pym/_emerge/depgraph.py | 31 ++++++++++++-----
10 .../resolver/test_slot_operator_exclusive_slots.py | 39 ++++++++++++++++++++++
11 pym/portage/util/digraph.py | 6 ++++
12 3 files changed, 68 insertions(+), 8 deletions(-)
13
14 diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py
15 index f4145d0..e94b96c 100644
16 --- a/pym/_emerge/depgraph.py
17 +++ b/pym/_emerge/depgraph.py
18 @@ -1844,14 +1844,29 @@ class depgraph(object):
19 if (not self._too_deep(parent.depth) and
20 not self._frozen_config.excluded_pkgs.
21 findAtomForPackage(parent,
22 - modified_use=self._pkg_use_enabled(parent)) and
23 - (self._upgrade_available(parent) or
24 - (parent.installed and self._in_blocker_conflict(parent)))):
25 - # This parent may be irrelevant, since an
26 - # update is available (see bug 584626), or
27 - # it could be uninstalled in order to solve
28 - # a blocker conflict (bug 612772).
29 - continue
30 + modified_use=self._pkg_use_enabled(parent))):
31 + # Check for common reasons that the parent's
32 + # dependency might be irrelevant.
33 + if self._upgrade_available(parent):
34 + # This parent could be replaced by
35 + # an upgrade (bug 584626).
36 + continue
37 + if parent.installed and self._in_blocker_conflict(parent):
38 + # This parent could be uninstalled in order
39 + # to solve a blocker conflict (bug 612772).
40 + continue
41 + if self._dynamic_config.digraph.has_edge(parent,
42 + existing_pkg):
43 + # There is a direct circular dependency between
44 + # parent and existing_pkg. This type of
45 + # relationship tends to prevent updates
46 + # of packages (bug 612874). Since candidate_pkg
47 + # is available, we risk a missed update if we
48 + # don't try to eliminate this parent from the
49 + # graph. Therefore, we give candidate_pkg a
50 + # chance, and assume that it will be masked
51 + # by backtracking if necessary.
52 + continue
53
54 atom_set = InternalPackageSet(initial_atoms=(atom,),
55 allow_repo=True)
56 diff --git a/pym/portage/tests/resolver/test_slot_operator_exclusive_slots.py b/pym/portage/tests/resolver/test_slot_operator_exclusive_slots.py
57 index 2ab379c..689ed31 100644
58 --- a/pym/portage/tests/resolver/test_slot_operator_exclusive_slots.py
59 +++ b/pym/portage/tests/resolver/test_slot_operator_exclusive_slots.py
60 @@ -107,3 +107,42 @@ class SlotOperatorExclusiveSlotsTestCase(TestCase):
61 test_case.fail_msg)
62 finally:
63 playground.cleanup()
64 +
65 +
66 + world = ["media-libs/mesa"]
67 +
68 + test_cases = (
69 +
70 + # Test bug #612874, where a direct circular dependency
71 + # between llvm-3.9.1 and clang-3.9.1-r100 causes a
72 + # missed update from llvm:0 to llvm:4. Since llvm:4 does
73 + # not have a dependency on clang, the upgrade from llvm:0
74 + # to llvm:4 makes the installed sys-devel/clang-3.9.1-r100
75 + # instance eligible for removal by emerge --depclean, which
76 + # explains why clang does not appear in the mergelist.
77 + ResolverPlaygroundTestCase(
78 + ["@world"],
79 + options = {"--update": True, "--deep": True},
80 + success = True,
81 + ambiguous_merge_order = True,
82 + mergelist = [
83 + 'sys-devel/llvm-4.0.0',
84 + (
85 + 'media-libs/mesa-17.0.1',
86 + '[uninstall]sys-devel/llvm-3.9.1',
87 + '!sys-devel/llvm:0',
88 + )
89 + ],
90 + ),
91 +
92 + )
93 +
94 + playground = ResolverPlayground(ebuilds=ebuilds,
95 + installed=installed, world=world)
96 + try:
97 + for test_case in test_cases:
98 + playground.run_TestCase(test_case)
99 + self.assertEqual(test_case.test_success, True,
100 + test_case.fail_msg)
101 + finally:
102 + playground.cleanup()
103 diff --git a/pym/portage/util/digraph.py b/pym/portage/util/digraph.py
104 index 4a9cb43..b6be0c9 100644
105 --- a/pym/portage/util/digraph.py
106 +++ b/pym/portage/util/digraph.py
107 @@ -93,6 +93,12 @@ class digraph(object):
108 del self.nodes[node]
109 self.order = order
110
111 + def has_edge(self, child, parent):
112 + """
113 + Return True if the given edge exists.
114 + """
115 + return child in self.nodes[parent][0]
116 +
117 def remove_edge(self, child, parent):
118 """
119 Remove edge in the direction from child to parent. Note that it is
120 --
121 2.10.2

Replies