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] Solve more slot-operator conflicts (531656)
Date: Fri, 26 Dec 2014 05:00:06
Message-Id: 1419569979-17935-1-git-send-email-zmedico@gentoo.org
1 Add some heuristics to handle slot conflicts triggered by interaction
2 of slot-operator dependencies with dependencies like those of labgl:
3
4 ocaml:= || ( labltk <ocaml-4.02 )
5
6 The new heuristics involve some behavior modifications in the depgraph
7 _solve_non_slot_operator_slot_conflicts method and in dep_zapdeps. The
8 dep_zapdeps changes affect the behavior of _select_atoms_probe calls
9 in the depgraph _slot_operator_update_probe method.
10
11 X-Gentoo-Bug: 531656
12 X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=531656
13 ---
14 pym/_emerge/depgraph.py | 30 ++++++++++-
15 pym/portage/dep/dep_check.py | 14 +++++
16 pym/portage/tests/resolver/test_or_choices.py | 78 +++++++++++++++++++++++++++
17 3 files changed, 121 insertions(+), 1 deletion(-)
18
19 diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py
20 index 28abea4..b067a6d 100644
21 --- a/pym/_emerge/depgraph.py
22 +++ b/pym/_emerge/depgraph.py
23 @@ -451,6 +451,7 @@ class _dynamic_depgraph_config(object):
24 self._graph_trees[myroot]["graph_db"] = graph_tree.dbapi
25 self._graph_trees[myroot]["graph"] = self.digraph
26 self._graph_trees[myroot]["want_update_pkg"] = depgraph._want_update_pkg
27 + self._graph_trees[myroot]["downgrade_probe"] = depgraph._downgrade_probe
28 def filtered_tree():
29 pass
30 filtered_tree.dbapi = _dep_check_composite_db(depgraph, myroot)
31 @@ -478,6 +479,7 @@ class _dynamic_depgraph_config(object):
32 self._filtered_trees[myroot]["vartree"] = \
33 depgraph._frozen_config.trees[myroot]["vartree"]
34 self._filtered_trees[myroot]["want_update_pkg"] = depgraph._want_update_pkg
35 + self._filtered_trees[myroot]["downgrade_probe"] = depgraph._downgrade_probe
36
37 dbs = []
38 # (db, pkg_type, built, installed, db_keys)
39 @@ -1144,7 +1146,13 @@ class depgraph(object):
40 writemsg_level(" pkg: %s\n" % pkg, level=logging.DEBUG, noiselevel=-1)
41
42 all_parent_atoms = set()
43 + highest_pkg = None
44 + inst_pkg = None
45 for pkg in conflict:
46 + if pkg.installed:
47 + inst_pkg = pkg
48 + if highest_pkg is None or highest_pkg < pkg:
49 + highest_pkg = pkg
50 all_parent_atoms.update(
51 self._dynamic_config._parent_atoms.get(pkg, []))
52
53 @@ -1167,6 +1175,15 @@ class depgraph(object):
54
55 matched = []
56 for pkg in conflict:
57 + if (pkg is highest_pkg and
58 + not highest_pkg.installed and
59 + inst_pkg is not None and
60 + inst_pkg.sub_slot != highest_pkg.sub_slot and
61 + not self._downgrade_probe(highest_pkg)):
62 + # If an upgrade is desired, force the highest
63 + # version into the graph (bug #531656).
64 + non_matching_forced.add(highest_pkg)
65 +
66 if atom_set.findAtomForPackage(pkg, \
67 modified_use=self._pkg_use_enabled(pkg)) and \
68 not (is_arg_parent and pkg.installed):
69 @@ -1220,14 +1237,20 @@ class depgraph(object):
70 # the packages in the tuple. This way we don't have
71 # to choose one.
72 unexplored_tuples = set()
73 + explored_nodes = set()
74
75 while unexplored:
76 # Handle all unexplored packages.
77 while unexplored:
78 node = unexplored.pop()
79 for child in conflict_graph.child_nodes(node):
80 - if child in forced:
81 + # Don't explore a node more than once, in order
82 + # to avoid infinite recursion. The forced set
83 + # cannot be used for this purpose, since it can
84 + # contain unexplored nodes from non_matching_forced.
85 + if child in explored_nodes:
86 continue
87 + explored_nodes.add(child)
88 forced.add(child)
89 if isinstance(child, Package):
90 unexplored.add(child)
91 @@ -8817,6 +8840,11 @@ def _backtrack_depgraph(settings, trees, myopts, myparams, myaction, myfiles, sp
92 mydepgraph.display_problems()
93
94 backtrack_parameters = backtracker.get()
95 + if debug and backtrack_parameters.runtime_pkg_mask:
96 + writemsg_level(
97 + "\n\nruntime_pkg_mask: %s \n\n" %
98 + backtrack_parameters.runtime_pkg_mask,
99 + noiselevel=-1, level=logging.DEBUG)
100
101 mydepgraph = depgraph(settings, trees, myopts, myparams, spinner,
102 frozen_config=frozen_config,
103 diff --git a/pym/portage/dep/dep_check.py b/pym/portage/dep/dep_check.py
104 index ccdda59..c40382d 100644
105 --- a/pym/portage/dep/dep_check.py
106 +++ b/pym/portage/dep/dep_check.py
107 @@ -319,6 +319,7 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None):
108 graph = trees[myroot].get("graph")
109 pkg_use_enabled = trees[myroot].get("pkg_use_enabled")
110 want_update_pkg = trees[myroot].get("want_update_pkg")
111 + downgrade_probe = trees[myroot].get("downgrade_probe")
112 vardb = None
113 if "vartree" in trees[myroot]:
114 vardb = trees[myroot]["vartree"].dbapi
115 @@ -351,6 +352,7 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None):
116 all_available = True
117 all_use_satisfied = True
118 all_use_unmasked = True
119 + conflict_downgrade = False
120 slot_map = {}
121 cp_map = {}
122 for atom in atoms:
123 @@ -367,6 +369,16 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None):
124 all_use_satisfied = False
125 break
126
127 + if graph_db is not None and downgrade_probe is not None:
128 + slot_matches = graph_db.match_pkgs(avail_slot)
129 + if (len(slot_matches) > 1 and
130 + avail_pkg < slot_matches[-1] and
131 + not downgrade_probe(avail_pkg)):
132 + # If a downgrade is not desirable, then avoid a
133 + # choice that pulls in a lower version involved
134 + # in a slot conflict (bug #531656).
135 + conflict_downgrade = True
136 +
137 if atom.use:
138 avail_pkg_use = mydbapi_match_pkgs(atom)
139 if not avail_pkg_use:
140 @@ -450,6 +462,8 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None):
141 unsat_use_installed.append(this_choice)
142 else:
143 unsat_use_non_installed.append(this_choice)
144 + elif conflict_downgrade:
145 + other.append(this_choice)
146 else:
147 all_in_graph = True
148 for atom in atoms:
149 diff --git a/pym/portage/tests/resolver/test_or_choices.py b/pym/portage/tests/resolver/test_or_choices.py
150 index 4aae0b2..3c02dfd 100644
151 --- a/pym/portage/tests/resolver/test_or_choices.py
152 +++ b/pym/portage/tests/resolver/test_or_choices.py
153 @@ -262,3 +262,81 @@ class OrChoicesTestCase(TestCase):
154 test_case.fail_msg)
155 finally:
156 playground.cleanup()
157 +
158 + def testConflictMissedUpdate(self):
159 +
160 + ebuilds = {
161 + "dev-lang/ocaml-4.02.1" : {
162 + "EAPI": "5",
163 + "SLOT": "0/4.02.1",
164 + },
165 +
166 + "dev-lang/ocaml-4.01.0" : {
167 + "EAPI": "5",
168 + "SLOT": "0/4.01.0",
169 + },
170 +
171 + "dev-ml/lablgl-1.05" : {
172 + "EAPI": "5",
173 + "DEPEND": (">=dev-lang/ocaml-3.10.2:= "
174 + "|| ( dev-ml/labltk:= <dev-lang/ocaml-4.02 )"),
175 + "RDEPEND": (">=dev-lang/ocaml-3.10.2:= "
176 + "|| ( dev-ml/labltk:= <dev-lang/ocaml-4.02 )"),
177 + },
178 +
179 + "dev-ml/labltk-8.06.0" : {
180 + "EAPI": "5",
181 + "SLOT": "0/8.06.0",
182 + "DEPEND": ">=dev-lang/ocaml-4.02:=",
183 + "RDEPEND": ">=dev-lang/ocaml-4.02:=",
184 + },
185 + }
186 +
187 + installed = {
188 + "dev-lang/ocaml-4.01.0" : {
189 + "EAPI": "5",
190 + "SLOT": "0/4.01.0",
191 + },
192 +
193 + "dev-ml/lablgl-1.05" : {
194 + "EAPI": "5",
195 + "DEPEND": (">=dev-lang/ocaml-3.10.2:0/4.01.0= "
196 + "|| ( dev-ml/labltk:= <dev-lang/ocaml-4.02 )"),
197 + "RDEPEND": (">=dev-lang/ocaml-3.10.2:0/4.01.0= "
198 + "|| ( dev-ml/labltk:= <dev-lang/ocaml-4.02 )"),
199 + },
200 + }
201 +
202 + world = (
203 + "dev-lang/ocaml",
204 + "dev-ml/lablgl",
205 + )
206 +
207 + test_cases = (
208 +
209 + # bug #531656: If an ocaml update is desirable,
210 + # then we need to pull in dev-ml/labltk.
211 + ResolverPlaygroundTestCase(
212 + ["@world"],
213 + options = {"--update": True, "--deep": True},
214 + success = True,
215 + mergelist = [
216 + "dev-lang/ocaml-4.02.1",
217 + "dev-ml/labltk-8.06.0",
218 + "dev-ml/lablgl-1.05",
219 + ]
220 + ),
221 +
222 + )
223 +
224 + playground = ResolverPlayground(debug=False,
225 + ebuilds=ebuilds, installed=installed, world=world)
226 + try:
227 + for test_case in test_cases:
228 + playground.run_TestCase(test_case)
229 + self.assertEqual(test_case.test_success, True,
230 + test_case.fail_msg)
231 + finally:
232 + # Disable debug so that cleanup works.
233 + playground.debug = False
234 + playground.cleanup()
235 --
236 2.0.5

Replies

Subject Author
Re: [gentoo-portage-dev] [PATCH] Solve more slot-operator conflicts (531656) Alexander Berntsen <bernalex@g.o>