Optimize the new --skipfirst code so that in only has to build
authorZac Medico <zmedico@gentoo.org>
Sat, 31 May 2008 02:08:25 +0000 (02:08 -0000)
committerZac Medico <zmedico@gentoo.org>
Sat, 31 May 2008 02:08:25 +0000 (02:08 -0000)
a new depgraph one time when there are unsatisfied deps. This
works by recursively traversing the digraph to remove the parent
packages whose deps become unsatisfied when their dependencies are
pruned from the mergelist. (trunk r10512:10514)

svn path=/main/branches/2.1.2/; revision=10515

bin/emerge

index 72955612f0ef7afb0f4505307446e686c7fc0d03..a1761e7e7ccc7606fe13d9b0bf4e9d6e42dbeca9 100755 (executable)
@@ -8314,19 +8314,49 @@ def action_build(settings, trees, mtimedb,
                                except depgraph.UnsatisfiedResumeDep, e:
                                        if "--skipfirst" not in myopts:
                                                raise
-                                       unsatisfied_parents = set(dep.parent for dep in e.value)
-                                       pruned_mergelist = []
-                                       for task in mergelist:
-                                               if isinstance(task, list) and \
-                                                       tuple(task) in unsatisfied_parents:
+
+                                       graph = mydepgraph.digraph
+                                       unsatisfied_parents = dict((dep.parent, dep.parent) \
+                                               for dep in e.value)
+                                       traversed_nodes = set()
+                                       unsatisfied_stack = list(unsatisfied_parents)
+                                       while unsatisfied_stack:
+                                               pkg = unsatisfied_stack.pop()
+                                               if pkg in traversed_nodes:
                                                        continue
-                                               pruned_mergelist.append(task)
+                                               traversed_nodes.add(pkg)
+
+                                               # If this package was pulled in by a parent
+                                               # package scheduled for merge, removing this
+                                               # package may cause the the parent package's
+                                               # dependency to become unsatisfied.
+                                               for parent_node in graph.parent_nodes(pkg):
+                                                       if not isinstance(parent_node, Package) \
+                                                               or parent_node.operation != "merge":
+                                                               continue
+                                                       unsatisfied = \
+                                                               graph.child_nodes(parent_node,
+                                                               ignore_priority=DepPriority.SOFT)
+                                                       if pkg in unsatisfied:
+                                                               unsatisfied_parents[parent_node] = parent_node
+                                                               unsatisfied_stack.append(parent_node)
+
+                                       pruned_mergelist = [x for x in mergelist \
+                                               if isinstance(x, list) and \
+                                               tuple(x) not in unsatisfied_parents]
+
+                                       # It shouldn't happen, but if the size of mergelist
+                                       # does not decrease for some reason then the loop
+                                       # will be infinite. Therefore, if that case ever
+                                       # occurs for some reason, raise the exception to
+                                       # break out of the loop.
                                        if not pruned_mergelist or \
                                                len(pruned_mergelist) == len(mergelist):
                                                raise
                                        mergelist[:] = pruned_mergelist
                                        dropped_tasks.update(unsatisfied_parents)
-                                       del e, unsatisfied_parents
+                                       del e, graph, traversed_nodes, \
+                                               unsatisfied_parents, unsatisfied_stack
                                        continue
                                else:
                                        break