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
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
del e
return 0
- if arg:
- self._set_nodes.add(jbigkey)
built = mytype != "ebuild"
installed = mytype == "installed"
if installed:
# - 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
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
# 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
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