Support ACCEPT_RESTRICT for bug #467622. v2.2.0_alpha174
authorZac Medico <zmedico@gentoo.org>
Fri, 3 May 2013 03:45:39 +0000 (20:45 -0700)
committerZac Medico <zmedico@gentoo.org>
Fri, 3 May 2013 03:46:38 +0000 (20:46 -0700)
cnf/make.globals
man/emerge.1
man/make.conf.5
man/portage.5
pym/_emerge/Package.py
pym/_emerge/main.py
pym/portage/dbapi/bintree.py
pym/portage/dbapi/porttree.py
pym/portage/package/ebuild/_config/special_env_vars.py
pym/portage/package/ebuild/config.py
pym/portage/package/ebuild/getmaskingstatus.py

index f0597c1236db15797b69090ad9ccbd0d027c7174..6dd350992e9bfe6ad99e3773baa72fc27a532987 100644 (file)
@@ -28,6 +28,7 @@ GENTOO_MIRRORS="http://distfiles.gentoo.org"
 
 ACCEPT_LICENSE="* -@EULA"
 ACCEPT_PROPERTIES="*"
+ACCEPT_RESTRICT="*"
 
 # Repository Paths
 PORTDIR=/usr/portage
index 15e8185fa568615148bda10c9a16c926b30c36d3..23b023cf027d1124885e3dcf97dcc96dbe78311e 100644 (file)
@@ -277,6 +277,21 @@ temporarily mask interactive packages. With default
 configuration, this would result in an effective
 \fBACCEPT_PROPERTIES\fR value of "* -interactive".
 .TP
+.BR \-\-accept\-restrict=ACCEPT_RESTRICT
+This option temporarily overrides the \fBACCEPT_RESTRICT\fR
+variable. The \fBACCEPT_RESTRICT\fR variable is incremental,
+which means that the specified setting is appended to the
+existing value from your configuration. The special \fB-*\fR
+token can be used to discard the existing configuration
+value and start fresh. See the \fBMASKED PACKAGES\fR section
+and \fBmake.conf\fR(5) for more information about
+ACCEPT_RESTRICT. A typical usage example for this option
+would be to use \fI\-\-accept\-restrict=\-bindist\fR to
+temporarily mask packages that are not binary
+re\-distributable. With default
+configuration, this would result in an effective
+\fBACCEPT_RESTRICT\fR value of "* -bindist".
+.TP
 .BR "\-\-alphabetical "
 When displaying USE and other flag output, combines the enabled and
 disabled lists into one list and sorts the whole list alphabetically.
@@ -1041,6 +1056,15 @@ of a package masked by \fBPROPERTIES\fR. See \fBmake.conf\fR(5) for information
 about \fBACCEPT_PROPERTIES\fR, and see \fBportage\fR(5) for information about
 \fI/etc/portage/package.properties\fR. Use the \fB\-\-accept\-properties\fR
 option to temporarily override \fBACCEPT_PROPERTIES\fR.
+.TP
+.BR RESTRICT
+The \fBRESTRICT\fR variable in an \fBebuild\fR file can be used to mask
+packages based on RESTRICT tokens. \fBemerge\fR examines the
+\fBACCEPT_RESTRICT\fR environment variable to allow or disallow the emerging
+of a package masked by \fBRESTRICT\fR. See \fBmake.conf\fR(5) for information
+about \fBACCEPT_RESTRICT\fR, and see \fBportage\fR(5) for information about
+\fI/etc/portage/package.accept_restrict\fR. Use the \fB\-\-accept\-restrict\fR
+option to temporarily override \fBACCEPT_RESTRICT\fR.
 .SH "CONFIGURATION FILES"
 Portage has a special feature called "config file protection". The purpose of
 this feature is to prevent new package installs from clobbering existing
index 8c6d477ce7c94bc586cbab8462785934560f28d9..19118ff7e613c98c45afe095e656a740bdaa09f6 100644 (file)
@@ -80,6 +80,23 @@ ACCEPT_PROPERTIES="*"
 ACCEPT_PROPERTIES="* -interactive"
 .fi
 .TP
+\fBACCEPT_RESTRICT\fR = \fI[space delimited list of RESTRICT tokens]\fR
+This variable is used to mask packages based on RESTRICT tokens.
+In addition to RESTRICT tokens, the \fI*\fR and \fI-*\fR wildcard tokens are
+also supported. This variable can be temporarily overridden using the
+\fB\-\-accept\-restrict\fR option of \fBemerge\fR(1).
+See \fBebuild\fR(5) for more information about RESTRICT.
+.br
+Defaults to the value of *.
+.br
+.I Examples:
+.nf
+# Accept any restrict tokens
+ACCEPT_RESTRICT="*"
+# Accept any tokens except "bindist"
+ACCEPT_RESTRICT="* -bindist"
+.fi
+.TP
 .B CBUILD
 This variable is passed by the \fIebuild scripts\fR to the \fIconfigure\fR
 as \fI\-\-build=${CBUILD}\fR only if it is defined.  Do not set this yourself
index 686e318e28872bcfd9b9961020223ba660d95d8c..46a64f106b7c2170578feff3850ff20801da8ef1 100644 (file)
@@ -57,6 +57,7 @@ make.conf
 mirrors
 modules
 package.accept_keywords
+package.accept_restrict
 package.env
 package.keywords
 package.license
@@ -672,6 +673,16 @@ package.accept_keywords like this:
 
 games-fps/quake3-demo x86
 
+.TP
+.BR package.accept_restrict
+This will allow ACCEPT_RESTRICT (see \fBmake.conf\fR(5)) to be augmented for a
+single package.
+
+.I Format:
+.nf
+\- comment lines begin with # (no inline comments)
+\- one DEPEND atom per line followed by additional RESTRICT tokens
+.fi
 .TP
 .BR package.env
 Per\-package environment variable settings. Entries refer to
index ae0357661343bc2ac48c7e20472b9c1f470db63e..c795568e56fd7f65dde7002fdd7146f094708653 100644 (file)
@@ -332,6 +332,15 @@ class Package(Task):
                        # already recorded as 'invalid'
                        pass
 
+               try:
+                       missing_restricts = settings._getMissingRestrict(
+                               self.cpv, self._metadata)
+                       if missing_restricts:
+                               masks['RESTRICT'] = missing_restricts
+               except InvalidDependString:
+                       # already recorded as 'invalid'
+                       pass
+
                mask_atom = settings._getMaskAtom(self.cpv, self._metadata)
                if mask_atom is not None:
                        masks['package.mask'] = mask_atom
@@ -364,7 +373,8 @@ class Package(Task):
                                'CHOST' in masks or \
                                'EAPI.deprecated' in masks or \
                                'KEYWORDS' in masks or \
-                               'PROPERTIES' in masks):
+                               'PROPERTIES' in masks or \
+                               'RESTRICT' in masks):
                                return False
 
                        if 'package.mask' in masks or \
index c0e2d9643f918d068a753f4bb329bd094ff9aa1e..8afb56da9763d85b2f63879312436572588c8240 100644 (file)
@@ -326,6 +326,11 @@ def parse_opts(tmpcmdline, silent=False):
                        "action":"store"
                },
 
+               "--accept-restrict": {
+                       "help":"temporarily override ACCEPT_RESTRICT",
+                       "action":"store"
+               },
+
                "--backtrack": {
 
                        "help"   : "Specifies how many times to backtrack if dependency " + \
@@ -1016,6 +1021,8 @@ def emerge_main(args=None):
                os.environ["ROOT"] = myopts["--root"]
        if "--accept-properties" in myopts:
                os.environ["ACCEPT_PROPERTIES"] = myopts["--accept-properties"]
+       if "--accept-restrict" in myopts:
+               os.environ["ACCEPT_RESTRICT"] = myopts["--accept-restrict"]
 
        # optimize --help (no need to load config / EMERGE_DEFAULT_OPTS)
        if myaction == "help":
index 01dbad18aec692ac1265704c8d17443f0be97c97..cdd10b37adad76779cf0659894f884005f619008 100644 (file)
@@ -314,7 +314,7 @@ class binarytree(object):
                                "PDEPEND", "PROPERTIES", "PROVIDE")
                        self._pkgindex_header_keys = set([
                                "ACCEPT_KEYWORDS", "ACCEPT_LICENSE",
-                               "ACCEPT_PROPERTIES", "CBUILD",
+                               "ACCEPT_PROPERTIES", "ACCEPT_RESTRICT", "CBUILD",
                                "CONFIG_PROTECT", "CONFIG_PROTECT_MASK", "FEATURES",
                                "GENTOO_MIRRORS", "INSTALL_MASK", "SYNC", "USE"])
                        self._pkgindex_default_pkg_data = {
index e21e53ce61059867a1e9a9e9c897ec87f1cf729b..77f633f75e9e6011db2ed3ba3f499d957c52363d 100644 (file)
@@ -988,6 +988,8 @@ class portdbapi(dbapi):
                                        return False
                                if settings._getMissingProperties(cpv, metadata):
                                        return False
+                               if settings._getMissingRestrict(cpv, metadata):
+                                       return False
                        except InvalidDependString:
                                return False
 
index 481ce693d2392867c5aac0d47203473ad1063f24..96625713bfc66ec8779fe72e08ada15823139601 100644 (file)
@@ -144,7 +144,8 @@ environ_filter += [
 
 # portage config variables and variables set directly by portage
 environ_filter += [
-       "ACCEPT_CHOSTS", "ACCEPT_KEYWORDS", "ACCEPT_PROPERTIES", "AUTOCLEAN",
+       "ACCEPT_CHOSTS", "ACCEPT_KEYWORDS", "ACCEPT_PROPERTIES",
+       "ACCEPT_RESTRICT", "AUTOCLEAN",
        "CLEAN_DELAY", "COLLISION_IGNORE",
        "CONFIG_PROTECT", "CONFIG_PROTECT_MASK",
        "DCO_SIGNED_OFF_BY",
index 96c1734ebb3ec202a8edfd18b5388709937f7f1e..1c29af9eb74d4c42c35629e86e274bd6474652fe 100644 (file)
@@ -219,6 +219,7 @@ class config(object):
                self.uvlist = []
                self._accept_chost_re = None
                self._accept_properties = None
+               self._accept_restrict = None
                self._features_overrides = []
                self._make_defaults = None
                self._parent_stable = None
@@ -307,6 +308,8 @@ class config(object):
 
                        self._accept_properties = copy.deepcopy(clone._accept_properties)
                        self._ppropertiesdict = copy.deepcopy(clone._ppropertiesdict)
+                       self._accept_restrict = copy.deepcopy(clone._accept_restrict)
+                       self._paccept_restrict = copy.deepcopy(clone._paccept_restrict)
                        self._penvdict = copy.deepcopy(clone._penvdict)
                        self._expand_map = copy.deepcopy(clone._expand_map)
 
@@ -603,6 +606,7 @@ class config(object):
                        self.backup_changes("EROOT")
 
                        self._ppropertiesdict = portage.dep.ExtendedAtomDict(dict)
+                       self._paccept_restrict = portage.dep.ExtendedAtomDict(dict)
                        self._penvdict = portage.dep.ExtendedAtomDict(dict)
 
                        #filling PORTDIR and PORTDIR_OVERLAY variable for compatibility
@@ -677,6 +681,20 @@ class config(object):
                                for k, v in propdict.items():
                                        self._ppropertiesdict.setdefault(k.cp, {})[k] = v
 
+                               # package.accept_restrict
+                               d = grabdict_package(os.path.join(
+                                       abs_user_config, "package.accept_restrict"),
+                                       recursive=True, allow_wildcard=True,
+                                       allow_repo=True, verify_eapi=False)
+                               v = d.pop("*/*", None)
+                               if v is not None:
+                                       if "ACCEPT_RESTRICT" in self.configdict["conf"]:
+                                               self.configdict["conf"]["ACCEPT_RESTRICT"] += " " + " ".join(v)
+                                       else:
+                                               self.configdict["conf"]["ACCEPT_RESTRICT"] = " ".join(v)
+                               for k, v in d.items():
+                                       self._paccept_restrict.setdefault(k.cp, {})[k] = v
+
                                #package.env
                                penvdict = grabdict_package(os.path.join(
                                        abs_user_config, "package.env"), recursive=1, allow_wildcard=True, \
@@ -1970,6 +1988,56 @@ class config(object):
                return [x for x in use_reduce(properties_str, uselist=use, flat=True)
                        if x not in acceptable_properties]
 
+       def _getMissingRestrict(self, cpv, metadata):
+               """
+               Take a RESTRICT string and return a list of any tokens the user
+               may need to accept for the given package.  The returned list will not
+               contain any tokens that have already been accepted.  This method
+               can throw an InvalidDependString exception.
+
+               @param cpv: The package name (for package.accept_restrict support)
+               @type cpv: String
+               @param metadata: A dictionary of raw package metadata
+               @type metadata: dict
+               @rtype: List
+               @return: A list of tokens that have not been accepted.
+               """
+               accept_restrict = self._accept_restrict
+               try:
+                       cpv.slot
+               except AttributeError:
+                       cpv = _pkg_str(cpv, metadata=metadata, settings=self)
+               cp = cpv_getkey(cpv)
+               cpdict = self._paccept_restrict.get(cp)
+               if cpdict:
+                       paccept_restrict_list = ordered_by_atom_specificity(cpdict, cpv)
+                       if paccept_restrict_list:
+                               accept_restrict = list(self._accept_restrict)
+                               for x in paccept_restrict_list:
+                                       accept_restrict.extend(x)
+
+               restrict_str = metadata.get("RESTRICT", "")
+               all_restricts = set(use_reduce(restrict_str, matchall=1, flat=True))
+
+               acceptable_restricts = set()
+               for x in accept_restrict:
+                       if x == '*':
+                               acceptable_restricts.update(all_restricts)
+                       elif x == '-*':
+                               acceptable_restricts.clear()
+                       elif x[:1] == '-':
+                               acceptable_restricts.discard(x[1:])
+                       else:
+                               acceptable_restricts.add(x)
+
+               if "?" in restrict_str:
+                       use = metadata["USE"].split()
+               else:
+                       use = []
+
+               return [x for x in use_reduce(restrict_str, uselist=use, flat=True)
+                       if x not in acceptable_restricts]
+
        def _accept_chost(self, cpv, metadata):
                """
                @return True if pkg CHOST is accepted, False otherwise.
@@ -2107,6 +2175,18 @@ class config(object):
                        # repoman will accept any property
                        self._accept_properties = ('*',)
 
+               if self.local_config:
+                       mysplit = []
+                       for curdb in mydbs:
+                               mysplit.extend(curdb.get('ACCEPT_RESTRICT', '').split())
+                       mysplit = prune_incremental(mysplit)
+                       self.configlist[-1]['ACCEPT_RESTRICT'] = ' '.join(mysplit)
+                       if tuple(mysplit) != self._accept_restrict:
+                               self._accept_restrict = tuple(mysplit)
+               else:
+                       # repoman will accept any property
+                       self._accept_restrict = ('*',)
+
                increment_lists = {}
                for k in myincrementals:
                        incremental_list = []
index 5c14b36ffddc95721814490d73580cbaff83abba..c8954aa951d917dd7470fb01016f5b95b9062252 100644 (file)
@@ -1,12 +1,15 @@
-# Copyright 2010-2012 Gentoo Foundation
+# Copyright 2010-2013 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
@@ -84,6 +87,7 @@ def _getmaskingstatus(mycpv, settings, portdb, myrepo=None):
        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:
@@ -169,6 +173,15 @@ def _getmaskingstatus(mycpv, settings, portdb, myrepo=None):
        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):