Add more dependency priority levels for merge order calculations. Previously, all...
authorZac Medico <zmedico@gentoo.org>
Wed, 18 Oct 2006 07:32:43 +0000 (07:32 -0000)
committerZac Medico <zmedico@gentoo.org>
Wed, 18 Oct 2006 07:32:43 +0000 (07:32 -0000)
svn path=/main/trunk/; revision=4745

bin/emerge
pym/portage.py

index a3277b2397e59a48f36caf46d302af9e29d81278..e249face27cd3f1cdc2bc43ea2c2450ab574b07f 100755 (executable)
@@ -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
 
index aecbda2937b1e3c2690de38f048220db2b171fac..4d6c86a040c959a5a94d2f78d509116d04ec4957 100644 (file)
@@ -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]