Make depgraph creation more tolerant of missing or masked packages when
authorZac Medico <zmedico@gentoo.org>
Mon, 31 Mar 2008 20:06:10 +0000 (20:06 -0000)
committerZac Medico <zmedico@gentoo.org>
Mon, 31 Mar 2008 20:06:10 +0000 (20:06 -0000)
the relevant deps are satisfied by installed packages. This kind of
friendliness is especially desired in cases such as --emptytree where
it might not be possible to reinstall every single package. Also, it
allows multislot atoms from the world file (that are necessary to prevent
them from being removed by depclean) trigger warning messages while
still allowing a --emptytree to proceed. (trunk r9643:9648)

svn path=/main/branches/2.1.2/; revision=9649

bin/emerge

index 49e521ba24698ed2ff01e7b54b7a0a0ea52c3172..44715665497ab216c2035d0de7127c8db93dc8a1 100755 (executable)
@@ -1269,7 +1269,7 @@ def show_masked_packages(masked_packages):
 class Package(object):
        __slots__ = ("__weakref__", "built", "cpv", "depth",
                "installed", "metadata", "root", "onlydeps", "type_name",
-               "cpv_slot", "slot_atom", "_digraph_node")
+               "cp", "cpv_slot", "slot_atom", "_digraph_node")
        def __init__(self, **kwargs):
                for myattr in self.__slots__:
                        if myattr == "__weakref__":
@@ -1277,9 +1277,8 @@ class Package(object):
                        myvalue = kwargs.get(myattr, None)
                        setattr(self, myattr, myvalue)
 
-               self.slot_atom = "%s:%s" % \
-                       (portage.cpv_getkey(self.cpv), self.metadata["SLOT"])
-
+               self.cp = portage.cpv_getkey(self.cpv)
+               self.slot_atom = "%s:%s" % (self.cp, self.metadata["SLOT"])
                self.cpv_slot = "%s:%s" % (self.cpv, self.metadata["SLOT"])
 
                status = "merge"
@@ -2087,9 +2086,12 @@ class depgraph:
                                        return False, myfavorites
 
                                if pkg.installed and "selective" not in self.myparams:
+                                       # Previous behavior was to bail out in this case, but
+                                       # since the dep is satisfied by the installed package,
+                                       # it's more friendly to continue building the graph
+                                       # and just show a warning message.
                                        self._unsatisfied_deps_for_display.append(
                                                ((myroot, myatom), {"myparent":None}))
-                                       return 0, myfavorites
 
                                try:
                                        self.mysd = self.create(pkg, None)
@@ -2212,7 +2214,6 @@ class depgraph:
                empty = "empty" in self.myparams
                selective = "selective" in self.myparams
                noreplace = "--noreplace" in self.myopts
-               reinstall = False
                # Behavior of the "selective" parameter depends on
                # whether or not a package matches an argument atom.
                # If an installed package provides an old-style
@@ -2231,14 +2232,6 @@ class depgraph:
                        for db, pkg_type, built, installed, db_keys in dbs:
                                if existing_node:
                                        break
-                               if installed and not find_existing_node and \
-                                       (reinstall or not selective) and \
-                                       (matched_packages or empty):
-                                       # We only need to select an installed package in the
-                                       # following cases:
-                                       #   1) there is no other choice
-                                       #   2) selective is True
-                                       continue
                                if hasattr(db, "xmatch"):
                                        cpv_list = db.xmatch("match-all", atom)
                                else:
@@ -2328,7 +2321,7 @@ class depgraph:
                                        if not installed and \
                                                ("--newuse" in self.myopts or \
                                                "--reinstall" in self.myopts) and \
-                                               vardb.cpv_exists(cpv):
+                                               cpv in vardb.match(atom):
                                                pkgsettings.setcpv(cpv, mydb=metadata)
                                                forced_flags = set()
                                                forced_flags.update(pkgsettings.useforce)
@@ -2343,8 +2336,6 @@ class depgraph:
                                                        self._reinstall_for_flags(
                                                        forced_flags, old_use, old_iuse,
                                                        cur_use, cur_iuse)
-                                               if reinstall_for_flags:
-                                                       reinstall = True
                                        if not installed:
                                                must_reinstall = empty or \
                                                        (myarg and not selective)
@@ -2352,11 +2343,6 @@ class depgraph:
                                                        not must_reinstall and \
                                                        cpv in vardb.match(atom):
                                                        break
-                                       if installed:
-                                               must_reinstall = empty or \
-                                                       (found_available_arg and not selective)
-                                               if must_reinstall:
-                                                       break
                                        # Metadata accessed above is cached internally by
                                        # each db in order to optimize visibility checks.
                                        # Now that all possible checks visibility checks
@@ -2369,14 +2355,20 @@ class depgraph:
                                                pkgsettings.setcpv(cpv, mydb=metadata)
                                                metadata["USE"] = pkgsettings["PORTAGE_USE"]
                                                myeb = cpv
-                                       matched_packages.append(
-                                               Package(type_name=pkg_type, root=root,
-                                                       cpv=cpv, metadata=metadata,
-                                                       built=built, installed=installed,
-                                                       onlydeps=onlydeps))
+                                       want_reinstall = False
+                                       if installed:
+                                               want_reinstall = empty or \
+                                                       (found_available_arg and not selective)
+                                       pkg = Package(type_name=pkg_type, root=root,
+                                               cpv=cpv, metadata=metadata,
+                                               built=built, installed=installed,
+                                               onlydeps=onlydeps)
+                                       if installed and want_reinstall:
+                                               matched_packages.insert(0, pkg)
+                                       else:
+                                               matched_packages.append(pkg)
                                        if reinstall_for_flags:
-                                               pkg_node = (pkg_type, root, cpv, "merge")
-                                               self._reinstall_nodes[pkg_node] = \
+                                               self._reinstall_nodes[pkg] = \
                                                        reinstall_for_flags
                                        break
 
@@ -2387,11 +2379,25 @@ class depgraph:
                        for pkg in matched_packages:
                                print (pkg.type_name + ":").rjust(10), pkg.cpv
 
+               # Filter out any old-style virtual matches if they are
+               # mixed with new-style virtual matches.
+               cp = portage.dep_getkey(atom)
+               if len(matched_packages) > 1 and \
+                       "virtual" == portage.catsplit(cp)[0]:
+                       for pkg in matched_packages:
+                               if pkg.cp != cp:
+                                       continue
+                               # Got a new-style virtual, so filter
+                               # out any old-style virtuals.
+                               matched_packages = [pkg for pkg in matched_packages \
+                                       if pkg.cp == cp]
+                               break
+
                if len(matched_packages) > 1:
                        bestmatch = portage.best(
                                [pkg.cpv for pkg in matched_packages])
                        matched_packages = [pkg for pkg in matched_packages \
-                               if pkg.cpv == bestmatch]
+                               if portage_dep.cpvequal(pkg.cpv, bestmatch)]
 
                # ordered by type preference ("ebuild" type is the last resort)
                return  matched_packages[-1], existing_node
@@ -3106,6 +3112,14 @@ class depgraph:
                                self._missing_args.append(mydep)
                                continue
 
+                       if pkg.installed and "selective" not in self.myparams:
+                               # Previous behavior was to bail out in this case, but
+                               # since the dep is satisfied by the installed package,
+                               # it's more friendly to continue building the graph
+                               # and just show a warning message.
+                               self._unsatisfied_deps_for_display.append(
+                                       ((myroot, mydep), {"myparent":None}))
+
                        if not self.create(pkg, None):
                                print >> sys.stderr, "\n\n!!! Problem resolving dependencies for", mydep
                                return 0
@@ -3746,6 +3760,7 @@ class depgraph:
                                print bold('*'+revision)
                                sys.stdout.write(text)
 
+               sys.stdout.flush()
                self.display_problems()
                return os.EX_OK