046ec465f51fee6715f0e0a2a9c122716830dbf1
[portage.git] / pym / portage / package / ebuild / config.py
1 # Copyright 2010-2012 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
3
4 __all__ = [
5         'autouse', 'best_from_dict', 'check_config_instance', 'config',
6 ]
7
8 import copy
9 from itertools import chain
10 import grp
11 import logging
12 import platform
13 import pwd
14 import re
15 import sys
16 import warnings
17
18 from _emerge.Package import Package
19 import portage
20 portage.proxy.lazyimport.lazyimport(globals(),
21         'portage.data:portage_gid',
22 )
23 from portage import bsd_chflags, \
24         load_mod, os, selinux, _unicode_decode
25 from portage.const import CACHE_PATH, \
26         DEPCACHE_PATH, INCREMENTALS, MAKE_CONF_FILE, \
27         MODULES_FILE_PATH, \
28         PRIVATE_PATH, PROFILE_PATH, USER_CONFIG_PATH, \
29         USER_VIRTUALS_FILE
30 from portage.dbapi import dbapi
31 from portage.dbapi.porttree import portdbapi
32 from portage.dbapi.vartree import vartree
33 from portage.dep import Atom, isvalidatom, match_from_list, use_reduce, _repo_separator, _slot_separator
34 from portage.eapi import eapi_exports_AA, eapi_exports_merge_type, \
35         eapi_supports_prefix, eapi_exports_replace_vars
36 from portage.env.loaders import KeyValuePairFileLoader
37 from portage.exception import InvalidDependString, PortageException
38 from portage.localization import _
39 from portage.output import colorize
40 from portage.process import fakeroot_capable, sandbox_capable
41 from portage.repository.config import load_repository_config
42 from portage.util import ensure_dirs, getconfig, grabdict, \
43         grabdict_package, grabfile, grabfile_package, LazyItemsDict, \
44         normalize_path, shlex_split, stack_dictlist, stack_dicts, stack_lists, \
45         writemsg, writemsg_level
46 from portage.versions import catpkgsplit, catsplit, cpv_getkey, _pkg_str
47
48 from portage.package.ebuild._config import special_env_vars
49 from portage.package.ebuild._config.env_var_validation import validate_cmd_var
50 from portage.package.ebuild._config.features_set import features_set
51 from portage.package.ebuild._config.KeywordsManager import KeywordsManager
52 from portage.package.ebuild._config.LicenseManager import LicenseManager
53 from portage.package.ebuild._config.UseManager import UseManager
54 from portage.package.ebuild._config.LocationsManager import LocationsManager
55 from portage.package.ebuild._config.MaskManager import MaskManager
56 from portage.package.ebuild._config.VirtualsManager import VirtualsManager
57 from portage.package.ebuild._config.helper import ordered_by_atom_specificity, prune_incremental
58
59 if sys.hexversion >= 0x3000000:
60         basestring = str
61
62 def autouse(myvartree, use_cache=1, mysettings=None):
63         warnings.warn("portage.autouse() is deprecated",
64                 DeprecationWarning, stacklevel=2)
65         return ""
66
67 def check_config_instance(test):
68         if not isinstance(test, config):
69                 raise TypeError("Invalid type for config object: %s (should be %s)" % (test.__class__, config))
70
71 def best_from_dict(key, top_dict, key_order, EmptyOnError=1, FullCopy=1, AllowEmpty=1):
72         for x in key_order:
73                 if x in top_dict and key in top_dict[x]:
74                         if FullCopy:
75                                 return copy.deepcopy(top_dict[x][key])
76                         else:
77                                 return top_dict[x][key]
78         if EmptyOnError:
79                 return ""
80         else:
81                 raise KeyError("Key not found in list; '%s'" % key)
82
83 def _lazy_iuse_regex(iuse_implicit):
84         """
85         The PORTAGE_IUSE value is lazily evaluated since re.escape() is slow
86         and the value is only used when an ebuild phase needs to be executed
87         (it's used only to generate QA notices).
88         """
89         # Escape anything except ".*" which is supposed to pass through from
90         # _get_implicit_iuse().
91         regex = sorted(re.escape(x) for x in iuse_implicit)
92         regex = "^(%s)$" % "|".join(regex)
93         regex = regex.replace("\\.\\*", ".*")
94         return regex
95
96 class _iuse_implicit_match_cache(object):
97
98         def __init__(self, settings):
99                 self._iuse_implicit_re = re.compile("^(%s)$" % \
100                         "|".join(settings._get_implicit_iuse()))
101                 self._cache = {}
102
103         def __call__(self, flag):
104                 """
105                 Returns True if the flag is matched, False otherwise.
106                 """
107                 try:
108                         return self._cache[flag]
109                 except KeyError:
110                         m = self._iuse_implicit_re.match(flag) is not None
111                         self._cache[flag] = m
112                         return m
113
114 class config(object):
115         """
116         This class encompasses the main portage configuration.  Data is pulled from
117         ROOT/PORTDIR/profiles/, from ROOT/etc/make.profile incrementally through all
118         parent profiles as well as from ROOT/PORTAGE_CONFIGROOT/* for user specified
119         overrides.
120
121         Generally if you need data like USE flags, FEATURES, environment variables,
122         virtuals ...etc you look in here.
123         """
124
125         _constant_keys = frozenset(['PORTAGE_BIN_PATH', 'PORTAGE_GID',
126                 'PORTAGE_PYM_PATH'])
127
128         _setcpv_aux_keys = ('DEFINED_PHASES', 'DEPEND', 'EAPI',
129                 'INHERITED', 'IUSE', 'REQUIRED_USE', 'KEYWORDS', 'LICENSE', 'PDEPEND',
130                 'PROPERTIES', 'PROVIDE', 'RDEPEND', 'SLOT',
131                 'repository', 'RESTRICT', 'LICENSE',)
132
133         _module_aliases = {
134                 "cache.metadata_overlay.database" : "portage.cache.flat_hash.database",
135                 "portage.cache.metadata_overlay.database" : "portage.cache.flat_hash.database",
136         }
137
138         _case_insensitive_vars = special_env_vars.case_insensitive_vars
139         _default_globals = special_env_vars.default_globals
140         _env_blacklist = special_env_vars.env_blacklist
141         _environ_filter = special_env_vars.environ_filter
142         _environ_whitelist = special_env_vars.environ_whitelist
143         _environ_whitelist_re = special_env_vars.environ_whitelist_re
144         _global_only_vars = special_env_vars.global_only_vars
145
146         def __init__(self, clone=None, mycpv=None, config_profile_path=None,
147                 config_incrementals=None, config_root=None, target_root=None,
148                 eprefix=None, local_config=True, env=None,
149                 _unmatched_removal=False):
150                 """
151                 @param clone: If provided, init will use deepcopy to copy by value the instance.
152                 @type clone: Instance of config class.
153                 @param mycpv: CPV to load up (see setcpv), this is the same as calling init with mycpv=None
154                 and then calling instance.setcpv(mycpv).
155                 @type mycpv: String
156                 @param config_profile_path: Configurable path to the profile (usually PROFILE_PATH from portage.const)
157                 @type config_profile_path: String
158                 @param config_incrementals: List of incremental variables
159                         (defaults to portage.const.INCREMENTALS)
160                 @type config_incrementals: List
161                 @param config_root: path to read local config from (defaults to "/", see PORTAGE_CONFIGROOT)
162                 @type config_root: String
163                 @param target_root: __init__ override of $ROOT env variable.
164                 @type target_root: String
165                 @param eprefix: set the EPREFIX variable (default is portage.const.EPREFIX)
166                 @type eprefix: String
167                 @param local_config: Enables loading of local config (/etc/portage); used most by repoman to
168                 ignore local config (keywording and unmasking)
169                 @type local_config: Boolean
170                 @param env: The calling environment which is used to override settings.
171                         Defaults to os.environ if unspecified.
172                 @type env: dict
173                 @param _unmatched_removal: Enabled by repoman when the
174                         --unmatched-removal option is given.
175                 @type _unmatched_removal: Boolean
176                 """
177
178                 # When initializing the global portage.settings instance, avoid
179                 # raising exceptions whenever possible since exceptions thrown
180                 # from 'import portage' or 'import portage.exceptions' statements
181                 # can practically render the api unusable for api consumers.
182                 tolerant = hasattr(portage, '_initializing_globals')
183                 self._tolerant = tolerant
184                 self._unmatched_removal = _unmatched_removal
185
186                 self.locked   = 0
187                 self.mycpv    = None
188                 self._setcpv_args_hash = None
189                 self.puse     = ""
190                 self._penv    = []
191                 self.modifiedkeys = []
192                 self.uvlist = []
193                 self._accept_chost_re = None
194                 self._accept_properties = None
195                 self._features_overrides = []
196                 self._make_defaults = None
197
198                 # _unknown_features records unknown features that
199                 # have triggered warning messages, and ensures that
200                 # the same warning isn't shown twice.
201                 self._unknown_features = set()
202
203                 self.local_config = local_config
204
205                 if clone:
206                         # For immutable attributes, use shallow copy for
207                         # speed and memory conservation.
208                         self._tolerant = clone._tolerant
209                         self._unmatched_removal = clone._unmatched_removal
210                         self.categories = clone.categories
211                         self.depcachedir = clone.depcachedir
212                         self.incrementals = clone.incrementals
213                         self.module_priority = clone.module_priority
214                         self.profile_path = clone.profile_path
215                         self.profiles = clone.profiles
216                         self.packages = clone.packages
217                         self.repositories = clone.repositories
218                         self._iuse_implicit_match = clone._iuse_implicit_match
219                         self._non_user_variables = clone._non_user_variables
220                         self._env_d_blacklist = clone._env_d_blacklist
221                         self._repo_make_defaults = clone._repo_make_defaults
222                         self.usemask = clone.usemask
223                         self.useforce = clone.useforce
224                         self.puse = clone.puse
225                         self.user_profile_dir = clone.user_profile_dir
226                         self.local_config = clone.local_config
227                         self.make_defaults_use = clone.make_defaults_use
228                         self.mycpv = clone.mycpv
229                         self._setcpv_args_hash = clone._setcpv_args_hash
230
231                         # immutable attributes (internal policy ensures lack of mutation)
232                         self._locations_manager = clone._locations_manager
233                         self._use_manager = clone._use_manager
234                         # force instantiation of lazy immutable objects when cloning, so
235                         # that they're not instantiated more than once
236                         self._keywords_manager_obj = clone._keywords_manager
237                         self._mask_manager_obj = clone._mask_manager
238
239                         # shared mutable attributes
240                         self._unknown_features = clone._unknown_features
241
242                         self.modules         = copy.deepcopy(clone.modules)
243                         self._penv = copy.deepcopy(clone._penv)
244
245                         self.configdict = copy.deepcopy(clone.configdict)
246                         self.configlist = [
247                                 self.configdict['env.d'],
248                                 self.configdict['repo'],
249                                 self.configdict['pkginternal'],
250                                 self.configdict['globals'],
251                                 self.configdict['defaults'],
252                                 self.configdict['conf'],
253                                 self.configdict['pkg'],
254                                 self.configdict['env'],
255                         ]
256                         self.lookuplist = self.configlist[:]
257                         self.lookuplist.reverse()
258                         self._use_expand_dict = copy.deepcopy(clone._use_expand_dict)
259                         self.backupenv  = self.configdict["backupenv"]
260                         self.prevmaskdict = copy.deepcopy(clone.prevmaskdict)
261                         self.pprovideddict = copy.deepcopy(clone.pprovideddict)
262                         self.features = features_set(self)
263                         self.features._features = copy.deepcopy(clone.features._features)
264                         self._features_overrides = copy.deepcopy(clone._features_overrides)
265
266                         #Strictly speaking _license_manager is not immutable. Users need to ensure that
267                         #extract_global_changes() is called right after __init__ (if at all).
268                         #It also has the mutable member _undef_lic_groups. It is used to track
269                         #undefined license groups, to not display an error message for the same
270                         #group again and again. Because of this, it's useful to share it between
271                         #all LicenseManager instances.
272                         self._license_manager = clone._license_manager
273
274                         self._virtuals_manager = copy.deepcopy(clone._virtuals_manager)
275
276                         self._accept_properties = copy.deepcopy(clone._accept_properties)
277                         self._ppropertiesdict = copy.deepcopy(clone._ppropertiesdict)
278                         self._penvdict = copy.deepcopy(clone._penvdict)
279                         self._expand_map = copy.deepcopy(clone._expand_map)
280
281                 else:
282                         # lazily instantiated objects
283                         self._keywords_manager_obj = None
284                         self._mask_manager_obj = None
285
286                         locations_manager = LocationsManager(config_root=config_root,
287                                 config_profile_path=config_profile_path, eprefix=eprefix,
288                                 local_config=local_config, target_root=target_root)
289                         self._locations_manager = locations_manager
290
291                         eprefix = locations_manager.eprefix
292                         config_root = locations_manager.config_root
293                         abs_user_config = locations_manager.abs_user_config
294
295                         make_conf = getconfig(
296                                 os.path.join(config_root, MAKE_CONF_FILE),
297                                 tolerant=tolerant, allow_sourcing=True) or {}
298
299                         make_conf.update(getconfig(
300                                 os.path.join(abs_user_config, 'make.conf'),
301                                 tolerant=tolerant, allow_sourcing=True,
302                                 expand=make_conf) or {})
303
304                         # Allow ROOT setting to come from make.conf if it's not overridden
305                         # by the constructor argument (from the calling environment).
306                         locations_manager.set_root_override(make_conf.get("ROOT"))
307                         target_root = locations_manager.target_root
308                         eroot = locations_manager.eroot
309                         self.global_config_path = locations_manager.global_config_path
310
311                         # The expand_map is used for variable substitution
312                         # in getconfig() calls, and the getconfig() calls
313                         # update expand_map with the value of each variable
314                         # assignment that occurs. Variable substitution occurs
315                         # in the following order, which corresponds to the
316                         # order of appearance in self.lookuplist:
317                         #
318                         #   * env.d
319                         #   * make.globals
320                         #   * make.defaults
321                         #   * make.conf
322                         #
323                         # Notably absent is "env", since we want to avoid any
324                         # interaction with the calling environment that might
325                         # lead to unexpected results.
326
327                         env_d = getconfig(os.path.join(eroot, "etc", "profile.env"),
328                                 expand=False) or {}
329                         expand_map = env_d.copy()
330                         self._expand_map = expand_map
331
332                         # Allow make.globals to set default paths relative to ${EPREFIX}.
333                         expand_map["EPREFIX"] = eprefix
334
335                         make_globals = getconfig(os.path.join(
336                                 self.global_config_path, 'make.globals'), expand=expand_map)
337                         if make_globals is None:
338                                 make_globals = {}
339
340                         for k, v in self._default_globals.items():
341                                 make_globals.setdefault(k, v)
342
343                         if config_incrementals is None:
344                                 self.incrementals = INCREMENTALS
345                         else:
346                                 self.incrementals = config_incrementals
347                         if not isinstance(self.incrementals, frozenset):
348                                 self.incrementals = frozenset(self.incrementals)
349
350                         self.module_priority    = ("user", "default")
351                         self.modules            = {}
352                         modules_file = os.path.join(config_root, MODULES_FILE_PATH)
353                         modules_loader = KeyValuePairFileLoader(modules_file, None, None)
354                         modules_dict, modules_errors = modules_loader.load()
355                         self.modules["user"] = modules_dict
356                         if self.modules["user"] is None:
357                                 self.modules["user"] = {}
358                         user_auxdbmodule = \
359                                 self.modules["user"].get("portdbapi.auxdbmodule")
360                         if user_auxdbmodule is not None and \
361                                 user_auxdbmodule in self._module_aliases:
362                                 warnings.warn("'%s' is deprecated: %s" %
363                                 (user_auxdbmodule, modules_file))
364
365                         self.modules["default"] = {
366                                 "portdbapi.auxdbmodule":  "portage.cache.flat_hash.database",
367                         }
368
369                         self.configlist=[]
370
371                         # back up our incremental variables:
372                         self.configdict={}
373                         self._use_expand_dict = {}
374                         # configlist will contain: [ env.d, globals, defaults, conf, pkg, backupenv, env ]
375                         self.configlist.append({})
376                         self.configdict["env.d"] = self.configlist[-1]
377
378                         self.configlist.append({})
379                         self.configdict["repo"] = self.configlist[-1]
380
381                         self.configlist.append({})
382                         self.configdict["pkginternal"] = self.configlist[-1]
383
384                         # env_d will be None if profile.env doesn't exist.
385                         if env_d:
386                                 self.configdict["env.d"].update(env_d)
387
388                         # backupenv is used for calculating incremental variables.
389                         if env is None:
390                                 env = os.environ
391
392                         # Avoid potential UnicodeDecodeError exceptions later.
393                         env_unicode = dict((_unicode_decode(k), _unicode_decode(v))
394                                 for k, v in env.items())
395
396                         self.backupenv = env_unicode
397
398                         if env_d:
399                                 # Remove duplicate values so they don't override updated
400                                 # profile.env values later (profile.env is reloaded in each
401                                 # call to self.regenerate).
402                                 for k, v in env_d.items():
403                                         try:
404                                                 if self.backupenv[k] == v:
405                                                         del self.backupenv[k]
406                                         except KeyError:
407                                                 pass
408                                 del k, v
409
410                         self.configdict["env"] = LazyItemsDict(self.backupenv)
411
412                         self.configlist.append(make_globals)
413                         self.configdict["globals"]=self.configlist[-1]
414
415                         self.make_defaults_use = []
416
417                         #Loading Repositories
418                         self["PORTAGE_CONFIGROOT"] = config_root
419                         self["ROOT"] = target_root
420                         self["EPREFIX"] = eprefix
421                         self["EROOT"] = eroot
422                         known_repos = []
423                         portdir = ""
424                         portdir_overlay = ""
425                         for confs in [make_globals, make_conf, self.configdict["env"]]:
426                                 v = confs.get("PORTDIR")
427                                 if v is not None:
428                                         portdir = v
429                                         known_repos.append(v)
430                                 v = confs.get("PORTDIR_OVERLAY")
431                                 if v is not None:
432                                         portdir_overlay = v
433                                         known_repos.extend(shlex_split(v))
434                         known_repos = frozenset(known_repos)
435                         self["PORTDIR"] = portdir
436                         self["PORTDIR_OVERLAY"] = portdir_overlay
437                         self.lookuplist = [self.configdict["env"]]
438                         self.repositories = load_repository_config(self)
439
440                         locations_manager.load_profiles(self.repositories, known_repos)
441
442                         profiles_complex = locations_manager.profiles_complex
443                         self.profiles = locations_manager.profiles
444                         self.profile_path = locations_manager.profile_path
445                         self.user_profile_dir = locations_manager.user_profile_dir
446
447                         packages_list = [grabfile_package(os.path.join(x, "packages"),
448                                 verify_eapi=True) for x in self.profiles]
449                         self.packages = tuple(stack_lists(packages_list, incremental=1))
450
451                         # revmaskdict
452                         self.prevmaskdict={}
453                         for x in self.packages:
454                                 # Negative atoms are filtered by the above stack_lists() call.
455                                 if not isinstance(x, Atom):
456                                         x = Atom(x.lstrip('*'))
457                                 self.prevmaskdict.setdefault(x.cp, []).append(x)
458
459
460                         mygcfg = {}
461                         if self.profiles:
462                                 mygcfg_dlists = [getconfig(os.path.join(x, "make.defaults"),
463                                         expand=expand_map) for x in self.profiles]
464                                 self._make_defaults = mygcfg_dlists
465                                 mygcfg = stack_dicts(mygcfg_dlists,
466                                         incrementals=self.incrementals)
467                                 if mygcfg is None:
468                                         mygcfg = {}
469                         self.configlist.append(mygcfg)
470                         self.configdict["defaults"]=self.configlist[-1]
471
472                         mygcfg = getconfig(
473                                 os.path.join(config_root, MAKE_CONF_FILE),
474                                 tolerant=tolerant, allow_sourcing=True,
475                                 expand=expand_map) or {}
476
477                         mygcfg.update(getconfig(
478                                 os.path.join(abs_user_config, 'make.conf'),
479                                 tolerant=tolerant, allow_sourcing=True,
480                                 expand=expand_map) or {})
481
482                         # Don't allow the user to override certain variables in make.conf
483                         profile_only_variables = self.configdict["defaults"].get(
484                                 "PROFILE_ONLY_VARIABLES", "").split()
485                         profile_only_variables = stack_lists([profile_only_variables])
486                         non_user_variables = set()
487                         non_user_variables.update(profile_only_variables)
488                         non_user_variables.update(self._env_blacklist)
489                         non_user_variables.update(self._global_only_vars)
490                         non_user_variables = frozenset(non_user_variables)
491                         self._non_user_variables = non_user_variables
492
493                         self._env_d_blacklist = frozenset(chain(
494                                 profile_only_variables,
495                                 self._env_blacklist,
496                         ))
497                         env_d = self.configdict["env.d"]
498                         for k in self._env_d_blacklist:
499                                 env_d.pop(k, None)
500
501                         for k in profile_only_variables:
502                                 mygcfg.pop(k, None)
503
504                         self.configlist.append(mygcfg)
505                         self.configdict["conf"]=self.configlist[-1]
506
507                         self.configlist.append(LazyItemsDict())
508                         self.configdict["pkg"]=self.configlist[-1]
509
510                         self.configdict["backupenv"] = self.backupenv
511
512                         # Don't allow the user to override certain variables in the env
513                         for k in profile_only_variables:
514                                 self.backupenv.pop(k, None)
515
516                         self.configlist.append(self.configdict["env"])
517
518                         # make lookuplist for loading package.*
519                         self.lookuplist=self.configlist[:]
520                         self.lookuplist.reverse()
521
522                         # Blacklist vars that could interfere with portage internals.
523                         for blacklisted in self._env_blacklist:
524                                 for cfg in self.lookuplist:
525                                         cfg.pop(blacklisted, None)
526                                 self.backupenv.pop(blacklisted, None)
527                         del blacklisted, cfg
528
529                         self["PORTAGE_CONFIGROOT"] = config_root
530                         self.backup_changes("PORTAGE_CONFIGROOT")
531                         self["ROOT"] = target_root
532                         self.backup_changes("ROOT")
533
534                         # The PORTAGE_OVERRIDE_EPREFIX variable propagates the EPREFIX
535                         # of this config instance to any portage commands or API
536                         # consumers running in subprocesses.
537                         self["EPREFIX"] = eprefix
538                         self.backup_changes("EPREFIX")
539                         self["PORTAGE_OVERRIDE_EPREFIX"] = eprefix
540                         self.backup_changes("PORTAGE_OVERRIDE_EPREFIX")
541                         self["EROOT"] = eroot
542                         self.backup_changes("EROOT")
543
544                         self._ppropertiesdict = portage.dep.ExtendedAtomDict(dict)
545                         self._penvdict = portage.dep.ExtendedAtomDict(dict)
546
547                         #filling PORTDIR and PORTDIR_OVERLAY variable for compatibility
548                         main_repo = self.repositories.mainRepo()
549                         if main_repo is not None:
550                                 self["PORTDIR"] = main_repo.user_location
551                                 self.backup_changes("PORTDIR")
552
553                         # repoman controls PORTDIR_OVERLAY via the environment, so no
554                         # special cases are needed here.
555                         portdir_overlay = list(self.repositories.repoUserLocationList())
556                         if portdir_overlay and portdir_overlay[0] == self["PORTDIR"]:
557                                 portdir_overlay = portdir_overlay[1:]
558
559                         new_ov = []
560                         if portdir_overlay:
561                                 shell_quote_re = re.compile(r"[\s\\\"'$`]")
562                                 for ov in portdir_overlay:
563                                         ov = normalize_path(ov)
564                                         if os.path.isdir(ov):
565                                                 if shell_quote_re.search(ov) is not None:
566                                                         ov = portage._shell_quote(ov)
567                                                 new_ov.append(ov)
568                                         else:
569                                                 writemsg(_("!!! Invalid PORTDIR_OVERLAY"
570                                                         " (not a dir): '%s'\n") % ov, noiselevel=-1)
571
572                         self["PORTDIR_OVERLAY"] = " ".join(new_ov)
573                         self.backup_changes("PORTDIR_OVERLAY")
574
575                         locations_manager.set_port_dirs(self["PORTDIR"], self["PORTDIR_OVERLAY"])
576
577                         self._repo_make_defaults = {}
578                         for repo in self.repositories.repos_with_profiles():
579                                 d = getconfig(os.path.join(repo.location, "profiles", "make.defaults"),
580                                         expand=self.configdict["globals"].copy()) or {}
581                                 if d:
582                                         for k in chain(self._env_blacklist,
583                                                 profile_only_variables, self._global_only_vars):
584                                                 d.pop(k, None)
585                                 self._repo_make_defaults[repo.name] = d
586
587                         #Read all USE related files from profiles and optionally from user config.
588                         self._use_manager = UseManager(self.repositories, profiles_complex, abs_user_config, user_config=local_config)
589                         #Initialize all USE related variables we track ourselves.
590                         self.usemask = self._use_manager.getUseMask()
591                         self.useforce = self._use_manager.getUseForce()
592                         self.configdict["conf"]["USE"] = \
593                                 self._use_manager.extract_global_USE_changes( \
594                                         self.configdict["conf"].get("USE", ""))
595
596                         #Read license_groups and optionally license_groups and package.license from user config
597                         self._license_manager = LicenseManager(locations_manager.profile_locations, \
598                                 abs_user_config, user_config=local_config)
599                         #Extract '*/*' entries from package.license
600                         self.configdict["conf"]["ACCEPT_LICENSE"] = \
601                                 self._license_manager.extract_global_changes( \
602                                         self.configdict["conf"].get("ACCEPT_LICENSE", ""))
603
604                         self._virtuals_manager = VirtualsManager(self.profiles)
605
606                         if local_config:
607                                 #package.properties
608                                 propdict = grabdict_package(os.path.join(
609                                         abs_user_config, "package.properties"), recursive=1, allow_wildcard=True, \
610                                         allow_repo=True, verify_eapi=False)
611                                 v = propdict.pop("*/*", None)
612                                 if v is not None:
613                                         if "ACCEPT_PROPERTIES" in self.configdict["conf"]:
614                                                 self.configdict["conf"]["ACCEPT_PROPERTIES"] += " " + " ".join(v)
615                                         else:
616                                                 self.configdict["conf"]["ACCEPT_PROPERTIES"] = " ".join(v)
617                                 for k, v in propdict.items():
618                                         self._ppropertiesdict.setdefault(k.cp, {})[k] = v
619
620                                 #package.env
621                                 penvdict = grabdict_package(os.path.join(
622                                         abs_user_config, "package.env"), recursive=1, allow_wildcard=True, \
623                                         allow_repo=True, verify_eapi=False)
624                                 v = penvdict.pop("*/*", None)
625                                 if v is not None:
626                                         global_wildcard_conf = {}
627                                         self._grab_pkg_env(v, global_wildcard_conf)
628                                         incrementals = self.incrementals
629                                         conf_configdict = self.configdict["conf"]
630                                         for k, v in global_wildcard_conf.items():
631                                                 if k in incrementals:
632                                                         if k in conf_configdict:
633                                                                 conf_configdict[k] = \
634                                                                         conf_configdict[k] + " " + v
635                                                         else:
636                                                                 conf_configdict[k] = v
637                                                 else:
638                                                         conf_configdict[k] = v
639                                                 expand_map[k] = v
640
641                                 for k, v in penvdict.items():
642                                         self._penvdict.setdefault(k.cp, {})[k] = v
643
644                         #getting categories from an external file now
645                         self.categories = [grabfile(os.path.join(x, "categories")) \
646                                 for x in locations_manager.profile_and_user_locations]
647                         category_re = dbapi._category_re
648                         # categories used to be a tuple, but now we use a frozenset
649                         # for hashed category validation in pordbapi.cp_list()
650                         self.categories = frozenset(
651                                 x for x in stack_lists(self.categories, incremental=1)
652                                 if category_re.match(x) is not None)
653
654                         archlist = [grabfile(os.path.join(x, "arch.list")) \
655                                 for x in locations_manager.profile_and_user_locations]
656                         archlist = stack_lists(archlist, incremental=1)
657                         self.configdict["conf"]["PORTAGE_ARCHLIST"] = " ".join(archlist)
658
659                         pkgprovidedlines = [grabfile(
660                                 os.path.join(x.location, "package.provided"),
661                                 recursive=x.portage1_directories)
662                                 for x in profiles_complex]
663                         pkgprovidedlines = stack_lists(pkgprovidedlines, incremental=1)
664                         has_invalid_data = False
665                         for x in range(len(pkgprovidedlines)-1, -1, -1):
666                                 myline = pkgprovidedlines[x]
667                                 if not isvalidatom("=" + myline):
668                                         writemsg(_("Invalid package name in package.provided: %s\n") % \
669                                                 myline, noiselevel=-1)
670                                         has_invalid_data = True
671                                         del pkgprovidedlines[x]
672                                         continue
673                                 cpvr = catpkgsplit(pkgprovidedlines[x])
674                                 if not cpvr or cpvr[0] == "null":
675                                         writemsg(_("Invalid package name in package.provided: ")+pkgprovidedlines[x]+"\n",
676                                                 noiselevel=-1)
677                                         has_invalid_data = True
678                                         del pkgprovidedlines[x]
679                                         continue
680                                 if cpvr[0] == "virtual":
681                                         writemsg(_("Virtual package in package.provided: %s\n") % \
682                                                 myline, noiselevel=-1)
683                                         has_invalid_data = True
684                                         del pkgprovidedlines[x]
685                                         continue
686                         if has_invalid_data:
687                                 writemsg(_("See portage(5) for correct package.provided usage.\n"),
688                                         noiselevel=-1)
689                         self.pprovideddict = {}
690                         for x in pkgprovidedlines:
691                                 x_split = catpkgsplit(x)
692                                 if x_split is None:
693                                         continue
694                                 mycatpkg = cpv_getkey(x)
695                                 if mycatpkg in self.pprovideddict:
696                                         self.pprovideddict[mycatpkg].append(x)
697                                 else:
698                                         self.pprovideddict[mycatpkg]=[x]
699
700                         # reasonable defaults; this is important as without USE_ORDER,
701                         # USE will always be "" (nothing set)!
702                         if "USE_ORDER" not in self:
703                                 self.backupenv["USE_ORDER"] = "env:pkg:conf:defaults:pkginternal:repo:env.d"
704
705                         self.depcachedir = DEPCACHE_PATH
706                         if eprefix:
707                                 # See comments about make.globals and EPREFIX
708                                 # above. DEPCACHE_PATH is similar.
709                                 if target_root == "/":
710                                         # case (1) above
711                                         self.depcachedir = os.path.join(eprefix,
712                                                 DEPCACHE_PATH.lstrip(os.sep))
713                                 else:
714                                         # case (2) above
715                                         # For now, just assume DEPCACHE_PATH is relative
716                                         # to EPREFIX.
717                                         # TODO: Pass in more info to the constructor,
718                                         # so we know the host system configuration.
719                                         self.depcachedir = os.path.join(eprefix,
720                                                 DEPCACHE_PATH.lstrip(os.sep))
721
722                         if self.get("PORTAGE_DEPCACHEDIR", None):
723                                 self.depcachedir = self["PORTAGE_DEPCACHEDIR"]
724                         self["PORTAGE_DEPCACHEDIR"] = self.depcachedir
725                         self.backup_changes("PORTAGE_DEPCACHEDIR")
726
727                         if "CBUILD" not in self and "CHOST" in self:
728                                 self["CBUILD"] = self["CHOST"]
729                                 self.backup_changes("CBUILD")
730
731                         if "USERLAND" not in self:
732                                 # Set default USERLAND so that our test cases can assume that
733                                 # it's always set. This allows isolated-functions.sh to avoid
734                                 # calling uname -s when sourced.
735                                 system = platform.system()
736                                 if system is not None and \
737                                         (system.endswith("BSD") or system == "DragonFly"):
738                                         self["USERLAND"] = "BSD"
739                                 else:
740                                         self["USERLAND"] = "GNU"
741                                 self.backup_changes("USERLAND")
742
743                         default_inst_ids = {
744                                 "PORTAGE_INST_GID": "0",
745                                 "PORTAGE_INST_UID": "0",
746                         }
747
748                         if eprefix:
749                                 # For prefix environments, default to the UID and GID of
750                                 # the top-level EROOT directory.
751                                 try:
752                                         eroot_st = os.stat(eroot)
753                                 except OSError:
754                                         pass
755                                 else:
756                                         default_inst_ids["PORTAGE_INST_GID"] = str(eroot_st.st_gid)
757                                         default_inst_ids["PORTAGE_INST_UID"] = str(eroot_st.st_uid)
758
759                                         if "PORTAGE_USERNAME" not in self:
760                                                 try:
761                                                         pwd_struct = pwd.getpwuid(eroot_st.st_uid)
762                                                 except KeyError:
763                                                         pass
764                                                 else:
765                                                         self["PORTAGE_USERNAME"] = pwd_struct.pw_name
766                                                         self.backup_changes("PORTAGE_USERNAME")
767
768                                         if "PORTAGE_GRPNAME" not in self:
769                                                 try:
770                                                         grp_struct = grp.getgrgid(eroot_st.st_gid)
771                                                 except KeyError:
772                                                         pass
773                                                 else:
774                                                         self["PORTAGE_GRPNAME"] = grp_struct.gr_name
775                                                         self.backup_changes("PORTAGE_GRPNAME")
776
777                         for var, default_val in default_inst_ids.items():
778                                 try:
779                                         self[var] = str(int(self.get(var, default_val)))
780                                 except ValueError:
781                                         writemsg(_("!!! %s='%s' is not a valid integer.  "
782                                                 "Falling back to %s.\n") % (var, self[var], default_val),
783                                                 noiselevel=-1)
784                                         self[var] = default_val
785                                 self.backup_changes(var)
786
787                         # initialize self.features
788                         self.regenerate()
789
790                         if bsd_chflags:
791                                 self.features.add('chflags')
792
793                         self._iuse_implicit_match = _iuse_implicit_match_cache(self)
794
795                         self._validate_commands()
796
797                         for k in self._case_insensitive_vars:
798                                 if k in self:
799                                         self[k] = self[k].lower()
800                                         self.backup_changes(k)
801
802                         if main_repo is not None and not main_repo.sync:
803                                 main_repo_sync = self.get("SYNC")
804                                 if main_repo_sync:
805                                         main_repo.sync = main_repo_sync
806
807                         # The first constructed config object initializes these modules,
808                         # and subsequent calls to the _init() functions have no effect.
809                         portage.output._init(config_root=self['PORTAGE_CONFIGROOT'])
810                         portage.data._init(self)
811
812                 if mycpv:
813                         self.setcpv(mycpv)
814
815         @property
816         def mygcfg(self):
817                 warnings.warn("portage.config.mygcfg is deprecated", stacklevel=3)
818                 return {}
819
820         def _validate_commands(self):
821                 for k in special_env_vars.validate_commands:
822                         v = self.get(k)
823                         if v is not None:
824                                 valid, v_split = validate_cmd_var(v)
825
826                                 if not valid:
827                                         if v_split:
828                                                 writemsg_level(_("%s setting is invalid: '%s'\n") % \
829                                                         (k, v), level=logging.ERROR, noiselevel=-1)
830
831                                         # before deleting the invalid setting, backup
832                                         # the default value if available
833                                         v = self.configdict['globals'].get(k)
834                                         if v is not None:
835                                                 default_valid, v_split = validate_cmd_var(v)
836                                                 if not default_valid:
837                                                         if v_split:
838                                                                 writemsg_level(
839                                                                         _("%s setting from make.globals" + \
840                                                                         " is invalid: '%s'\n") % \
841                                                                         (k, v), level=logging.ERROR, noiselevel=-1)
842                                                         # make.globals seems corrupt, so try for
843                                                         # a hardcoded default instead
844                                                         v = self._default_globals.get(k)
845
846                                         # delete all settings for this key,
847                                         # including the invalid one
848                                         del self[k]
849                                         self.backupenv.pop(k, None)
850                                         if v:
851                                                 # restore validated default
852                                                 self.configdict['globals'][k] = v
853
854         def _init_dirs(self):
855                 """
856                 Create a few directories that are critical to portage operation
857                 """
858                 if not os.access(self["EROOT"], os.W_OK):
859                         return
860
861                 #                                gid, mode, mask, preserve_perms
862                 dir_mode_map = {
863                         "tmp"             : (         -1, 0o1777,  0,  True),
864                         "var/tmp"         : (         -1, 0o1777,  0,  True),
865                         PRIVATE_PATH      : (portage_gid, 0o2750, 0o2, False),
866                         CACHE_PATH        : (portage_gid,  0o755, 0o2, False)
867                 }
868
869                 for mypath, (gid, mode, modemask, preserve_perms) \
870                         in dir_mode_map.items():
871                         mydir = os.path.join(self["EROOT"], mypath)
872                         if preserve_perms and os.path.isdir(mydir):
873                                 # Only adjust permissions on some directories if
874                                 # they don't exist yet. This gives freedom to the
875                                 # user to adjust permissions to suit their taste.
876                                 continue
877                         try:
878                                 ensure_dirs(mydir, gid=gid, mode=mode, mask=modemask)
879                         except PortageException as e:
880                                 writemsg(_("!!! Directory initialization failed: '%s'\n") % mydir,
881                                         noiselevel=-1)
882                                 writemsg("!!! %s\n" % str(e),
883                                         noiselevel=-1)
884
885         @property
886         def _keywords_manager(self):
887                 if self._keywords_manager_obj is None:
888                         self._keywords_manager_obj = KeywordsManager(
889                                 self._locations_manager.profiles_complex,
890                                 self._locations_manager.abs_user_config,
891                                 self.local_config,
892                                 global_accept_keywords=self.configdict["defaults"].get("ACCEPT_KEYWORDS", ""))
893                 return self._keywords_manager_obj
894
895         @property
896         def _mask_manager(self):
897                 if self._mask_manager_obj is None:
898                         self._mask_manager_obj = MaskManager(self.repositories,
899                                 self._locations_manager.profiles_complex,
900                                 self._locations_manager.abs_user_config,
901                                 user_config=self.local_config,
902                                 strict_umatched_removal=self._unmatched_removal)
903                 return self._mask_manager_obj
904
905         @property
906         def pkeywordsdict(self):
907                 result = self._keywords_manager.pkeywordsdict.copy()
908                 for k, v in result.items():
909                         result[k] = v.copy()
910                 return result
911
912         @property
913         def pmaskdict(self):
914                 return self._mask_manager._pmaskdict.copy()
915
916         @property
917         def punmaskdict(self):
918                 return self._mask_manager._punmaskdict.copy()
919
920         def expandLicenseTokens(self, tokens):
921                 """ Take a token from ACCEPT_LICENSE or package.license and expand it
922                 if it's a group token (indicated by @) or just return it if it's not a
923                 group.  If a group is negated then negate all group elements."""
924                 return self._license_manager.expandLicenseTokens(tokens)
925
926         def validate(self):
927                 """Validate miscellaneous settings and display warnings if necessary.
928                 (This code was previously in the global scope of portage.py)"""
929
930                 groups = self["ACCEPT_KEYWORDS"].split()
931                 archlist = self.archlist()
932                 if not archlist:
933                         writemsg(_("--- 'profiles/arch.list' is empty or "
934                                 "not available. Empty portage tree?\n"), noiselevel=1)
935                 else:
936                         for group in groups:
937                                 if group not in archlist and \
938                                         not (group.startswith("-") and group[1:] in archlist) and \
939                                         group not in ("*", "~*", "**"):
940                                         writemsg(_("!!! INVALID ACCEPT_KEYWORDS: %s\n") % str(group),
941                                                 noiselevel=-1)
942
943                 profile_broken = not self.profile_path or \
944                         not os.path.exists(os.path.join(self.profile_path, "parent")) and \
945                         os.path.exists(os.path.join(self["PORTDIR"], "profiles"))
946
947                 if profile_broken:
948                         abs_profile_path = None
949                         for x in (PROFILE_PATH, 'etc/portage/make.profile'):
950                                 x = os.path.join(self["PORTAGE_CONFIGROOT"], x)
951                                 try:
952                                         os.lstat(x)
953                                 except OSError:
954                                         pass
955                                 else:
956                                         abs_profile_path = x
957                                         break
958
959                         if abs_profile_path is None:
960                                 abs_profile_path = os.path.join(self["PORTAGE_CONFIGROOT"],
961                                         PROFILE_PATH)
962
963                         writemsg(_("\n\n!!! %s is not a symlink and will probably prevent most merges.\n") % abs_profile_path,
964                                 noiselevel=-1)
965                         writemsg(_("!!! It should point into a profile within %s/profiles/\n") % self["PORTDIR"])
966                         writemsg(_("!!! (You can safely ignore this message when syncing. It's harmless.)\n\n\n"))
967
968                 abs_user_virtuals = os.path.join(self["PORTAGE_CONFIGROOT"],
969                         USER_VIRTUALS_FILE)
970                 if os.path.exists(abs_user_virtuals):
971                         writemsg("\n!!! /etc/portage/virtuals is deprecated in favor of\n")
972                         writemsg("!!! /etc/portage/profile/virtuals. Please move it to\n")
973                         writemsg("!!! this new location.\n\n")
974
975                 if not sandbox_capable and \
976                         ("sandbox" in self.features or "usersandbox" in self.features):
977                         if self.profile_path is not None and \
978                                 os.path.realpath(self.profile_path) == \
979                                 os.path.realpath(os.path.join(
980                                 self["PORTAGE_CONFIGROOT"], PROFILE_PATH)):
981                                 # Don't show this warning when running repoman and the
982                                 # sandbox feature came from a profile that doesn't belong
983                                 # to the user.
984                                 writemsg(colorize("BAD", _("!!! Problem with sandbox"
985                                         " binary. Disabling...\n\n")), noiselevel=-1)
986
987                 if "fakeroot" in self.features and \
988                         not fakeroot_capable:
989                         writemsg(_("!!! FEATURES=fakeroot is enabled, but the "
990                                 "fakeroot binary is not installed.\n"), noiselevel=-1)
991
992                 if os.getuid() == 0 and not hasattr(os, "setgroups"):
993                         warning_shown = False
994
995                         if "userpriv" in self.features:
996                                 writemsg(_("!!! FEATURES=userpriv is enabled, but "
997                                         "os.setgroups is not available.\n"), noiselevel=-1)
998                                 warning_shown = True
999
1000                         if "userfetch" in self.features:
1001                                 writemsg(_("!!! FEATURES=userfetch is enabled, but "
1002                                         "os.setgroups is not available.\n"), noiselevel=-1)
1003                                 warning_shown = True
1004
1005                         if warning_shown and platform.python_implementation() == 'PyPy':
1006                                 writemsg(_("!!! See https://bugs.pypy.org/issue833 for details.\n"),
1007                                         noiselevel=-1)
1008
1009         def load_best_module(self,property_string):
1010                 best_mod = best_from_dict(property_string,self.modules,self.module_priority)
1011                 mod = None
1012                 try:
1013                         mod = load_mod(best_mod)
1014                 except ImportError:
1015                         if best_mod in self._module_aliases:
1016                                 mod = load_mod(self._module_aliases[best_mod])
1017                         elif not best_mod.startswith("cache."):
1018                                 raise
1019                         else:
1020                                 best_mod = "portage." + best_mod
1021                                 try:
1022                                         mod = load_mod(best_mod)
1023                                 except ImportError:
1024                                         raise
1025                 return mod
1026
1027         def lock(self):
1028                 self.locked = 1
1029
1030         def unlock(self):
1031                 self.locked = 0
1032
1033         def modifying(self):
1034                 if self.locked:
1035                         raise Exception(_("Configuration is locked."))
1036
1037         def backup_changes(self,key=None):
1038                 self.modifying()
1039                 if key and key in self.configdict["env"]:
1040                         self.backupenv[key] = copy.deepcopy(self.configdict["env"][key])
1041                 else:
1042                         raise KeyError(_("No such key defined in environment: %s") % key)
1043
1044         def reset(self, keeping_pkg=0, use_cache=None):
1045                 """
1046                 Restore environment from self.backupenv, call self.regenerate()
1047                 @param keeping_pkg: Should we keep the setcpv() data or delete it.
1048                 @type keeping_pkg: Boolean
1049                 @rype: None
1050                 """
1051
1052                 if use_cache is not None:
1053                         warnings.warn("The use_cache parameter for config.reset() is deprecated and without effect.",
1054                                 DeprecationWarning, stacklevel=2)
1055
1056                 self.modifying()
1057                 self.configdict["env"].clear()
1058                 self.configdict["env"].update(self.backupenv)
1059
1060                 self.modifiedkeys = []
1061                 if not keeping_pkg:
1062                         self.mycpv = None
1063                         self._setcpv_args_hash = None
1064                         self.puse = ""
1065                         del self._penv[:]
1066                         self.configdict["pkg"].clear()
1067                         self.configdict["pkginternal"].clear()
1068                         self.configdict["repo"].clear()
1069                         self.configdict["defaults"]["USE"] = \
1070                                 " ".join(self.make_defaults_use)
1071                         self.usemask = self._use_manager.getUseMask()
1072                         self.useforce = self._use_manager.getUseForce()
1073                 self.regenerate()
1074
1075         class _lazy_vars(object):
1076
1077                 __slots__ = ('built_use', 'settings', 'values')
1078
1079                 def __init__(self, built_use, settings):
1080                         self.built_use = built_use
1081                         self.settings = settings
1082                         self.values = None
1083
1084                 def __getitem__(self, k):
1085                         if self.values is None:
1086                                 self.values = self._init_values()
1087                         return self.values[k]
1088
1089                 def _init_values(self):
1090                         values = {}
1091                         settings = self.settings
1092                         use = self.built_use
1093                         if use is None:
1094                                 use = frozenset(settings['PORTAGE_USE'].split())
1095
1096                         values['ACCEPT_LICENSE'] = settings._license_manager.get_prunned_accept_license( \
1097                                 settings.mycpv, use, settings['LICENSE'], settings['SLOT'], settings.get('PORTAGE_REPO_NAME'))
1098                         values['PORTAGE_RESTRICT'] = self._restrict(use, settings)
1099                         return values
1100
1101                 def _restrict(self, use, settings):
1102                         try:
1103                                 restrict = set(use_reduce(settings['RESTRICT'], uselist=use, flat=True))
1104                         except InvalidDependString:
1105                                 restrict = set()
1106                         return ' '.join(sorted(restrict))
1107
1108         class _lazy_use_expand(object):
1109                 """
1110                 Lazily evaluate USE_EXPAND variables since they are only needed when
1111                 an ebuild shell is spawned. Variables values are made consistent with
1112                 the previously calculated USE settings.
1113                 """
1114
1115                 def __init__(self, use, usemask, iuse_implicit,
1116                         use_expand_split, use_expand_dict):
1117                         self._use = use
1118                         self._usemask = usemask
1119                         self._iuse_implicit = iuse_implicit
1120                         self._use_expand_split = use_expand_split
1121                         self._use_expand_dict = use_expand_dict
1122
1123                 def __getitem__(self, key):
1124                         prefix = key.lower() + '_'
1125                         prefix_len = len(prefix)
1126                         expand_flags = set( x[prefix_len:] for x in self._use \
1127                                 if x[:prefix_len] == prefix )
1128                         var_split = self._use_expand_dict.get(key, '').split()
1129                         # Preserve the order of var_split because it can matter for things
1130                         # like LINGUAS.
1131                         var_split = [ x for x in var_split if x in expand_flags ]
1132                         var_split.extend(expand_flags.difference(var_split))
1133                         has_wildcard = '*' in expand_flags
1134                         if has_wildcard:
1135                                 var_split = [ x for x in var_split if x != "*" ]
1136                         has_iuse = set()
1137                         for x in self._iuse_implicit:
1138                                 if x[:prefix_len] == prefix:
1139                                         has_iuse.add(x[prefix_len:])
1140                         if has_wildcard:
1141                                 # * means to enable everything in IUSE that's not masked
1142                                 if has_iuse:
1143                                         usemask = self._usemask
1144                                         for suffix in has_iuse:
1145                                                 x = prefix + suffix
1146                                                 if x not in usemask:
1147                                                         if suffix not in expand_flags:
1148                                                                 var_split.append(suffix)
1149                                 else:
1150                                         # If there is a wildcard and no matching flags in IUSE then
1151                                         # LINGUAS should be unset so that all .mo files are
1152                                         # installed.
1153                                         var_split = []
1154                         # Make the flags unique and filter them according to IUSE.
1155                         # Also, continue to preserve order for things like LINGUAS
1156                         # and filter any duplicates that variable may contain.
1157                         filtered_var_split = []
1158                         remaining = has_iuse.intersection(var_split)
1159                         for x in var_split:
1160                                 if x in remaining:
1161                                         remaining.remove(x)
1162                                         filtered_var_split.append(x)
1163                         var_split = filtered_var_split
1164
1165                         if var_split:
1166                                 value = ' '.join(var_split)
1167                         else:
1168                                 # Don't export empty USE_EXPAND vars unless the user config
1169                                 # exports them as empty.  This is required for vars such as
1170                                 # LINGUAS, where unset and empty have different meanings.
1171                                 if has_wildcard:
1172                                         # ebuild.sh will see this and unset the variable so
1173                                         # that things like LINGUAS work properly
1174                                         value = '*'
1175                                 else:
1176                                         if has_iuse:
1177                                                 value = ''
1178                                         else:
1179                                                 # It's not in IUSE, so just allow the variable content
1180                                                 # to pass through if it is defined somewhere.  This
1181                                                 # allows packages that support LINGUAS but don't
1182                                                 # declare it in IUSE to use the variable outside of the
1183                                                 # USE_EXPAND context.
1184                                                 value = None
1185
1186                         return value
1187
1188         def setcpv(self, mycpv, use_cache=None, mydb=None):
1189                 """
1190                 Load a particular CPV into the config, this lets us see the
1191                 Default USE flags for a particular ebuild as well as the USE
1192                 flags from package.use.
1193
1194                 @param mycpv: A cpv to load
1195                 @type mycpv: string
1196                 @param mydb: a dbapi instance that supports aux_get with the IUSE key.
1197                 @type mydb: dbapi or derivative.
1198                 @rtype: None
1199                 """
1200
1201                 if use_cache is not None:
1202                         warnings.warn("The use_cache parameter for config.setcpv() is deprecated and without effect.",
1203                                 DeprecationWarning, stacklevel=2)
1204
1205                 self.modifying()
1206
1207                 pkg = None
1208                 built_use = None
1209                 explicit_iuse = None
1210                 if not isinstance(mycpv, basestring):
1211                         pkg = mycpv
1212                         mycpv = pkg.cpv
1213                         mydb = pkg.metadata
1214                         explicit_iuse = pkg.iuse.all
1215                         args_hash = (mycpv, id(pkg))
1216                         if pkg.built:
1217                                 built_use = pkg.use.enabled
1218                 else:
1219                         args_hash = (mycpv, id(mydb))
1220
1221                 if args_hash == self._setcpv_args_hash:
1222                         return
1223                 self._setcpv_args_hash = args_hash
1224
1225                 has_changed = False
1226                 self.mycpv = mycpv
1227                 cat, pf = catsplit(mycpv)
1228                 cp = cpv_getkey(mycpv)
1229                 cpv_slot = self.mycpv
1230                 pkginternaluse = ""
1231                 iuse = ""
1232                 pkg_configdict = self.configdict["pkg"]
1233                 previous_iuse = pkg_configdict.get("IUSE")
1234                 previous_features = pkg_configdict.get("FEATURES")
1235
1236                 aux_keys = self._setcpv_aux_keys
1237
1238                 # Discard any existing metadata and package.env settings from
1239                 # the previous package instance.
1240                 pkg_configdict.clear()
1241
1242                 pkg_configdict["CATEGORY"] = cat
1243                 pkg_configdict["PF"] = pf
1244                 repository = None
1245                 if mydb:
1246                         if not hasattr(mydb, "aux_get"):
1247                                 for k in aux_keys:
1248                                         if k in mydb:
1249                                                 # Make these lazy, since __getitem__ triggers
1250                                                 # evaluation of USE conditionals which can't
1251                                                 # occur until PORTAGE_USE is calculated below.
1252                                                 pkg_configdict.addLazySingleton(k,
1253                                                         mydb.__getitem__, k)
1254                         else:
1255                                 # When calling dbapi.aux_get(), grab USE for built/installed
1256                                 # packages since we want to save it PORTAGE_BUILT_USE for
1257                                 # evaluating conditional USE deps in atoms passed via IPC to
1258                                 # helpers like has_version and best_version.
1259                                 aux_keys = set(aux_keys)
1260                                 if hasattr(mydb, '_aux_cache_keys'):
1261                                         aux_keys = aux_keys.intersection(mydb._aux_cache_keys)
1262                                 aux_keys.add('USE')
1263                                 aux_keys = list(aux_keys)
1264                                 for k, v in zip(aux_keys, mydb.aux_get(self.mycpv, aux_keys)):
1265                                         pkg_configdict[k] = v
1266                                 built_use = frozenset(pkg_configdict.pop('USE').split())
1267                                 if not built_use:
1268                                         # Empty USE means this dbapi instance does not contain
1269                                         # built packages.
1270                                         built_use = None
1271
1272                         repository = pkg_configdict.pop("repository", None)
1273                         if repository is not None:
1274                                 pkg_configdict["PORTAGE_REPO_NAME"] = repository
1275                         slot = pkg_configdict["SLOT"]
1276                         iuse = pkg_configdict["IUSE"]
1277                         if pkg is None:
1278                                 cpv_slot = _pkg_str(self.mycpv, slot=slot, repo=repository)
1279                         else:
1280                                 cpv_slot = pkg
1281                         pkginternaluse = []
1282                         for x in iuse.split():
1283                                 if x.startswith("+"):
1284                                         pkginternaluse.append(x[1:])
1285                                 elif x.startswith("-"):
1286                                         pkginternaluse.append(x)
1287                         pkginternaluse = " ".join(pkginternaluse)
1288                 if pkginternaluse != self.configdict["pkginternal"].get("USE", ""):
1289                         self.configdict["pkginternal"]["USE"] = pkginternaluse
1290                         has_changed = True
1291
1292                 repo_env = []
1293                 if repository and repository != Package.UNKNOWN_REPO:
1294                         repos = []
1295                         try:
1296                                 repos.extend(repo.name for repo in
1297                                         self.repositories[repository].masters)
1298                         except KeyError:
1299                                 pass
1300                         repos.append(repository)
1301                         for repo in repos:
1302                                 d = self._repo_make_defaults.get(repo)
1303                                 if d is None:
1304                                         d = {}
1305                                 else:
1306                                         # make a copy, since we might modify it with
1307                                         # package.use settings
1308                                         d = d.copy()
1309                                 cpdict = self._use_manager._repo_puse_dict.get(repo, {}).get(cp)
1310                                 if cpdict:
1311                                         repo_puse = ordered_by_atom_specificity(cpdict, cpv_slot)
1312                                         if repo_puse:
1313                                                 for x in repo_puse:
1314                                                         d["USE"] = d.get("USE", "") + " " + " ".join(x)
1315                                 if d:
1316                                         repo_env.append(d)
1317
1318                 if repo_env or self.configdict["repo"]:
1319                         self.configdict["repo"].clear()
1320                         self.configdict["repo"].update(stack_dicts(repo_env,
1321                                 incrementals=self.incrementals))
1322                         has_changed = True
1323
1324                 defaults = []
1325                 for i, pkgprofileuse_dict in enumerate(self._use_manager._pkgprofileuse):
1326                         if self.make_defaults_use[i]:
1327                                 defaults.append(self.make_defaults_use[i])
1328                         cpdict = pkgprofileuse_dict.get(cp)
1329                         if cpdict:
1330                                 pkg_defaults = ordered_by_atom_specificity(cpdict, cpv_slot)
1331                                 if pkg_defaults:
1332                                         defaults.extend(pkg_defaults)
1333                 defaults = " ".join(defaults)
1334                 if defaults != self.configdict["defaults"].get("USE",""):
1335                         self.configdict["defaults"]["USE"] = defaults
1336                         has_changed = True
1337
1338                 useforce = self._use_manager.getUseForce(cpv_slot)
1339                 if useforce != self.useforce:
1340                         self.useforce = useforce
1341                         has_changed = True
1342
1343                 usemask = self._use_manager.getUseMask(cpv_slot)
1344                 if usemask != self.usemask:
1345                         self.usemask = usemask
1346                         has_changed = True
1347
1348                 oldpuse = self.puse
1349                 self.puse = self._use_manager.getPUSE(cpv_slot)
1350                 if oldpuse != self.puse:
1351                         has_changed = True
1352                 self.configdict["pkg"]["PKGUSE"] = self.puse[:] # For saving to PUSE file
1353                 self.configdict["pkg"]["USE"]    = self.puse[:] # this gets appended to USE
1354
1355                 if previous_features:
1356                         # The package from the previous setcpv call had package.env
1357                         # settings which modified FEATURES. Therefore, trigger a
1358                         # regenerate() call in order to ensure that self.features
1359                         # is accurate.
1360                         has_changed = True
1361
1362                 self._penv = []
1363                 cpdict = self._penvdict.get(cp)
1364                 if cpdict:
1365                         penv_matches = ordered_by_atom_specificity(cpdict, cpv_slot)
1366                         if penv_matches:
1367                                 for x in penv_matches:
1368                                         self._penv.extend(x)
1369
1370                 protected_pkg_keys = set(pkg_configdict)
1371                 protected_pkg_keys.discard('USE')
1372
1373                 # If there are _any_ package.env settings for this package
1374                 # then it automatically triggers config.reset(), in order
1375                 # to account for possible incremental interaction between
1376                 # package.use, package.env, and overrides from the calling
1377                 # environment (configdict['env']).
1378                 if self._penv:
1379                         has_changed = True
1380                         # USE is special because package.use settings override
1381                         # it. Discard any package.use settings here and they'll
1382                         # be added back later.
1383                         pkg_configdict.pop('USE', None)
1384                         self._grab_pkg_env(self._penv, pkg_configdict,
1385                                 protected_keys=protected_pkg_keys)
1386
1387                         # Now add package.use settings, which override USE from
1388                         # package.env
1389                         if self.puse:
1390                                 if 'USE' in pkg_configdict:
1391                                         pkg_configdict['USE'] = \
1392                                                 pkg_configdict['USE'] + " " + self.puse
1393                                 else:
1394                                         pkg_configdict['USE'] = self.puse
1395
1396                 if has_changed:
1397                         self.reset(keeping_pkg=1)
1398
1399                 env_configdict = self.configdict['env']
1400
1401                 # Ensure that "pkg" values are always preferred over "env" values.
1402                 # This must occur _after_ the above reset() call, since reset()
1403                 # copies values from self.backupenv.
1404                 for k in protected_pkg_keys:
1405                         env_configdict.pop(k, None)
1406
1407                 lazy_vars = self._lazy_vars(built_use, self)
1408                 env_configdict.addLazySingleton('ACCEPT_LICENSE',
1409                         lazy_vars.__getitem__, 'ACCEPT_LICENSE')
1410                 env_configdict.addLazySingleton('PORTAGE_RESTRICT',
1411                         lazy_vars.__getitem__, 'PORTAGE_RESTRICT')
1412
1413                 if built_use is not None:
1414                         pkg_configdict['PORTAGE_BUILT_USE'] = ' '.join(built_use)
1415
1416                 # If reset() has not been called, it's safe to return
1417                 # early if IUSE has not changed.
1418                 if not has_changed and previous_iuse == iuse:
1419                         return
1420
1421                 # Filter out USE flags that aren't part of IUSE. This has to
1422                 # be done for every setcpv() call since practically every
1423                 # package has different IUSE.
1424                 use = set(self["USE"].split())
1425                 if explicit_iuse is None:
1426                         explicit_iuse = frozenset(x.lstrip("+-") for x in iuse.split())
1427                 iuse_implicit_match = self._iuse_implicit_match
1428                 portage_iuse = self._get_implicit_iuse()
1429                 portage_iuse.update(explicit_iuse)
1430
1431                 # PORTAGE_IUSE is not always needed so it's lazily evaluated.
1432                 self.configdict["env"].addLazySingleton(
1433                         "PORTAGE_IUSE", _lazy_iuse_regex, portage_iuse)
1434
1435                 ebuild_force_test = self.get("EBUILD_FORCE_TEST") == "1"
1436                 if ebuild_force_test and \
1437                         not hasattr(self, "_ebuild_force_test_msg_shown"):
1438                                 self._ebuild_force_test_msg_shown = True
1439                                 writemsg(_("Forcing test.\n"), noiselevel=-1)
1440                 if "test" in self.features:
1441                         if "test" in self.usemask and not ebuild_force_test:
1442                                 # "test" is in IUSE and USE=test is masked, so execution
1443                                 # of src_test() probably is not reliable. Therefore,
1444                                 # temporarily disable FEATURES=test just for this package.
1445                                 self["FEATURES"] = " ".join(x for x in self.features \
1446                                         if x != "test")
1447                                 use.discard("test")
1448                         else:
1449                                 use.add("test")
1450                                 if ebuild_force_test and "test" in self.usemask:
1451                                         self.usemask = \
1452                                                 frozenset(x for x in self.usemask if x != "test")
1453
1454                 # Allow _* flags from USE_EXPAND wildcards to pass through here.
1455                 use.difference_update([x for x in use \
1456                         if (x not in explicit_iuse and \
1457                         not iuse_implicit_match(x)) and x[-2:] != '_*'])
1458
1459                 # Use the calculated USE flags to regenerate the USE_EXPAND flags so
1460                 # that they are consistent. For optimal performance, use slice
1461                 # comparison instead of startswith().
1462                 use_expand_split = set(x.lower() for \
1463                         x in self.get('USE_EXPAND', '').split())
1464                 lazy_use_expand = self._lazy_use_expand(use, self.usemask,
1465                         portage_iuse, use_expand_split, self._use_expand_dict)
1466
1467                 use_expand_iuses = {}
1468                 for x in portage_iuse:
1469                         x_split = x.split('_')
1470                         if len(x_split) == 1:
1471                                 continue
1472                         for i in range(len(x_split) - 1):
1473                                 k = '_'.join(x_split[:i+1])
1474                                 if k in use_expand_split:
1475                                         v = use_expand_iuses.get(k)
1476                                         if v is None:
1477                                                 v = set()
1478                                                 use_expand_iuses[k] = v
1479                                         v.add(x)
1480                                         break
1481
1482                 # If it's not in IUSE, variable content is allowed
1483                 # to pass through if it is defined somewhere.  This
1484                 # allows packages that support LINGUAS but don't
1485                 # declare it in IUSE to use the variable outside of the
1486                 # USE_EXPAND context.
1487                 for k, use_expand_iuse in use_expand_iuses.items():
1488                         if k + '_*' in use:
1489                                 use.update( x for x in use_expand_iuse if x not in usemask )
1490                         k = k.upper()
1491                         self.configdict['env'].addLazySingleton(k,
1492                                 lazy_use_expand.__getitem__, k)
1493
1494                 # Filtered for the ebuild environment. Store this in a separate
1495                 # attribute since we still want to be able to see global USE
1496                 # settings for things like emerge --info.
1497
1498                 self.configdict["env"]["PORTAGE_USE"] = \
1499                         " ".join(sorted(x for x in use if x[-2:] != '_*'))
1500
1501         def _grab_pkg_env(self, penv, container, protected_keys=None):
1502                 if protected_keys is None:
1503                         protected_keys = ()
1504                 abs_user_config = os.path.join(
1505                         self['PORTAGE_CONFIGROOT'], USER_CONFIG_PATH)
1506                 non_user_variables = self._non_user_variables
1507                 # Make a copy since we don't want per-package settings
1508                 # to pollute the global expand_map.
1509                 expand_map = self._expand_map.copy()
1510                 incrementals = self.incrementals
1511                 for envname in penv:
1512                         penvfile = os.path.join(abs_user_config, "env", envname)
1513                         penvconfig = getconfig(penvfile, tolerant=self._tolerant,
1514                                 allow_sourcing=True, expand=expand_map)
1515                         if penvconfig is None:
1516                                 writemsg("!!! %s references non-existent file: %s\n" % \
1517                                         (os.path.join(abs_user_config, 'package.env'), penvfile),
1518                                         noiselevel=-1)
1519                         else:
1520                                 for k, v in penvconfig.items():
1521                                         if k in protected_keys or \
1522                                                 k in non_user_variables:
1523                                                 writemsg("!!! Illegal variable " + \
1524                                                         "'%s' assigned in '%s'\n" % \
1525                                                         (k, penvfile), noiselevel=-1)
1526                                         elif k in incrementals:
1527                                                 if k in container:
1528                                                         container[k] = container[k] + " " + v
1529                                                 else:
1530                                                         container[k] = v
1531                                         else:
1532                                                 container[k] = v
1533
1534         def _get_implicit_iuse(self):
1535                 """
1536                 Some flags are considered to
1537                 be implicit members of IUSE:
1538                   * Flags derived from ARCH
1539                   * Flags derived from USE_EXPAND_HIDDEN variables
1540                   * Masked flags, such as those from {,package}use.mask
1541                   * Forced flags, such as those from {,package}use.force
1542                   * build and bootstrap flags used by bootstrap.sh
1543                 """
1544                 iuse_implicit = set()
1545                 # Flags derived from ARCH.
1546                 arch = self.configdict["defaults"].get("ARCH")
1547                 if arch:
1548                         iuse_implicit.add(arch)
1549                 iuse_implicit.update(self.get("PORTAGE_ARCHLIST", "").split())
1550
1551                 # Flags derived from USE_EXPAND_HIDDEN variables
1552                 # such as ELIBC, KERNEL, and USERLAND.
1553                 use_expand_hidden = self.get("USE_EXPAND_HIDDEN", "").split()
1554                 for x in use_expand_hidden:
1555                         iuse_implicit.add(x.lower() + "_.*")
1556
1557                 # Flags that have been masked or forced.
1558                 iuse_implicit.update(self.usemask)
1559                 iuse_implicit.update(self.useforce)
1560
1561                 # build and bootstrap flags used by bootstrap.sh
1562                 iuse_implicit.add("build")
1563                 iuse_implicit.add("bootstrap")
1564
1565                 # Controlled by FEATURES=test. Make this implicit, so handling
1566                 # of FEATURES=test is consistent regardless of explicit IUSE.
1567                 # Users may use use.mask/package.use.mask to control
1568                 # FEATURES=test for all ebuilds, regardless of explicit IUSE.
1569                 iuse_implicit.add("test")
1570
1571                 return iuse_implicit
1572
1573         def _getUseMask(self, pkg):
1574                 return self._use_manager.getUseMask(pkg)
1575
1576         def _getUseForce(self, pkg):
1577                 return self._use_manager.getUseForce(pkg)
1578
1579         def _getMaskAtom(self, cpv, metadata):
1580                 """
1581                 Take a package and return a matching package.mask atom, or None if no
1582                 such atom exists or it has been cancelled by package.unmask. PROVIDE
1583                 is not checked, so atoms will not be found for old-style virtuals.
1584
1585                 @param cpv: The package name
1586                 @type cpv: String
1587                 @param metadata: A dictionary of raw package metadata
1588                 @type metadata: dict
1589                 @rtype: String
1590                 @return: A matching atom string or None if one is not found.
1591                 """
1592                 return self._mask_manager.getMaskAtom(cpv, metadata["SLOT"], metadata.get('repository'))
1593
1594         def _getRawMaskAtom(self, cpv, metadata):
1595                 """
1596                 Take a package and return a matching package.mask atom, or None if no
1597                 such atom exists or it has been cancelled by package.unmask. PROVIDE
1598                 is not checked, so atoms will not be found for old-style virtuals.
1599
1600                 @param cpv: The package name
1601                 @type cpv: String
1602                 @param metadata: A dictionary of raw package metadata
1603                 @type metadata: dict
1604                 @rtype: String
1605                 @return: A matching atom string or None if one is not found.
1606                 """
1607                 return self._mask_manager.getRawMaskAtom(cpv, metadata["SLOT"], metadata.get('repository'))
1608
1609
1610         def _getProfileMaskAtom(self, cpv, metadata):
1611                 """
1612                 Take a package and return a matching profile atom, or None if no
1613                 such atom exists. Note that a profile atom may or may not have a "*"
1614                 prefix. PROVIDE is not checked, so atoms will not be found for
1615                 old-style virtuals.
1616
1617                 @param cpv: The package name
1618                 @type cpv: String
1619                 @param metadata: A dictionary of raw package metadata
1620                 @type metadata: dict
1621                 @rtype: String
1622                 @return: A matching profile atom string or None if one is not found.
1623                 """
1624
1625                 warnings.warn("The config._getProfileMaskAtom() method is deprecated.",
1626                         DeprecationWarning, stacklevel=2)
1627
1628                 cp = cpv_getkey(cpv)
1629                 profile_atoms = self.prevmaskdict.get(cp)
1630                 if profile_atoms:
1631                         pkg = "".join((cpv, _slot_separator, metadata["SLOT"]))
1632                         repo = metadata.get("repository")
1633                         if repo and repo != Package.UNKNOWN_REPO:
1634                                 pkg = "".join((pkg, _repo_separator, repo))
1635                         pkg_list = [pkg]
1636                         for x in profile_atoms:
1637                                 if match_from_list(x, pkg_list):
1638                                         continue
1639                                 return x
1640                 return None
1641
1642         def _getKeywords(self, cpv, metadata):
1643                 return self._keywords_manager.getKeywords(cpv, metadata["SLOT"], \
1644                         metadata.get("KEYWORDS", ""), metadata.get("repository"))
1645
1646         def _getMissingKeywords(self, cpv, metadata):
1647                 """
1648                 Take a package and return a list of any KEYWORDS that the user may
1649                 need to accept for the given package. If the KEYWORDS are empty
1650                 and the the ** keyword has not been accepted, the returned list will
1651                 contain ** alone (in order to distinguish from the case of "none
1652                 missing").
1653
1654                 @param cpv: The package name (for package.keywords support)
1655                 @type cpv: String
1656                 @param metadata: A dictionary of raw package metadata
1657                 @type metadata: dict
1658                 @rtype: List
1659                 @return: A list of KEYWORDS that have not been accepted.
1660                 """
1661
1662                 # Hack: Need to check the env directly here as otherwise stacking
1663                 # doesn't work properly as negative values are lost in the config
1664                 # object (bug #139600)
1665                 backuped_accept_keywords = self.configdict["backupenv"].get("ACCEPT_KEYWORDS", "")
1666                 global_accept_keywords = self["ACCEPT_KEYWORDS"]
1667
1668                 return self._keywords_manager.getMissingKeywords(cpv, metadata["SLOT"], \
1669                         metadata.get("KEYWORDS", ""), metadata.get('repository'), \
1670                         global_accept_keywords, backuped_accept_keywords)
1671
1672         def _getRawMissingKeywords(self, cpv, metadata):
1673                 """
1674                 Take a package and return a list of any KEYWORDS that the user may
1675                 need to accept for the given package. If the KEYWORDS are empty,
1676                 the returned list will contain ** alone (in order to distinguish
1677                 from the case of "none missing").  This DOES NOT apply any user config
1678                 package.accept_keywords acceptance.
1679
1680                 @param cpv: The package name (for package.keywords support)
1681                 @type cpv: String
1682                 @param metadata: A dictionary of raw package metadata
1683                 @type metadata: dict
1684                 @rtype: List
1685                 @return: lists of KEYWORDS that have not been accepted
1686                 and the keywords it looked for.
1687                 """
1688                 return self._keywords_manager.getRawMissingKeywords(cpv, metadata["SLOT"], \
1689                         metadata.get("KEYWORDS", ""), metadata.get('repository'), \
1690                         self.get("ACCEPT_KEYWORDS", ""))
1691
1692         def _getPKeywords(self, cpv, metadata):
1693                 global_accept_keywords = self.get("ACCEPT_KEYWORDS", "")
1694
1695                 return self._keywords_manager.getPKeywords(cpv, metadata["SLOT"], \
1696                         metadata.get('repository'), global_accept_keywords)
1697
1698         def _getMissingLicenses(self, cpv, metadata):
1699                 """
1700                 Take a LICENSE string and return a list of any licenses that the user
1701                 may need to accept for the given package.  The returned list will not
1702                 contain any licenses that have already been accepted.  This method
1703                 can throw an InvalidDependString exception.
1704
1705                 @param cpv: The package name (for package.license support)
1706                 @type cpv: String
1707                 @param metadata: A dictionary of raw package metadata
1708                 @type metadata: dict
1709                 @rtype: List
1710                 @return: A list of licenses that have not been accepted.
1711                 """
1712                 return self._license_manager.getMissingLicenses( \
1713                         cpv, metadata["USE"], metadata["LICENSE"], metadata["SLOT"], metadata.get('repository'))
1714
1715         def _getMissingProperties(self, cpv, metadata):
1716                 """
1717                 Take a PROPERTIES string and return a list of any properties the user
1718                 may need to accept for the given package.  The returned list will not
1719                 contain any properties that have already been accepted.  This method
1720                 can throw an InvalidDependString exception.
1721
1722                 @param cpv: The package name (for package.properties support)
1723                 @type cpv: String
1724                 @param metadata: A dictionary of raw package metadata
1725                 @type metadata: dict
1726                 @rtype: List
1727                 @return: A list of properties that have not been accepted.
1728                 """
1729                 accept_properties = self._accept_properties
1730                 if not hasattr(cpv, 'slot'):
1731                         cpv = _pkg_str(cpv, slot=metadata["SLOT"],
1732                                 repo=metadata.get("repository"))
1733                 cp = cpv_getkey(cpv)
1734                 cpdict = self._ppropertiesdict.get(cp)
1735                 if cpdict:
1736                         pproperties_list = ordered_by_atom_specificity(cpdict, cpv)
1737                         if pproperties_list:
1738                                 accept_properties = list(self._accept_properties)
1739                                 for x in pproperties_list:
1740                                         accept_properties.extend(x)
1741
1742                 properties_str = metadata.get("PROPERTIES", "")
1743                 properties = set(use_reduce(properties_str, matchall=1, flat=True))
1744                 properties.discard('||')
1745
1746                 acceptable_properties = set()
1747                 for x in accept_properties:
1748                         if x == '*':
1749                                 acceptable_properties.update(properties)
1750                         elif x == '-*':
1751                                 acceptable_properties.clear()
1752                         elif x[:1] == '-':
1753                                 acceptable_properties.discard(x[1:])
1754                         else:
1755                                 acceptable_properties.add(x)
1756
1757                 if "?" in properties_str:
1758                         use = metadata["USE"].split()
1759                 else:
1760                         use = []
1761
1762                 properties_struct = use_reduce(properties_str, uselist=use, opconvert=True)
1763                 return self._getMaskedProperties(properties_struct, acceptable_properties)
1764
1765         def _getMaskedProperties(self, properties_struct, acceptable_properties):
1766                 if not properties_struct:
1767                         return []
1768                 if properties_struct[0] == "||":
1769                         ret = []
1770                         for element in properties_struct[1:]:
1771                                 if isinstance(element, list):
1772                                         if element:
1773                                                 tmp = self._getMaskedProperties(
1774                                                         element, acceptable_properties)
1775                                                 if not tmp:
1776                                                         return []
1777                                                 ret.extend(tmp)
1778                                 else:
1779                                         if element in acceptable_properties:
1780                                                 return[]
1781                                         ret.append(element)
1782                         # Return all masked properties, since we don't know which combination
1783                         # (if any) the user will decide to unmask
1784                         return ret
1785
1786                 ret = []
1787                 for element in properties_struct:
1788                         if isinstance(element, list):
1789                                 if element:
1790                                         ret.extend(self._getMaskedProperties(element,
1791                                                 acceptable_properties))
1792                         else:
1793                                 if element not in acceptable_properties:
1794                                         ret.append(element)
1795                 return ret
1796
1797         def _accept_chost(self, cpv, metadata):
1798                 """
1799                 @return True if pkg CHOST is accepted, False otherwise.
1800                 """
1801                 if self._accept_chost_re is None:
1802                         accept_chost = self.get("ACCEPT_CHOSTS", "").split()
1803                         if not accept_chost:
1804                                 chost = self.get("CHOST")
1805                                 if chost:
1806                                         accept_chost.append(chost)
1807                         if not accept_chost:
1808                                 self._accept_chost_re = re.compile(".*")
1809                         elif len(accept_chost) == 1:
1810                                 try:
1811                                         self._accept_chost_re = re.compile(r'^%s$' % accept_chost[0])
1812                                 except re.error as e:
1813                                         writemsg(_("!!! Invalid ACCEPT_CHOSTS value: '%s': %s\n") % \
1814                                                 (accept_chost[0], e), noiselevel=-1)
1815                                         self._accept_chost_re = re.compile("^$")
1816                         else:
1817                                 try:
1818                                         self._accept_chost_re = re.compile(
1819                                                 r'^(%s)$' % "|".join(accept_chost))
1820                                 except re.error as e:
1821                                         writemsg(_("!!! Invalid ACCEPT_CHOSTS value: '%s': %s\n") % \
1822                                                 (" ".join(accept_chost), e), noiselevel=-1)
1823                                         self._accept_chost_re = re.compile("^$")
1824
1825                 pkg_chost = metadata.get('CHOST', '')
1826                 return not pkg_chost or \
1827                         self._accept_chost_re.match(pkg_chost) is not None
1828
1829         def setinst(self, mycpv, mydbapi):
1830                 """This updates the preferences for old-style virtuals,
1831                 affecting the behavior of dep_expand() and dep_check()
1832                 calls. It can change dbapi.match() behavior since that
1833                 calls dep_expand(). However, dbapi instances have
1834                 internal match caches that are not invalidated when
1835                 preferences are updated here. This can potentially
1836                 lead to some inconsistency (relevant to bug #1343)."""
1837                 self.modifying()
1838
1839                 # Grab the virtuals this package provides and add them into the tree virtuals.
1840                 if not hasattr(mydbapi, "aux_get"):
1841                         provides = mydbapi["PROVIDE"]
1842                 else:
1843                         provides = mydbapi.aux_get(mycpv, ["PROVIDE"])[0]
1844                 if not provides:
1845                         return
1846                 if isinstance(mydbapi, portdbapi):
1847                         self.setcpv(mycpv, mydb=mydbapi)
1848                         myuse = self["PORTAGE_USE"]
1849                 elif not hasattr(mydbapi, "aux_get"):
1850                         myuse = mydbapi["USE"]
1851                 else:
1852                         myuse = mydbapi.aux_get(mycpv, ["USE"])[0]
1853                 virts = use_reduce(provides, uselist=myuse.split(), flat=True)
1854
1855                 # Ensure that we don't trigger the _treeVirtuals
1856                 # assertion in VirtualsManager._compile_virtuals().
1857                 self.getvirtuals()
1858                 self._virtuals_manager.add_depgraph_virtuals(mycpv, virts)
1859
1860         def reload(self):
1861                 """Reload things like /etc/profile.env that can change during runtime."""
1862                 env_d_filename = os.path.join(self["EROOT"], "etc", "profile.env")
1863                 self.configdict["env.d"].clear()
1864                 env_d = getconfig(env_d_filename, expand=False)
1865                 if env_d:
1866                         # env_d will be None if profile.env doesn't exist.
1867                         for k in self._env_d_blacklist:
1868                                 env_d.pop(k, None)
1869                         self.configdict["env.d"].update(env_d)
1870
1871         def regenerate(self, useonly=0, use_cache=None):
1872                 """
1873                 Regenerate settings
1874                 This involves regenerating valid USE flags, re-expanding USE_EXPAND flags
1875                 re-stacking USE flags (-flag and -*), as well as any other INCREMENTAL
1876                 variables.  This also updates the env.d configdict; useful in case an ebuild
1877                 changes the environment.
1878
1879                 If FEATURES has already stacked, it is not stacked twice.
1880
1881                 @param useonly: Only regenerate USE flags (not any other incrementals)
1882                 @type useonly: Boolean
1883                 @rtype: None
1884                 """
1885
1886                 if use_cache is not None:
1887                         warnings.warn("The use_cache parameter for config.regenerate() is deprecated and without effect.",
1888                                 DeprecationWarning, stacklevel=2)
1889
1890                 self.modifying()
1891
1892                 if useonly:
1893                         myincrementals=["USE"]
1894                 else:
1895                         myincrementals = self.incrementals
1896                 myincrementals = set(myincrementals)
1897
1898                 # Process USE last because it depends on USE_EXPAND which is also
1899                 # an incremental!
1900                 myincrementals.discard("USE")
1901
1902                 mydbs = self.configlist[:-1]
1903                 mydbs.append(self.backupenv)
1904
1905                 # ACCEPT_LICENSE is a lazily evaluated incremental, so that * can be
1906                 # used to match all licenses without every having to explicitly expand
1907                 # it to all licenses.
1908                 if self.local_config:
1909                         mysplit = []
1910                         for curdb in mydbs:
1911                                 mysplit.extend(curdb.get('ACCEPT_LICENSE', '').split())
1912                         mysplit = prune_incremental(mysplit)
1913                         accept_license_str = ' '.join(mysplit)
1914                         self.configlist[-1]['ACCEPT_LICENSE'] = accept_license_str
1915                         self._license_manager.set_accept_license_str(accept_license_str)
1916                 else:
1917                         # repoman will accept any license
1918                         self._license_manager.set_accept_license_str("*")
1919
1920                 # ACCEPT_PROPERTIES works like ACCEPT_LICENSE, without groups
1921                 if self.local_config:
1922                         mysplit = []
1923                         for curdb in mydbs:
1924                                 mysplit.extend(curdb.get('ACCEPT_PROPERTIES', '').split())
1925                         mysplit = prune_incremental(mysplit)
1926                         self.configlist[-1]['ACCEPT_PROPERTIES'] = ' '.join(mysplit)
1927                         if tuple(mysplit) != self._accept_properties:
1928                                 self._accept_properties = tuple(mysplit)
1929                 else:
1930                         # repoman will accept any property
1931                         self._accept_properties = ('*',)
1932
1933                 increment_lists = {}
1934                 for k in myincrementals:
1935                         incremental_list = []
1936                         increment_lists[k] = incremental_list
1937                         for curdb in mydbs:
1938                                 v = curdb.get(k)
1939                                 if v is not None:
1940                                         incremental_list.append(v.split())
1941
1942                 if 'FEATURES' in increment_lists:
1943                         increment_lists['FEATURES'].append(self._features_overrides)
1944
1945                 myflags = set()
1946                 for mykey, incremental_list in increment_lists.items():
1947
1948                         myflags.clear()
1949                         for mysplit in incremental_list:
1950
1951                                 for x in mysplit:
1952                                         if x=="-*":
1953                                                 # "-*" is a special "minus" var that means "unset all settings".
1954                                                 # so USE="-* gnome" will have *just* gnome enabled.
1955                                                 myflags.clear()
1956                                                 continue
1957
1958                                         if x[0]=="+":
1959                                                 # Not legal. People assume too much. Complain.
1960                                                 writemsg(colorize("BAD",
1961                                                         _("%s values should not start with a '+': %s") % (mykey,x)) \
1962                                                         + "\n", noiselevel=-1)
1963                                                 x=x[1:]
1964                                                 if not x:
1965                                                         continue
1966
1967                                         if (x[0]=="-"):
1968                                                 myflags.discard(x[1:])
1969                                                 continue
1970
1971                                         # We got here, so add it now.
1972                                         myflags.add(x)
1973
1974                         #store setting in last element of configlist, the original environment:
1975                         if myflags or mykey in self:
1976                                 self.configlist[-1][mykey] = " ".join(sorted(myflags))
1977
1978                 # Do the USE calculation last because it depends on USE_EXPAND.
1979                 use_expand = self.get("USE_EXPAND", "").split()
1980                 use_expand_dict = self._use_expand_dict
1981                 use_expand_dict.clear()
1982                 for k in use_expand:
1983                         v = self.get(k)
1984                         if v is not None:
1985                                 use_expand_dict[k] = v
1986
1987                 # In order to best accomodate the long-standing practice of
1988                 # setting default USE_EXPAND variables in the profile's
1989                 # make.defaults, we translate these variables into their
1990                 # equivalent USE flags so that useful incremental behavior
1991                 # is enabled (for sub-profiles).
1992                 configdict_defaults = self.configdict['defaults']
1993                 if self._make_defaults is not None:
1994                         for i, cfg in enumerate(self._make_defaults):
1995                                 if not cfg:
1996                                         self.make_defaults_use.append("")
1997                                         continue
1998                                 use = cfg.get("USE", "")
1999                                 expand_use = []
2000                                 for k in use_expand_dict:
2001                                         v = cfg.get(k)
2002                                         if v is None:
2003                                                 continue
2004                                         prefix = k.lower() + '_'
2005                                         if k in myincrementals:
2006                                                 for x in v.split():
2007                                                         if x[:1] == '-':
2008                                                                 expand_use.append('-' + prefix + x[1:])
2009                                                         else:
2010                                                                 expand_use.append(prefix + x)
2011                                         else:
2012                                                 for x in v.split():
2013                                                         expand_use.append(prefix + x)
2014                                 if expand_use:
2015                                         expand_use.append(use)
2016                                         use  = ' '.join(expand_use)
2017                                 self.make_defaults_use.append(use)
2018                         self.make_defaults_use = tuple(self.make_defaults_use)
2019                         configdict_defaults['USE'] = ' '.join(
2020                                 stack_lists([x.split() for x in self.make_defaults_use]))
2021                         # Set to None so this code only runs once.
2022                         self._make_defaults = None
2023
2024                 if not self.uvlist:
2025                         for x in self["USE_ORDER"].split(":"):
2026                                 if x in self.configdict:
2027                                         self.uvlist.append(self.configdict[x])
2028                         self.uvlist.reverse()
2029
2030                 # For optimal performance, use slice
2031                 # comparison instead of startswith().
2032                 iuse = self.configdict["pkg"].get("IUSE")
2033                 if iuse is not None:
2034                         iuse = [x.lstrip("+-") for x in iuse.split()]
2035                 myflags = set()
2036                 for curdb in self.uvlist:
2037                         cur_use_expand = [x for x in use_expand if x in curdb]
2038                         mysplit = curdb.get("USE", "").split()
2039                         if not mysplit and not cur_use_expand:
2040                                 continue
2041                         for x in mysplit:
2042                                 if x == "-*":
2043                                         myflags.clear()
2044                                         continue
2045
2046                                 if x[0] == "+":
2047                                         writemsg(colorize("BAD", _("USE flags should not start "
2048                                                 "with a '+': %s\n") % x), noiselevel=-1)
2049                                         x = x[1:]
2050                                         if not x:
2051                                                 continue
2052
2053                                 if x[0] == "-":
2054                                         if x[-2:] == '_*':
2055                                                 prefix = x[1:-1]
2056                                                 prefix_len = len(prefix)
2057                                                 myflags.difference_update(
2058                                                         [y for y in myflags if \
2059                                                         y[:prefix_len] == prefix])
2060                                         myflags.discard(x[1:])
2061                                         continue
2062
2063                                 if iuse is not None and x[-2:] == '_*':
2064                                         # Expand wildcards here, so that cases like
2065                                         # USE="linguas_* -linguas_en_US" work correctly.
2066                                         prefix = x[:-1]
2067                                         prefix_len = len(prefix)
2068                                         has_iuse = False
2069                                         for y in iuse:
2070                                                 if y[:prefix_len] == prefix:
2071                                                         has_iuse = True
2072                                                         myflags.add(y)
2073                                         if not has_iuse:
2074                                                 # There are no matching IUSE, so allow the
2075                                                 # wildcard to pass through. This allows
2076                                                 # linguas_* to trigger unset LINGUAS in
2077                                                 # cases when no linguas_ flags are in IUSE.
2078                                                 myflags.add(x)
2079                                 else:
2080                                         myflags.add(x)
2081
2082                         if curdb is configdict_defaults:
2083                                 # USE_EXPAND flags from make.defaults are handled
2084                                 # earlier, in order to provide useful incremental
2085                                 # behavior (for sub-profiles).
2086                                 continue
2087
2088                         for var in cur_use_expand:
2089                                 var_lower = var.lower()
2090                                 is_not_incremental = var not in myincrementals
2091                                 if is_not_incremental:
2092                                         prefix = var_lower + "_"
2093                                         prefix_len = len(prefix)
2094                                         for x in list(myflags):
2095                                                 if x[:prefix_len] == prefix:
2096                                                         myflags.remove(x)
2097                                 for x in curdb[var].split():
2098                                         if x[0] == "+":
2099                                                 if is_not_incremental:
2100                                                         writemsg(colorize("BAD", _("Invalid '+' "
2101                                                                 "operator in non-incremental variable "
2102                                                                  "'%s': '%s'\n") % (var, x)), noiselevel=-1)
2103                                                         continue
2104                                                 else:
2105                                                         writemsg(colorize("BAD", _("Invalid '+' "
2106                                                                 "operator in incremental variable "
2107                                                                  "'%s': '%s'\n") % (var, x)), noiselevel=-1)
2108                                                 x = x[1:]
2109                                         if x[0] == "-":
2110                                                 if is_not_incremental:
2111                                                         writemsg(colorize("BAD", _("Invalid '-' "
2112                                                                 "operator in non-incremental variable "
2113                                                                  "'%s': '%s'\n") % (var, x)), noiselevel=-1)
2114                                                         continue
2115                                                 myflags.discard(var_lower + "_" + x[1:])
2116                                                 continue
2117                                         myflags.add(var_lower + "_" + x)
2118
2119                 if hasattr(self, "features"):
2120                         self.features._features.clear()
2121                 else:
2122                         self.features = features_set(self)
2123                 self.features._features.update(self.get('FEATURES', '').split())
2124                 self.features._sync_env_var()
2125                 self.features._validate()
2126
2127                 myflags.update(self.useforce)
2128                 arch = self.configdict["defaults"].get("ARCH")
2129                 if arch:
2130                         myflags.add(arch)
2131
2132                 myflags.difference_update(self.usemask)
2133                 self.configlist[-1]["USE"]= " ".join(sorted(myflags))
2134
2135                 if self.mycpv is None:
2136                         # Generate global USE_EXPAND variables settings that are
2137                         # consistent with USE, for display by emerge --info. For
2138                         # package instances, these are instead generated via
2139                         # setcpv().
2140                         for k in use_expand:
2141                                 prefix = k.lower() + '_'
2142                                 prefix_len = len(prefix)
2143                                 expand_flags = set( x[prefix_len:] for x in myflags \
2144                                         if x[:prefix_len] == prefix )
2145                                 var_split = use_expand_dict.get(k, '').split()
2146                                 var_split = [ x for x in var_split if x in expand_flags ]
2147                                 var_split.extend(sorted(expand_flags.difference(var_split)))
2148                                 if var_split:
2149                                         self.configlist[-1][k] = ' '.join(var_split)
2150                                 elif k in self:
2151                                         self.configlist[-1][k] = ''
2152
2153         @property
2154         def virts_p(self):
2155                 warnings.warn("portage config.virts_p attribute " + \
2156                         "is deprecated, use config.get_virts_p()",
2157                         DeprecationWarning, stacklevel=2)
2158                 return self.get_virts_p()
2159
2160         @property
2161         def virtuals(self):
2162                 warnings.warn("portage config.virtuals attribute " + \
2163                         "is deprecated, use config.getvirtuals()",
2164                         DeprecationWarning, stacklevel=2)
2165                 return self.getvirtuals()
2166
2167         def get_virts_p(self):
2168                 # Ensure that we don't trigger the _treeVirtuals
2169                 # assertion in VirtualsManager._compile_virtuals().
2170                 self.getvirtuals()
2171                 return self._virtuals_manager.get_virts_p()
2172
2173         def getvirtuals(self):
2174                 if self._virtuals_manager._treeVirtuals is None:
2175                         #Hack around the fact that VirtualsManager needs a vartree
2176                         #and vartree needs a config instance.
2177                         #This code should be part of VirtualsManager.getvirtuals().
2178                         if self.local_config:
2179                                 temp_vartree = vartree(settings=self)
2180                                 self._virtuals_manager._populate_treeVirtuals(temp_vartree)
2181                         else:
2182                                 self._virtuals_manager._treeVirtuals = {}
2183
2184                 return self._virtuals_manager.getvirtuals()
2185
2186         def _populate_treeVirtuals_if_needed(self, vartree):
2187                 """Reduce the provides into a list by CP."""
2188                 if self._virtuals_manager._treeVirtuals is None:
2189                         if self.local_config:
2190                                 self._virtuals_manager._populate_treeVirtuals(vartree)
2191                         else:
2192                                 self._virtuals_manager._treeVirtuals = {}
2193
2194         def __delitem__(self,mykey):
2195                 self.pop(mykey)
2196
2197         def __getitem__(self, key):
2198                 try:
2199                         return self._getitem(key)
2200                 except KeyError:
2201                         return '' # for backward compat, don't raise KeyError
2202
2203         def _getitem(self, mykey):
2204
2205                 if mykey in self._constant_keys:
2206                         # These two point to temporary values when
2207                         # portage plans to update itself.
2208                         if mykey == "PORTAGE_BIN_PATH":
2209                                 return portage._bin_path
2210                         elif mykey == "PORTAGE_PYM_PATH":
2211                                 return portage._pym_path
2212
2213                         elif mykey == "PORTAGE_GID":
2214                                 return _unicode_decode(str(portage_gid))
2215
2216                 for d in self.lookuplist:
2217                         try:
2218                                 return d[mykey]
2219                         except KeyError:
2220                                 pass
2221
2222                 raise KeyError(mykey)
2223
2224         def get(self, k, x=None):
2225                 try:
2226                         return self._getitem(k)
2227                 except KeyError:
2228                         return x
2229
2230         def pop(self, key, *args):
2231                 self.modifying()
2232                 if len(args) > 1:
2233                         raise TypeError(
2234                                 "pop expected at most 2 arguments, got " + \
2235                                 repr(1 + len(args)))
2236                 v = self
2237                 for d in reversed(self.lookuplist):
2238                         v = d.pop(key, v)
2239                 if v is self:
2240                         if args:
2241                                 return args[0]
2242                         raise KeyError(key)
2243                 return v
2244
2245         def __contains__(self, mykey):
2246                 """Called to implement membership test operators (in and not in)."""
2247                 try:
2248                          self._getitem(mykey)
2249                 except KeyError:
2250                         return False
2251                 else:
2252                         return True
2253
2254         def setdefault(self, k, x=None):
2255                 v = self.get(k)
2256                 if v is not None:
2257                         return v
2258                 else:
2259                         self[k] = x
2260                         return x
2261
2262         def keys(self):
2263                 return list(self)
2264
2265         def __iter__(self):
2266                 keys = set()
2267                 keys.update(self._constant_keys)
2268                 for d in self.lookuplist:
2269                         keys.update(d)
2270                 return iter(keys)
2271
2272         def iterkeys(self):
2273                 return iter(self)
2274
2275         def iteritems(self):
2276                 for k in self:
2277                         yield (k, self._getitem(k))
2278
2279         def items(self):
2280                 return list(self.iteritems())
2281
2282         def __setitem__(self,mykey,myvalue):
2283                 "set a value; will be thrown away at reset() time"
2284                 if not isinstance(myvalue, basestring):
2285                         raise ValueError("Invalid type being used as a value: '%s': '%s'" % (str(mykey),str(myvalue)))
2286
2287                 # Avoid potential UnicodeDecodeError exceptions later.
2288                 mykey = _unicode_decode(mykey)
2289                 myvalue = _unicode_decode(myvalue)
2290
2291                 self.modifying()
2292                 self.modifiedkeys.append(mykey)
2293                 self.configdict["env"][mykey]=myvalue
2294
2295         def environ(self):
2296                 "return our locally-maintained environment"
2297                 mydict={}
2298                 environ_filter = self._environ_filter
2299
2300                 eapi = self.get('EAPI')
2301                 phase = self.get('EBUILD_PHASE')
2302                 filter_calling_env = False
2303                 if self.mycpv is not None and \
2304                         phase not in ('clean', 'cleanrm', 'depend', 'fetch'):
2305                         temp_dir = self.get('T')
2306                         if temp_dir is not None and \
2307                                 os.path.exists(os.path.join(temp_dir, 'environment')):
2308                                 filter_calling_env = True
2309
2310                 environ_whitelist = self._environ_whitelist
2311                 for x in self:
2312                         if x in environ_filter:
2313                                 continue
2314                         myvalue = self[x]
2315                         if not isinstance(myvalue, basestring):
2316                                 writemsg(_("!!! Non-string value in config: %s=%s\n") % \
2317                                         (x, myvalue), noiselevel=-1)
2318                                 continue
2319                         if filter_calling_env and \
2320                                 x not in environ_whitelist and \
2321                                 not self._environ_whitelist_re.match(x):
2322                                 # Do not allow anything to leak into the ebuild
2323                                 # environment unless it is explicitly whitelisted.
2324                                 # This ensures that variables unset by the ebuild
2325                                 # remain unset (bug #189417).
2326                                 continue
2327                         mydict[x] = myvalue
2328                 if "HOME" not in mydict and "BUILD_PREFIX" in mydict:
2329                         writemsg("*** HOME not set. Setting to "+mydict["BUILD_PREFIX"]+"\n")
2330                         mydict["HOME"]=mydict["BUILD_PREFIX"][:]
2331
2332                 if filter_calling_env:
2333                         if phase:
2334                                 whitelist = []
2335                                 if "rpm" == phase:
2336                                         whitelist.append("RPMDIR")
2337                                 for k in whitelist:
2338                                         v = self.get(k)
2339                                         if v is not None:
2340                                                 mydict[k] = v
2341
2342                 # At some point we may want to stop exporting FEATURES to the ebuild
2343                 # environment, in order to prevent ebuilds from abusing it. In
2344                 # preparation for that, export it as PORTAGE_FEATURES so that bashrc
2345                 # users will be able to migrate any FEATURES conditional code to
2346                 # use this alternative variable.
2347                 mydict["PORTAGE_FEATURES"] = self["FEATURES"]
2348
2349                 # Filtered by IUSE and implicit IUSE.
2350                 mydict["USE"] = self.get("PORTAGE_USE", "")
2351
2352                 # Don't export AA to the ebuild environment in EAPIs that forbid it
2353                 if not eapi_exports_AA(eapi):
2354                         mydict.pop("AA", None)
2355
2356                 if not eapi_exports_merge_type(eapi):
2357                         mydict.pop("MERGE_TYPE", None)
2358
2359                 # Prefix variables are supported beginning with EAPI 3, or when
2360                 # force-prefix is in FEATURES, since older EAPIs would otherwise be
2361                 # useless with prefix configurations. This brings compatibility with
2362                 # the prefix branch of portage, which also supports EPREFIX for all
2363                 # EAPIs (for obvious reasons).
2364                 if phase == 'depend' or \
2365                         ('force-prefix' not in self.features and
2366                         eapi is not None and not eapi_supports_prefix(eapi)):
2367                         mydict.pop("ED", None)
2368                         mydict.pop("EPREFIX", None)
2369                         mydict.pop("EROOT", None)
2370
2371                 if phase == 'depend':
2372                         mydict.pop('FILESDIR', None)
2373
2374                 if phase not in ("pretend", "setup", "preinst", "postinst") or \
2375                         not eapi_exports_replace_vars(eapi):
2376                         mydict.pop("REPLACING_VERSIONS", None)
2377
2378                 if phase not in ("prerm", "postrm") or \
2379                         not eapi_exports_replace_vars(eapi):
2380                         mydict.pop("REPLACED_BY_VERSION", None)
2381
2382                 return mydict
2383
2384         def thirdpartymirrors(self):
2385                 if getattr(self, "_thirdpartymirrors", None) is None:
2386                         profileroots = [os.path.join(self["PORTDIR"], "profiles")]
2387                         for x in shlex_split(self.get("PORTDIR_OVERLAY", "")):
2388                                 profileroots.insert(0, os.path.join(x, "profiles"))
2389                         thirdparty_lists = [grabdict(os.path.join(x, "thirdpartymirrors")) for x in profileroots]
2390                         self._thirdpartymirrors = stack_dictlist(thirdparty_lists, incremental=True)
2391                 return self._thirdpartymirrors
2392
2393         def archlist(self):
2394                 _archlist = []
2395                 for myarch in self["PORTAGE_ARCHLIST"].split():
2396                         _archlist.append(myarch)
2397                         _archlist.append("~" + myarch)
2398                 return _archlist
2399
2400         def selinux_enabled(self):
2401                 if getattr(self, "_selinux_enabled", None) is None:
2402                         self._selinux_enabled = 0
2403                         if "selinux" in self["USE"].split():
2404                                 if selinux:
2405                                         if selinux.is_selinux_enabled() == 1:
2406                                                 self._selinux_enabled = 1
2407                                         else:
2408                                                 self._selinux_enabled = 0
2409                                 else:
2410                                         writemsg(_("!!! SELinux module not found. Please verify that it was installed.\n"),
2411                                                 noiselevel=-1)
2412                                         self._selinux_enabled = 0
2413
2414                 return self._selinux_enabled
2415
2416         if sys.hexversion >= 0x3000000:
2417                 keys = __iter__
2418                 items = iteritems