| # Copyright 2010-2014 Gentoo Foundation |
| # Distributed under the terms of the GNU General Public License v2 |
| |
| from __future__ import unicode_literals |
| |
| __all__ = ['getmaskingstatus'] |
| |
| import sys |
| |
| import portage |
| from portage import eapi_is_supported, _eapi_is_deprecated |
| from portage.exception import InvalidDependString |
| from portage.localization import _ |
| from portage.package.ebuild.config import config |
| from portage.versions import catpkgsplit, _pkg_str |
| |
| if sys.hexversion >= 0x3000000: |
| # pylint: disable=W0622 |
| basestring = str |
| |
| class _UnmaskHint(object): |
| |
| __slots__ = ('key', 'value') |
| |
| def __init__(self, key, value): |
| self.key = key |
| self.value = value |
| |
| class _MaskReason(object): |
| |
| __slots__ = ('category', 'message', 'unmask_hint') |
| |
| def __init__(self, category, message, unmask_hint=None): |
| self.category = category |
| self.message = message |
| self.unmask_hint = unmask_hint |
| |
| def getmaskingstatus(mycpv, settings=None, portdb=None, myrepo=None): |
| if settings is None: |
| settings = config(clone=portage.settings) |
| if portdb is None: |
| portdb = portage.portdb |
| |
| return [mreason.message for \ |
| mreason in _getmaskingstatus(mycpv, settings, portdb,myrepo)] |
| |
| def _getmaskingstatus(mycpv, settings, portdb, myrepo=None): |
| |
| metadata = None |
| installed = False |
| if not isinstance(mycpv, basestring): |
| # emerge passed in a Package instance |
| pkg = mycpv |
| mycpv = pkg.cpv |
| metadata = pkg._metadata |
| installed = pkg.installed |
| |
| if metadata is None: |
| db_keys = list(portdb._aux_cache_keys) |
| try: |
| metadata = dict(zip(db_keys, portdb.aux_get(mycpv, db_keys, myrepo=myrepo))) |
| except KeyError: |
| if not portdb.cpv_exists(mycpv): |
| raise |
| return [_MaskReason("corruption", "corruption")] |
| if "?" in metadata["LICENSE"]: |
| settings.setcpv(mycpv, mydb=metadata) |
| metadata["USE"] = settings["PORTAGE_USE"] |
| else: |
| metadata["USE"] = "" |
| |
| try: |
| mycpv.slot |
| except AttributeError: |
| try: |
| mycpv = _pkg_str(mycpv, metadata=metadata, settings=settings) |
| except portage.exception.InvalidData: |
| raise ValueError(_("invalid CPV: %s") % mycpv) |
| |
| rValue = [] |
| |
| # package.mask checking |
| if settings._getMaskAtom(mycpv, metadata): |
| rValue.append(_MaskReason("package.mask", "package.mask", _UnmaskHint("p_mask", None))) |
| |
| # keywords checking |
| eapi = metadata["EAPI"] |
| mygroups = settings._getKeywords(mycpv, metadata) |
| licenses = metadata["LICENSE"] |
| properties = metadata["PROPERTIES"] |
| restrict = metadata["RESTRICT"] |
| if not eapi_is_supported(eapi): |
| return [_MaskReason("EAPI", "EAPI %s" % eapi)] |
| elif _eapi_is_deprecated(eapi) and not installed: |
| return [_MaskReason("EAPI", "EAPI %s" % eapi)] |
| egroups = settings.configdict["backupenv"].get( |
| "ACCEPT_KEYWORDS", "").split() |
| global_accept_keywords = settings.get("ACCEPT_KEYWORDS", "") |
| pgroups = global_accept_keywords.split() |
| myarch = settings["ARCH"] |
| if pgroups and myarch not in pgroups: |
| """For operating systems other than Linux, ARCH is not necessarily a |
| valid keyword.""" |
| myarch = pgroups[0].lstrip("~") |
| |
| # NOTE: This logic is copied from KeywordsManager.getMissingKeywords(). |
| unmaskgroups = settings._keywords_manager.getPKeywords(mycpv, |
| metadata["SLOT"], metadata["repository"], global_accept_keywords) |
| pgroups.extend(unmaskgroups) |
| if unmaskgroups or egroups: |
| pgroups = settings._keywords_manager._getEgroups(egroups, pgroups) |
| else: |
| pgroups = set(pgroups) |
| |
| kmask = "missing" |
| kmask_hint = None |
| |
| if '**' in pgroups: |
| kmask = None |
| else: |
| for keyword in pgroups: |
| if keyword in mygroups: |
| kmask = None |
| break |
| |
| if kmask: |
| for gp in mygroups: |
| if gp=="*": |
| kmask=None |
| break |
| elif gp == "~*": |
| for x in pgroups: |
| if x[:1] == "~": |
| kmask = None |
| break |
| if kmask is None: |
| break |
| elif gp=="-"+myarch and myarch in pgroups: |
| kmask="-"+myarch |
| break |
| elif gp=="~"+myarch and myarch in pgroups: |
| kmask="~"+myarch |
| kmask_hint = _UnmaskHint("unstable keyword", kmask) |
| break |
| |
| if kmask == "missing": |
| kmask_hint = _UnmaskHint("unstable keyword", "**") |
| |
| try: |
| missing_licenses = settings._getMissingLicenses(mycpv, metadata) |
| if missing_licenses: |
| allowed_tokens = set(["||", "(", ")"]) |
| allowed_tokens.update(missing_licenses) |
| license_split = licenses.split() |
| license_split = [x for x in license_split \ |
| if x in allowed_tokens] |
| msg = license_split[:] |
| msg.append("license(s)") |
| rValue.append(_MaskReason("LICENSE", " ".join(msg), _UnmaskHint("license", set(missing_licenses)))) |
| except portage.exception.InvalidDependString as e: |
| rValue.append(_MaskReason("invalid", "LICENSE: "+str(e))) |
| |
| try: |
| missing_properties = settings._getMissingProperties(mycpv, metadata) |
| if missing_properties: |
| allowed_tokens = set(["||", "(", ")"]) |
| allowed_tokens.update(missing_properties) |
| properties_split = properties.split() |
| properties_split = [x for x in properties_split \ |
| if x in allowed_tokens] |
| msg = properties_split[:] |
| msg.append("properties") |
| rValue.append(_MaskReason("PROPERTIES", " ".join(msg))) |
| except portage.exception.InvalidDependString as e: |
| rValue.append(_MaskReason("invalid", "PROPERTIES: "+str(e))) |
| |
| try: |
| missing_restricts = settings._getMissingRestrict(mycpv, metadata) |
| if missing_restricts: |
| msg = list(missing_restricts) |
| msg.append("in RESTRICT") |
| rValue.append(_MaskReason("RESTRICT", " ".join(msg))) |
| except InvalidDependString as e: |
| rValue.append(_MaskReason("invalid", "RESTRICT: %s" % (e,))) |
| |
| # Only show KEYWORDS masks for installed packages |
| # if they're not masked for any other reason. |
| if kmask and (not installed or not rValue): |
| rValue.append(_MaskReason("KEYWORDS", |
| kmask + " keyword", unmask_hint=kmask_hint)) |
| |
| return rValue |