Gentoo Archives: gentoo-commits

From: Brian Dolbec <brian.dolbec@×××××.com>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/portage:master commit in: pym/portage/tests/resolver/, pym/_emerge/
Date: Thu, 05 Dec 2013 15:39:00
Message-Id: 1386256467.dee9512d2ffec94b4a9eb4ece5c8345e86d04d32.dol-sen@gentoo
1 commit: dee9512d2ffec94b4a9eb4ece5c8345e86d04d32
2 Author: Sebastian Luther <SebastianLuther <AT> gmx <DOT> de>
3 AuthorDate: Mon Dec 2 12:52:36 2013 +0000
4 Commit: Brian Dolbec <brian.dolbec <AT> gmail <DOT> com>
5 CommitDate: Thu Dec 5 15:14:27 2013 +0000
6 URL: http://git.overlays.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=dee9512d
7
8 Fix unnecessary rebuild (bug 487198)
9
10 This one was caused by a mix of >= and < dependencies.
11 Rename the test as requested by Sebastian to testSlotConflictMixedDependencies
12
13 ---
14 pym/_emerge/depgraph.py | 92 +++++++++++++++++-----
15 .../tests/resolver/test_slot_conflict_rebuild.py | 66 ++++++++++++++++
16 2 files changed, 139 insertions(+), 19 deletions(-)
17
18 diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py
19 index 6600bc2..763f3fd 100644
20 --- a/pym/_emerge/depgraph.py
21 +++ b/pym/_emerge/depgraph.py
22 @@ -1298,7 +1298,34 @@ class depgraph(object):
23
24 selected_atoms = None
25
26 - for atom in replacement_parent.validated_atoms:
27 + atoms = set()
28 + invalid_metadata = False
29 + for dep_key in ("DEPEND", "HDEPEND", "RDEPEND", "PDEPEND"):
30 + dep_string = replacement_parent._metadata[dep_key]
31 + if not dep_string:
32 + continue
33 +
34 + try:
35 + dep_string = portage.dep.use_reduce(dep_string,
36 + uselist=self._pkg_use_enabled(replacement_parent),
37 + is_valid_flag=replacement_parent.iuse.is_valid_flag,
38 + flat=True, token_class=Atom,
39 + eapi=replacement_parent.eapi)
40 + except portage.exception.InvalidDependString:
41 + invalid_metadata = True
42 + break
43 +
44 + atoms.update(token for token in dep_string if isinstance(token, Atom))
45 +
46 + if invalid_metadata:
47 + continue
48 +
49 + # List of list of child,atom pairs for each atom.
50 + replacement_candidates = []
51 + # Set of all packages all atoms can agree on.
52 + all_candidate_pkgs = None
53 +
54 + for atom in atoms:
55 if atom.blocker or \
56 atom.cp != dep.atom.cp:
57 continue
58 @@ -1316,6 +1343,8 @@ class depgraph(object):
59 # parent and search for another.
60 break
61
62 + candidate_pkg_atoms = []
63 + candidate_pkgs = []
64 for pkg in self._iter_similar_available(
65 dep.child, atom):
66 if pkg.slot == dep.child.slot and \
67 @@ -1367,26 +1396,51 @@ class depgraph(object):
68 if unevaluated_atom not in selected_atoms:
69 continue
70
71 - if debug:
72 - msg = []
73 - msg.append("")
74 - msg.append("")
75 - msg.append("slot_operator_update_probe:")
76 - msg.append(" existing child package: %s" % dep.child)
77 - msg.append(" existing parent package: %s" % dep.parent)
78 - msg.append(" new child package: %s" % pkg)
79 - msg.append(" new parent package: %s" % replacement_parent)
80 - if insignificant:
81 - msg.append("insignificant changes detected")
82 - msg.append("")
83 - writemsg_level("\n".join(msg),
84 - noiselevel=-1, level=logging.DEBUG)
85 + if not insignificant:
86 + candidate_pkg_atoms.append((pkg, unevaluated_atom))
87 + candidate_pkgs.append(pkg)
88 +
89 + replacement_candidates.append(candidate_pkg_atoms)
90 + if all_candidate_pkgs is None:
91 + all_candidate_pkgs = set(candidate_pkgs)
92 + else:
93 + all_candidate_pkgs.intersection_update(candidate_pkgs)
94 +
95 + if not all_candidate_pkgs:
96 + # If the atoms that connect parent and child can't agree on
97 + # any replacement child, we can't do anything.
98 + continue
99 +
100 + # Now select one of the pkgs as replacement. This is as easy as
101 + # selecting the highest version.
102 + # The more complicated part is to choose an atom for the
103 + # new Dependency object. Choose the one which ranked the selected
104 + # parent highest.
105 + selected = None
106 + for candidate_pkg_atoms in replacement_candidates:
107 + for i, (pkg, atom) in enumerate(candidate_pkg_atoms):
108 + if pkg not in all_candidate_pkgs:
109 + continue
110 + if selected is None or \
111 + selected[0] < pkg or \
112 + (selected[0] is pkg and i < selected[2]):
113 + selected = (pkg, atom, i)
114
115 - if insignificant:
116 - return None
117 + if debug:
118 + msg = []
119 + msg.append("")
120 + msg.append("")
121 + msg.append("slot_operator_update_probe:")
122 + msg.append(" existing child package: %s" % dep.child)
123 + msg.append(" existing parent package: %s" % dep.parent)
124 + msg.append(" new child package: %s" % selected[0])
125 + msg.append(" new parent package: %s" % replacement_parent)
126 + msg.append("")
127 + writemsg_level("\n".join(msg),
128 + noiselevel=-1, level=logging.DEBUG)
129
130 - return Dependency(parent=replacement_parent,
131 - child=pkg, atom=unevaluated_atom)
132 + return Dependency(parent=replacement_parent,
133 + child=selected[0], atom=selected[1])
134
135 if debug:
136 msg = []
137
138 diff --git a/pym/portage/tests/resolver/test_slot_conflict_rebuild.py b/pym/portage/tests/resolver/test_slot_conflict_rebuild.py
139 index c7c62dd..1950550 100644
140 --- a/pym/portage/tests/resolver/test_slot_conflict_rebuild.py
141 +++ b/pym/portage/tests/resolver/test_slot_conflict_rebuild.py
142 @@ -298,3 +298,69 @@ class SlotConflictRebuildTestCase(TestCase):
143 self.assertEqual(test_case.test_success, True, test_case.fail_msg)
144 finally:
145 playground.cleanup()
146 +
147 +
148 + def testSlotConflictMixedDependencies(self):
149 + """
150 + Bug 487198
151 + For parents with mixed >= and < dependencies, we scheduled rebuilds for the
152 + >= atom, but in the end didn't install the child update becaue of the < atom.
153 + """
154 + ebuilds = {
155 + "cat/slotted-lib-1" : {
156 + "EAPI": "5",
157 + "SLOT": "1"
158 + },
159 + "cat/slotted-lib-2" : {
160 + "EAPI": "5",
161 + "SLOT": "2"
162 + },
163 + "cat/slotted-lib-3" : {
164 + "EAPI": "5",
165 + "SLOT": "3"
166 + },
167 + "cat/slotted-lib-4" : {
168 + "EAPI": "5",
169 + "SLOT": "4"
170 + },
171 + "cat/slotted-lib-5" : {
172 + "EAPI": "5",
173 + "SLOT": "5"
174 + },
175 + "cat/user-1" : {
176 + "EAPI": "5",
177 + "DEPEND": ">=cat/slotted-lib-2:= <cat/slotted-lib-4:=",
178 + "RDEPEND": ">=cat/slotted-lib-2:= <cat/slotted-lib-4:=",
179 + },
180 + }
181 +
182 + installed = {
183 + "cat/slotted-lib-3" : {
184 + "EAPI": "5",
185 + "SLOT": "3"
186 + },
187 + "cat/user-1" : {
188 + "EAPI": "5",
189 + "DEPEND": ">=cat/slotted-lib-2:3/3= <cat/slotted-lib-4:3/3=",
190 + "RDEPEND": ">=cat/slotted-lib-2:3/3= <cat/slotted-lib-4:3/3=",
191 + },
192 + }
193 +
194 + test_cases = (
195 + ResolverPlaygroundTestCase(
196 + ["cat/user"],
197 + options = {"--deep": True, "--update": True},
198 + success = True,
199 + mergelist = []),
200 + )
201 +
202 + world = []
203 +
204 + playground = ResolverPlayground(ebuilds=ebuilds,
205 + installed=installed, world=world, debug=False)
206 + try:
207 + for test_case in test_cases:
208 + playground.run_TestCase(test_case)
209 + self.assertEqual(test_case.test_success, True, test_case.fail_msg)
210 + finally:
211 + playground.cleanup()