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