In the topological sort for merge order, try to avoid selecting root nodes
authorZac Medico <zmedico@gentoo.org>
Wed, 5 Sep 2007 23:09:21 +0000 (23:09 -0000)
committerZac Medico <zmedico@gentoo.org>
Wed, 5 Sep 2007 23:09:21 +0000 (23:09 -0000)
whenever possible. This helps ensure that the maximimum possible number of
soft dependencies  have been removed from the graph before their parent nodes
have been selected. This is especially important when those dependencies are
going to be rebuilt by revdep-rebuild or `emerge -e system` after the CHOST
has been changed (like when building a stage3 from a stage2). With this patch,
`emerge -e system` properly rebuilds dev-lang/python before sys-apps/file,
which helps to avoid a potential build failure.

svn path=/main/trunk/; revision=7728

pym/emerge/__init__.py

index 8354da39f463f857c254880105c5fd1041adb581..2550da4c432f935c6d5465336b9048c649950e26 100644 (file)
@@ -2246,6 +2246,26 @@ class depgraph(object):
                # failed to select any nodes.  It is reset whenever nodes are
                # successfully selected.
                prefer_asap = True
+
+               # By default, try to avoid selecting root nodes whenever possible. This
+               # helps ensure that the maximimum possible number of soft dependencies
+               # have been removed from the graph before their parent nodes have
+               # selected. This is especially important when those dependencies are
+               # going to be rebuilt by revdep-rebuild or `emerge -e system` after the
+               # CHOST has been changed (like when building a stage3 from a stage2).
+               accept_root_node = False
+
+               # State of prefer_asap and accept_root_node flags for successive
+               # iterations that loosen the criteria for node selection.
+               #
+               # iteration   prefer_asap   accept_root_node
+               # 1           True          False
+               # 2           False         False
+               # 3           False         True
+               #
+               # If no nodes are selected on the 4th iteration, it is due to
+               # unresolved blockers or circular dependencies.
+
                while not mygraph.empty():
                        selected_nodes = None
                        if prefer_asap and asap_nodes:
@@ -2280,7 +2300,8 @@ class depgraph(object):
                                                                # found a non-root node
                                                                selected_nodes = [node]
                                                                break
-                                               if not selected_nodes:
+                                               if not selected_nodes and \
+                                                       (accept_root_node or ignore_priority is None):
                                                        # settle for a root node
                                                        selected_nodes = [nodes[0]]
                        if not selected_nodes:
@@ -2313,6 +2334,9 @@ class depgraph(object):
                                        for ignore_priority in xrange(DepPriority.SOFT,
                                                DepPriority.MEDIUM_SOFT + 1):
                                                for node in nodes:
+                                                       if not accept_root_node and \
+                                                               not mygraph.parent_nodes(node):
+                                                               continue
                                                        selected_nodes = set()
                                                        if gather_deps(ignore_priority,
                                                                mergeable_nodes, selected_nodes, node):
@@ -2328,6 +2352,12 @@ class depgraph(object):
                                                prefer_asap = False
                                                continue
 
+                                       if not selected_nodes and not accept_root_node:
+                                               # Maybe there are only root nodes left, so accept them
+                                               # for the next iteration.
+                                               accept_root_node = True
+                                               continue
+
                                        if selected_nodes and ignore_priority > DepPriority.SOFT:
                                                # Try to merge ignored medium deps as soon as possible.
                                                for node in selected_nodes:
@@ -2408,8 +2438,10 @@ class depgraph(object):
                                sys.exit(1)
 
                        # At this point, we've succeeded in selecting one or more nodes, so
-                       # it's now safe to reset the prefer_asap to it's default state.
+                       # it's now safe to reset the prefer_asap and accept_root_node flags
+                       # to their default states.
                        prefer_asap = True
+                       accept_root_node = False
 
                        for node in selected_nodes:
                                if node[-1] != "nomerge":