diff options
Diffstat (limited to 'pym/portage/__init__.py')
-rw-r--r-- | pym/portage/__init__.py | 2568 |
1 files changed, 2 insertions, 2566 deletions
diff --git a/pym/portage/__init__.py b/pym/portage/__init__.py index add0c008a..7e3143496 100644 --- a/pym/portage/__init__.py +++ b/pym/portage/__init__.py @@ -102,6 +102,8 @@ try: 'portage.mail', 'portage.output', 'portage.output:bold,colorize', + 'portage.package.ebuild.config:autouse,best_from_dict,' + \ + 'check_config_instance,config', 'portage.process', 'portage.process:atexit_register,run_exitfuncs', 'portage.update:dep_transform,fixdbentries,grab_updates,' + \ @@ -512,18 +514,6 @@ def load_mod(name): mod = getattr(mod, comp) return mod -def best_from_dict(key, top_dict, key_order, EmptyOnError=1, FullCopy=1, AllowEmpty=1): - for x in key_order: - if x in top_dict and key in top_dict[x]: - if FullCopy: - return copy.deepcopy(top_dict[x][key]) - else: - return top_dict[x][key] - if EmptyOnError: - return "" - else: - raise KeyError("Key not found in list; '%s'" % key) - def getcwd(): "this fixes situations where the current directory doesn't exist" try: @@ -1008,2560 +998,6 @@ def ExtractKernelVersion(base_dir): return (version,None) -def autouse(myvartree, use_cache=1, mysettings=None): - """ - autuse returns a list of USE variables auto-enabled to packages being installed - - @param myvartree: Instance of the vartree class (from /var/db/pkg...) - @type myvartree: vartree - @param use_cache: read values from cache - @type use_cache: Boolean - @param mysettings: Instance of config - @type mysettings: config - @rtype: string - @returns: A string containing a list of USE variables that are enabled via use.defaults - """ - if mysettings is None: - global settings - mysettings = settings - if mysettings.profile_path is None: - return "" - myusevars="" - usedefaults = mysettings.use_defs - for myuse in usedefaults: - dep_met = True - for mydep in usedefaults[myuse]: - if not myvartree.dep_match(mydep,use_cache=True): - dep_met = False - break - if dep_met: - myusevars += " "+myuse - return myusevars - -def check_config_instance(test): - if not isinstance(test, config): - raise TypeError("Invalid type for config object: %s (should be %s)" % (test.__class__, config)) - -def _lazy_iuse_regex(iuse_implicit): - """ - The PORTAGE_IUSE value is lazily evaluated since re.escape() is slow - and the value is only used when an ebuild phase needs to be executed - (it's used only to generate QA notices). - """ - # Escape anything except ".*" which is supposed to pass through from - # _get_implicit_iuse(). - regex = sorted(re.escape(x) for x in iuse_implicit) - regex = "^(%s)$" % "|".join(regex) - regex = regex.replace("\\.\\*", ".*") - return regex - -class _local_repo_config(object): - __slots__ = ('aliases', 'eclass_overrides', 'masters', 'name',) - def __init__(self, name, repo_opts): - self.name = name - - aliases = repo_opts.get('aliases') - if aliases is not None: - aliases = tuple(aliases.split()) - self.aliases = aliases - - eclass_overrides = repo_opts.get('eclass-overrides') - if eclass_overrides is not None: - eclass_overrides = tuple(eclass_overrides.split()) - self.eclass_overrides = eclass_overrides - - masters = repo_opts.get('masters') - if masters is not None: - masters = tuple(masters.split()) - self.masters = masters - -class config(object): - """ - This class encompasses the main portage configuration. Data is pulled from - ROOT/PORTDIR/profiles/, from ROOT/etc/make.profile incrementally through all - parent profiles as well as from ROOT/PORTAGE_CONFIGROOT/* for user specified - overrides. - - Generally if you need data like USE flags, FEATURES, environment variables, - virtuals ...etc you look in here. - """ - - _setcpv_aux_keys = ('DEFINED_PHASES', 'DEPEND', 'EAPI', - 'INHERITED', 'IUSE', 'KEYWORDS', 'LICENSE', 'PDEPEND', - 'PROPERTIES', 'PROVIDE', 'RDEPEND', 'SLOT', - 'repository', 'RESTRICT', 'LICENSE',) - - _env_blacklist = [ - "A", "AA", "CATEGORY", "DEPEND", "DESCRIPTION", "EAPI", - "EBUILD_PHASE", "ED", "EMERGE_FROM", "EPREFIX", "EROOT", - "HOMEPAGE", "INHERITED", "IUSE", - "KEYWORDS", "LICENSE", "PDEPEND", "PF", "PKGUSE", - "PORTAGE_CONFIGROOT", "PORTAGE_IUSE", - "PORTAGE_NONFATAL", "PORTAGE_REPO_NAME", - "PORTAGE_USE", "PROPERTIES", "PROVIDE", "RDEPEND", "RESTRICT", - "ROOT", "SLOT", "SRC_URI" - ] - - _environ_whitelist = [] - - # Whitelisted variables are always allowed to enter the ebuild - # environment. Generally, this only includes special portage - # variables. Ebuilds can unset variables that are not whitelisted - # and rely on them remaining unset for future phases, without them - # leaking back in from various locations (bug #189417). It's very - # important to set our special BASH_ENV variable in the ebuild - # environment in order to prevent sandbox from sourcing /etc/profile - # in it's bashrc (causing major leakage). - _environ_whitelist += [ - "ACCEPT_LICENSE", "BASH_ENV", "BUILD_PREFIX", "D", - "DISTDIR", "DOC_SYMLINKS_DIR", "EAPI", "EBUILD", - "EBUILD_EXIT_STATUS_FILE", "EBUILD_FORCE_TEST", - "EBUILD_PHASE", "ECLASSDIR", "ECLASS_DEPTH", "ED", - "EMERGE_FROM", "EPREFIX", "EROOT", - "FEATURES", "FILESDIR", "HOME", "NOCOLOR", "PATH", - "PKGDIR", - "PKGUSE", "PKG_LOGDIR", "PKG_TMPDIR", - "PORTAGE_ACTUAL_DISTDIR", "PORTAGE_ARCHLIST", - "PORTAGE_BASHRC", - "PORTAGE_BINPKG_FILE", "PORTAGE_BINPKG_TAR_OPTS", - "PORTAGE_BINPKG_TMPFILE", - "PORTAGE_BIN_PATH", - "PORTAGE_BUILDDIR", "PORTAGE_COLORMAP", - "PORTAGE_CONFIGROOT", "PORTAGE_DEBUG", "PORTAGE_DEPCACHEDIR", - "PORTAGE_GID", "PORTAGE_INST_GID", "PORTAGE_INST_UID", - "PORTAGE_IUSE", - "PORTAGE_LOG_FILE", "PORTAGE_MASTER_PID", - "PORTAGE_PYM_PATH", "PORTAGE_QUIET", - "PORTAGE_REPO_NAME", "PORTAGE_RESTRICT", - "PORTAGE_TMPDIR", "PORTAGE_UPDATE_ENV", - "PORTAGE_VERBOSE", "PORTAGE_WORKDIR_MODE", - "PORTDIR", "PORTDIR_OVERLAY", "PREROOTPATH", "PROFILE_PATHS", - "ROOT", "ROOTPATH", "T", "TMP", "TMPDIR", - "USE_EXPAND", "USE_ORDER", "WORKDIR", - "XARGS", - ] - - # user config variables - _environ_whitelist += [ - "DOC_SYMLINKS_DIR", "INSTALL_MASK", "PKG_INSTALL_MASK" - ] - - _environ_whitelist += [ - "A", "AA", "CATEGORY", "P", "PF", "PN", "PR", "PV", "PVR" - ] - - # misc variables inherited from the calling environment - _environ_whitelist += [ - "COLORTERM", "DISPLAY", "EDITOR", "LESS", - "LESSOPEN", "LOGNAME", "LS_COLORS", "PAGER", - "TERM", "TERMCAP", "USER", - ] - - # tempdir settings - _environ_whitelist += [ - "TMPDIR", "TEMP", "TMP", - ] - - # localization settings - _environ_whitelist += [ - "LANG", "LC_COLLATE", "LC_CTYPE", "LC_MESSAGES", - "LC_MONETARY", "LC_NUMERIC", "LC_TIME", "LC_PAPER", - "LC_ALL", - ] - - # other variables inherited from the calling environment - _environ_whitelist += [ - "CVS_RSH", "ECHANGELOG_USER", - "GPG_AGENT_INFO", - "SSH_AGENT_PID", "SSH_AUTH_SOCK", - "STY", "WINDOW", "XAUTHORITY", - ] - - _environ_whitelist = frozenset(_environ_whitelist) - - _environ_whitelist_re = re.compile(r'^(CCACHE_|DISTCC_).*') - - # Filter selected variables in the config.environ() method so that - # they don't needlessly propagate down into the ebuild environment. - _environ_filter = [] - - # Exclude anything that could be extremely long here (like SRC_URI) - # since that could cause execve() calls to fail with E2BIG errors. For - # example, see bug #262647. - _environ_filter += [ - 'DEPEND', 'RDEPEND', 'PDEPEND', 'SRC_URI', - ] - - # misc variables inherited from the calling environment - _environ_filter += [ - "INFOPATH", "MANPATH", "USER", - ] - - # variables that break bash - _environ_filter += [ - "HISTFILE", "POSIXLY_CORRECT", - ] - - # portage config variables and variables set directly by portage - _environ_filter += [ - "ACCEPT_KEYWORDS", "ACCEPT_PROPERTIES", "AUTOCLEAN", - "CLEAN_DELAY", "COLLISION_IGNORE", "CONFIG_PROTECT", - "CONFIG_PROTECT_MASK", "EGENCACHE_DEFAULT_OPTS", "EMERGE_DEFAULT_OPTS", - "EMERGE_LOG_DIR", - "EMERGE_WARNING_DELAY", "FETCHCOMMAND", "FETCHCOMMAND_FTP", - "FETCHCOMMAND_HTTP", "FETCHCOMMAND_SFTP", - "GENTOO_MIRRORS", "NOCONFMEM", "O", - "PORTAGE_BACKGROUND", - "PORTAGE_BINHOST_CHUNKSIZE", "PORTAGE_CALLER", - "PORTAGE_ELOG_CLASSES", - "PORTAGE_ELOG_MAILFROM", "PORTAGE_ELOG_MAILSUBJECT", - "PORTAGE_ELOG_MAILURI", "PORTAGE_ELOG_SYSTEM", - "PORTAGE_FETCH_CHECKSUM_TRY_MIRRORS", "PORTAGE_FETCH_RESUME_MIN_SIZE", - "PORTAGE_GPG_DIR", - "PORTAGE_GPG_KEY", "PORTAGE_IONICE_COMMAND", - "PORTAGE_PACKAGE_EMPTY_ABORT", - "PORTAGE_REPO_DUPLICATE_WARN", - "PORTAGE_RO_DISTDIRS", - "PORTAGE_RSYNC_EXTRA_OPTS", "PORTAGE_RSYNC_OPTS", - "PORTAGE_RSYNC_RETRIES", "PORTAGE_USE", "PORT_LOGDIR", - "QUICKPKG_DEFAULT_OPTS", - "RESUMECOMMAND", "RESUMECOMMAND_HTTP", "RESUMECOMMAND_HTTP", - "RESUMECOMMAND_SFTP", "SYNC", "USE_EXPAND_HIDDEN", "USE_ORDER", - ] - - _environ_filter = frozenset(_environ_filter) - - _undef_lic_groups = set() - _default_globals = ( - ('ACCEPT_LICENSE', '* -@EULA'), - ('ACCEPT_PROPERTIES', '*'), - ) - - # To enhance usability, make some vars case insensitive - # by forcing them to lower case. - _case_insensitive_vars = ('AUTOCLEAN', 'NOCOLOR',) - - def __init__(self, clone=None, mycpv=None, config_profile_path=None, - config_incrementals=None, config_root=None, target_root=None, - local_config=True, env=None): - """ - @param clone: If provided, init will use deepcopy to copy by value the instance. - @type clone: Instance of config class. - @param mycpv: CPV to load up (see setcpv), this is the same as calling init with mycpv=None - and then calling instance.setcpv(mycpv). - @type mycpv: String - @param config_profile_path: Configurable path to the profile (usually PROFILE_PATH from portage.const) - @type config_profile_path: String - @param config_incrementals: List of incremental variables - (defaults to portage.const.INCREMENTALS) - @type config_incrementals: List - @param config_root: path to read local config from (defaults to "/", see PORTAGE_CONFIGROOT) - @type config_root: String - @param target_root: __init__ override of $ROOT env variable. - @type target_root: String - @param local_config: Enables loading of local config (/etc/portage); used most by repoman to - ignore local config (keywording and unmasking) - @type local_config: Boolean - @param env: The calling environment which is used to override settings. - Defaults to os.environ if unspecified. - @type env: dict - """ - - # When initializing the global portage.settings instance, avoid - # raising exceptions whenever possible since exceptions thrown - # from 'import portage' or 'import portage.exceptions' statements - # can practically render the api unusable for api consumers. - tolerant = "_initializing_globals" in globals() - - self.already_in_regenerate = 0 - - self.locked = 0 - self.mycpv = None - self._setcpv_args_hash = None - self.puse = [] - self.modifiedkeys = [] - self.uvlist = [] - self._accept_chost_re = None - self._accept_license = None - self._accept_license_str = None - self._license_groups = {} - self._accept_properties = None - - self.virtuals = {} - self.virts_p = {} - self.dirVirtuals = None - self.v_count = 0 - - # Virtuals obtained from the vartree - self.treeVirtuals = {} - # Virtuals by user specification. Includes negatives. - self.userVirtuals = {} - # Virtual negatives from user specifications. - self.negVirtuals = {} - # Virtuals added by the depgraph via self.setinst(). - self._depgraphVirtuals = {} - - self.user_profile_dir = None - self.local_config = local_config - self._local_repo_configs = None - self._local_repo_conf_path = None - - if clone: - # For immutable attributes, use shallow copy for - # speed and memory conservation. - self.categories = clone.categories - self.depcachedir = clone.depcachedir - self.incrementals = clone.incrementals - self.module_priority = clone.module_priority - self.profile_path = clone.profile_path - self.profiles = clone.profiles - self.packages = clone.packages - self.useforce_list = clone.useforce_list - self.usemask_list = clone.usemask_list - - self.user_profile_dir = copy.deepcopy(clone.user_profile_dir) - self.local_config = copy.deepcopy(clone.local_config) - self._local_repo_configs = \ - copy.deepcopy(clone._local_repo_configs) - self._local_repo_conf_path = \ - copy.deepcopy(clone._local_repo_conf_path) - self.modules = copy.deepcopy(clone.modules) - self.virtuals = copy.deepcopy(clone.virtuals) - self.dirVirtuals = copy.deepcopy(clone.dirVirtuals) - self.treeVirtuals = copy.deepcopy(clone.treeVirtuals) - self.userVirtuals = copy.deepcopy(clone.userVirtuals) - self.negVirtuals = copy.deepcopy(clone.negVirtuals) - self._depgraphVirtuals = copy.deepcopy(clone._depgraphVirtuals) - - self.use_defs = copy.deepcopy(clone.use_defs) - self.usemask = copy.deepcopy(clone.usemask) - self.pusemask_list = copy.deepcopy(clone.pusemask_list) - self.useforce = copy.deepcopy(clone.useforce) - self.puseforce_list = copy.deepcopy(clone.puseforce_list) - self.puse = copy.deepcopy(clone.puse) - self.make_defaults_use = copy.deepcopy(clone.make_defaults_use) - self.pkgprofileuse = copy.deepcopy(clone.pkgprofileuse) - self.mycpv = copy.deepcopy(clone.mycpv) - self._setcpv_args_hash = copy.deepcopy(clone._setcpv_args_hash) - - self.configdict = copy.deepcopy(clone.configdict) - self.configlist = [ - self.configdict['env.d'], - self.configdict['pkginternal'], - self.configdict['globals'], - self.configdict['defaults'], - self.configdict['conf'], - self.configdict['pkg'], - self.configdict['auto'], - self.configdict['env'], - ] - self.lookuplist = self.configlist[:] - self.lookuplist.reverse() - self._use_expand_dict = copy.deepcopy(clone._use_expand_dict) - self.backupenv = self.configdict["backupenv"] - self.pusedict = copy.deepcopy(clone.pusedict) - self.pkeywordsdict = copy.deepcopy(clone.pkeywordsdict) - self._pkeywords_list = copy.deepcopy(clone._pkeywords_list) - self.pmaskdict = copy.deepcopy(clone.pmaskdict) - self.punmaskdict = copy.deepcopy(clone.punmaskdict) - self.prevmaskdict = copy.deepcopy(clone.prevmaskdict) - self.pprovideddict = copy.deepcopy(clone.pprovideddict) - self.features = copy.deepcopy(clone.features) - - self._accept_license = copy.deepcopy(clone._accept_license) - self._plicensedict = copy.deepcopy(clone._plicensedict) - self._license_groups = copy.deepcopy(clone._license_groups) - self._accept_properties = copy.deepcopy(clone._accept_properties) - self._ppropertiesdict = copy.deepcopy(clone._ppropertiesdict) - else: - - def check_var_directory(varname, var): - if not os.path.isdir(var): - writemsg(_("!!! Error: %s='%s' is not a directory. " - "Please correct this.\n") % (varname, var), - noiselevel=-1) - raise portage.exception.DirectoryNotFound(var) - - if config_root is None: - config_root = "/" - - config_root = normalize_path(os.path.abspath( - config_root)).rstrip(os.path.sep) + os.path.sep - - check_var_directory("PORTAGE_CONFIGROOT", config_root) - - self.depcachedir = DEPCACHE_PATH - - if not config_profile_path: - config_profile_path = \ - os.path.join(config_root, PROFILE_PATH) - if os.path.isdir(config_profile_path): - self.profile_path = config_profile_path - else: - self.profile_path = None - else: - self.profile_path = config_profile_path - - if config_incrementals is None: - self.incrementals = portage.const.INCREMENTALS - else: - self.incrementals = config_incrementals - if not isinstance(self.incrementals, tuple): - self.incrementals = tuple(self.incrementals) - - self.module_priority = ("user", "default") - self.modules = {} - modules_loader = portage.env.loaders.KeyValuePairFileLoader( - os.path.join(config_root, MODULES_FILE_PATH), None, None) - modules_dict, modules_errors = modules_loader.load() - self.modules["user"] = modules_dict - if self.modules["user"] is None: - self.modules["user"] = {} - self.modules["default"] = { - "portdbapi.metadbmodule": "portage.cache.metadata.database", - "portdbapi.auxdbmodule": "portage.cache.flat_hash.database", - } - - self.usemask=[] - self.configlist=[] - - # back up our incremental variables: - self.configdict={} - self._use_expand_dict = {} - # configlist will contain: [ env.d, globals, defaults, conf, pkg, auto, backupenv, env ] - self.configlist.append({}) - self.configdict["env.d"] = self.configlist[-1] - - self.configlist.append({}) - self.configdict["pkginternal"] = self.configlist[-1] - - # The symlink might not exist or might not be a symlink. - if self.profile_path is None: - self.profiles = [] - else: - self.profiles = [] - def addProfile(currentPath): - parentsFile = os.path.join(currentPath, "parent") - eapi_file = os.path.join(currentPath, "eapi") - try: - eapi = codecs.open(_unicode_encode(eapi_file, - encoding=_encodings['fs'], errors='strict'), - mode='r', encoding=_encodings['content'], errors='replace' - ).readline().strip() - except IOError: - pass - else: - if not eapi_is_supported(eapi): - raise portage.exception.ParseError(_( - "Profile contains unsupported " - "EAPI '%s': '%s'") % \ - (eapi, os.path.realpath(eapi_file),)) - if os.path.exists(parentsFile): - parents = grabfile(parentsFile) - if not parents: - raise portage.exception.ParseError( - _("Empty parent file: '%s'") % parentsFile) - for parentPath in parents: - parentPath = normalize_path(os.path.join( - currentPath, parentPath)) - if os.path.exists(parentPath): - addProfile(parentPath) - else: - raise portage.exception.ParseError( - _("Parent '%s' not found: '%s'") % \ - (parentPath, parentsFile)) - self.profiles.append(currentPath) - try: - addProfile(os.path.realpath(self.profile_path)) - except portage.exception.ParseError as e: - writemsg(_("!!! Unable to parse profile: '%s'\n") % \ - self.profile_path, noiselevel=-1) - writemsg("!!! ParseError: %s\n" % str(e), noiselevel=-1) - del e - self.profiles = [] - if local_config and self.profiles: - custom_prof = os.path.join( - config_root, CUSTOM_PROFILE_PATH) - if os.path.exists(custom_prof): - self.user_profile_dir = custom_prof - self.profiles.append(custom_prof) - del custom_prof - - self.profiles = tuple(self.profiles) - self.packages_list = [grabfile_package(os.path.join(x, "packages")) for x in self.profiles] - self.packages = tuple(stack_lists(self.packages_list, incremental=1)) - del self.packages_list - #self.packages = grab_stacked("packages", self.profiles, grabfile, incremental_lines=1) - - # revmaskdict - self.prevmaskdict={} - for x in self.packages: - # Negative atoms are filtered by the above stack_lists() call. - if not isinstance(x, dep.Atom): - x = dep.Atom(x.lstrip('*')) - self.prevmaskdict.setdefault(x.cp, []).append(x) - - self._pkeywords_list = [] - rawpkeywords = [grabdict_package( - os.path.join(x, "package.keywords"), recursive=1) \ - for x in self.profiles] - for pkeyworddict in rawpkeywords: - cpdict = {} - for k, v in pkeyworddict.items(): - cpdict.setdefault(k.cp, {})[k] = v - self._pkeywords_list.append(cpdict) - - # get profile-masked use flags -- INCREMENTAL Child over parent - self.usemask_list = tuple( - tuple(grabfile(os.path.join(x, "use.mask"), recursive=1)) - for x in self.profiles) - self.usemask = set(stack_lists( - self.usemask_list, incremental=True)) - use_defs_lists = [grabdict(os.path.join(x, "use.defaults")) for x in self.profiles] - self.use_defs = stack_dictlist(use_defs_lists, incremental=True) - del use_defs_lists - - self.pusemask_list = [] - rawpusemask = [grabdict_package(os.path.join(x, "package.use.mask"), - recursive=1) for x in self.profiles] - for pusemaskdict in rawpusemask: - cpdict = {} - for k, v in pusemaskdict.items(): - cpdict.setdefault(k.cp, {})[k] = v - self.pusemask_list.append(cpdict) - del rawpusemask - - self.pkgprofileuse = [] - rawprofileuse = [grabdict_package(os.path.join(x, "package.use"), - juststrings=True, recursive=1) for x in self.profiles] - for rawpusedict in rawprofileuse: - cpdict = {} - for k, v in rawpusedict.items(): - cpdict.setdefault(k.cp, {})[k] = v - self.pkgprofileuse.append(cpdict) - del rawprofileuse - - self.useforce_list = tuple( - tuple(grabfile(os.path.join(x, "use.force"), recursive=1)) - for x in self.profiles) - self.useforce = set(stack_lists( - self.useforce_list, incremental=True)) - - self.puseforce_list = [] - rawpuseforce = [grabdict_package( - os.path.join(x, "package.use.force"), recursive=1) \ - for x in self.profiles] - for rawpusefdict in rawpuseforce: - cpdict = {} - for k, v in rawpusefdict.items(): - cpdict.setdefault(k.cp, {})[k] = v - self.puseforce_list.append(cpdict) - del rawpuseforce - - make_conf = getconfig( - os.path.join(config_root, MAKE_CONF_FILE), - tolerant=tolerant, allow_sourcing=True) - if make_conf is None: - make_conf = {} - - # Allow ROOT setting to come from make.conf if it's not overridden - # by the constructor argument (from the calling environment). - if target_root is None and "ROOT" in make_conf: - target_root = make_conf["ROOT"] - if not target_root.strip(): - target_root = None - if target_root is None: - target_root = "/" - - target_root = normalize_path(os.path.abspath( - target_root)).rstrip(os.path.sep) + os.path.sep - - portage.util.ensure_dirs(target_root) - check_var_directory("ROOT", target_root) - - # The expand_map is used for variable substitution - # in getconfig() calls, and the getconfig() calls - # update expand_map with the value of each variable - # assignment that occurs. Variable substitution occurs - # in the following order, which corresponds to the - # order of appearance in self.lookuplist: - # - # * env.d - # * make.globals - # * make.defaults - # * make.conf - # - # Notably absent is "env", since we want to avoid any - # interaction with the calling environment that might - # lead to unexpected results. - expand_map = {} - - env_d = getconfig(os.path.join(target_root, "etc", "profile.env"), - expand=expand_map) - # env_d will be None if profile.env doesn't exist. - if env_d: - self.configdict["env.d"].update(env_d) - expand_map.update(env_d) - - # backupenv is used for calculating incremental variables. - if env is None: - env = os.environ - - # Avoid potential UnicodeDecodeError exceptions later. - env_unicode = dict((_unicode_decode(k), _unicode_decode(v)) - for k, v in env.items()) - - self.backupenv = env_unicode - - if env_d: - # Remove duplicate values so they don't override updated - # profile.env values later (profile.env is reloaded in each - # call to self.regenerate). - for k, v in env_d.items(): - try: - if self.backupenv[k] == v: - del self.backupenv[k] - except KeyError: - pass - del k, v - - self.configdict["env"] = util.LazyItemsDict(self.backupenv) - - # make.globals should not be relative to config_root - # because it only contains constants. - for x in (portage.const.GLOBAL_CONFIG_PATH, "/etc"): - self.mygcfg = getconfig(os.path.join(x, "make.globals"), - expand=expand_map) - if self.mygcfg: - break - - if self.mygcfg is None: - self.mygcfg = {} - - for k, v in self._default_globals: - self.mygcfg.setdefault(k, v) - - self.configlist.append(self.mygcfg) - self.configdict["globals"]=self.configlist[-1] - - self.make_defaults_use = [] - self.mygcfg = {} - if self.profiles: - mygcfg_dlists = [getconfig(os.path.join(x, "make.defaults"), - expand=expand_map) for x in self.profiles] - - for cfg in mygcfg_dlists: - if cfg: - self.make_defaults_use.append(cfg.get("USE", "")) - else: - self.make_defaults_use.append("") - self.mygcfg = stack_dicts(mygcfg_dlists, - incrementals=portage.const.INCREMENTALS) - if self.mygcfg is None: - self.mygcfg = {} - self.configlist.append(self.mygcfg) - self.configdict["defaults"]=self.configlist[-1] - - self.mygcfg = getconfig( - os.path.join(config_root, MAKE_CONF_FILE), - tolerant=tolerant, allow_sourcing=True, expand=expand_map) - if self.mygcfg is None: - self.mygcfg = {} - - # Don't allow the user to override certain variables in make.conf - profile_only_variables = self.configdict["defaults"].get( - "PROFILE_ONLY_VARIABLES", "").split() - for k in profile_only_variables: - self.mygcfg.pop(k, None) - - self.configlist.append(self.mygcfg) - self.configdict["conf"]=self.configlist[-1] - - self.configlist.append(util.LazyItemsDict()) - self.configdict["pkg"]=self.configlist[-1] - - #auto-use: - self.configlist.append({}) - self.configdict["auto"]=self.configlist[-1] - - self.configdict["backupenv"] = self.backupenv - - # Don't allow the user to override certain variables in the env - for k in profile_only_variables: - self.backupenv.pop(k, None) - - self.configlist.append(self.configdict["env"]) - - # make lookuplist for loading package.* - self.lookuplist=self.configlist[:] - self.lookuplist.reverse() - - # Blacklist vars that could interfere with portage internals. - for blacklisted in self._env_blacklist: - for cfg in self.lookuplist: - cfg.pop(blacklisted, None) - self.backupenv.pop(blacklisted, None) - del blacklisted, cfg - - self["PORTAGE_CONFIGROOT"] = config_root - self.backup_changes("PORTAGE_CONFIGROOT") - self["ROOT"] = target_root - self.backup_changes("ROOT") - - # Prefix forward compatability, set EPREFIX to the empty string - self["EPREFIX"] = '' - self.backup_changes("EPREFIX") - self["EROOT"] = target_root - self.backup_changes("EROOT") - - self.pusedict = {} - self.pkeywordsdict = {} - self._plicensedict = {} - self._ppropertiesdict = {} - self.punmaskdict = {} - abs_user_config = os.path.join(config_root, USER_CONFIG_PATH) - - # locations for "categories" and "arch.list" files - locations = [os.path.join(self["PORTDIR"], "profiles")] - pmask_locations = [os.path.join(self["PORTDIR"], "profiles")] - pmask_locations.extend(self.profiles) - - """ repoman controls PORTDIR_OVERLAY via the environment, so no - special cases are needed here.""" - overlay_profiles = [] - for ov in self["PORTDIR_OVERLAY"].split(): - ov = normalize_path(ov) - profiles_dir = os.path.join(ov, "profiles") - if os.path.isdir(profiles_dir): - overlay_profiles.append(profiles_dir) - locations += overlay_profiles - - pmask_locations.extend(overlay_profiles) - - if local_config: - locations.append(abs_user_config) - pmask_locations.append(abs_user_config) - pusedict = grabdict_package( - os.path.join(abs_user_config, "package.use"), recursive=1) - for k, v in pusedict.items(): - self.pusedict.setdefault(k.cp, {})[k] = v - - #package.keywords - pkgdict = grabdict_package( - os.path.join(abs_user_config, "package.keywords"), - recursive=1) - for k, v in pkgdict.items(): - # default to ~arch if no specific keyword is given - if not v: - mykeywordlist = [] - if self.configdict["defaults"] and \ - "ACCEPT_KEYWORDS" in self.configdict["defaults"]: - groups = self.configdict["defaults"]["ACCEPT_KEYWORDS"].split() - else: - groups = [] - for keyword in groups: - if not keyword[0] in "~-": - mykeywordlist.append("~"+keyword) - v = mykeywordlist - self.pkeywordsdict.setdefault(k.cp, {})[k] = v - - #package.license - licdict = grabdict_package(os.path.join( - abs_user_config, "package.license"), recursive=1) - for k, v in licdict.items(): - cp = k.cp - cp_dict = self._plicensedict.get(cp) - if not cp_dict: - cp_dict = {} - self._plicensedict[cp] = cp_dict - cp_dict[k] = self.expandLicenseTokens(v) - - #package.properties - propdict = grabdict_package(os.path.join( - abs_user_config, "package.properties"), recursive=1) - for k, v in propdict.items(): - cp = k.cp - cp_dict = self._ppropertiesdict.get(cp) - if not cp_dict: - cp_dict = {} - self._ppropertiesdict[cp] = cp_dict - cp_dict[k] = v - - self._local_repo_configs = {} - self._local_repo_conf_path = \ - os.path.join(abs_user_config, 'repos.conf') - try: - from configparser import SafeConfigParser, ParsingError - except ImportError: - from ConfigParser import SafeConfigParser, ParsingError - repo_conf_parser = SafeConfigParser() - try: - repo_conf_parser.readfp( - codecs.open( - _unicode_encode(self._local_repo_conf_path, - encoding=_encodings['fs'], errors='strict'), - mode='r', encoding=_encodings['content'], errors='replace') - ) - except EnvironmentError as e: - if e.errno != errno.ENOENT: - raise - del e - except ParsingError as e: - portage.util.writemsg_level( - _("!!! Error parsing '%s': %s\n") % \ - (self._local_repo_conf_path, e), - level=logging.ERROR, noiselevel=-1) - del e - else: - repo_defaults = repo_conf_parser.defaults() - if repo_defaults: - self._local_repo_configs['DEFAULT'] = \ - _local_repo_config('DEFAULT', repo_defaults) - for repo_name in repo_conf_parser.sections(): - repo_opts = repo_defaults.copy() - for opt_name in repo_conf_parser.options(repo_name): - repo_opts[opt_name] = \ - repo_conf_parser.get(repo_name, opt_name) - self._local_repo_configs[repo_name] = \ - _local_repo_config(repo_name, repo_opts) - - #getting categories from an external file now - categories = [grabfile(os.path.join(x, "categories")) for x in locations] - category_re = dbapi.dbapi._category_re - self.categories = tuple(sorted( - x for x in stack_lists(categories, incremental=1) - if category_re.match(x) is not None)) - del categories - - archlist = [grabfile(os.path.join(x, "arch.list")) for x in locations] - archlist = stack_lists(archlist, incremental=1) - self.configdict["conf"]["PORTAGE_ARCHLIST"] = " ".join(archlist) - - # package.mask and package.unmask - pkgmasklines = [] - pkgunmasklines = [] - for x in pmask_locations: - pkgmasklines.append(grabfile_package( - os.path.join(x, "package.mask"), recursive=1)) - pkgunmasklines.append(grabfile_package( - os.path.join(x, "package.unmask"), recursive=1)) - pkgmasklines = stack_lists(pkgmasklines, incremental=1) - pkgunmasklines = stack_lists(pkgunmasklines, incremental=1) - - self.pmaskdict = {} - for x in pkgmasklines: - self.pmaskdict.setdefault(x.cp, []).append(x) - - for x in pkgunmasklines: - self.punmaskdict.setdefault(x.cp, []).append(x) - - pkgprovidedlines = [grabfile(os.path.join(x, "package.provided"), recursive=1) for x in self.profiles] - pkgprovidedlines = stack_lists(pkgprovidedlines, incremental=1) - has_invalid_data = False - for x in range(len(pkgprovidedlines)-1, -1, -1): - myline = pkgprovidedlines[x] - if not isvalidatom("=" + myline): - writemsg(_("Invalid package name in package.provided: %s\n") % \ - myline, noiselevel=-1) - has_invalid_data = True - del pkgprovidedlines[x] - continue - cpvr = catpkgsplit(pkgprovidedlines[x]) - if not cpvr or cpvr[0] == "null": - writemsg(_("Invalid package name in package.provided: ")+pkgprovidedlines[x]+"\n", - noiselevel=-1) - has_invalid_data = True - del pkgprovidedlines[x] - continue - if cpvr[0] == "virtual": - writemsg(_("Virtual package in package.provided: %s\n") % \ - myline, noiselevel=-1) - has_invalid_data = True - del pkgprovidedlines[x] - continue - if has_invalid_data: - writemsg(_("See portage(5) for correct package.provided usage.\n"), - noiselevel=-1) - self.pprovideddict = {} - for x in pkgprovidedlines: - cpv=catpkgsplit(x) - if not x: - continue - mycatpkg = cpv_getkey(x) - if mycatpkg in self.pprovideddict: - self.pprovideddict[mycatpkg].append(x) - else: - self.pprovideddict[mycatpkg]=[x] - - # parse licensegroups - license_groups = self._license_groups - for x in locations: - for k, v in grabdict( - os.path.join(x, "license_groups")).items(): - license_groups.setdefault(k, []).extend(v) - - # reasonable defaults; this is important as without USE_ORDER, - # USE will always be "" (nothing set)! - if "USE_ORDER" not in self: - self.backupenv["USE_ORDER"] = "env:pkg:conf:defaults:pkginternal:env.d" - - self["PORTAGE_GID"] = str(portage_gid) - self.backup_changes("PORTAGE_GID") - - if self.get("PORTAGE_DEPCACHEDIR", None): - self.depcachedir = self["PORTAGE_DEPCACHEDIR"] - self["PORTAGE_DEPCACHEDIR"] = self.depcachedir - self.backup_changes("PORTAGE_DEPCACHEDIR") - - overlays = self.get("PORTDIR_OVERLAY","").split() - if overlays: - new_ov = [] - for ov in overlays: - ov = normalize_path(ov) - if os.path.isdir(ov): - new_ov.append(ov) - else: - writemsg(_("!!! Invalid PORTDIR_OVERLAY" - " (not a dir): '%s'\n") % ov, noiselevel=-1) - self["PORTDIR_OVERLAY"] = " ".join(new_ov) - self.backup_changes("PORTDIR_OVERLAY") - - if "CBUILD" not in self and "CHOST" in self: - self["CBUILD"] = self["CHOST"] - self.backup_changes("CBUILD") - - self["PORTAGE_BIN_PATH"] = PORTAGE_BIN_PATH - self.backup_changes("PORTAGE_BIN_PATH") - self["PORTAGE_PYM_PATH"] = PORTAGE_PYM_PATH - self.backup_changes("PORTAGE_PYM_PATH") - - for var in ("PORTAGE_INST_UID", "PORTAGE_INST_GID"): - try: - self[var] = str(int(self.get(var, "0"))) - except ValueError: - writemsg(_("!!! %s='%s' is not a valid integer. " - "Falling back to '0'.\n") % (var, self[var]), - noiselevel=-1) - self[var] = "0" - self.backup_changes(var) - - # initialize self.features - self.regenerate() - - if bsd_chflags: - self.features.add('chflags') - - self["FEATURES"] = " ".join(sorted(self.features)) - self.backup_changes("FEATURES") - global _glep_55_enabled, _validate_cache_for_unsupported_eapis - if 'parse-eapi-ebuild-head' in self.features: - _validate_cache_for_unsupported_eapis = False - if 'parse-eapi-glep-55' in self.features: - _validate_cache_for_unsupported_eapis = False - _glep_55_enabled = True - - for k in self._case_insensitive_vars: - if k in self: - self[k] = self[k].lower() - self.backup_changes(k) - - if mycpv: - self.setcpv(mycpv) - - def _init_dirs(self): - """ - Create a few directories that are critical to portage operation - """ - if not os.access(self["ROOT"], os.W_OK): - return - - # gid, mode, mask, preserve_perms - dir_mode_map = { - "tmp" : ( -1, 0o1777, 0, True), - "var/tmp" : ( -1, 0o1777, 0, True), - PRIVATE_PATH : (portage_gid, 0o2750, 0o2, False), - CACHE_PATH : (portage_gid, 0o755, 0o2, False) - } - - for mypath, (gid, mode, modemask, preserve_perms) \ - in dir_mode_map.items(): - mydir = os.path.join(self["ROOT"], mypath) - if preserve_perms and os.path.isdir(mydir): - # Only adjust permissions on some directories if - # they don't exist yet. This gives freedom to the - # user to adjust permissions to suit their taste. - continue - try: - portage.util.ensure_dirs(mydir, gid=gid, mode=mode, mask=modemask) - except portage.exception.PortageException as e: - writemsg(_("!!! Directory initialization failed: '%s'\n") % mydir, - noiselevel=-1) - writemsg("!!! %s\n" % str(e), - noiselevel=-1) - - def expandLicenseTokens(self, tokens): - """ Take a token from ACCEPT_LICENSE or package.license and expand it - if it's a group token (indicated by @) or just return it if it's not a - group. If a group is negated then negate all group elements.""" - expanded_tokens = [] - for x in tokens: - expanded_tokens.extend(self._expandLicenseToken(x, None)) - return expanded_tokens - - def _expandLicenseToken(self, token, traversed_groups): - negate = False - rValue = [] - if token.startswith("-"): - negate = True - license_name = token[1:] - else: - license_name = token - if not license_name.startswith("@"): - rValue.append(token) - return rValue - group_name = license_name[1:] - if traversed_groups is None: - traversed_groups = set() - license_group = self._license_groups.get(group_name) - if group_name in traversed_groups: - writemsg(_("Circular license group reference" - " detected in '%s'\n") % group_name, noiselevel=-1) - rValue.append("@"+group_name) - elif license_group: - traversed_groups.add(group_name) - for l in license_group: - if l.startswith("-"): - writemsg(_("Skipping invalid element %s" - " in license group '%s'\n") % (l, group_name), - noiselevel=-1) - else: - rValue.extend(self._expandLicenseToken(l, traversed_groups)) - else: - if self._license_groups and \ - group_name not in self._undef_lic_groups: - self._undef_lic_groups.add(group_name) - writemsg(_("Undefined license group '%s'\n") % group_name, - noiselevel=-1) - rValue.append("@"+group_name) - if negate: - rValue = ["-" + token for token in rValue] - return rValue - - def validate(self): - """Validate miscellaneous settings and display warnings if necessary. - (This code was previously in the global scope of portage.py)""" - - groups = self["ACCEPT_KEYWORDS"].split() - archlist = self.archlist() - if not archlist: - writemsg(_("--- 'profiles/arch.list' is empty or " - "not available. Empty portage tree?\n"), noiselevel=1) - else: - for group in groups: - if group not in archlist and \ - not (group.startswith("-") and group[1:] in archlist) and \ - group not in ("*", "~*", "**"): - writemsg(_("!!! INVALID ACCEPT_KEYWORDS: %s\n") % str(group), - noiselevel=-1) - - abs_profile_path = os.path.join(self["PORTAGE_CONFIGROOT"], - PROFILE_PATH) - if not self.profile_path or (not os.path.islink(abs_profile_path) and \ - not os.path.exists(os.path.join(abs_profile_path, "parent")) and \ - os.path.exists(os.path.join(self["PORTDIR"], "profiles"))): - writemsg(_("\a\n\n!!! %s is not a symlink and will probably prevent most merges.\n") % abs_profile_path, - noiselevel=-1) - writemsg(_("!!! It should point into a profile within %s/profiles/\n") % self["PORTDIR"]) - writemsg(_("!!! (You can safely ignore this message when syncing. It's harmless.)\n\n\n")) - - abs_user_virtuals = os.path.join(self["PORTAGE_CONFIGROOT"], - USER_VIRTUALS_FILE) - if os.path.exists(abs_user_virtuals): - writemsg("\n!!! /etc/portage/virtuals is deprecated in favor of\n") - writemsg("!!! /etc/portage/profile/virtuals. Please move it to\n") - writemsg("!!! this new location.\n\n") - - if not process.sandbox_capable and \ - ("sandbox" in self.features or "usersandbox" in self.features): - if self.profile_path is not None and \ - os.path.realpath(self.profile_path) == \ - os.path.realpath(os.path.join( - self["PORTAGE_CONFIGROOT"], PROFILE_PATH)): - # Don't show this warning when running repoman and the - # sandbox feature came from a profile that doesn't belong - # to the user. - writemsg(colorize("BAD", _("!!! Problem with sandbox" - " binary. Disabling...\n\n")), noiselevel=-1) - - if "fakeroot" in self.features and \ - not portage.process.fakeroot_capable: - writemsg(_("!!! FEATURES=fakeroot is enabled, but the " - "fakeroot binary is not installed.\n"), noiselevel=-1) - - def loadVirtuals(self,root): - """Not currently used by portage.""" - writemsg("DEPRECATED: portage.config.loadVirtuals\n") - self.getvirtuals(root) - - def load_best_module(self,property_string): - best_mod = best_from_dict(property_string,self.modules,self.module_priority) - mod = None - try: - mod = load_mod(best_mod) - except ImportError: - if best_mod.startswith("cache."): - best_mod = "portage." + best_mod - try: - mod = load_mod(best_mod) - except ImportError: - pass - if mod is None: - raise - return mod - - def lock(self): - self.locked = 1 - - def unlock(self): - self.locked = 0 - - def modifying(self): - if self.locked: - raise Exception(_("Configuration is locked.")) - - def backup_changes(self,key=None): - self.modifying() - if key and key in self.configdict["env"]: - self.backupenv[key] = copy.deepcopy(self.configdict["env"][key]) - else: - raise KeyError(_("No such key defined in environment: %s") % key) - - def reset(self,keeping_pkg=0,use_cache=1): - """ - Restore environment from self.backupenv, call self.regenerate() - @param keeping_pkg: Should we keep the set_cpv() data or delete it. - @type keeping_pkg: Boolean - @param use_cache: Should self.regenerate use the cache or not - @type use_cache: Boolean - @rype: None - """ - self.modifying() - self.configdict["env"].clear() - self.configdict["env"].update(self.backupenv) - - self.modifiedkeys = [] - if not keeping_pkg: - self.mycpv = None - self.puse = "" - self.configdict["pkg"].clear() - self.configdict["pkginternal"].clear() - self.configdict["defaults"]["USE"] = \ - " ".join(self.make_defaults_use) - self.usemask = set(stack_lists( - self.usemask_list, incremental=True)) - self.useforce = set(stack_lists( - self.useforce_list, incremental=True)) - self.regenerate(use_cache=use_cache) - - class _lazy_vars(object): - - __slots__ = ('built_use', 'settings', 'values') - - def __init__(self, built_use, settings): - self.built_use = built_use - self.settings = settings - self.values = None - - def __getitem__(self, k): - if self.values is None: - self.values = self._init_values() - return self.values[k] - - def _init_values(self): - values = {} - settings = self.settings - use = self.built_use - if use is None: - use = frozenset(settings['PORTAGE_USE'].split()) - values['ACCEPT_LICENSE'] = self._accept_license(use, settings) - values['PORTAGE_RESTRICT'] = self._restrict(use, settings) - return values - - def _accept_license(self, use, settings): - """ - Generate a pruned version of ACCEPT_LICENSE, by intersection with - LICENSE. This is required since otherwise ACCEPT_LICENSE might be - too big (bigger than ARG_MAX), causing execve() calls to fail with - E2BIG errors as in bug #262647. - """ - try: - licenses = set(flatten( - dep.use_reduce(dep.paren_reduce( - settings['LICENSE']), - uselist=use))) - except exception.InvalidDependString: - licenses = set() - licenses.discard('||') - if settings._accept_license: - acceptable_licenses = set() - for x in settings._accept_license: - if x == '*': - acceptable_licenses.update(licenses) - elif x == '-*': - acceptable_licenses.clear() - elif x[:1] == '-': - acceptable_licenses.discard(x[1:]) - elif x in licenses: - acceptable_licenses.add(x) - - licenses = acceptable_licenses - return ' '.join(sorted(licenses)) - - def _restrict(self, use, settings): - try: - restrict = set(flatten( - dep.use_reduce(dep.paren_reduce( - settings['RESTRICT']), - uselist=use))) - except exception.InvalidDependString: - restrict = set() - return ' '.join(sorted(restrict)) - - class _lazy_use_expand(object): - """ - Lazily evaluate USE_EXPAND variables since they are only needed when - an ebuild shell is spawned. Variables values are made consistent with - the previously calculated USE settings. - """ - - def __init__(self, use, usemask, iuse_implicit, - use_expand_split, use_expand_dict): - self._use = use - self._usemask = usemask - self._iuse_implicit = iuse_implicit - self._use_expand_split = use_expand_split - self._use_expand_dict = use_expand_dict - - def __getitem__(self, key): - prefix = key.lower() + '_' - prefix_len = len(prefix) - expand_flags = set( x[prefix_len:] for x in self._use \ - if x[:prefix_len] == prefix ) - var_split = self._use_expand_dict.get(key, '').split() - # Preserve the order of var_split because it can matter for things - # like LINGUAS. - var_split = [ x for x in var_split if x in expand_flags ] - var_split.extend(expand_flags.difference(var_split)) - has_wildcard = '*' in expand_flags - if has_wildcard: - var_split = [ x for x in var_split if x != "*" ] - has_iuse = set() - for x in self._iuse_implicit: - if x[:prefix_len] == prefix: - has_iuse.add(x[prefix_len:]) - if has_wildcard: - # * means to enable everything in IUSE that's not masked - if has_iuse: - usemask = self._usemask - for suffix in has_iuse: - x = prefix + suffix - if x not in usemask: - if suffix not in expand_flags: - var_split.append(suffix) - else: - # If there is a wildcard and no matching flags in IUSE then - # LINGUAS should be unset so that all .mo files are - # installed. - var_split = [] - # Make the flags unique and filter them according to IUSE. - # Also, continue to preserve order for things like LINGUAS - # and filter any duplicates that variable may contain. - filtered_var_split = [] - remaining = has_iuse.intersection(var_split) - for x in var_split: - if x in remaining: - remaining.remove(x) - filtered_var_split.append(x) - var_split = filtered_var_split - - if var_split: - value = ' '.join(var_split) - else: - # Don't export empty USE_EXPAND vars unless the user config - # exports them as empty. This is required for vars such as - # LINGUAS, where unset and empty have different meanings. - if has_wildcard: - # ebuild.sh will see this and unset the variable so - # that things like LINGUAS work properly - value = '*' - else: - if has_iuse: - value = '' - else: - # It's not in IUSE, so just allow the variable content - # to pass through if it is defined somewhere. This - # allows packages that support LINGUAS but don't - # declare it in IUSE to use the variable outside of the - # USE_EXPAND context. - value = None - - return value - - def setcpv(self, mycpv, use_cache=1, mydb=None): - """ - Load a particular CPV into the config, this lets us see the - Default USE flags for a particular ebuild as well as the USE - flags from package.use. - - @param mycpv: A cpv to load - @type mycpv: string - @param use_cache: Enables caching - @type use_cache: Boolean - @param mydb: a dbapi instance that supports aux_get with the IUSE key. - @type mydb: dbapi or derivative. - @rtype: None - """ - - self.modifying() - - pkg = None - built_use = None - if not isinstance(mycpv, basestring): - pkg = mycpv - mycpv = pkg.cpv - mydb = pkg.metadata - args_hash = (mycpv, id(pkg)) - if pkg.built: - built_use = pkg.use.enabled - else: - args_hash = (mycpv, id(mydb)) - - if args_hash == self._setcpv_args_hash: - return - self._setcpv_args_hash = args_hash - - has_changed = False - self.mycpv = mycpv - cat, pf = catsplit(mycpv) - cp = cpv_getkey(mycpv) - cpv_slot = self.mycpv - pkginternaluse = "" - iuse = "" - pkg_configdict = self.configdict["pkg"] - previous_iuse = pkg_configdict.get("IUSE") - - aux_keys = self._setcpv_aux_keys - - # Discard any existing metadata from the previous package, but - # preserve things like USE_EXPAND values and PORTAGE_USE which - # might be reused. - for k in aux_keys: - pkg_configdict.pop(k, None) - - pkg_configdict["CATEGORY"] = cat - pkg_configdict["PF"] = pf - if mydb: - if not hasattr(mydb, "aux_get"): - for k in aux_keys: - if k in mydb: - # Make these lazy, since __getitem__ triggers - # evaluation of USE conditionals which can't - # occur until PORTAGE_USE is calculated below. - pkg_configdict.addLazySingleton(k, - mydb.__getitem__, k) - else: - for k, v in zip(aux_keys, mydb.aux_get(self.mycpv, aux_keys)): - pkg_configdict[k] = v - repository = pkg_configdict.pop("repository", None) - if repository is not None: - pkg_configdict["PORTAGE_REPO_NAME"] = repository - slot = pkg_configdict["SLOT"] - iuse = pkg_configdict["IUSE"] - if pkg is None: - cpv_slot = "%s:%s" % (self.mycpv, slot) - else: - cpv_slot = pkg - pkginternaluse = [] - for x in iuse.split(): - if x.startswith("+"): - pkginternaluse.append(x[1:]) - elif x.startswith("-"): - pkginternaluse.append(x) - pkginternaluse = " ".join(pkginternaluse) - if pkginternaluse != self.configdict["pkginternal"].get("USE", ""): - self.configdict["pkginternal"]["USE"] = pkginternaluse - has_changed = True - - defaults = [] - pos = 0 - for i, pkgprofileuse_dict in enumerate(self.pkgprofileuse): - cpdict = pkgprofileuse_dict.get(cp) - if cpdict: - keys = list(cpdict) - while keys: - bestmatch = best_match_to_list(cpv_slot, keys) - if bestmatch: - keys.remove(bestmatch) - defaults.insert(pos, cpdict[bestmatch]) - else: - break - del keys - if self.make_defaults_use[i]: - defaults.insert(pos, self.make_defaults_use[i]) - pos = len(defaults) - defaults = " ".join(defaults) - if defaults != self.configdict["defaults"].get("USE",""): - self.configdict["defaults"]["USE"] = defaults - has_changed = True - - useforce = self._getUseForce(cpv_slot) - if useforce != self.useforce: - self.useforce = useforce - has_changed = True - - usemask = self._getUseMask(cpv_slot) - if usemask != self.usemask: - self.usemask = usemask - has_changed = True - oldpuse = self.puse - self.puse = "" - cpdict = self.pusedict.get(cp) - if cpdict: - keys = list(cpdict) - while keys: - self.pusekey = best_match_to_list(cpv_slot, keys) - if self.pusekey: - keys.remove(self.pusekey) - self.puse = (" ".join(cpdict[self.pusekey])) + " " + self.puse - else: - break - del keys - if oldpuse != self.puse: - has_changed = True - self.configdict["pkg"]["PKGUSE"] = self.puse[:] # For saving to PUSE file - self.configdict["pkg"]["USE"] = self.puse[:] # this gets appended to USE - - if has_changed: - self.reset(keeping_pkg=1,use_cache=use_cache) - - # Ensure that "pkg" values are always preferred over "env" values. - # This must occur _after_ the above reset() call, since reset() - # copies values from self.backupenv. - env_configdict = self.configdict['env'] - for k in pkg_configdict: - if k != 'USE': - env_configdict.pop(k, None) - - lazy_vars = self._lazy_vars(built_use, self) - env_configdict.addLazySingleton('ACCEPT_LICENSE', - lazy_vars.__getitem__, 'ACCEPT_LICENSE') - env_configdict.addLazySingleton('PORTAGE_RESTRICT', - lazy_vars.__getitem__, 'PORTAGE_RESTRICT') - - # If reset() has not been called, it's safe to return - # early if IUSE has not changed. - if not has_changed and previous_iuse == iuse: - return - - # Filter out USE flags that aren't part of IUSE. This has to - # be done for every setcpv() call since practically every - # package has different IUSE. - use = set(self["USE"].split()) - iuse_implicit = self._get_implicit_iuse() - iuse_implicit.update(x.lstrip("+-") for x in iuse.split()) - - # PORTAGE_IUSE is not always needed so it's lazily evaluated. - self.configdict["pkg"].addLazySingleton( - "PORTAGE_IUSE", _lazy_iuse_regex, iuse_implicit) - - ebuild_force_test = self.get("EBUILD_FORCE_TEST") == "1" - if ebuild_force_test and \ - not hasattr(self, "_ebuild_force_test_msg_shown"): - self._ebuild_force_test_msg_shown = True - writemsg(_("Forcing test.\n"), noiselevel=-1) - if "test" in self.features: - if "test" in self.usemask and not ebuild_force_test: - # "test" is in IUSE and USE=test is masked, so execution - # of src_test() probably is not reliable. Therefore, - # temporarily disable FEATURES=test just for this package. - self["FEATURES"] = " ".join(x for x in self.features \ - if x != "test") - use.discard("test") - else: - use.add("test") - if ebuild_force_test: - self.usemask.discard("test") - - # Allow _* flags from USE_EXPAND wildcards to pass through here. - use.difference_update([x for x in use \ - if x not in iuse_implicit and x[-2:] != '_*']) - - # Use the calculated USE flags to regenerate the USE_EXPAND flags so - # that they are consistent. For optimal performance, use slice - # comparison instead of startswith(). - use_expand_split = set(x.lower() for \ - x in self.get('USE_EXPAND', '').split()) - lazy_use_expand = self._lazy_use_expand(use, self.usemask, - iuse_implicit, use_expand_split, self._use_expand_dict) - - use_expand_iuses = {} - for x in iuse_implicit: - x_split = x.split('_') - if len(x_split) == 1: - continue - for i in range(len(x_split) - 1): - k = '_'.join(x_split[:i+1]) - if k in use_expand_split: - v = use_expand_iuses.get(k) - if v is None: - v = set() - use_expand_iuses[k] = v - v.add(x) - break - - # If it's not in IUSE, variable content is allowed - # to pass through if it is defined somewhere. This - # allows packages that support LINGUAS but don't - # declare it in IUSE to use the variable outside of the - # USE_EXPAND context. - for k, use_expand_iuse in use_expand_iuses.items(): - if k + '_*' in use: - use.update( x for x in use_expand_iuse if x not in usemask ) - k = k.upper() - self.configdict['env'].addLazySingleton(k, - lazy_use_expand.__getitem__, k) - - # Filtered for the ebuild environment. Store this in a separate - # attribute since we still want to be able to see global USE - # settings for things like emerge --info. - - self.configdict["pkg"]["PORTAGE_USE"] = \ - " ".join(sorted(x for x in use if x[-2:] != '_*')) - - def _get_implicit_iuse(self): - """ - Some flags are considered to - be implicit members of IUSE: - * Flags derived from ARCH - * Flags derived from USE_EXPAND_HIDDEN variables - * Masked flags, such as those from {,package}use.mask - * Forced flags, such as those from {,package}use.force - * build and bootstrap flags used by bootstrap.sh - """ - iuse_implicit = set() - # Flags derived from ARCH. - arch = self.configdict["defaults"].get("ARCH") - if arch: - iuse_implicit.add(arch) - iuse_implicit.update(self.get("PORTAGE_ARCHLIST", "").split()) - - # Flags derived from USE_EXPAND_HIDDEN variables - # such as ELIBC, KERNEL, and USERLAND. - use_expand_hidden = self.get("USE_EXPAND_HIDDEN", "").split() - for x in use_expand_hidden: - iuse_implicit.add(x.lower() + "_.*") - - # Flags that have been masked or forced. - iuse_implicit.update(self.usemask) - iuse_implicit.update(self.useforce) - - # build and bootstrap flags used by bootstrap.sh - iuse_implicit.add("build") - iuse_implicit.add("bootstrap") - - # Controlled by FEATURES=test. Make this implicit, so handling - # of FEATURES=test is consistent regardless of explicit IUSE. - # Users may use use.mask/package.use.mask to control - # FEATURES=test for all ebuilds, regardless of explicit IUSE. - iuse_implicit.add("test") - - return iuse_implicit - - def _getUseMask(self, pkg): - cp = getattr(pkg, "cp", None) - if cp is None: - cp = cpv_getkey(dep.remove_slot(pkg)) - usemask = [] - pos = 0 - for i, pusemask_dict in enumerate(self.pusemask_list): - cpdict = pusemask_dict.get(cp) - if cpdict: - keys = list(cpdict) - while keys: - best_match = best_match_to_list(pkg, keys) - if best_match: - keys.remove(best_match) - usemask.insert(pos, cpdict[best_match]) - else: - break - del keys - if self.usemask_list[i]: - usemask.insert(pos, self.usemask_list[i]) - pos = len(usemask) - return set(stack_lists(usemask, incremental=True)) - - def _getUseForce(self, pkg): - cp = getattr(pkg, "cp", None) - if cp is None: - cp = cpv_getkey(dep.remove_slot(pkg)) - useforce = [] - pos = 0 - for i, puseforce_dict in enumerate(self.puseforce_list): - cpdict = puseforce_dict.get(cp) - if cpdict: - keys = list(cpdict) - while keys: - best_match = best_match_to_list(pkg, keys) - if best_match: - keys.remove(best_match) - useforce.insert(pos, cpdict[best_match]) - else: - break - del keys - if self.useforce_list[i]: - useforce.insert(pos, self.useforce_list[i]) - pos = len(useforce) - return set(stack_lists(useforce, incremental=True)) - - def _getMaskAtom(self, cpv, metadata): - """ - Take a package and return a matching package.mask atom, or None if no - such atom exists or it has been cancelled by package.unmask. PROVIDE - is not checked, so atoms will not be found for old-style virtuals. - - @param cpv: The package name - @type cpv: String - @param metadata: A dictionary of raw package metadata - @type metadata: dict - @rtype: String - @return: An matching atom string or None if one is not found. - """ - - cp = cpv_getkey(cpv) - mask_atoms = self.pmaskdict.get(cp) - if mask_atoms: - pkg_list = ["%s:%s" % (cpv, metadata["SLOT"])] - unmask_atoms = self.punmaskdict.get(cp) - for x in mask_atoms: - if not match_from_list(x, pkg_list): - continue - if unmask_atoms: - for y in unmask_atoms: - if match_from_list(y, pkg_list): - return None - return x - return None - - def _getProfileMaskAtom(self, cpv, metadata): - """ - Take a package and return a matching profile atom, or None if no - such atom exists. Note that a profile atom may or may not have a "*" - prefix. PROVIDE is not checked, so atoms will not be found for - old-style virtuals. - - @param cpv: The package name - @type cpv: String - @param metadata: A dictionary of raw package metadata - @type metadata: dict - @rtype: String - @return: An matching profile atom string or None if one is not found. - """ - - cp = cpv_getkey(cpv) - profile_atoms = self.prevmaskdict.get(cp) - if profile_atoms: - pkg_list = ["%s:%s" % (cpv, metadata["SLOT"])] - for x in profile_atoms: - if match_from_list(x, pkg_list): - continue - return x - return None - - def _getKeywords(self, cpv, metadata): - cp = cpv_getkey(cpv) - pkg = "%s:%s" % (cpv, metadata["SLOT"]) - keywords = [[x for x in metadata["KEYWORDS"].split() if x != "-*"]] - pos = len(keywords) - for pkeywords_dict in self._pkeywords_list: - cpdict = pkeywords_dict.get(cp) - if cpdict: - keys = list(cpdict) - while keys: - best_match = best_match_to_list(pkg, keys) - if best_match: - keys.remove(best_match) - keywords.insert(pos, cpdict[best_match]) - else: - break - pos = len(keywords) - return stack_lists(keywords, incremental=True) - - def _getMissingKeywords(self, cpv, metadata): - """ - Take a package and return a list of any KEYWORDS that the user may - may need to accept for the given package. If the KEYWORDS are empty - and the the ** keyword has not been accepted, the returned list will - contain ** alone (in order to distiguish from the case of "none - missing"). - - @param cpv: The package name (for package.keywords support) - @type cpv: String - @param metadata: A dictionary of raw package metadata - @type metadata: dict - @rtype: List - @return: A list of KEYWORDS that have not been accepted. - """ - - # Hack: Need to check the env directly here as otherwise stacking - # doesn't work properly as negative values are lost in the config - # object (bug #139600) - egroups = self.configdict["backupenv"].get( - "ACCEPT_KEYWORDS", "").split() - mygroups = self._getKeywords(cpv, metadata) - # Repoman may modify this attribute as necessary. - pgroups = self["ACCEPT_KEYWORDS"].split() - match=0 - cp = cpv_getkey(cpv) - pkgdict = self.pkeywordsdict.get(cp) - matches = False - if pkgdict: - cpv_slot_list = ["%s:%s" % (cpv, metadata["SLOT"])] - for atom, pkgkeywords in pkgdict.items(): - if match_from_list(atom, cpv_slot_list): - matches = True - pgroups.extend(pkgkeywords) - if matches or egroups: - pgroups.extend(egroups) - inc_pgroups = set() - for x in pgroups: - if x.startswith("-"): - if x == "-*": - inc_pgroups.clear() - else: - inc_pgroups.discard(x[1:]) - else: - inc_pgroups.add(x) - pgroups = inc_pgroups - del inc_pgroups - hasstable = False - hastesting = False - for gp in mygroups: - if gp == "*" or (gp == "-*" and len(mygroups) == 1): - writemsg(_("--- WARNING: Package '%(cpv)s' uses" - " '%(keyword)s' keyword.\n") % {"cpv": cpv, "keyword": gp}, noiselevel=-1) - if gp == "*": - match = 1 - break - elif gp in pgroups: - match=1 - break - elif gp.startswith("~"): - hastesting = True - elif not gp.startswith("-"): - hasstable = True - if not match and \ - ((hastesting and "~*" in pgroups) or \ - (hasstable and "*" in pgroups) or "**" in pgroups): - match=1 - if match: - missing = [] - else: - if not mygroups: - # If KEYWORDS is empty then we still have to return something - # in order to distiguish from the case of "none missing". - mygroups.append("**") - missing = mygroups - return missing - - def _getMissingLicenses(self, cpv, metadata): - """ - Take a LICENSE string and return a list any licenses that the user may - may need to accept for the given package. The returned list will not - contain any licenses that have already been accepted. This method - can throw an InvalidDependString exception. - - @param cpv: The package name (for package.license support) - @type cpv: String - @param metadata: A dictionary of raw package metadata - @type metadata: dict - @rtype: List - @return: A list of licenses that have not been accepted. - """ - accept_license = self._accept_license - cpdict = self._plicensedict.get(cpv_getkey(cpv), None) - if cpdict: - accept_license = list(self._accept_license) - cpv_slot = "%s:%s" % (cpv, metadata["SLOT"]) - for atom in match_to_list(cpv_slot, list(cpdict)): - accept_license.extend(cpdict[atom]) - - licenses = set(flatten(dep.use_reduce(dep.paren_reduce( - metadata["LICENSE"]), matchall=1))) - licenses.discard('||') - - acceptable_licenses = set() - for x in accept_license: - if x == '*': - acceptable_licenses.update(licenses) - elif x == '-*': - acceptable_licenses.clear() - elif x[:1] == '-': - acceptable_licenses.discard(x[1:]) - else: - acceptable_licenses.add(x) - - license_str = metadata["LICENSE"] - if "?" in license_str: - use = metadata["USE"].split() - else: - use = [] - - license_struct = portage.dep.use_reduce( - portage.dep.paren_reduce(license_str), uselist=use) - license_struct = portage.dep.dep_opconvert(license_struct) - return self._getMaskedLicenses(license_struct, acceptable_licenses) - - def _getMaskedLicenses(self, license_struct, acceptable_licenses): - if not license_struct: - return [] - if license_struct[0] == "||": - ret = [] - for element in license_struct[1:]: - if isinstance(element, list): - if element: - ret.append(self._getMaskedLicenses( - element, acceptable_licenses)) - if not ret[-1]: - return [] - else: - if element in acceptable_licenses: - return [] - ret.append(element) - # Return all masked licenses, since we don't know which combination - # (if any) the user will decide to unmask. - return flatten(ret) - - ret = [] - for element in license_struct: - if isinstance(element, list): - if element: - ret.extend(self._getMaskedLicenses(element, - acceptable_licenses)) - else: - if element not in acceptable_licenses: - ret.append(element) - return ret - - def _getMissingProperties(self, cpv, metadata): - """ - Take a PROPERTIES string and return a list of any properties the user may - may need to accept for the given package. The returned list will not - contain any properties that have already been accepted. This method - can throw an InvalidDependString exception. - - @param cpv: The package name (for package.properties support) - @type cpv: String - @param metadata: A dictionary of raw package metadata - @type metadata: dict - @rtype: List - @return: A list of properties that have not been accepted. - """ - accept_properties = self._accept_properties - cpdict = self._ppropertiesdict.get(cpv_getkey(cpv), None) - if cpdict: - accept_properties = list(self._accept_properties) - cpv_slot = "%s:%s" % (cpv, metadata["SLOT"]) - for atom in match_to_list(cpv_slot, list(cpdict)): - accept_properties.extend(cpdict[atom]) - - properties = set(flatten(dep.use_reduce(dep.paren_reduce( - metadata["PROPERTIES"]), matchall=1))) - properties.discard('||') - - acceptable_properties = set() - for x in accept_properties: - if x == '*': - acceptable_properties.update(properties) - elif x == '-*': - acceptable_properties.clear() - elif x[:1] == '-': - acceptable_properties.discard(x[1:]) - else: - acceptable_properties.add(x) - - properties_str = metadata["PROPERTIES"] - if "?" in properties_str: - use = metadata["USE"].split() - else: - use = [] - - properties_struct = portage.dep.use_reduce( - portage.dep.paren_reduce(properties_str), uselist=use) - properties_struct = portage.dep.dep_opconvert(properties_struct) - return self._getMaskedProperties(properties_struct, acceptable_properties) - - def _getMaskedProperties(self, properties_struct, acceptable_properties): - if not properties_struct: - return [] - if properties_struct[0] == "||": - ret = [] - for element in properties_struct[1:]: - if isinstance(element, list): - if element: - ret.append(self._getMaskedProperties( - element, acceptable_properties)) - if not ret[-1]: - return [] - else: - if element in acceptable_properties: - return[] - ret.append(element) - # Return all masked properties, since we don't know which combination - # (if any) the user will decide to unmask - return flatten(ret) - - ret = [] - for element in properties_struct: - if isinstance(element, list): - if element: - ret.extend(self._getMaskedProperties(element, - acceptable_properties)) - else: - if element not in acceptable_properties: - ret.append(element) - return ret - - def _accept_chost(self, cpv, metadata): - """ - @return True if pkg CHOST is accepted, False otherwise. - """ - if self._accept_chost_re is None: - accept_chost = self.get("ACCEPT_CHOSTS", "").split() - if not accept_chost: - chost = self.get("CHOST") - if chost: - accept_chost.append(chost) - if not accept_chost: - self._accept_chost_re = re.compile(".*") - elif len(accept_chost) == 1: - try: - self._accept_chost_re = re.compile(r'^%s$' % accept_chost[0]) - except re.error as e: - writemsg(_("!!! Invalid ACCEPT_CHOSTS value: '%s': %s\n") % \ - (accept_chost[0], e), noiselevel=-1) - self._accept_chost_re = re.compile("^$") - else: - try: - self._accept_chost_re = re.compile( - r'^(%s)$' % "|".join(accept_chost)) - except re.error as e: - writemsg(_("!!! Invalid ACCEPT_CHOSTS value: '%s': %s\n") % \ - (" ".join(accept_chost), e), noiselevel=-1) - self._accept_chost_re = re.compile("^$") - - pkg_chost = metadata.get('CHOST', '') - return not pkg_chost or \ - self._accept_chost_re.match(pkg_chost) is not None - - def setinst(self,mycpv,mydbapi): - """This updates the preferences for old-style virtuals, - affecting the behavior of dep_expand() and dep_check() - calls. It can change dbapi.match() behavior since that - calls dep_expand(). However, dbapi instances have - internal match caches that are not invalidated when - preferences are updated here. This can potentially - lead to some inconsistency (relevant to bug #1343).""" - self.modifying() - if len(self.virtuals) == 0: - self.getvirtuals() - # Grab the virtuals this package provides and add them into the tree virtuals. - if not hasattr(mydbapi, "aux_get"): - provides = mydbapi["PROVIDE"] - else: - provides = mydbapi.aux_get(mycpv, ["PROVIDE"])[0] - if not provides: - return - if isinstance(mydbapi, portdbapi): - self.setcpv(mycpv, mydb=mydbapi) - myuse = self["PORTAGE_USE"] - elif not hasattr(mydbapi, "aux_get"): - myuse = mydbapi["USE"] - else: - myuse = mydbapi.aux_get(mycpv, ["USE"])[0] - virts = flatten(portage.dep.use_reduce(portage.dep.paren_reduce(provides), uselist=myuse.split())) - - modified = False - cp = dep.Atom(cpv_getkey(mycpv)) - for virt in virts: - try: - virt = dep.Atom(virt).cp - except exception.InvalidAtom: - continue - providers = self.virtuals.get(virt) - if providers and cp in providers: - continue - providers = self._depgraphVirtuals.get(virt) - if providers is None: - providers = [] - self._depgraphVirtuals[virt] = providers - if cp not in providers: - providers.append(cp) - modified = True - - if modified: - self.virtuals = self.__getvirtuals_compile() - - def reload(self): - """Reload things like /etc/profile.env that can change during runtime.""" - env_d_filename = os.path.join(self["ROOT"], "etc", "profile.env") - self.configdict["env.d"].clear() - env_d = getconfig(env_d_filename, expand=False) - if env_d: - # env_d will be None if profile.env doesn't exist. - self.configdict["env.d"].update(env_d) - - def _prune_incremental(self, split): - """ - Prune off any parts of an incremental variable that are - made irrelevant by the latest occuring * or -*. This - could be more aggressive but that might be confusing - and the point is just to reduce noise a bit. - """ - for i, x in enumerate(reversed(split)): - if x == '*': - split = split[-i-1:] - break - elif x == '-*': - if i == 0: - split = [] - else: - split = split[-i:] - break - return split - - def regenerate(self,useonly=0,use_cache=1): - """ - Regenerate settings - This involves regenerating valid USE flags, re-expanding USE_EXPAND flags - re-stacking USE flags (-flag and -*), as well as any other INCREMENTAL - variables. This also updates the env.d configdict; useful in case an ebuild - changes the environment. - - If FEATURES has already stacked, it is not stacked twice. - - @param useonly: Only regenerate USE flags (not any other incrementals) - @type useonly: Boolean - @param use_cache: Enable Caching (only for autouse) - @type use_cache: Boolean - @rtype: None - """ - - self.modifying() - if self.already_in_regenerate: - # XXX: THIS REALLY NEEDS TO GET FIXED. autouse() loops. - writemsg("!!! Looping in regenerate.\n",1) - return - else: - self.already_in_regenerate = 1 - - if useonly: - myincrementals=["USE"] - else: - myincrementals = self.incrementals - myincrementals = set(myincrementals) - # If self.features exists, it has already been stacked and may have - # been mutated, so don't stack it again or else any mutations will be - # reverted. - if "FEATURES" in myincrementals and hasattr(self, "features"): - myincrementals.remove("FEATURES") - - if "USE" in myincrementals: - # Process USE last because it depends on USE_EXPAND which is also - # an incremental! - myincrementals.remove("USE") - - mydbs = self.configlist[:-1] - mydbs.append(self.backupenv) - - # ACCEPT_LICENSE is a lazily evaluated incremental, so that * can be - # used to match all licenses without every having to explicitly expand - # it to all licenses. - if self.local_config: - mysplit = [] - for curdb in mydbs: - mysplit.extend(curdb.get('ACCEPT_LICENSE', '').split()) - mysplit = self._prune_incremental(mysplit) - accept_license_str = ' '.join(mysplit) - self.configlist[-1]['ACCEPT_LICENSE'] = accept_license_str - if accept_license_str != self._accept_license_str: - self._accept_license_str = accept_license_str - self._accept_license = tuple(self.expandLicenseTokens(mysplit)) - else: - # repoman will accept any license - self._accept_license = ('*',) - - # ACCEPT_PROPERTIES works like ACCEPT_LICENSE, without groups - if self.local_config: - mysplit = [] - for curdb in mydbs: - mysplit.extend(curdb.get('ACCEPT_PROPERTIES', '').split()) - mysplit = self._prune_incremental(mysplit) - self.configlist[-1]['ACCEPT_PROPERTIES'] = ' '.join(mysplit) - if tuple(mysplit) != self._accept_properties: - self._accept_properties = tuple(mysplit) - else: - # repoman will accept any property - self._accept_properties = ('*',) - - for mykey in myincrementals: - - myflags=[] - for curdb in mydbs: - if mykey not in curdb: - continue - #variables are already expanded - mysplit = curdb[mykey].split() - - for x in mysplit: - if x=="-*": - # "-*" is a special "minus" var that means "unset all settings". - # so USE="-* gnome" will have *just* gnome enabled. - myflags = [] - continue - - if x[0]=="+": - # Not legal. People assume too much. Complain. - writemsg(colorize("BAD", - _("USE flags should not start with a '+': %s") % x) \ - + "\n", noiselevel=-1) - x=x[1:] - if not x: - continue - - if (x[0]=="-"): - if (x[1:] in myflags): - # Unset/Remove it. - del myflags[myflags.index(x[1:])] - continue - - # We got here, so add it now. - if x not in myflags: - myflags.append(x) - - myflags.sort() - #store setting in last element of configlist, the original environment: - if myflags or mykey in self: - self.configlist[-1][mykey] = " ".join(myflags) - del myflags - - # Do the USE calculation last because it depends on USE_EXPAND. - if "auto" in self["USE_ORDER"].split(":"): - self.configdict["auto"]["USE"] = autouse( - vartree(root=self["ROOT"], categories=self.categories, - settings=self), - use_cache=use_cache, mysettings=self) - else: - self.configdict["auto"]["USE"] = "" - - use_expand = self.get("USE_EXPAND", "").split() - use_expand_dict = self._use_expand_dict - use_expand_dict.clear() - for k in use_expand: - v = self.get(k) - if v is not None: - use_expand_dict[k] = v - - if not self.uvlist: - for x in self["USE_ORDER"].split(":"): - if x in self.configdict: - self.uvlist.append(self.configdict[x]) - self.uvlist.reverse() - - # For optimal performance, use slice - # comparison instead of startswith(). - myflags = set() - for curdb in self.uvlist: - cur_use_expand = [x for x in use_expand if x in curdb] - mysplit = curdb.get("USE", "").split() - if not mysplit and not cur_use_expand: - continue - for x in mysplit: - if x == "-*": - myflags.clear() - continue - - if x[0] == "+": - writemsg(colorize("BAD", _("USE flags should not start " - "with a '+': %s\n") % x), noiselevel=-1) - x = x[1:] - if not x: - continue - - if x[0] == "-": - myflags.discard(x[1:]) - continue - - myflags.add(x) - - for var in cur_use_expand: - var_lower = var.lower() - is_not_incremental = var not in myincrementals - if is_not_incremental: - prefix = var_lower + "_" - prefix_len = len(prefix) - for x in list(myflags): - if x[:prefix_len] == prefix: - myflags.remove(x) - for x in curdb[var].split(): - if x[0] == "+": - if is_not_incremental: - writemsg(colorize("BAD", _("Invalid '+' " - "operator in non-incremental variable " - "'%s': '%s'\n") % (var, x)), noiselevel=-1) - continue - else: - writemsg(colorize("BAD", _("Invalid '+' " - "operator in incremental variable " - "'%s': '%s'\n") % (var, x)), noiselevel=-1) - x = x[1:] - if x[0] == "-": - if is_not_incremental: - writemsg(colorize("BAD", _("Invalid '-' " - "operator in non-incremental variable " - "'%s': '%s'\n") % (var, x)), noiselevel=-1) - continue - myflags.discard(var_lower + "_" + x[1:]) - continue - myflags.add(var_lower + "_" + x) - - if hasattr(self, "features"): - self.features.clear() - else: - self.features = set() - self.features.update(self.configlist[-1].get('FEATURES', '').split()) - self['FEATURES'] = ' '.join(sorted(self.features)) - - myflags.update(self.useforce) - arch = self.configdict["defaults"].get("ARCH") - if arch: - myflags.add(arch) - - myflags.difference_update(self.usemask) - self.configlist[-1]["USE"]= " ".join(sorted(myflags)) - - self.already_in_regenerate = 0 - - def get_virts_p(self, myroot=None): - - if myroot is not None: - warnings.warn("The 'myroot' parameter for " + \ - "portage.config.get_virts_p() is deprecated", - DeprecationWarning, stacklevel=2) - - if self.virts_p: - return self.virts_p - virts = self.getvirtuals() - if virts: - for x in virts: - vkeysplit = x.split("/") - if vkeysplit[1] not in self.virts_p: - self.virts_p[vkeysplit[1]] = virts[x] - return self.virts_p - - def getvirtuals(self, myroot=None): - """myroot is now ignored because, due to caching, it has always been - broken for all but the first call.""" - - if myroot is not None: - warnings.warn("The 'myroot' parameter for " + \ - "portage.config.getvirtuals() is deprecated", - DeprecationWarning, stacklevel=2) - - myroot = self["ROOT"] - if self.virtuals: - return self.virtuals - - virtuals_list = [] - for x in self.profiles: - virtuals_file = os.path.join(x, "virtuals") - virtuals_dict = grabdict(virtuals_file) - atoms_dict = {} - for k, v in virtuals_dict.items(): - try: - virt_atom = portage.dep.Atom(k) - except portage.exception.InvalidAtom: - virt_atom = None - else: - if virt_atom.blocker or \ - str(virt_atom) != str(virt_atom.cp): - virt_atom = None - if virt_atom is None: - writemsg(_("--- Invalid virtuals atom in %s: %s\n") % \ - (virtuals_file, k), noiselevel=-1) - continue - providers = [] - for atom in v: - atom_orig = atom - if atom[:1] == '-': - # allow incrementals - atom = atom[1:] - try: - atom = portage.dep.Atom(atom) - except portage.exception.InvalidAtom: - atom = None - else: - if atom.blocker: - atom = None - if atom is None: - writemsg(_("--- Invalid atom in %s: %s\n") % \ - (virtuals_file, myatom), noiselevel=-1) - else: - if atom_orig == str(atom): - # normal atom, so return as Atom instance - providers.append(atom) - else: - # atom has special prefix, so return as string - providers.append(atom_orig) - if providers: - atoms_dict[virt_atom] = providers - if atoms_dict: - virtuals_list.append(atoms_dict) - - self.dirVirtuals = stack_dictlist(virtuals_list, incremental=True) - del virtuals_list - - for virt in self.dirVirtuals: - # Preference for virtuals decreases from left to right. - self.dirVirtuals[virt].reverse() - - # Repoman does not use user or tree virtuals. - if self.local_config and not self.treeVirtuals: - temp_vartree = vartree(myroot, None, - categories=self.categories, settings=self) - self._populate_treeVirtuals(temp_vartree) - - self.virtuals = self.__getvirtuals_compile() - return self.virtuals - - def _populate_treeVirtuals(self, vartree): - """Reduce the provides into a list by CP.""" - for provide, cpv_list in vartree.get_all_provides().items(): - try: - provide = dep.Atom(provide) - except exception.InvalidAtom: - continue - self.treeVirtuals[provide.cp] = \ - [dep.Atom(cpv_getkey(cpv)) for cpv in cpv_list] - - def __getvirtuals_compile(self): - """Stack installed and profile virtuals. Preference for virtuals - decreases from left to right. - Order of preference: - 1. installed and in profile - 2. installed only - 3. profile only - """ - - # Virtuals by profile+tree preferences. - ptVirtuals = {} - - for virt, installed_list in self.treeVirtuals.items(): - profile_list = self.dirVirtuals.get(virt, None) - if not profile_list: - continue - for cp in installed_list: - if cp in profile_list: - ptVirtuals.setdefault(virt, []) - ptVirtuals[virt].append(cp) - - virtuals = stack_dictlist([ptVirtuals, self.treeVirtuals, - self.dirVirtuals, self._depgraphVirtuals]) - return virtuals - - def __delitem__(self,mykey): - self.modifying() - for x in self.lookuplist: - if x != None: - if mykey in x: - del x[mykey] - - def __getitem__(self,mykey): - for d in self.lookuplist: - if mykey in d: - return d[mykey] - return '' # for backward compat, don't raise KeyError - - def get(self, k, x=None): - for d in self.lookuplist: - if k in d: - return d[k] - return x - - def pop(self, key, *args): - if len(args) > 1: - raise TypeError( - "pop expected at most 2 arguments, got " + \ - repr(1 + len(args))) - v = self - for d in reversed(self.lookuplist): - v = d.pop(key, v) - if v is self: - if args: - return args[0] - raise KeyError(key) - return v - - def has_key(self,mykey): - warnings.warn("portage.config.has_key() is deprecated, " - "use the in operator instead", - DeprecationWarning, stacklevel=2) - return mykey in self - - def __contains__(self, mykey): - """Called to implement membership test operators (in and not in).""" - for d in self.lookuplist: - if mykey in d: - return True - return False - - def setdefault(self, k, x=None): - v = self.get(k) - if v is not None: - return v - else: - self[k] = x - return x - - def keys(self): - return list(self) - - def __iter__(self): - keys = set() - for d in self.lookuplist: - keys.update(d) - return iter(keys) - - def iterkeys(self): - return iter(self) - - def iteritems(self): - for k in self: - yield (k, self[k]) - - def items(self): - return list(self.iteritems()) - - def __setitem__(self,mykey,myvalue): - "set a value; will be thrown away at reset() time" - if not isinstance(myvalue, basestring): - raise ValueError("Invalid type being used as a value: '%s': '%s'" % (str(mykey),str(myvalue))) - - # Avoid potential UnicodeDecodeError exceptions later. - mykey = _unicode_decode(mykey) - myvalue = _unicode_decode(myvalue) - - self.modifying() - self.modifiedkeys.append(mykey) - self.configdict["env"][mykey]=myvalue - - def environ(self): - "return our locally-maintained environment" - mydict={} - environ_filter = self._environ_filter - - eapi = self.get('EAPI') - phase = self.get('EBUILD_PHASE') - filter_calling_env = False - if phase not in ('clean', 'cleanrm', 'depend'): - temp_dir = self.get('T') - if temp_dir is not None and \ - os.path.exists(os.path.join(temp_dir, 'environment')): - filter_calling_env = True - - environ_whitelist = self._environ_whitelist - env_d = self.configdict["env.d"] - for x in self: - if x in environ_filter: - continue - myvalue = self[x] - if not isinstance(myvalue, basestring): - writemsg(_("!!! Non-string value in config: %s=%s\n") % \ - (x, myvalue), noiselevel=-1) - continue - if filter_calling_env and \ - x not in environ_whitelist and \ - not self._environ_whitelist_re.match(x): - # Do not allow anything to leak into the ebuild - # environment unless it is explicitly whitelisted. - # This ensures that variables unset by the ebuild - # remain unset. - continue - mydict[x] = myvalue - if "HOME" not in mydict and "BUILD_PREFIX" in mydict: - writemsg("*** HOME not set. Setting to "+mydict["BUILD_PREFIX"]+"\n") - mydict["HOME"]=mydict["BUILD_PREFIX"][:] - - if filter_calling_env: - if phase: - whitelist = [] - if "rpm" == phase: - whitelist.append("RPMDIR") - for k in whitelist: - v = self.get(k) - if v is not None: - mydict[k] = v - - # Filtered by IUSE and implicit IUSE. - mydict["USE"] = self.get("PORTAGE_USE", "") - - # Don't export AA to the ebuild environment in EAPIs that forbid it - if eapi not in ("0", "1", "2", "3", "3_pre2"): - mydict.pop("AA", None) - - # Prefix variables are supported starting with EAPI 3. - if phase == 'depend' or eapi in (None, "0", "1", "2"): - mydict.pop("ED", None) - mydict.pop("EPREFIX", None) - mydict.pop("EROOT", None) - - if phase == 'depend': - mydict.pop('FILESDIR', None) - - return mydict - - def thirdpartymirrors(self): - if getattr(self, "_thirdpartymirrors", None) is None: - profileroots = [os.path.join(self["PORTDIR"], "profiles")] - for x in self["PORTDIR_OVERLAY"].split(): - profileroots.insert(0, os.path.join(x, "profiles")) - thirdparty_lists = [grabdict(os.path.join(x, "thirdpartymirrors")) for x in profileroots] - self._thirdpartymirrors = stack_dictlist(thirdparty_lists, incremental=True) - return self._thirdpartymirrors - - def archlist(self): - return flatten([[myarch, "~" + myarch] \ - for myarch in self["PORTAGE_ARCHLIST"].split()]) - - def selinux_enabled(self): - if getattr(self, "_selinux_enabled", None) is None: - self._selinux_enabled = 0 - if "selinux" in self["USE"].split(): - if selinux: - if selinux.is_selinux_enabled() == 1: - self._selinux_enabled = 1 - else: - self._selinux_enabled = 0 - else: - writemsg(_("!!! SELinux module not found. Please verify that it was installed.\n"), - noiselevel=-1) - self._selinux_enabled = 0 - - return self._selinux_enabled - - if sys.hexversion >= 0x3000000: - keys = __iter__ - items = iteritems - def _can_test_pty_eof(): """ The _test_pty_eof() function seems to hang on most |