From bb56b6ea575b796565962ec95741f71aa4d056d4 Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Wed, 18 Oct 2006 07:32:43 +0000 Subject: Add more dependency priority levels for merge order calculations. Previously, all installed deps were categorized at the same level with other soft deps. Now there are 3 priority levels for soft deps: satisfied buildtime, satisfied runtime, and other. svn path=/main/trunk/; revision=4745 --- bin/emerge | 105 ++++++++++++++++++++++++++++++++++++++++++++++++--------- pym/portage.py | 23 ++++--------- 2 files changed, 97 insertions(+), 31 deletions(-) diff --git a/bin/emerge b/bin/emerge index a3277b239..e249face2 100755 --- a/bin/emerge +++ b/bin/emerge @@ -629,6 +629,76 @@ def filter_iuse_defaults(iuse): else: yield flag +class DepPriority(object): + """ + This class generates an integer priority level based of various + attributes of the dependency relationship. Attributes can be assigned + at any time and the new integer value will be generated on calls to the + __int__() method. Rich comparison operators are supported. + + The boolean attributes that affect the integer value are "satisfied", + "buildtime", "runtime", and "system". Various combinations of + attributes lead to the following priority levels: + + Combination of properties Priority level + + not satisfied and buildtime 0 + not satisfied and runtime -1 + satisfied and buildtime -2 + satisfied and runtime -3 + (none of the above) -4 + + Several integer constants are defined for categorization of priority + levels: + + MEDIUM The upper boundary for medium dependencies. + SOFT The upper boundary for soft dependencies. + MIN The lower boundary for soft dependencies. + """ + __slots__ = ["satisfied", "buildtime", "runtime", "system"] + MEDIUM = -1 + SOFT = -2 + MIN = -4 + def __init__(self, **kwargs): + for myattr in self.__slots__: + myvalue = kwargs.get(myattr, False) + setattr(self, myattr, myvalue) + def __int__(self): + if not self.satisfied: + if self.buildtime: + return 0 + if self.runtime: + return -1 + if self.buildtime: + return -2 + if self.runtime: + return -3 + if self.system: + return -4 + return -5 + def __lt__(self, other): + return int(self) < other + def __le__(self, other): + return int(self) <= other + def __eq__(self, other): + return int(self) == other + def __ne__(self, other): + return int(self) != other + def __gt__(self, other): + return int(self) > other + def __ge__(self, other): + return int(self) >= other + def copy(self): + import copy + return copy.copy(self) + def __str__(self): + myvalue = int(self) + if myvalue > self.MEDIUM: + return "hard" + if myvalue > self.SOFT: + return "medium" + return "soft" + class depgraph: pkg_tree_map = { @@ -691,7 +761,7 @@ class depgraph: self.blocker_parents = {} def create(self, mybigkey, myparent=None, addme=1, myuse=None, - priority=digraph.HARD, rev_dep=False, arg=None): + priority=DepPriority(), rev_dep=False, arg=None): """ Fills the digraph with nodes comprised of packages to merge. mybigkey is the package spec of the package to merge. @@ -734,7 +804,7 @@ class depgraph: if addme and "--buildpkgonly" not in self.myopts and myparent: mybigkey[1] = myparent.split()[1] self.digraph.addnode(" ".join(mybigkey), myparent, - priority=digraph.SOFT) + priority=DepPriority()) return 1 if not arg: arg = portage.best_match_to_list(mykey, self.args_keys) @@ -845,7 +915,8 @@ class depgraph: try: if not self.select_dep("/", edepend["DEPEND"], myparent=mp, - myuse=myuse, parent_arg=arg): + myuse=myuse, priority=DepPriority(buildtime=True), + parent_arg=arg): return 0 """RDEPEND is soft by definition. However, in order to ensure correct merge order, we make it a hard dependency. Otherwise, a @@ -853,13 +924,15 @@ class depgraph: dependencies not being installed yet. """ if not self.select_dep(myroot,edepend["RDEPEND"], myparent=mp, - myuse=myuse, priority=digraph.MEDIUM, parent_arg=arg): + myuse=myuse, priority=DepPriority(runtime=True), + parent_arg=arg): return 0 if edepend.has_key("PDEPEND") and edepend["PDEPEND"]: # 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=digraph.SOFT, rev_deps=True, parent_arg=arg): + myuse=myuse, priority=DepPriority(), rev_deps=True, + parent_arg=arg): return 0 except ValueError, e: pkgs = e.args[0] @@ -1055,8 +1128,8 @@ class depgraph: return match def select_dep(self, myroot, depstring, myparent=None, arg=None, - myuse=None, raise_on_missing=False, priority=digraph.HARD, rev_deps=False, - parent_arg=None): + myuse=None, raise_on_missing=False, priority=DepPriority(), + rev_deps=False, parent_arg=None): """ Given a depstring, create the depgraph such that all dependencies are satisfied. myroot = $ROOT from environment, where {R,P}DEPENDs are merged to. myparent = the node whose depstring is being passed in @@ -1301,9 +1374,9 @@ class depgraph: if myparent: #we are a dependency, so we want to be unconditionally added - mypriority = priority - if mypriority > digraph.SOFT and vardb.match(x): - mypriority = digraph.SOFT + mypriority = priority.copy() + if vardb.match(x): + mypriority.satisfied = True if not self.create(selected_pkg[0:3], myparent, myuse=selected_pkg[-1], priority=mypriority, rev_dep=rev_deps, arg=arg): @@ -1398,15 +1471,17 @@ class depgraph: get_nodes = mygraph.root_nodes else: get_nodes = mygraph.leaf_nodes + ignore_priority_range = [None] + ignore_priority_range.extend( + xrange(DepPriority.MIN, DepPriority.MEDIUM)) while not mygraph.empty(): - for ignore_priority in \ - (digraph.NONE, digraph.SOFT, digraph.MEDIUM): + for ignore_priority in ignore_priority_range: nodes = get_nodes(ignore_priority=ignore_priority) if nodes: break selected_nodes = None if nodes: - if ignore_priority <= digraph.SOFT: + if ignore_priority <= DepPriority.SOFT: selected_nodes = [nodes[0]] else: """Recursively gather a group of nodes that RDEPEND on @@ -1419,7 +1494,7 @@ class depgraph: return False selected_nodes.add(node) for child in mygraph.child_nodes(node, - ignore_priority=digraph.SOFT): + ignore_priority=DepPriority.SOFT): if not gather_deps( mergeable_nodes, selected_nodes, child): return False @@ -1476,7 +1551,7 @@ class depgraph: for node in myblockers.root_nodes(): retlist.append(node.split()) for parent in self.blocker_parents[node]: - self.digraph.add(node, parent, priority=digraph.SOFT) + self.digraph.add(node, parent, priority=DepPriority()) return retlist diff --git a/pym/portage.py b/pym/portage.py index aecbda293..4d6c86a04 100644 --- a/pym/portage.py +++ b/pym/portage.py @@ -312,10 +312,6 @@ def flatten(mytokens): #beautiful directed graph object class digraph: - NONE = -1 - SOFT = 0 - MEDIUM = 1 - HARD = 2 def __init__(self): """Create an empty digraph""" @@ -323,7 +319,7 @@ class digraph: self.nodes = {} self.order = [] - def add(self, node, parent, priority=2): + def add(self, node, parent, priority=0): """Adds the specified node with the specified parent. If the dep is a soft-dep and the node already has a hard @@ -376,9 +372,9 @@ class digraph: """Return a list of all nodes in the graph""" return self.order[:] - def child_nodes(self, node, ignore_priority=-1): + def child_nodes(self, node, ignore_priority=None): """Return all children of the specified node""" - if ignore_priority == -1: + if ignore_priority is None: return self.nodes[node][0].keys() children = [] for child, priority in self.nodes[node][0].iteritems(): @@ -390,7 +386,7 @@ class digraph: """Return all parents of the specified node""" return self.nodes[node][1].keys() - def leaf_nodes(self, ignore_priority=-1): + def leaf_nodes(self, ignore_priority=None): """Return all nodes that have no children If ignore_soft_deps is True, soft deps are not counted as @@ -407,7 +403,7 @@ class digraph: leaf_nodes.append(node) return leaf_nodes - def root_nodes(self, ignore_priority=-1): + def root_nodes(self, ignore_priority=None): """Return all nodes that have no parents. If ignore_soft_deps is True, soft deps are not counted as @@ -454,7 +450,7 @@ class digraph: return leaf_nodes[0] return None - def hasallzeros(self, ignore_priority=-1): + def hasallzeros(self, ignore_priority=None): return len(self.leaf_nodes(ignore_priority=ignore_priority)) == \ len(self.order) @@ -467,12 +463,7 @@ class digraph: print "(no children)" for child in self.nodes[node][0]: print " ",child, - if self.nodes[node][0][child] == self.HARD: - print "(hard)" - elif self.nodes[node][0][child] == self.MEDIUM: - print "(medium)" - else: - print "(soft)" + print "(%s)" % self.nodes[node][0][child] -- cgit v1.2.3-1-g7c22