Gentoo Archives: gentoo-portage-dev

From: Sebastian Luther <SebastianLuther@×××.de>
To: gentoo-portage-dev@l.g.o
Subject: [gentoo-portage-dev] [PATCH 08/10] Some small output fixes for the slot conflict handler
Date: Wed, 29 Jan 2014 15:34:55
Message-Id: 1391009594-22750-9-git-send-email-SebastianLuther@gmx.de
In Reply to: [gentoo-portage-dev] [PATCH 00/10] First steps to get rid of backtracking by Sebastian Luther
1 * unmatched atom printing now uses ^^ markers
2 * unmatched atom printing properly supports sub-slots
3 * Fix spurious "no parents" message caused by AtomArg parents
4 ---
5 pym/_emerge/resolver/slot_collision.py | 119 ++++++++++++++++++++++++++-------
6 1 file changed, 96 insertions(+), 23 deletions(-)
7
8 diff --git a/pym/_emerge/resolver/slot_collision.py b/pym/_emerge/resolver/slot_collision.py
9 index ca3fb74..c5936ad 100644
10 --- a/pym/_emerge/resolver/slot_collision.py
11 +++ b/pym/_emerge/resolver/slot_collision.py
12 @@ -1,4 +1,4 @@
13 -# Copyright 2010-2013 Gentoo Foundation
14 +# Copyright 2010-2014 Gentoo Foundation
15 # Distributed under the terms of the GNU General Public License v2
16
17 from __future__ import print_function, unicode_literals
18 @@ -273,12 +273,14 @@ class slot_conflict_handler(object):
19 for ppkg, atom in parent_atoms:
20 atom_set = InternalPackageSet(initial_atoms=(atom,))
21 atom_without_use_set = InternalPackageSet(initial_atoms=(atom.without_use,))
22 + atom_without_use_and_slot_set = InternalPackageSet(initial_atoms=(
23 + atom.without_use.without_slot,))
24
25 for other_pkg in pkgs:
26 if other_pkg == pkg:
27 continue
28
29 - if not atom_without_use_set.findAtomForPackage(other_pkg, \
30 + if not atom_without_use_and_slot_set.findAtomForPackage(other_pkg, \
31 modified_use=_pkg_use_enabled(other_pkg)):
32 if atom.operator is not None:
33 # The version range does not match.
34 @@ -295,9 +297,11 @@ class slot_conflict_handler(object):
35 atoms.add((ppkg, atom, other_pkg))
36 num_all_specific_atoms += 1
37 collision_reasons[key] = atoms
38 - else:
39 - # The sub_slot does not match.
40 - key = ("sub-slot", atom.sub_slot)
41 +
42 + elif not atom_without_use_set.findAtomForPackage(other_pkg, \
43 + modified_use=_pkg_use_enabled(other_pkg)):
44 + # The slot and/or sub_slot does not match.
45 + key = ("slot", (atom.slot, atom.sub_slot, atom.slot_operator))
46 atoms = collision_reasons.get(key, set())
47 atoms.add((ppkg, atom, other_pkg))
48 num_all_specific_atoms += 1
49 @@ -342,6 +346,11 @@ class slot_conflict_handler(object):
50 atoms.add((ppkg, atom, other_pkg))
51 collision_reasons[("use", flag)] = atoms
52 num_all_specific_atoms += 1
53 + elif isinstance(ppkg, AtomArg) and other_pkg.installed:
54 + parent_atoms = collision_reasons.get(("AtomArg", None), set())
55 + parent_atoms.add((ppkg, atom))
56 + collision_reasons[("AtomArg", None)] = parent_atoms
57 + num_all_specific_atoms += 1
58
59 msg.append(" pulled in by\n")
60
61 @@ -372,9 +381,11 @@ class slot_conflict_handler(object):
62 if not verboseconflicts:
63 selected_for_display.update(
64 best_matches.values())
65 - elif type == "sub-slot":
66 + elif type == "slot":
67 for ppkg, atom, other_pkg in parents:
68 selected_for_display.add((ppkg, atom))
69 + if not verboseconflicts:
70 + break
71 elif type == "use":
72 #Prefer atoms with unconditional use deps over, because it's
73 #not possible to change them on the parent, which means there
74 @@ -416,21 +427,50 @@ class slot_conflict_handler(object):
75 # If the list is long, people can simply
76 # use a pager.
77 selected_for_display.add((ppkg, atom))
78 + elif type == "AtomArg":
79 + for ppkg, atom in parents:
80 + selected_for_display.add((ppkg, atom))
81
82 - def highlight_violations(atom, version, use=[]):
83 + def highlight_violations(atom, version, use, slot_violated):
84 """Colorize parts of an atom"""
85 atom_str = "%s" % (atom,)
86 + colored_idx = set()
87 if version:
88 op = atom.operator
89 ver = None
90 if atom.cp != atom.cpv:
91 ver = cpv_getversion(atom.cpv)
92 slot = atom.slot
93 + sub_slot = atom.sub_slot
94 + slot_operator = atom.slot_operator
95
96 if op == "=*":
97 op = "="
98 ver += "*"
99
100 + slot_str = ""
101 + if slot:
102 + slot_str = ":" + slot
103 + if sub_slot:
104 + slot_str += "/" + sub_slot
105 + if slot_operator:
106 + slot_str += slot_operator
107 +
108 + # Compute color_idx before adding the color codes
109 + # as these change the indices of the letters.
110 + if op is not None:
111 + colored_idx.update(range(len(op)))
112 +
113 + if ver is not None:
114 + start = atom_str.rfind(ver)
115 + end = start + len(ver)
116 + colored_idx.update(range(start, end))
117 +
118 + if slot_str:
119 + ii = atom_str.find(slot_str)
120 + colored_idx.update(range(ii, ii + len(slot_str)))
121 +
122 +
123 if op is not None:
124 atom_str = atom_str.replace(op, colorize("BAD", op), 1)
125
126 @@ -440,25 +480,48 @@ class slot_conflict_handler(object):
127 atom_str = atom_str[:start] + \
128 colorize("BAD", ver) + \
129 atom_str[end:]
130 +
131 + if slot_str:
132 + atom_str = atom_str.replace(slot_str, colorize("BAD", slot_str), 1)
133 +
134 + elif slot_violated:
135 + slot = atom.slot
136 + sub_slot = atom.sub_slot
137 + slot_operator = atom.slot_operator
138 +
139 + slot_str = ""
140 if slot:
141 - atom_str = atom_str.replace(":" + slot, colorize("BAD", ":" + slot))
142 + slot_str = ":" + slot
143 + if sub_slot:
144 + slot_str += "/" + sub_slot
145 + if slot_operator:
146 + slot_str += slot_operator
147 +
148 + if slot_str:
149 + ii = atom_str.find(slot_str)
150 + colored_idx.update(range(ii, ii + len(slot_str)))
151 + atom_str = atom_str.replace(slot_str, colorize("BAD", slot_str), 1)
152
153 if use and atom.use.tokens:
154 use_part_start = atom_str.find("[")
155 use_part_end = atom_str.find("]")
156
157 new_tokens = []
158 + # Compute start index in non-colored atom.
159 + ii = str(atom).find("[") + 1
160 for token in atom.use.tokens:
161 if token.lstrip("-!").rstrip("=?") in use:
162 new_tokens.append(colorize("BAD", token))
163 + colored_idx.update(range(ii, ii + len(token)))
164 else:
165 new_tokens.append(token)
166 + ii += 1 + len(token)
167
168 atom_str = atom_str[:use_part_start] \
169 + "[%s]" % (",".join(new_tokens),) + \
170 atom_str[use_part_end+1:]
171
172 - return atom_str
173 + return atom_str, colored_idx
174
175 # Show unconditional use deps first, since those
176 # are more problematic than the conditional kind.
177 @@ -469,37 +532,48 @@ class slot_conflict_handler(object):
178 ordered_list.append(parent_atom)
179 for parent_atom in ordered_list:
180 parent, atom = parent_atom
181 - msg.append(2*indent)
182 - if isinstance(parent,
183 - (PackageArg, AtomArg)):
184 - # For PackageArg and AtomArg types, it's
185 + if isinstance(parent, PackageArg):
186 + # For PackageArg it's
187 # redundant to display the atom attribute.
188 - msg.append("%s" % (parent,))
189 + msg.append("%s\n" % (parent,))
190 + elif isinstance(parent, AtomArg):
191 + msg.append("%s (Argument)\n" % (atom,))
192 else:
193 # Display the specific atom from SetArg or
194 # Package types.
195 version_violated = False
196 - sub_slot_violated = False
197 + slot_violated = False
198 use = []
199 for (type, sub_type), parents in collision_reasons.items():
200 for x in parents:
201 if parent == x[0] and atom == x[1]:
202 if type == "version":
203 version_violated = True
204 - elif type == "sub-slot":
205 - sub_slot_violated = True
206 + elif type == "slot":
207 + slot_violated = True
208 elif type == "use":
209 use.append(sub_type)
210 break
211
212 - atom_str = highlight_violations(atom.unevaluated_atom, version_violated, use)
213 + atom_str, colored_idx = highlight_violations(atom.unevaluated_atom,
214 + version_violated, use, slot_violated)
215
216 - if version_violated or sub_slot_violated:
217 + if version_violated or slot_violated:
218 self.is_a_version_conflict = True
219
220 - msg.append("%s required by %s" % (atom_str, parent))
221 - msg.append("\n")
222 -
223 + cur_line = "%s required by %s\n" % (atom_str, parent)
224 + marker_line = ""
225 + for ii in range(len(cur_line)):
226 + if ii in colored_idx:
227 + marker_line += "^"
228 + else:
229 + marker_line += " "
230 + marker_line += "\n"
231 + msg.append(2*indent)
232 + msg.append(cur_line)
233 + msg.append(2*indent)
234 + msg.append(marker_line)
235 +
236 if not selected_for_display:
237 msg.append(2*indent)
238 msg.append("(no parents that aren't satisfied by other packages in this slot)\n")
239 @@ -519,7 +593,6 @@ class slot_conflict_handler(object):
240
241 def get_explanation(self):
242 msg = ""
243 - _pkg_use_enabled = self.depgraph._pkg_use_enabled
244
245 if self.is_a_version_conflict:
246 return None
247 --
248 1.8.3.2