protected by \fICONFIG_PROTECT\fR, unmerge it even if the modification time or
checksum differs from the file that was originally installed.
.TP
+.B unknown\-features\-filter
+Filter out any unknown values that the FEATURES variable contains.
+.TP
.B unknown\-features\-warn
Warn if FEATURES contains one or more unknown values.
.TP
"selinux", "sesandbox", "severe", "sfperms",
"sign", "skiprocheck", "split-elog", "split-log", "splitdebug",
"strict", "stricter", "suidctl", "test", "test-fail-continue",
- "unknown-features-warn",
+ "unknown-features-filter", "unknown-features-warn",
"unmerge-logs", "unmerge-orphans", "userfetch", "userpriv",
"usersandbox", "usersync", "webrsync-gpg"])
'features_set',
)
+import logging
+
+from portage.const import SUPPORTED_FEATURES
+from portage.localization import _
+from portage.output import colorize
+from portage.util import writemsg_level
+
class features_set(object):
"""
Provides relevant set operations needed for access and modification of
if need_sync:
self._sync_env_var()
+ def difference_update(self, values):
+ self._settings.modifying()
+ values = list(values)
+ self._settings._features_overrides.extend('-' + k for k in values)
+ remove_us = self._features.intersection(values)
+ if remove_us:
+ self._features.difference_update(values)
+ self._sync_env_var()
+
def remove(self, k):
"""
This never raises KeyError, since it records a permanent override
if k in self._features:
self._features.remove(k)
self._sync_env_var()
+
+ def _validate(self):
+ """
+ Implements unknown-features-warn and unknown-features-filter.
+ """
+ if 'unknown-features-warn' in self._features:
+ unknown_features = \
+ self._features.difference(SUPPORTED_FEATURES)
+ if unknown_features:
+ unknown_features = unknown_features.difference(
+ self._settings._unknown_features)
+ if unknown_features:
+ self._settings._unknown_features.update(unknown_features)
+ writemsg_level(colorize("BAD",
+ _("FEATURES variable contains unknown value(s): %s") % \
+ ", ".join(sorted(unknown_features))) \
+ + "\n", level=logging.WARNING, noiselevel=-1)
+
+ if 'unknown-features-filter' in self._features:
+ unknown_features = \
+ self._features.difference(SUPPORTED_FEATURES)
+ if unknown_features:
+ self.difference_update(unknown_features)
+ self._prune_overrides()
+
+ def _prune_overrides(self):
+ """
+ If there are lots of invalid package.env FEATURES settings
+ then unknown-features-filter can make _features_overrides
+ grow larger and larger, so prune it. This performs incremental
+ stacking with preservation of negative values since they need
+ to persist for future config.regenerate() calls.
+ """
+ overrides_set = set(self._settings._features_overrides)
+ if len(overrides_set) < len(self._settings._features_overrides):
+ positive = set()
+ negative = set()
+ for x in self._settings._features_overrides:
+ if x[:1] == '-':
+ positive.discard(x[:1])
+ negative.add(x[:1])
+ else:
+ positive.add(x)
+ negative.discard(x)
+ self._settings._features_overrides[:] = \
+ list(positive) + list(negative)
from portage.const import CACHE_PATH, \
DEPCACHE_PATH, INCREMENTALS, MAKE_CONF_FILE, \
MODULES_FILE_PATH, PORTAGE_BIN_PATH, PORTAGE_PYM_PATH, \
- PRIVATE_PATH, PROFILE_PATH, SUPPORTED_FEATURES, USER_CONFIG_PATH, \
+ PRIVATE_PATH, PROFILE_PATH, USER_CONFIG_PATH, \
USER_VIRTUALS_FILE
from portage.dbapi import dbapi
from portage.dbapi.porttree import portdbapi
self.features = features_set(self)
self.features._features.update(self.get('FEATURES', '').split())
self.features._sync_env_var()
-
- if 'unknown-features-warn' in self.features:
- unknown_features = \
- self.features._features.difference(SUPPORTED_FEATURES)
- if unknown_features:
- unknown_features = \
- unknown_features.difference(self._unknown_features)
- if unknown_features:
- self._unknown_features.update(unknown_features)
- writemsg_level(colorize("BAD",
- _("FEATURES variable contains unknown value(s): %s") % \
- ", ".join(sorted(unknown_features))) \
- + "\n", noiselevel=-1)
+ self.features._validate()
myflags.update(self.useforce)
arch = self.configdict["defaults"].get("ARCH")