Bug #337540 - Record nested package set information in the digraph.
authorZac Medico <zmedico@gentoo.org>
Fri, 17 Sep 2010 11:21:38 +0000 (04:21 -0700)
committerZac Medico <zmedico@gentoo.org>
Fri, 17 Sep 2010 11:21:38 +0000 (04:21 -0700)
A new depgraph._expand_set_args() method adds nested SetArg instances
to the digraph, in order to record parent -> child relationships from
nested sets.

pym/_emerge/AtomArg.py
pym/_emerge/PackageArg.py
pym/_emerge/SetArg.py
pym/_emerge/depgraph.py

index 871e2b71da22c404ada3d92b29f9b78c352ea583..f7740753c0147735c7cc437fbf7149cb1e869f0e 100644 (file)
@@ -1,10 +1,11 @@
 # Copyright 1999-2010 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
 
+from portage._sets.base import InternalPackageSet
 from _emerge.DependencyArg import DependencyArg
 
 class AtomArg(DependencyArg):
        def __init__(self, atom=None, **kwargs):
                DependencyArg.__init__(self, **kwargs)
                self.atom = atom
-               self.set = (self.atom, )
+               self.pset = InternalPackageSet(initial_atoms=(self.atom,))
index c4121e31f860d69b0ea9c98c92b8c5dcd34a0306..a169845cc594d1dfbd935c9cf855af9a16049395 100644 (file)
@@ -3,10 +3,11 @@
 
 from _emerge.DependencyArg import DependencyArg
 import portage
+from portage._sets.base import InternalPackageSet
 
 class PackageArg(DependencyArg):
        def __init__(self, package=None, **kwargs):
                DependencyArg.__init__(self, **kwargs)
                self.package = package
                self.atom = portage.dep.Atom("=" + package.cpv)
-               self.set = (self.atom, )
+               self.pset = InternalPackageSet(initial_atoms=(self.atom,))
index 2941695a85f58c8be66bdae5cf87374f173a988b..94cf0a6ceb4e7b76ae6a2555f5d4b7483dde7262 100644 (file)
@@ -1,11 +1,11 @@
-# Copyright 1999-2009 Gentoo Foundation
+# Copyright 1999-2010 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
 
 from _emerge.DependencyArg import DependencyArg
 from portage._sets import SETPREFIX
 class SetArg(DependencyArg):
-       def __init__(self, set=None, **kwargs):
+       def __init__(self, pset=None, **kwargs):
                DependencyArg.__init__(self, **kwargs)
-               self.set = set
+               self.pset = pset
                self.name = self.arg[len(SETPREFIX):]
 
index d47517ebbd14131d1e581a409dfd1c92e40deed6..6a7eb04b7646de1a6dc5a6ce4e8106f7d6f7de95 100644 (file)
@@ -610,6 +610,54 @@ class depgraph(object):
                                        return 0
                return 1
 
+       def _expand_set_args(self, input_args, add_to_digraph=False):
+               """
+               Iterate over a list of DependencyArg instances and yield all
+               instances given in the input together with additional SetArg
+               instances that are generated from nested sets.
+               @param input_args: An iterable of DependencyArg instances
+               @type input_args: Iterable
+               @param add_to_digraph: If True then add SetArg instances
+                       to the digraph, in order to record parent -> child
+                       relationships from nested sets
+               @type add_to_digraph: Boolean
+               @rtype: Iterable
+               @returns: All args given in the input together with additional
+                       SetArg instances that are generated from nested sets
+               """
+
+               traversed_set_args = set()
+
+               for arg in input_args:
+                       if not isinstance(arg, SetArg):
+                               yield arg
+                               continue
+
+                       root_config = arg.root_config
+                       arg_stack = [arg]
+                       while arg_stack:
+                               arg = arg_stack.pop()
+                               if arg in traversed_set_args:
+                                       continue
+                               traversed_set_args.add(arg)
+                               yield arg
+
+                               # Traverse nested sets and add them to the stack
+                               # if they're not already in the graph. Also, graph
+                               # edges between parent and nested sets.
+                               for token in arg.pset.getNonAtoms():
+                                       if not token.startswith(SETPREFIX):
+                                               continue
+                                       s = token[len(SETPREFIX):]
+                                       nested_set = root_config.sets.get(s)
+                                       if nested_set is not None:
+                                               nested_arg = SetArg(arg=token, pset=nested_set,
+                                                       root_config=root_config)
+                                               arg_stack.append(nested_arg)
+                                               if add_to_digraph:
+                                                       self._dynamic_config.digraph.add(nested_arg, arg,
+                                                               priority=BlockerDepPriority.instance)
+
        def _add_dep(self, dep, allow_unsatisfied=False):
                debug = "--debug" in self._frozen_config.myopts
                buildpkgonly = "--buildpkgonly" in self._frozen_config.myopts
@@ -1442,7 +1490,6 @@ class depgraph(object):
                debug = "--debug" in self._frozen_config.myopts
                root_config = self._frozen_config.roots[self._frozen_config.target_root]
                sets = root_config.sets
-               getSetAtoms = root_config.setconfig.getSetAtoms
                myfavorites=[]
                myroot = self._frozen_config.target_root
                dbs = self._dynamic_config._filtered_trees[myroot]["dbs"]
@@ -1530,13 +1577,9 @@ class depgraph(object):
                                                raise portage.exception.PackageSetNotFound(s)
                                        if s in self._dynamic_config._sets:
                                                continue
-                                       # Recursively expand sets so that containment tests in
-                                       # self._get_parent_sets() properly match atoms in nested
-                                       # sets (like if world contains system).
-                                       expanded_set = InternalPackageSet(
-                                               initial_atoms=getSetAtoms(s))
-                                       self._dynamic_config._sets[s] = expanded_set
-                                       args.append(SetArg(arg=x, set=expanded_set,
+                                       pset = sets[s]
+                                       self._dynamic_config._sets[s] = pset
+                                       args.append(SetArg(arg=x, pset=pset,
                                                root_config=root_config))
                                        continue
                                if not is_valid_package_atom(x):
@@ -1723,8 +1766,10 @@ class depgraph(object):
                pkgsettings = self._frozen_config.pkgsettings[myroot]
                pprovideddict = pkgsettings.pprovideddict
                virtuals = pkgsettings.getvirtuals()
-               for arg in self._dynamic_config._initial_arg_list:
-                       for atom in arg.set:
+               for arg in self._expand_set_args(
+                       self._dynamic_config._initial_arg_list,
+                       add_to_digraph=True):
+                       for atom in arg.pset.getAtoms():
                                self._spinner_update()
                                dep = Dependency(atom=atom, onlydeps=onlydeps,
                                        root=myroot, parent=arg)
@@ -1880,11 +1925,17 @@ class depgraph(object):
                        args_set.add(atom)
 
                self._dynamic_config._set_atoms.clear()
-               self._dynamic_config._set_atoms.update(chain(*self._dynamic_config._sets.values()))
+               self._dynamic_config._set_atoms.update(chain.from_iterable(
+                       pset.getAtoms() for pset in self._dynamic_config._sets.values()))
                atom_arg_map = self._dynamic_config._atom_arg_map
                atom_arg_map.clear()
-               for arg in args:
-                       for atom in arg.set:
+
+               # We don't add set args to the digraph here since that
+               # happens at a later stage and we don't want to make
+               # any state changes here that aren't reversed by a
+               # another call to this method.
+               for arg in self._expand_set_args(args, add_to_digraph=False):
+                       for atom in arg.pset.getAtoms():
                                atom_key = (atom, arg.root_config.root)
                                refs = atom_arg_map.get(atom_key)
                                if refs is None:
@@ -3075,19 +3126,18 @@ class depgraph(object):
                        # Create new SetArg instances only when necessary.
                        for s in required_set_names:
                                if required_sets is None or root not in required_sets:
-                                       expanded_set = InternalPackageSet(
-                                               initial_atoms=setconfig.getSetAtoms(s))
+                                       pset = root_config.sets[s]
                                else:
-                                       expanded_set = required_sets[root][s]
+                                       pset = required_sets[root][s]
                                atom = SETPREFIX + s
-                               args.append(SetArg(arg=atom, set=expanded_set,
+                               args.append(SetArg(arg=atom, pset=pset,
                                        root_config=root_config))
                                if root == self._frozen_config.target_root:
-                                       self._dynamic_config._sets[s] = expanded_set
+                                       self._dynamic_config._sets[s] = pset
                        vardb = root_config.trees["vartree"].dbapi
                        while args:
                                arg = args.pop()
-                               for atom in arg.set.getAtoms():
+                               for atom in arg.pset.getAtoms():
                                        self._dynamic_config._dep_stack.append(
                                                Dependency(atom=atom, root=root, parent=arg))
 
@@ -3102,7 +3152,7 @@ class depgraph(object):
                                # Traverse nested sets and add them to the stack
                                # if they're not already in the graph. Also, graph
                                # edges between parent and nested sets.
-                               for token in arg.set.getNonAtoms():
+                               for token in arg.pset.getNonAtoms():
                                        if not token.startswith(SETPREFIX):
                                                continue
                                        s = token[len(SETPREFIX):]
@@ -3110,11 +3160,12 @@ class depgraph(object):
                                        if nested_set is None:
                                                nested_set = root_config.sets.get(s)
                                        if nested_set is not None:
-                                               nested_arg = SetArg(arg=token, set=nested_set,
+                                               nested_arg = SetArg(arg=token, pset=nested_set,
                                                        root_config=root_config)
                                                if nested_arg not in self._dynamic_config.digraph:
                                                        args.append(nested_arg)
-                                               self._dynamic_config.digraph.add(nested_arg, arg)
+                                               self._dynamic_config.digraph.add(nested_arg, arg,
+                                                       priority=BlockerDepPriority.instance)
 
                        if self._dynamic_config._ignored_deps:
                                self._dynamic_config._dep_stack.extend(self._dynamic_config._ignored_deps)
@@ -5653,8 +5704,8 @@ class depgraph(object):
                        # Packages for argument atoms need to be explicitly
                        # added via _add_pkg() so that they are included in the
                        # digraph (needed at least for --tree display).
-                       for arg in args:
-                               for atom in arg.set:
+                       for arg in self._expand_set_args(args, add_to_digraph=True):
+                               for atom in arg.pset.getAtoms():
                                        pkg, existing_node = self._select_package(
                                                arg.root_config.root, atom)
                                        if existing_node is None and \
@@ -5723,7 +5774,6 @@ class depgraph(object):
                DependencyArg instances during graph creation.
                """
                root_config = self._frozen_config.roots[self._frozen_config.target_root]
-               getSetAtoms = root_config.setconfig.getSetAtoms
                sets = root_config.sets
                args = []
                for x in favorites:
@@ -5737,13 +5787,9 @@ class depgraph(object):
                                        continue
                                if s in self._dynamic_config._sets:
                                        continue
-                               # Recursively expand sets so that containment tests in
-                               # self._get_parent_sets() properly match atoms in nested
-                               # sets (like if world contains system).
-                               expanded_set = InternalPackageSet(
-                                       initial_atoms=getSetAtoms(s))
-                               self._dynamic_config._sets[s] = expanded_set
-                               args.append(SetArg(arg=x, set=expanded_set,
+                               pset = sets[s]
+                               self._dynamic_config._sets[s] = pset
+                               args.append(SetArg(arg=x, pset=pset,
                                        root_config=root_config))
                        else:
                                try: