1 # portage.py -- core Portage functionality
2 # Copyright 1998-2013 Gentoo Foundation
3 # Distributed under the terms of the GNU General Public License v2
5 from __future__ import unicode_literals
9 # ===========================================================================
10 # START OF IMPORTS -- START OF IMPORTS -- START OF IMPORTS -- START OF IMPORT
11 # ===========================================================================
16 if not hasattr(errno, 'ESTALE'):
17 # ESTALE may not be defined on some systems, such as interix.
23 # Temporarily delete these imports, to ensure that only the
24 # wrapped versions are imported by portage internals.
30 except ImportError as e:
31 sys.stderr.write("\n\n")
32 sys.stderr.write("!!! Failed to complete python imports. These are internal modules for\n")
33 sys.stderr.write("!!! python and failure here indicates that you have a problem with python\n")
34 sys.stderr.write("!!! itself and thus portage is not able to continue processing.\n\n")
36 sys.stderr.write("!!! You might consider starting python with verbose flags to see what has\n")
37 sys.stderr.write("!!! gone wrong. Here is the information we got for this exception:\n")
38 sys.stderr.write(" "+str(e)+"\n\n");
43 import portage.proxy.lazyimport
44 import portage.proxy as proxy
45 proxy.lazyimport.lazyimport(globals(),
46 'portage.cache.cache_errors:CacheError',
48 'portage.checksum:perform_checksum,perform_md5,prelink_capable',
51 'portage.data:lchown,ostype,portage_gid,portage_uid,secpass,' + \
52 'uid,userland,userpriv_groups,wheelgid',
54 'portage.dbapi.bintree:bindbapi,binarytree',
55 'portage.dbapi.cpv_expand:cpv_expand',
56 'portage.dbapi.dep_expand:dep_expand',
57 'portage.dbapi.porttree:close_portdbapi_caches,FetchlistDict,' + \
58 'portagetree,portdbapi',
59 'portage.dbapi.vartree:dblink,merge,unmerge,vardbapi,vartree',
60 'portage.dbapi.virtual:fakedbapi',
62 'portage.dep:best_match_to_list,dep_getcpv,dep_getkey,' + \
63 'flatten,get_operator,isjustname,isspecific,isvalidatom,' + \
64 'match_from_list,match_to_list',
65 'portage.dep.dep_check:dep_check,dep_eval,dep_wordreduce,dep_zapdeps',
66 'portage.eclass_cache',
71 'portage.locks:lockdir,lockfile,unlockdir,unlockfile',
73 'portage.manifest:Manifest',
75 'portage.output:bold,colorize',
76 'portage.package.ebuild.doebuild:doebuild,' + \
77 'doebuild_environment,spawn,spawnebuild',
78 'portage.package.ebuild.config:autouse,best_from_dict,' + \
79 'check_config_instance,config',
80 'portage.package.ebuild.deprecated_profile_check:' + \
81 'deprecated_profile_check',
82 'portage.package.ebuild.digestcheck:digestcheck',
83 'portage.package.ebuild.digestgen:digestgen',
84 'portage.package.ebuild.fetch:fetch',
85 'portage.package.ebuild.getmaskingreason:getmaskingreason',
86 'portage.package.ebuild.getmaskingstatus:getmaskingstatus',
87 'portage.package.ebuild.prepare_build_dirs:prepare_build_dirs',
89 'portage.process:atexit_register,run_exitfuncs',
90 'portage.update:dep_transform,fixdbentries,grab_updates,' + \
91 'parse_updates,update_config_files,update_dbentries,' + \
94 'portage.util:atomic_ofstream,apply_secpass_permissions,' + \
95 'apply_recursive_permissions,dump_traceback,getconfig,' + \
96 'grabdict,grabdict_package,grabfile,grabfile_package,' + \
97 'map_dictlist_vals,new_protect_filename,normalize_path,' + \
98 'pickle_read,pickle_write,stack_dictlist,stack_dicts,' + \
99 'stack_lists,unique_array,varexpand,writedict,writemsg,' + \
100 'writemsg_stdout,write_atomic',
101 'portage.util.digraph:digraph',
102 'portage.util.env_update:env_update',
103 'portage.util.ExtractKernelVersion:ExtractKernelVersion',
104 'portage.util.listdir:cacheddir,listdir',
105 'portage.util.movefile:movefile',
106 'portage.util.mtimedb:MtimeDB',
108 'portage.versions:best,catpkgsplit,catsplit,cpv_getkey,' + \
109 'cpv_getkey@getCPFromCPV,endversion_keys,' + \
110 'suffix_value@endversion,pkgcmp,pkgsplit,vercmp,ververify',
117 from collections import OrderedDict
119 proxy.lazyimport.lazyimport(globals(),
120 'portage.cache.mappings:OrderedDict')
123 from portage.const import VDB_PATH, PRIVATE_PATH, CACHE_PATH, DEPCACHE_PATH, \
124 USER_CONFIG_PATH, MODULES_FILE_PATH, CUSTOM_PROFILE_PATH, PORTAGE_BASE_PATH, \
125 PORTAGE_BIN_PATH, PORTAGE_PYM_PATH, PROFILE_PATH, LOCALE_DATA_PATH, \
126 EBUILD_SH_BINARY, SANDBOX_BINARY, BASH_BINARY, \
127 MOVE_BINARY, PRELINK_BINARY, WORLD_FILE, MAKE_CONF_FILE, MAKE_DEFAULTS_FILE, \
128 DEPRECATED_PROFILE_FILE, USER_VIRTUALS_FILE, EBUILD_SH_ENV_FILE, \
129 INVALID_ENV_FILE, CUSTOM_MIRRORS_FILE, CONFIG_MEMORY_FILE,\
130 INCREMENTALS, EAPI, MISC_SH_BINARY, REPO_NAME_LOC, REPO_NAME_FILE
132 except ImportError as e:
133 sys.stderr.write("\n\n")
134 sys.stderr.write("!!! Failed to complete portage imports. There are internal modules for\n")
135 sys.stderr.write("!!! portage and failure here indicates that you have a problem with your\n")
136 sys.stderr.write("!!! installation of portage. Please try a rescue portage located in the\n")
137 sys.stderr.write("!!! portage tree under '/usr/portage/sys-apps/portage/files/' (default).\n")
138 sys.stderr.write("!!! There is a README.RESCUE file that details the steps required to perform\n")
139 sys.stderr.write("!!! a recovery of portage.\n")
140 sys.stderr.write(" "+str(e)+"\n\n")
143 if sys.hexversion >= 0x3000000:
147 # We use utf_8 encoding everywhere. Previously, we used
148 # sys.getfilesystemencoding() for the 'merge' encoding, but that had
151 # 1) If the locale is ever changed then it can cause orphan files due
152 # to changed character set translation.
154 # 2) Ebuilds typically install files with utf_8 encoded file names,
155 # and then portage would be forced to rename those files to match
156 # sys.getfilesystemencoding(), possibly breaking things.
158 # 3) Automatic translation between encodings can lead to nonsensical
159 # file names when the source encoding is unknown by portage.
161 # 4) It's inconvenient for ebuilds to convert the encodings of file
162 # names to match the current locale, and upstreams typically encode
163 # file names with utf_8 encoding.
165 # So, instead of relying on sys.getfilesystemencoding(), we avoid the above
166 # problems by using a constant utf_8 'merge' encoding for all locales, as
167 # discussed in bug #382199 and bug #381509.
172 'repo.content' : 'utf_8',
176 if sys.hexversion >= 0x3000000:
178 def _decode_argv(argv):
179 # With Python 3, the surrogateescape encoding error handler makes it
180 # possible to access the original argv bytes, which can be useful
181 # if their actual encoding does no match the filesystem encoding.
182 fs_encoding = sys.getfilesystemencoding()
183 return [_unicode_decode(x.encode(fs_encoding, 'surrogateescape'))
186 def _unicode_encode(s, encoding=_encodings['content'], errors='backslashreplace'):
187 if isinstance(s, str):
188 s = s.encode(encoding, errors)
191 def _unicode_decode(s, encoding=_encodings['content'], errors='replace'):
192 if isinstance(s, bytes):
193 s = str(s, encoding=encoding, errors=errors)
196 _native_string = _unicode_decode
199 def _decode_argv(argv):
200 return [_unicode_decode(x) for x in argv]
202 def _unicode_encode(s, encoding=_encodings['content'], errors='backslashreplace'):
203 if isinstance(s, unicode):
204 s = s.encode(encoding, errors)
207 def _unicode_decode(s, encoding=_encodings['content'], errors='replace'):
208 if isinstance(s, bytes):
209 s = unicode(s, encoding=encoding, errors=errors)
212 _native_string = _unicode_encode
214 if sys.hexversion >= 0x20605f0:
215 def _native_kwargs(kwargs):
218 # Avoid "TypeError: keywords must be strings" issue triggered
219 # by unicode_literals: http://bugs.python.org/issue4978
220 def _native_kwargs(kwargs):
221 return dict((_native_string(k), v) for k, v in kwargs.iteritems())
223 class _unicode_func_wrapper(object):
225 Wraps a function, converts arguments from unicode to bytes,
226 and return values to unicode from bytes. Function calls
227 will raise UnicodeEncodeError if an argument fails to be
228 encoded with the required encoding. Return values that
229 are single strings are decoded with errors='replace'. Return
230 values that are lists of strings are decoded with errors='strict'
231 and elements that fail to be decoded are omitted from the returned
234 __slots__ = ('_func', '_encoding')
236 def __init__(self, func, encoding=_encodings['fs']):
238 self._encoding = encoding
240 def _process_args(self, args, kwargs):
242 encoding = self._encoding
243 wrapped_args = [_unicode_encode(x, encoding=encoding, errors='strict')
246 wrapped_kwargs = dict(
247 (k, _unicode_encode(v, encoding=encoding, errors='strict'))
248 for k, v in kwargs.items())
252 return (wrapped_args, wrapped_kwargs)
254 def __call__(self, *args, **kwargs):
256 encoding = self._encoding
257 wrapped_args, wrapped_kwargs = self._process_args(args, kwargs)
259 rval = self._func(*wrapped_args, **wrapped_kwargs)
261 # Don't use isinstance() since we don't want to convert subclasses
262 # of tuple such as posix.stat_result in Python >=3.2.
263 if rval.__class__ in (list, tuple):
267 x = _unicode_decode(x, encoding=encoding, errors='strict')
268 except UnicodeDecodeError:
271 decoded_rval.append(x)
273 if isinstance(rval, tuple):
274 rval = tuple(decoded_rval)
278 rval = _unicode_decode(rval, encoding=encoding, errors='replace')
282 class _unicode_module_wrapper(object):
284 Wraps a module and wraps all functions with _unicode_func_wrapper.
286 __slots__ = ('_mod', '_encoding', '_overrides', '_cache')
288 def __init__(self, mod, encoding=_encodings['fs'], overrides=None, cache=True):
289 object.__setattr__(self, '_mod', mod)
290 object.__setattr__(self, '_encoding', encoding)
291 object.__setattr__(self, '_overrides', overrides)
296 object.__setattr__(self, '_cache', cache)
298 def __getattribute__(self, attr):
299 cache = object.__getattribute__(self, '_cache')
300 if cache is not None:
301 result = cache.get(attr)
302 if result is not None:
304 result = getattr(object.__getattribute__(self, '_mod'), attr)
305 encoding = object.__getattribute__(self, '_encoding')
306 overrides = object.__getattribute__(self, '_overrides')
308 if overrides is not None:
309 override = overrides.get(id(result))
310 if override is not None:
312 elif isinstance(result, type):
314 elif type(result) is types.ModuleType:
315 result = _unicode_module_wrapper(result,
316 encoding=encoding, overrides=overrides)
317 elif hasattr(result, '__call__'):
318 result = _unicode_func_wrapper(result, encoding=encoding)
319 if cache is not None:
325 id(_os.fdopen) : _os.fdopen,
326 id(_os.popen) : _os.popen,
327 id(_os.read) : _os.read,
328 id(_os.system) : _os.system,
333 _os_overrides[id(_os.mkfifo)] = _os.mkfifo
334 except AttributeError:
337 if hasattr(_os, 'statvfs'):
338 _os_overrides[id(_os.statvfs)] = _os.statvfs
340 os = _unicode_module_wrapper(_os, overrides=_os_overrides,
341 encoding=_encodings['fs'])
342 _os_merge = _unicode_module_wrapper(_os,
343 encoding=_encodings['merge'], overrides=_os_overrides)
345 import shutil as _shutil
346 shutil = _unicode_module_wrapper(_shutil, encoding=_encodings['fs'])
348 # Imports below this point rely on the above unicode wrapper definitions.
350 __import__('selinux')
351 import portage._selinux
352 selinux = _unicode_module_wrapper(_selinux,
353 encoding=_encodings['fs'])
354 _selinux_merge = _unicode_module_wrapper(_selinux,
355 encoding=_encodings['merge'])
356 except (ImportError, OSError) as e:
357 if isinstance(e, OSError):
358 sys.stderr.write("!!! SELinux not loaded: %s\n" % str(e))
362 _selinux_merge = None
364 # ===========================================================================
365 # END OF IMPORTS -- END OF IMPORTS -- END OF IMPORTS -- END OF IMPORTS -- END
366 # ===========================================================================
368 _python_interpreter = os.path.realpath(sys.executable)
369 _bin_path = PORTAGE_BIN_PATH
370 _pym_path = PORTAGE_PYM_PATH
371 _working_copy = VERSION == "HEAD"
373 # Api consumers included in portage should set this to True.
374 _internal_caller = False
376 _sync_disabled_warnings = False
380 Buggy code in python's multiprocessing/process.py closes sys.stdin
381 and reassigns it to open(os.devnull), but fails to update the
382 corresponding __stdin__ reference. So, detect that case and handle
385 if not sys.__stdin__.closed:
389 _shell_quote_re = re.compile(r"[\s><=*\\\"'$`]")
393 Quote a string in double-quotes and use backslashes to
394 escape any backslashes, double-quotes, dollar signs, or
395 backquotes in the string.
397 if _shell_quote_re.search(s) is None:
399 for letter in "\\\"$`":
401 s = s.replace(letter, "\\" + letter)
406 if platform.system() in ('FreeBSD',):
408 class bsd_chflags(object):
411 def chflags(cls, path, flags, opts=""):
415 cmd.append('%o' % (flags,))
418 if sys.hexversion < 0x3020000 and sys.hexversion >= 0x3000000:
419 # Python 3.1 _execvp throws TypeError for non-absolute executable
420 # path passed as bytes (see http://bugs.python.org/issue8513).
421 fullname = process.find_binary(cmd[0])
423 raise exception.CommandNotFound(cmd[0])
426 encoding = _encodings['fs']
427 cmd = [_unicode_encode(x, encoding=encoding, errors='strict')
429 proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
430 stderr=subprocess.STDOUT)
431 output = proc.communicate()[0]
433 if os.WIFEXITED(status) and os.WEXITSTATUS(status) == os.EX_OK:
435 # Try to generate an ENOENT error if appropriate.
437 _os_merge.lstat(path)
440 # Make sure the binary exists.
441 if not portage.process.find_binary('chflags'):
442 raise portage.exception.CommandNotFound('chflags')
443 # Now we're not sure exactly why it failed or what
444 # the real errno was, so just report EPERM.
445 output = _unicode_decode(output, encoding=encoding)
446 e = OSError(errno.EPERM, output)
447 e.errno = errno.EPERM
453 def lchflags(cls, path, flags):
454 return cls.chflags(path, flags, opts='-h')
457 modname = ".".join(name.split(".")[:-1])
458 mod = __import__(modname)
459 components = name.split('.')
460 for comp in components[1:]:
461 mod = getattr(mod, comp)
465 "this fixes situations where the current directory doesn't exist"
468 except OSError: #dir doesn't exist
473 def abssymlink(symlink, target=None):
475 This reads symlinks, resolving the relative symlinks,
476 and returning the absolute.
477 @param symlink: path of symlink (must be absolute)
478 @param target: the target of the symlink (as returned
481 @return: the absolute path of the symlink target
483 if target is not None:
486 mylink = os.readlink(symlink)
488 mydir=os.path.dirname(symlink)
489 mylink=mydir+"/"+mylink
490 return os.path.normpath(mylink)
492 _doebuild_manifest_exempt_depend = 0
494 _testing_eapis = frozenset(["4-python", "4-slot-abi", "5-progress", "5-hdepend"])
495 _deprecated_eapis = frozenset(["4_pre1", "3_pre2", "3_pre1", "5_pre1", "5_pre2"])
496 _supported_eapis = frozenset([str(x) for x in range(portage.const.EAPI)] + list(_testing_eapis) + list(_deprecated_eapis))
498 def _eapi_is_deprecated(eapi):
499 return eapi in _deprecated_eapis
501 def eapi_is_supported(eapi):
502 if not isinstance(eapi, basestring):
503 # Only call str() when necessary since with python2 it
504 # can trigger UnicodeEncodeError if EAPI is corrupt.
508 if _eapi_is_deprecated(eapi):
511 if eapi in _testing_eapis:
520 return eapi <= portage.const.EAPI
522 # This pattern is specified by PMS section 7.3.1.
523 _pms_eapi_re = re.compile(r"^[ \t]*EAPI=(['\"]?)([A-Za-z0-9+_.-]*)\1[ \t]*([ \t]#.*)?$")
524 _comment_or_blank_line = re.compile(r"^\s*(#.*)?$")
526 def _parse_eapi_ebuild_head(f):
532 m = _comment_or_blank_line.match(line)
535 m = _pms_eapi_re.match(line)
540 return (eapi, eapi_lineno)
542 def _movefile(src, dest, **kwargs):
543 """Calls movefile and raises a PortageException if an error occurs."""
544 if movefile(src, dest, **kwargs) is None:
545 raise portage.exception.PortageException(
546 "mv '%s' '%s'" % (src, dest))
549 'DEPEND', 'RDEPEND', 'SLOT', 'SRC_URI',
550 'RESTRICT', 'HOMEPAGE', 'LICENSE', 'DESCRIPTION',
551 'KEYWORDS', 'INHERITED', 'IUSE', 'REQUIRED_USE',
552 'PDEPEND', 'PROVIDE', 'EAPI',
553 'PROPERTIES', 'DEFINED_PHASES', 'HDEPEND', 'UNUSED_04',
554 'UNUSED_03', 'UNUSED_02', 'UNUSED_01',
556 auxdbkeylen=len(auxdbkeys)
561 class _trees_dict(dict):
562 __slots__ = ('_running_eroot', '_target_eroot',)
563 def __init__(self, *pargs, **kargs):
564 dict.__init__(self, *pargs, **kargs)
565 self._running_eroot = None
566 self._target_eroot = None
568 def create_trees(config_root=None, target_root=None, trees=None, env=None,
572 trees = _trees_dict()
573 elif not isinstance(trees, _trees_dict):
574 # caller passed a normal dict or something,
575 # but we need a _trees_dict instance
576 trees = _trees_dict(trees)
581 settings = config(config_root=config_root, target_root=target_root,
582 env=env, eprefix=eprefix)
585 trees._target_eroot = settings['EROOT']
586 myroots = [(settings['EROOT'], settings)]
587 if settings["ROOT"] == "/" and settings["EPREFIX"] == const.EPREFIX:
588 trees._running_eroot = trees._target_eroot
591 # When ROOT != "/" we only want overrides from the calling
592 # environment to apply to the config that's associated
593 # with ROOT != "/", so pass a nearly empty dict for the env parameter.
595 for k in ('PATH', 'PORTAGE_GRPNAME', 'PORTAGE_REPOSITORIES', 'PORTAGE_USERNAME',
596 'PYTHONPATH', 'SSH_AGENT_PID', 'SSH_AUTH_SOCK', 'TERM',
597 'ftp_proxy', 'http_proxy', 'no_proxy',
598 '__PORTAGE_TEST_HARDLINK_LOCKS'):
602 settings = config(config_root=None, target_root="/",
603 env=clean_env, eprefix=None)
605 trees._running_eroot = settings['EROOT']
606 myroots.append((settings['EROOT'], settings))
608 for myroot, mysettings in myroots:
609 trees[myroot] = portage.util.LazyItemsDict(trees.get(myroot, {}))
610 trees[myroot].addLazySingleton("virtuals", mysettings.getvirtuals)
611 trees[myroot].addLazySingleton(
612 "vartree", vartree, categories=mysettings.categories,
614 trees[myroot].addLazySingleton("porttree",
615 portagetree, settings=mysettings)
616 trees[myroot].addLazySingleton("bintree",
617 binarytree, pkgdir=mysettings["PKGDIR"], settings=mysettings)
620 if VERSION == 'HEAD':
621 class _LazyVersion(proxy.objectproxy.ObjectProxy):
622 def _get_target(self):
624 if VERSION is not self:
626 if os.path.isdir(os.path.join(PORTAGE_BASE_PATH, '.git')):
627 encoding = _encodings['fs']
628 cmd = [BASH_BINARY, "-c", ("cd %s ; git describe --tags || exit $? ; " + \
629 "if [ -n \"`git diff-index --name-only --diff-filter=M HEAD`\" ] ; " + \
630 "then echo modified ; git rev-list --format=%%ct -n 1 HEAD ; fi ; " + \
631 "exit 0") % _shell_quote(PORTAGE_BASE_PATH)]
632 cmd = [_unicode_encode(x, encoding=encoding, errors='strict')
634 proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
635 stderr=subprocess.STDOUT)
636 output = _unicode_decode(proc.communicate()[0], encoding=encoding)
638 if os.WIFEXITED(status) and os.WEXITSTATUS(status) == os.EX_OK:
639 output_lines = output.splitlines()
641 version_split = output_lines[0].split('-')
643 VERSION = version_split[0].lstrip('v')
645 if len(version_split) > 1:
647 VERSION = "%s_p%s" %(VERSION, version_split[1])
648 if len(output_lines) > 1 and output_lines[1] == 'modified':
649 head_timestamp = None
650 if len(output_lines) > 3:
652 head_timestamp = long(output_lines[3])
655 timestamp = long(time.time())
656 if head_timestamp is not None and timestamp > head_timestamp:
657 timestamp = timestamp - head_timestamp
659 VERSION = "%s_p0" % (VERSION,)
660 VERSION = "%s_p%d" % (VERSION, timestamp)
664 VERSION = _LazyVersion()
666 _legacy_global_var_names = ("archlist", "db", "features",
667 "groups", "mtimedb", "mtimedbfile", "pkglines",
668 "portdb", "profiledir", "root", "selinux_enabled",
669 "settings", "thirdpartymirrors")
671 def _reset_legacy_globals():
673 global _legacy_globals_constructed
674 _legacy_globals_constructed = set()
675 for k in _legacy_global_var_names:
676 globals()[k] = _LegacyGlobalProxy(k)
678 class _LegacyGlobalProxy(proxy.objectproxy.ObjectProxy):
680 __slots__ = ('_name',)
682 def __init__(self, name):
683 proxy.objectproxy.ObjectProxy.__init__(self)
684 object.__setattr__(self, '_name', name)
686 def _get_target(self):
687 name = object.__getattribute__(self, '_name')
688 from portage._legacy_globals import _get_legacy_global
689 return _get_legacy_global(name)
691 _reset_legacy_globals()
693 def _disable_legacy_globals():
695 This deletes the ObjectProxy instances that are used
696 for lazy initialization of legacy global variables.
697 The purpose of deleting them is to prevent new code
698 from referencing these deprecated variables.
700 global _legacy_global_var_names
701 for k in _legacy_global_var_names:
702 globals().pop(k, None)