summaryrefslogtreecommitdiffstats
path: root/pym/_emerge/__init__.py
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2009-01-12 08:21:52 +0000
committerZac Medico <zmedico@gentoo.org>2009-01-12 08:21:52 +0000
commit18469291ffc01ed8ca51e3f4d0f8fc8975e411b7 (patch)
tree318f626bd0badf17b4cd5cb34448d6dbc97b8f49 /pym/_emerge/__init__.py
parent44f6b5570ba3eee775d538fea072d41324a8e526 (diff)
downloadportage-18469291ffc01ed8ca51e3f4d0f8fc8975e411b7.tar.gz
portage-18469291ffc01ed8ca51e3f4d0f8fc8975e411b7.tar.bz2
portage-18469291ffc01ed8ca51e3f4d0f8fc8975e411b7.zip
When there are unresolved blockers, display the conflicting packages along
with the packages that pulled them in (similar to the slot conflict display). This is helpful for troubleshooting cases in which blockers don't solve automatically and the reasons are not apparent from the normal merge list display. (trunk r12408) svn path=/main/branches/2.1.6/; revision=12466
Diffstat (limited to 'pym/_emerge/__init__.py')
-rw-r--r--pym/_emerge/__init__.py82
1 files changed, 81 insertions, 1 deletions
diff --git a/pym/_emerge/__init__.py b/pym/_emerge/__init__.py
index 11500213f..ddc33d423 100644
--- a/pym/_emerge/__init__.py
+++ b/pym/_emerge/__init__.py
@@ -4468,6 +4468,12 @@ class depgraph(object):
self._irrelevant_blockers = digraph()
# Contains only unsolvable Package -> Blocker edges
self._unsolvable_blockers = digraph()
+ # Contains all Blocker -> Blocked Package edges
+ self._blocked_pkgs = digraph()
+ # Contains world packages that have been protected from
+ # uninstallation but may not have been added to the graph
+ # if the graph is not complete yet.
+ self._blocked_world_pkgs = {}
self._slot_collision_info = {}
# Slot collision nodes are not allowed to block other packages since
# blocker validation is only able to account for one package per slot.
@@ -6428,6 +6434,9 @@ class depgraph(object):
# is already done and this would be likely to
# confuse users if displayed like a normal blocker.
continue
+
+ self._blocked_pkgs.add(pkg, blocker)
+
if parent.operation == "merge":
# Maybe the blocked package can be replaced or simply
# unmerged to resolve this block.
@@ -6446,6 +6455,8 @@ class depgraph(object):
# merge of either package is triggered.
continue
+ self._blocked_pkgs.add(pkg, blocker)
+
# Maybe the blocking package can be
# unmerged to resolve this block.
if parent.operation == "merge" and pkg.installed:
@@ -6498,7 +6509,7 @@ class depgraph(object):
def _accept_blocker_conflicts(self):
acceptable = False
for x in ("--buildpkgonly", "--fetchonly",
- "--fetch-all-uri", "--nodeps", "--pretend"):
+ "--fetch-all-uri", "--nodeps"):
if x in self.myopts:
acceptable = True
break
@@ -6961,6 +6972,7 @@ class depgraph(object):
break
if not satisfied:
skip = True
+ self._blocked_world_pkgs[inst_pkg] = atom
break
except portage.exception.InvalidDependString, e:
portage.writemsg("!!! Invalid PROVIDE in " + \
@@ -7192,6 +7204,74 @@ class depgraph(object):
portage.writemsg("\n", noiselevel=-1)
for line in wrap(msg, 70):
portage.writemsg(prefix + line + "\n", noiselevel=-1)
+
+ # Display the conflicting packages along with the packages
+ # that pulled them in. This is helpful for troubleshooting
+ # cases in which blockers don't solve automatically and
+ # the reasons are not apparent from the normal merge list
+ # display.
+
+ conflict_pkgs = {}
+ for blocker in blockers:
+ for pkg in chain(self._blocked_pkgs.child_nodes(blocker), \
+ self._blocker_parents.parent_nodes(blocker)):
+ parent_atoms = self._parent_atoms.get(pkg)
+ if not parent_atoms:
+ atom = self._blocked_world_pkgs.get(pkg)
+ if atom is not None:
+ parent_atoms = set([("@world", atom)])
+ if parent_atoms:
+ conflict_pkgs[pkg] = parent_atoms
+
+ if conflict_pkgs:
+ msg = []
+ msg.append("\n")
+ indent = " "
+ # Max number of parents shown, to avoid flooding the display.
+ max_parents = 3
+ for pkg, parent_atoms in conflict_pkgs.iteritems():
+
+ pruned_list = set()
+
+ # Prefer conflict packages over others.
+ for parent_atom in parent_atoms:
+ if len(pruned_list) >= max_parents:
+ break
+ parent, atom = parent_atom
+ if parent in conflict_pkgs:
+ pruned_list.add(parent_atom)
+
+ for parent_atom in parent_atoms:
+ if len(pruned_list) >= max_parents:
+ break
+ pruned_list.add(parent_atom)
+
+ omitted_parents = len(parent_atoms) - len(pruned_list)
+ msg.append(indent + "%s pulled in by\n" % pkg)
+
+ for parent_atom in pruned_list:
+ parent, atom = parent_atom
+ msg.append(2*indent)
+ if isinstance(parent,
+ (PackageArg, AtomArg)):
+ # For PackageArg and AtomArg types, it's
+ # redundant to display the atom attribute.
+ msg.append(str(parent))
+ else:
+ # Display the specific atom from SetArg or
+ # Package types.
+ msg.append("%s required by %s" % (atom, parent))
+ msg.append("\n")
+
+ if omitted_parents:
+ msg.append(2*indent)
+ msg.append("(and %d more)\n" % omitted_parents)
+
+ msg.append("\n")
+
+ sys.stderr.write("".join(msg))
+ sys.stderr.flush()
+
if "--quiet" not in self.myopts:
show_blocker_docs_link()