Gentoo Archives: gentoo-portage-dev

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

Replies

Subject Author
Re: [gentoo-portage-dev] [PATCH] Fix unnecessary rebuild (bug 487198) Sebastian Luther <SebastianLuther@×××.de>