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 |