Prune circular nested sets from the digraph.
authorZac Medico <zmedico@gentoo.org>
Sat, 2 Oct 2010 20:49:08 +0000 (13:49 -0700)
committerZac Medico <zmedico@gentoo.org>
Sat, 2 Oct 2010 20:49:08 +0000 (13:49 -0700)
This prevents the following traceback which was reported in forum
thread 847007:

  File "pym/_emerge/depgraph.py", line 3694, in _merge_order_bias
    mygraph.order.sort(key=cmp_sort_key(cmp_merge_preference))
  File "pym/portage/util/__init__.py", line 808, in __lt__
    return self._cmp_func(self._obj, other._obj) < 0
  File "pym/_emerge/depgraph.py", line 3675, in cmp_merge_preference
    if node1.operation == 'uninstall':
AttributeError: 'SetArg' object has no attribute 'operation'

pym/_emerge/depgraph.py

index 045e5718476f78dc98c88bec53c40923bcb1da1c..7f5d168641cd0c43b313e0227cbaa4ed0b5d54ce 100644 (file)
@@ -3800,11 +3800,26 @@ class depgraph(object):
                                and node.operation == 'merge'], scheduler_graph)
 
                mygraph=self._dynamic_config.digraph.copy()
+
+               removed_nodes = set()
+
+               # Prune off all DependencyArg instances since they aren't
+               # needed, and because of nested sets this is faster than doing
+               # it with multiple digraph.root_nodes() calls below. This also
+               # takes care of nested sets that have circular references,
+               # which wouldn't be matched by digraph.root_nodes().
+               for node in mygraph:
+                       if isinstance(node, DependencyArg):
+                               removed_nodes.add(node)
+               if removed_nodes:
+                       mygraph.difference_update(removed_nodes)
+                       removed_nodes.clear()
+
                # Prune "nomerge" root nodes if nothing depends on them, since
                # otherwise they slow down merge order calculation. Don't remove
                # non-root nodes since they help optimize merge order in some cases
                # such as revdep-rebuild.
-               removed_nodes = set()
+
                while True:
                        for node in mygraph.root_nodes():
                                if not isinstance(node, Package) or \