Bug #208708 - Show informative warning messages for installed
authorZac Medico <zmedico@gentoo.org>
Sat, 9 Feb 2008 06:26:39 +0000 (06:26 -0000)
committerZac Medico <zmedico@gentoo.org>
Sat, 9 Feb 2008 06:26:39 +0000 (06:26 -0000)
packages that are masked. (trunk r9301)

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

bin/emerge
pym/portage.py

index 0536fb1cbed0de4d58600f666b670ef435852e50..3ed0211e553beba6030300a753afd047c0f75a33 100755 (executable)
@@ -1147,6 +1147,111 @@ def visible(pkgsettings, cpv, metadata, built=False, installed=False):
                return False
        return True
 
+def get_masking_status(pkg, pkgsettings, root_config):
+
+       mreasons = portage.getmaskingstatus(
+               pkg.cpv, metadata=pkg.metadata, settings=pkgsettings,
+               portdb=root_config.trees["porttree"].dbapi)
+
+       if pkg.built and \
+               pkg.metadata["CHOST"] != root_config.settings["CHOST"]:
+               mreasons.append("CHOST: %s" % \
+                       pkg.metadata["CHOST"])
+
+       if not pkg.metadata["SLOT"]:
+               mreasons.append("invalid: SLOT is undefined")
+
+       return mreasons
+
+def get_mask_info(root_config, cpv, pkgsettings,
+       db, pkg_type, built, installed, db_keys):
+       eapi_masked = False
+       try:
+               metadata = dict(izip(db_keys,
+                       db.aux_get(cpv, db_keys)))
+       except KeyError:
+               metadata = None
+       if metadata and not built:
+               pkgsettings.setcpv(cpv, mydb=metadata)
+               metadata["USE"] = pkgsettings.get("USE", "")
+       if metadata is None:
+               mreasons = ["corruption"]
+       else:
+               pkg = Package(type_name=pkg_type, root=root_config.root,
+                       cpv=cpv, built=built, metadata=metadata)
+               mreasons = get_masking_status(pkg, pkgsettings, root_config)
+       return metadata, mreasons
+
+def show_masked_packages(masked_packages):
+       shown_licenses = set()
+       shown_comments = set()
+       # Maybe there is both an ebuild and a binary. Only
+       # show one of them to avoid redundant appearance.
+       shown_cpvs = set()
+       have_eapi_mask = False
+       for (root_config, pkgsettings, cpv,
+               metadata, mreasons) in masked_packages:
+               if cpv in shown_cpvs:
+                       continue
+               shown_cpvs.add(cpv)
+               comment, filename = None, None
+               if "package.mask" in mreasons:
+                       comment, filename = \
+                               portage.getmaskingreason(
+                               cpv, metadata=metadata,
+                               settings=pkgsettings,
+                               portdb=root_config.trees["porttree"].dbapi,
+                               return_location=True)
+               missing_licenses = []
+               if metadata:
+                       if not portage.eapi_is_supported(metadata["EAPI"]):
+                               have_eapi_mask = True
+
+               print "- "+cpv+" (masked by: "+", ".join(mreasons)+")"
+               if comment and comment not in shown_comments:
+                       print filename+":"
+                       print comment
+                       shown_comments.add(comment)
+       return have_eapi_mask
+
+class Package(object):
+       __slots__ = ("__weakref__", "built", "cpv", "depth",
+               "installed", "metadata", "root", "onlydeps", "type_name",
+               "cpv_slot", "slot_atom", "_digraph_node")
+       def __init__(self, **kwargs):
+               for myattr in self.__slots__:
+                       if myattr == "__weakref__":
+                               continue
+                       myvalue = kwargs.get(myattr, None)
+                       setattr(self, myattr, myvalue)
+
+               self.slot_atom = "%s:%s" % \
+                       (portage.cpv_getkey(self.cpv), self.metadata["SLOT"])
+
+               self.cpv_slot = "%s:%s" % (self.cpv, self.metadata["SLOT"])
+
+               status = "merge"
+               if self.onlydeps or self.installed:
+                       status = "nomerge"
+               self._digraph_node = (self.type_name, self.root, self.cpv, status)
+
+       def __eq__(self, other):
+               return self._digraph_node == other
+       def __ne__(self, other):
+               return self._digraph_node != other
+       def __hash__(self):
+               return hash(self._digraph_node)
+       def __len__(self):
+               return len(self._digraph_node)
+       def __getitem__(self, key):
+               return self._digraph_node[key]
+       def __iter__(self):
+               return iter(self._digraph_node)
+       def __contains__(self, key):
+               return key in self._digraph_node
+       def __str__(self):
+               return str(self._digraph_node)
+
 class BlockerCache(DictMixin):
        """This caches blockers of installed packages so that dep_check does not
        have to be done for every single installed package on every invocation of
@@ -1377,6 +1482,7 @@ class depgraph:
                self._altlist_cache = {}
                self._pprovided_args = []
                self._missing_args = []
+               self._masked_installed = []
 
        def _show_slot_collision_notice(self):
                """Show an informational message advising the user to mask one of the
@@ -1658,8 +1764,6 @@ class depgraph:
                                        del e
                                        return 0
 
-               if arg:
-                       self._set_nodes.add(jbigkey)
                        built = mytype != "ebuild"
                        installed = mytype == "installed"
                        if installed:
@@ -1675,20 +1779,27 @@ class depgraph:
                                #  - multi-slot atoms listed in the world file
                                #    to prevent depclean from removing them
 
-                               installed_masked = not visible(
-                                       pkgsettings, mykey, metadata,
-                                       built=built, installed=installed)
+                               if arg:
+                                       all_ebuilds_masked = bool(
+                                               portdb.xmatch("match-all", arg) and
+                                               not portdb.xmatch("bestmatch-visible", arg))
+                                       if all_ebuilds_masked:
+                                               self._missing_args.append(arg)
 
-                               all_ebuilds_masked = bool(
-                                       portdb.xmatch("match-all", arg) and
-                                       not portdb.xmatch("bestmatch-visible", arg))
+                                       if "selective" not in self.myparams:
+                                               self._show_unsatisfied_dep(myroot, arg)
+                                               return 0
 
-                               if installed_masked or all_ebuilds_masked:
-                                       self._missing_args.append(arg)
+                               pkg = Package(type_name=mytype, root=myroot,
+                                       cpv=mykey, built=built, installed=installed,
+                                       metadata=metadata)
 
-                               if "selective" not in self.myparams:
-                                       self._show_unsatisfied_dep(myroot, arg)
-                                       return 0
+                               if not visible(pkgsettings, pkg.cpv, pkg.metadata,
+                                       built=pkg.built, installed=pkg.installed):
+                                       self._masked_installed.append((pkg, pkgsettings))
+
+               if arg:
+                       self._set_nodes.add(jbigkey)
 
                # Do this even when addme is False (--onlydeps) so that the
                # parent/child relationship is always known in case
@@ -2014,9 +2125,9 @@ class depgraph:
                                red(' [%s]' % myparent[0]) + ')'
                masked_packages = []
                missing_licenses = []
-               from textwrap import wrap
                have_eapi_mask = False
                pkgsettings = self.pkgsettings[root]
+               root_config = self.roots[root]
                portdb = self.roots[root].trees["porttree"].dbapi
                dbs = []
                portdb = self.trees[root]["porttree"].dbapi
@@ -2040,59 +2151,22 @@ class depgraph:
                        # descending order
                        cpv_list.reverse()
                        for cpv in cpv_list:
-                               try:
-                                       metadata = dict(izip(db_keys,
-                                               db.aux_get(cpv, db_keys)))
-                               except KeyError:
-                                       mreasons = ["corruption"]
-                                       metadata = None
-                               mreasons = portage.getmaskingstatus(
-                                       cpv, metadata=metadata,
-                                       settings=pkgsettings, portdb=portdb)
-                               comment, filename = None, None
-                               if "package.mask" in mreasons:
-                                       comment, filename = \
-                                               portage.getmaskingreason(
-                                               cpv, metadata=metadata,
-                                               settings=pkgsettings, portdb=portdb,
-                                               return_location=True)
-                               if built and \
-                                       metadata["CHOST"] != pkgsettings["CHOST"]:
-                                       mreasons.append("CHOST: %s" % \
-                                               metadata["CHOST"])
-                               missing_licenses = []
-                               if metadata:
-                                       if not metadata["SLOT"]:
-                                               mreasons.append("invalid: SLOT is undefined")
-                                       if not portage.eapi_is_supported(metadata["EAPI"]):
-                                               have_eapi_mask = True
-                               if not mreasons:
-                                       continue
-                               masked_packages.append((cpv, mreasons,
-                                       comment, filename, missing_licenses))
+                               metadata, mreasons  = get_mask_info(root_config, cpv,
+                                       pkgsettings, db, pkg_type, built, installed, db_keys)
+                               masked_packages.append(
+                                       (root_config, pkgsettings, cpv, metadata, mreasons))
+
                if masked_packages:
                        print "\n!!! "+red("All ebuilds that could satisfy ")+green(xinfo)+red(" have been masked.")
                        print "!!! One of the following masked packages is required to complete your request:"
-                       shown_licenses = set()
-                       shown_comments = set()
-                       # Maybe there is both an ebuild and a binary. Only
-                       # show one of them to avoid redundant appearance.
-                       shown_cpvs = set()
-                       for cpv, mreasons, comment, filename, missing_licenses in masked_packages:
-                               if cpv in shown_cpvs:
-                                       continue
-                               shown_cpvs.add(cpv)
-                               print "- "+cpv+" (masked by: "+", ".join(mreasons)+")"
-                               if comment and comment not in shown_comments:
-                                       print filename+":"
-                                       print comment
-                                       shown_comments.add(comment)
+                       have_eapi_mask = show_masked_packages(masked_packages)
                        if have_eapi_mask:
                                print
                                msg = ("The current version of portage supports " + \
                                        "EAPI '%s'. You must upgrade to a newer version" + \
                                        " of portage before EAPI masked packages can" + \
                                        " be installed.") % portage_const.EAPI
+                               from textwrap import wrap
                                for line in wrap(msg, 75):
                                        print line
                        print
@@ -2959,6 +3033,17 @@ class depgraph:
                        except portage_exception.PackageNotFound:
                                missing_atoms.append(mydep)
 
+               masked_packages = []
+               for pkg, pkgsettings in self._masked_installed:
+                       root_config = self.roots[pkg.root]
+                       mreasons = get_masking_status(pkg, pkgsettings, root_config)
+                       masked_packages.append((root_config, pkgsettings,
+                               pkg.cpv, pkg.metadata, mreasons))
+               if masked_packages:
+                       sys.stderr.write("\n" + colorize("BAD", "!!!") + \
+                               " The following installed packages are masked:\n")
+                       show_masked_packages(masked_packages)
+
                if not self.validate_blockers():
                        return False
 
index 43dc6704e22b2a9a55fb5efa5264e79bed45cc5e..e27e30a3d5e2455954708c052b6e08ae6a104f05 100644 (file)
@@ -1877,7 +1877,11 @@ class config:
                pkginternaluse = ""
                iuse = ""
                if mydb:
-                       slot, iuse = mydb.aux_get(self.mycpv, ["SLOT", "IUSE"])
+                       if isinstance(mydb, dict):
+                               slot = mydb["SLOT"]
+                               iuse = mydb["IUSE"]
+                       else:
+                               slot, iuse = mydb.aux_get(self.mycpv, ["SLOT", "IUSE"])
                        cpv_slot = "%s:%s" % (self.mycpv, slot)
                        pkginternaluse = []
                        for x in iuse.split():
@@ -6891,7 +6895,8 @@ class portdbapi(dbapi):
                                self.auxdb[x] = self.auxdbmodule(
                                        self.depcachedir, x, filtered_auxdbkeys, gid=portage_gid)
                # Selectively cache metadata in order to optimize dep matching.
-               self._aux_cache_keys = set(["EAPI", "KEYWORDS", "SLOT"])
+               self._aux_cache_keys = set(
+                       ["EAPI", "IUSE", "KEYWORDS", "LICENSE", "PROVIDE", "SLOT"])
                self._aux_cache = {}
                self._broken_ebuilds = set()