In the package uninstall sanity check, use RDEPEND from the currently
authorZac Medico <zmedico@gentoo.org>
Sun, 4 May 2008 19:41:52 +0000 (19:41 -0000)
committerZac Medico <zmedico@gentoo.org>
Sun, 4 May 2008 19:41:52 +0000 (19:41 -0000)
running 'sys-apps/portage' instance to create a set of protected atoms.

svn path=/main/trunk/; revision=10184

pym/_emerge/__init__.py
pym/portage/const.py

index e89f75ff6ae21ee2c447a23ed26a2475afdccdc3..c788263c505a753b44130108605f8a627e8b77e1 100644 (file)
@@ -3489,18 +3489,42 @@ class depgraph(object):
                                node.operation != "uninstall"]
 
                # sys-apps/portage needs special treatment if ROOT="/"
-               portage_python_dep = ">=dev-lang/python-2.4"
-               portage_unslotted_deps = frozenset(
-                       ["app-shells/bash", "sys-apps/portage"])
-               portage_node = self.mydbapi["/"].match_pkgs("sys-apps/portage")
-               if portage_node:
-                       portage_node = portage_node[0]
+               running_root = "/"
+               from portage.const import PORTAGE_PACKAGE_ATOM
+               runtime_deps = InternalPackageSet(
+                       initial_atoms=[PORTAGE_PACKAGE_ATOM])
+               running_portage = self.trees[running_root]["vartree"].dbapi.match_pkgs(
+                       PORTAGE_PACKAGE_ATOM)
+               replacement_portage = self.mydbapi[running_root].match_pkgs(
+                       PORTAGE_PACKAGE_ATOM)
+
+               if running_portage:
+                       running_portage = running_portage[0]
                else:
-                       portage_node = None
-               if portage_node is not None and \
-                       (not mygraph.contains(portage_node) or \
-                       portage_node.operation == "nomerge"):
-                       portage_node = None
+                       running_portage = None
+
+               if replacement_portage:
+                       replacement_portage = replacement_portage[0]
+               else:
+                       replacement_portage = None
+
+               if replacement_portage == running_portage:
+                       replacement_portage = None
+
+               if running_portage is not None:
+                       try:
+                               portage_rdepend = self._select_atoms_highest_available(
+                                       running_root, running_portage.metadata["RDEPEND"],
+                                       myuse=running_portage.metadata["USE"].split(),
+                                       parent=running_portage, strict=False)
+                       except portage.exception.InvalidDependString, e:
+                               portage.writemsg("!!! Invalid RDEPEND in " + \
+                                       "'%svar/db/pkg/%s/RDEPEND': %s\n" % \
+                                       (running_root, running_portage.cpv, e), noiselevel=-1)
+                               del e
+                               portage_rdepend = []
+                       runtime_deps.update(atom for atom in portage_rdepend \
+                               if not atom.startswith("!"))
 
                ignore_priority_soft_range = [None]
                ignore_priority_soft_range.extend(
@@ -3584,7 +3608,8 @@ class depgraph(object):
                                                        return True
                                                if node not in mergeable_nodes:
                                                        return False
-                                               if node == portage_node and mygraph.child_nodes(node,
+                                               if node == replacement_portage and \
+                                                       mygraph.child_nodes(node,
                                                        ignore_priority=DepPriority.MEDIUM_SOFT):
                                                        # Make sure that portage always has all of it's
                                                        # RDEPENDs installed first.
@@ -3679,20 +3704,26 @@ class depgraph(object):
                                        if self.digraph.contains(inst_pkg):
                                                continue
 
-                                       if "/" == task.root:
+                                       if running_root == task.root:
                                                # Never uninstall sys-apps/portage or it's essential
                                                # dependencies, except through replacement.
-                                               if task.cp in portage_unslotted_deps:
+                                               try:
+                                                       runtime_dep_atoms = \
+                                                               list(runtime_deps.iterAtomsForPackage(task))
+                                               except portage.exception.InvalidDependString, e:
+                                                       portage.writemsg("!!! Invalid PROVIDE in " + \
+                                                               "'%svar/db/pkg/%s/PROVIDE': %s\n" % \
+                                                               (task.root, task.cpv, e), noiselevel=-1)
+                                                       del e
                                                        continue
 
-                                               # Don't uninstall python if it appears to be
-                                               # the only suitable one installed.
-                                               if task.cp == "dev-lang/python" and \
-                                                       portage.match_from_list(
-                                                       portage_python_dep, [task.cpv_slot]):
-                                                       vardb = root_config.trees["vartree"].dbapi
+                                               # Don't uninstall a runtime dep if it appears
+                                               # to be the only suitable one installed.
+                                               skip = False
+                                               vardb = root_config.trees["vartree"].dbapi
+                                               for atom in runtime_dep_atoms:
                                                        other_version = None
-                                                       for pkg in vardb.match_pkgs(portage_python_dep):
+                                                       for pkg in vardb.match_pkgs(atom):
                                                                if pkg.cpv == task.cpv and \
                                                                        pkg.metadata["COUNTER"] == \
                                                                        task.metadata["COUNTER"]:
@@ -3700,7 +3731,10 @@ class depgraph(object):
                                                                other_version = pkg
                                                                break
                                                        if other_version is None:
-                                                               continue
+                                                               skip = True
+                                                               break
+                                               if skip:
+                                                       continue
 
                                                # For packages in the system set, don't take
                                                # any chances. If the conflict can't be resolved
index 733029fa46e4a988cf709fba98ad02b8be208416..bc949fb91a117288ffceb75ec2d74cca2e6e55ac 100644 (file)
@@ -24,6 +24,7 @@ GLOBAL_CONFIG_PATH      = "/usr/share/portage/config"
 PORTAGE_BASE_PATH       = os.path.join(os.sep, os.sep.join(__file__.split(os.sep)[:-3]))
 PORTAGE_BIN_PATH        = PORTAGE_BASE_PATH+"/bin"
 PORTAGE_PYM_PATH        = PORTAGE_BASE_PATH+"/pym"
+PORTAGE_PACKAGE_ATOM    = "sys-apps/portage"
 NEWS_LIB_PATH           = "/var/lib/gentoo"
 PROFILE_PATH            = "/etc/make.profile"
 LOCALE_DATA_PATH        = PORTAGE_BASE_PATH+"/locale"