From: Zac Medico Date: Mon, 30 Jul 2007 05:33:16 +0000 (-0000) Subject: For bug #180045, try to merge PDEPEND as soon as possible so that it behaves more... X-Git-Tag: v2.1.2.11~30 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=8613fbadb3583f147f156200a6d7f7d6e4248119;p=portage.git For bug #180045, try to merge PDEPEND as soon as possible so that it behaves more like RDEPEND. (branches/2.1.2 r7104:7107, r7116:7119, and r7122:7127) svn path=/main/branches/2.1.2.9/; revision=7487 --- diff --git a/bin/emerge b/bin/emerge index df06f74dd..be441ba59 100755 --- a/bin/emerge +++ b/bin/emerge @@ -624,13 +624,15 @@ class DepPriority(object): levels: MEDIUM The upper boundary for medium dependencies. + MEDIUM_SOFT The upper boundary for medium-soft dependencies. SOFT The upper boundary for soft dependencies. MIN The lower boundary for soft dependencies. """ - __slots__ = ("__weakref__", "satisfied", "buildtime", "runtime") + __slots__ = ("__weakref__", "satisfied", "buildtime", "runtime", "runtime_post") MEDIUM = -1 - SOFT = -2 - MIN = -4 + MEDIUM_SOFT = -2 + SOFT = -3 + MIN = -6 def __init__(self, **kwargs): for myattr in self.__slots__: if myattr == "__weakref__": @@ -643,11 +645,15 @@ class DepPriority(object): return 0 if self.runtime: return -1 + if self.runtime_post: + return -2 if self.buildtime: - return -2 - if self.runtime: return -3 - return -4 + if self.runtime: + return -4 + if self.runtime_post: + return -5 + return -6 def __lt__(self, other): return self.__int__() < other def __le__(self, other): @@ -667,8 +673,10 @@ class DepPriority(object): myvalue = self.__int__() if myvalue > self.MEDIUM: return "hard" - if myvalue > self.SOFT: + if myvalue > self.MEDIUM_SOFT: return "medium" + if myvalue > self.SOFT: + return "medium-soft" return "soft" class FakeVartree(portage.vartree): @@ -1261,7 +1269,7 @@ class depgraph: # Post Depend -- Add to the list without a parent, as it depends # on a package being present AND must be built after that package. if not self.select_dep(myroot, edepend["PDEPEND"], myparent=mp, - myuse=myuse, priority=DepPriority(), rev_deps=True, + myuse=myuse, priority=DepPriority(runtime_post=True), parent_arg=arg): return 0 except ValueError, e: @@ -2007,32 +2015,34 @@ class depgraph: if "portage" == portage.catsplit(portage.dep_getkey(cpv))[-1]: asap_nodes.append(node) break - ignore_priority_range = [None] - ignore_priority_range.extend( - xrange(DepPriority.MIN, DepPriority.MEDIUM + 1)) + ignore_priority_soft_range = [None] + ignore_priority_soft_range.extend( + xrange(DepPriority.MIN, DepPriority.SOFT + 1)) tree_mode = "--tree" in self.myopts + # Tracks whether or not the current iteration should prefer asap_nodes + # if available. This is set to False when the previous iteration + # failed to select any nodes. It is reset whenever nodes are + # successfully selected. + prefer_asap = True while not mygraph.empty(): - ignore_priority = None - nodes = None - if asap_nodes: + selected_nodes = None + if prefer_asap and asap_nodes: """ASAP nodes are merged before their soft deps.""" + asap_nodes = [node for node in asap_nodes \ + if mygraph.contains(node)] for node in asap_nodes: - if not mygraph.contains(node): - asap_nodes.remove(node) - continue if not mygraph.child_nodes(node, ignore_priority=DepPriority.SOFT): - nodes = [node] + selected_nodes = [node] asap_nodes.remove(node) break - if not nodes: - for ignore_priority in ignore_priority_range: + if not selected_nodes and \ + not (prefer_asap and asap_nodes): + for ignore_priority in ignore_priority_soft_range: nodes = get_nodes(ignore_priority=ignore_priority) if nodes: break - selected_nodes = None - if nodes: - if ignore_priority <= DepPriority.SOFT: + if nodes: if ignore_priority is None and not tree_mode: # Greedily pop all of these nodes since no relationship # has been ignored. This optimization destroys --tree @@ -2051,30 +2061,65 @@ class depgraph: if not selected_nodes: # settle for a root node selected_nodes = [nodes[0]] - else: + if not selected_nodes: + nodes = get_nodes(ignore_priority=DepPriority.MEDIUM) + if nodes: """Recursively gather a group of nodes that RDEPEND on eachother. This ensures that they are merged as a group and get their RDEPENDs satisfied as soon as possible.""" - def gather_deps(mergeable_nodes, selected_nodes, node): + def gather_deps(ignore_priority, + mergeable_nodes, selected_nodes, node): if node in selected_nodes: return True if node not in mergeable_nodes: return False selected_nodes.add(node) for child in mygraph.child_nodes(node, - ignore_priority=DepPriority.SOFT): - if not gather_deps( + ignore_priority=ignore_priority): + if not gather_deps(ignore_priority, mergeable_nodes, selected_nodes, child): return False return True mergeable_nodes = set(nodes) - for node in nodes: - selected_nodes = set() - if gather_deps( - mergeable_nodes, selected_nodes, node): + if prefer_asap and asap_nodes: + nodes = asap_nodes + for ignore_priority in xrange(DepPriority.SOFT, + DepPriority.MEDIUM_SOFT + 1): + for node in nodes: + selected_nodes = set() + if gather_deps(ignore_priority, + mergeable_nodes, selected_nodes, node): + break + else: + selected_nodes = None + if selected_nodes: break - else: - selected_nodes = None + + if prefer_asap and asap_nodes and not selected_nodes: + # We failed to find any asap nodes to merge, so ignore + # them for the next iteration. + prefer_asap = False + continue + + if selected_nodes and ignore_priority > DepPriority.SOFT: + # Try to merge ignored medium deps as soon as possible. + for node in selected_nodes: + children = set(mygraph.child_nodes(node)) + soft = children.difference( + mygraph.child_nodes(node, + ignore_priority=DepPriority.SOFT)) + medium_soft = children.difference( + mygraph.child_nodes(node, + ignore_priority=DepPriority.MEDIUM_SOFT)) + medium_soft.difference_update(soft) + for child in medium_soft: + if child in selected_nodes: + continue + if child in asap_nodes: + continue + # TODO: Try harder to make these nodes get + # merged absolutely as soon as possible. + asap_nodes.append(child) if not selected_nodes: if not myblockers.is_empty(): @@ -2135,6 +2180,10 @@ class depgraph: print "!!! disabling USE flags that trigger optional dependencies." 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. + prefer_asap = True + for node in selected_nodes: retlist.append(list(node)) mygraph.remove(node)