| Contains all the patches committed to portage_tool on top of 2.2.12: |
| |
| * make.defaults: negative incrementals in USE_EXPAND (530222) |
| * fs_template._ensure_dirs: handle EEXIST (529120) |
| * flat_hash: Fix race condition in _setitem. |
| * Add separatedebug feature |
| * package.bashrc: per profile, per-package bashrc mechanism |
| * Add profile-formats to profile_complex |
| * Refactor bashrc scripts sourcing |
| * Set "url" before marking the index as up to date. |
| * If a binhost file sets a TTL header, honor it. |
| * Make SYSROOT a portage variable |
| * Do not interrupt on SIGCONT |
| * Readonly detection logic should handle ROOT |
| * Remove repo_name warning |
| * Remove repos.conf |
| * Add a new portageq helper to reduce a string containing use conditionals |
| * re-order install hooks execution |
| * suppress splitdebug for .o files |
| * Commit fast-build patch to portage_tool repository. |
| * support suppressing env-update |
| * support fixing *.la |
| |
| diff --git a/Makefile b/Makefile |
| index 92ea195..babbda2 100644 |
| --- a/Makefile |
| +++ b/Makefile |
| @@ -27,7 +27,7 @@ INSMODE = 0644 |
| EXEMODE = 0755 |
| DIRMODE = 0755 |
| SYSCONFDIR_FILES = etc-update.conf dispatch-conf.conf |
| -PORTAGE_CONFDIR_FILES = make.conf.example make.globals repos.conf |
| +PORTAGE_CONFDIR_FILES = make.conf.example make.globals |
| LOGROTATE_FILES = elog-save-summary |
| BINDIR_FILES = ebuild egencache emerge emerge-webrsync \ |
| emirrordist portageq quickpkg repoman |
| diff --git a/bin/ebuild-helpers/prepstrip b/bin/ebuild-helpers/prepstrip |
| index 2ef8a1a..f37ddae 100755 |
| --- a/bin/ebuild-helpers/prepstrip |
| +++ b/bin/ebuild-helpers/prepstrip |
| @@ -350,7 +350,12 @@ do |
| elif [[ ${f} == *"SB executable"* || ${f} == *"SB shared object"* ]] ; then |
| process_elf "${x}" "${inode_link}" ${PORTAGE_STRIP_FLAGS} |
| elif [[ ${f} == *"SB relocatable"* ]] ; then |
| + # Disable splitdebug for object files as breakpad fails atm w/them. |
| + # http://crosbug.com/204974 |
| + FEATURES_splitdebug_save=${FEATURES_splitdebug} |
| + [[ ${x} != *.ko ]] && FEATURES_splitdebug=false |
| process_elf "${x}" "${inode_link}" ${SAFE_STRIP_FLAGS} |
| + FEATURES_splitdebug=${FEATURES_splitdebug_save} |
| fi |
| |
| if ${was_not_writable} ; then |
| diff --git a/bin/ebuild.sh b/bin/ebuild.sh |
| index be044e0..50909e1 100755 |
| --- a/bin/ebuild.sh |
| +++ b/bin/ebuild.sh |
| @@ -368,46 +368,71 @@ __source_all_bashrcs() { |
| # source the existing profile.bashrcs. |
| save_IFS |
| IFS=$'\n' |
| - local path_array=($PROFILE_PATHS) |
| + local bashenv_files=($PORTAGE_BASHRC_FILES) |
| restore_IFS |
| - for x in "${path_array[@]}" ; do |
| - [ -f "$x/profile.bashrc" ] && __qa_source "$x/profile.bashrc" |
| + for x in "${bashenv_files[@]}" ; do |
| + __try_source "${x}" |
| done |
| fi |
| |
| - if [ -r "${PORTAGE_BASHRC}" ] ; then |
| - if [ "$PORTAGE_DEBUG" != "1" ] || [ "${-/x/}" != "$-" ]; then |
| - source "${PORTAGE_BASHRC}" |
| - else |
| - set -x |
| - source "${PORTAGE_BASHRC}" |
| - set +x |
| - fi |
| - fi |
| + # The user's bashrc is the ONLY non-portage bit of code |
| + # that can change shopts without a QA violation. |
| + __try_source --no-qa "${PORTAGE_BASHRC}" |
| |
| if [[ $EBUILD_PHASE != depend ]] ; then |
| - # The user's bashrc is the ONLY non-portage bit of code that can |
| - # change shopts without a QA violation. |
| - for x in "${PM_EBUILD_HOOK_DIR}"/${CATEGORY}/{${PN},${PN}:${SLOT%/*},${P},${PF}}; do |
| - if [ -r "${x}" ]; then |
| - # If $- contains x, then tracing has already been enabled |
| - # elsewhere for some reason. We preserve it's state so as |
| - # not to interfere. |
| - if [ "$PORTAGE_DEBUG" != "1" ] || [ "${-/x/}" != "$-" ]; then |
| - source "${x}" |
| - else |
| - set -x |
| - source "${x}" |
| - set +x |
| - fi |
| - fi |
| - done |
| + __source_env_files --no-qa "${PM_EBUILD_HOOK_DIR}" |
| fi |
| |
| [ ! -z "${OCC}" ] && export CC="${OCC}" |
| [ ! -z "${OCXX}" ] && export CXX="${OCXX}" |
| } |
| |
| +# @FUNCTION: __source_env_files |
| +# @USAGE: [--no-qa] <ENV_DIRECTORY> |
| +# @DESCRIPTION: |
| +# Source the files relevant to the current package from the given path. |
| +# If --no-qa is specified, use source instead of __qa_source to source the |
| +# files. |
| +__source_env_files() { |
| + local argument=() |
| + if [[ $1 == --no-qa ]]; then |
| + argument=( --no-qa ) |
| + shift |
| + fi |
| + for x in "${1}"/${CATEGORY}/{${PN},${PN}:${SLOT%/*},${P},${PF}}; do |
| + __try_source "${argument[@]}" "${x}" |
| + done |
| +} |
| + |
| +# @FUNCTION: __try_source |
| +# @USAGE: [--no-qa] <FILE> |
| +# @DESCRIPTION: |
| +# If the path given as argument exists, source the file while preserving |
| +# $-. |
| +# If --no-qa is specified, source the file with source instead of __qa_source. |
| +__try_source() { |
| + local qa=true |
| + if [[ $1 == --no-qa ]]; then |
| + qa=false |
| + shift |
| + fi |
| + if [[ -r "$1" ]]; then |
| + local debug_on=false |
| + if [[ "$PORTAGE_DEBUG" == "1" ]] && [[ "${-/x/}" == "$-" ]]; then |
| + debug_on=true |
| + fi |
| + $debug_on && set -x |
| + # If $- contains x, then tracing has already been enabled |
| + # elsewhere for some reason. We preserve it's state so as |
| + # not to interfere. |
| + if [[ ${qa} ]]; then |
| + source "${1}" |
| + else |
| + __qa_source "${1}" |
| + fi |
| + $debug_on && set +x |
| + fi |
| +} |
| # === === === === === === === === === === === === === === === === === === |
| # === === === === === functions end, main part begins === === === === === |
| # === === === === === === === === === === === === === === === === === === |
| diff --git a/bin/misc-functions.sh b/bin/misc-functions.sh |
| index 961738f..b0d8b18 100755 |
| --- a/bin/misc-functions.sh |
| +++ b/bin/misc-functions.sh |
| @@ -1215,6 +1215,17 @@ __dyn_package() { |
| [ -z "${PORTAGE_BINPKG_TMPFILE}" ] && \ |
| die "PORTAGE_BINPKG_TMPFILE is unset" |
| mkdir -p "${PORTAGE_BINPKG_TMPFILE%/*}" || die "mkdir failed" |
| + |
| + if has separatedebug ${FEATURES} && [[ -d "${PROOT%/}${EPREFIX}/usr/lib/debug" ]]; then |
| + [[ -z "${PORTAGE_DEBUGSYMBOLS_TMPFILE}" ]] && \ |
| + die "PORTAGE_DEBUGSYMBOLS_TMPFILE is unset" |
| + mkdir -p "${PORTAGE_DEBUGSYMBOLS_TMPFILE%/*}" || die "mkdir failed" |
| + tar $tar_options -cf - $PORTAGE_BINPKG_TAR_OPTS \ |
| + -C "${PROOT}" ".${EPREFIX}/usr/lib/debug/" | \ |
| + $PORTAGE_BZIP2_COMMAND -c > "$PORTAGE_DEBUGSYMBOLS_TMPFILE" |
| + tar_options+=" --anchored --exclude=.${EPREFIX}/usr/lib/debug" |
| + fi |
| + |
| tar $tar_options -cf - $PORTAGE_BINPKG_TAR_OPTS -C "${PROOT}" . | \ |
| $PORTAGE_BZIP2_COMMAND -c > "$PORTAGE_BINPKG_TMPFILE" |
| assert "failed to pack binary package: '$PORTAGE_BINPKG_TMPFILE'" |
| diff --git a/bin/phase-functions.sh b/bin/phase-functions.sh |
| index f39a024..5dff3bb 100644 |
| --- a/bin/phase-functions.sh |
| +++ b/bin/phase-functions.sh |
| @@ -31,7 +31,7 @@ PORTAGE_READONLY_VARS="D EBUILD EBUILD_PHASE EBUILD_PHASE_FUNC \ |
| PORTAGE_TMPDIR PORTAGE_UPDATE_ENV PORTAGE_USERNAME \ |
| PORTAGE_VERBOSE PORTAGE_WORKDIR_MODE PORTAGE_XATTR_EXCLUDE \ |
| PORTDIR \ |
| - PROFILE_PATHS REPLACING_VERSIONS REPLACED_BY_VERSION T WORKDIR \ |
| + REPLACING_VERSIONS REPLACED_BY_VERSION T WORKDIR \ |
| __PORTAGE_HELPER __PORTAGE_TEST_HARDLINK_LOCKS" |
| |
| PORTAGE_SAVED_READONLY_VARS="A CATEGORY P PF PN PR PV PVR" |
| diff --git a/bin/portageq b/bin/portageq |
| index 79818f6..332122f 100755 |
| --- a/bin/portageq |
| +++ b/bin/portageq |
| @@ -1117,6 +1117,17 @@ def pquery(parser, opts, args): |
| return os.EX_OK |
| |
| |
| +def use_reduce(argv): |
| + """<depend_string> |
| + Reduce a dependency string possibly containing use conditionals. |
| + """ |
| + |
| + if len(argv) != 1: |
| + print("ERROR: wrong number of arguments") |
| + return 2 |
| + from portage.dep import use_reduce as use_internal |
| + print(' '.join(use_internal(argv[0], uselist=os.environ['USE'].split(' ')))) |
| + |
| #----------------------------------------------------------------------------- |
| # |
| # DO NOT CHANGE CODE BEYOND THIS POINT - IT'S NOT NEEDED! |
| diff --git a/bin/save-ebuild-env.sh b/bin/save-ebuild-env.sh |
| index 98cff83..8b32bc4 100644 |
| --- a/bin/save-ebuild-env.sh |
| +++ b/bin/save-ebuild-env.sh |
| @@ -75,6 +75,7 @@ __save_ebuild_env() { |
| __ebuild_main __ebuild_phase __ebuild_phase_with_hooks \ |
| __ebuild_arg_to_phase __ebuild_phase_funcs default \ |
| __unpack_tar __unset_colors \ |
| + __source_env_files __try_source \ |
| ${QA_INTERCEPTORS} |
| |
| ___eapi_has_usex && unset -f usex |
| @@ -96,7 +97,7 @@ __save_ebuild_env() { |
| GOOD HILITE HOME \ |
| LAST_E_CMD LAST_E_LEN LD_PRELOAD MISC_FUNCTIONS_ARGS MOPREFIX \ |
| NOCOLOR NORMAL PKGDIR PKGUSE PKG_LOGDIR PKG_TMPDIR \ |
| - PORTAGE_BASHRCS_SOURCED PORTAGE_COMPRESS \ |
| + PORTAGE_BASHRC_FILES PORTAGE_BASHRCS_SOURCED PORTAGE_COMPRESS \ |
| PORTAGE_COMPRESS_EXCLUDE_SUFFIXES \ |
| PORTAGE_DOHTML_UNWARNED_SKIPPED_EXTENSIONS \ |
| PORTAGE_DOHTML_UNWARNED_SKIPPED_FILES \ |
| @@ -106,7 +107,7 @@ __save_ebuild_env() { |
| PORTAGE_SANDBOX_READ PORTAGE_SANDBOX_WRITE PREROOTPATH \ |
| QA_INTERCEPTORS \ |
| RC_DEFAULT_INDENT RC_DOT_PATTERN RC_ENDCOL RC_INDENTATION \ |
| - ROOT ROOTPATH RPMDIR TEMP TMP TMPDIR USE_EXPAND \ |
| + ROOT ROOTPATH RPMDIR SYSROOT TEMP TMP TMPDIR USE_EXPAND \ |
| WARN XARGS _RC_GET_KV_CACHE |
| |
| # user config variables |
| diff --git a/man/make.conf.5 b/man/make.conf.5 |
| index 84e894b..9050ee7 100644 |
| --- a/man/make.conf.5 |
| +++ b/man/make.conf.5 |
| @@ -506,6 +506,11 @@ Output a verbose trace of python execution to stderr when a command's |
| .B sandbox |
| Enable sandbox\-ing when running \fBemerge\fR(1) and \fBebuild\fR(1). |
| .TP |
| +.B separatedebug |
| +When splitdebug is enabled, produces a separate tarball containing the debug |
| +symbols in \fBPKGDIR\fR. |
| +The debug symbols tarball has the name ${CATEGORY}/${PF}.debug.tbz2. |
| +.TP |
| .B sesandbox |
| Enable SELinux sandbox\-ing. Do not toggle this \fBFEATURE\fR yourself. |
| .TP |
| diff --git a/man/portage.5 b/man/portage.5 |
| index e399f0f..309e259 100644 |
| --- a/man/portage.5 |
| +++ b/man/portage.5 |
| @@ -24,6 +24,7 @@ make.defaults |
| packages |
| packages.build |
| package.accept_keywords |
| +package.bashrc |
| package.keywords |
| package.mask |
| package.provided |
| @@ -358,6 +359,31 @@ a '\-'. |
| A list of packages (one per line) that make up a stage1 tarball. Really only |
| useful for stage builders. |
| .TP |
| +.BR package.bashrc |
| +Per-package bashrc mechanism. Contains a list of bashrc files to be sourced |
| +before emerging a given atom. The bashrc files must be stored in bashrc/, in |
| +the profile directory. |
| + |
| +.I Note: |
| +.nf |
| +\- The bashrc files will be sourced after profile.bashrc for the same profile. |
| +\- profile-formats in metadata/layout.conf must contain profile-bashrcs for this |
| +to be enabled. |
| +.fi |
| + |
| +.I Format: |
| +.nf |
| +\- comments begin with # (no inline comments). |
| +\- one atom per line with space-delimited list of bashrc files. |
| +.fi |
| + |
| +.I Example: |
| +.nf |
| +# By setting INSTALL_MASK in bashrc/nostandardconf.conf, we can avoid installing |
| +# the standard configuration and enable another package to install it. |
| +net-misc/dhcp nostardardconf.conf |
| +.fi |
| +.TP |
| .BR package.provided |
| A list of packages (one per line) that portage should assume have been |
| provided. Useful for porting to non-Linux systems. Basically, it's a |
| @@ -1047,11 +1073,13 @@ The default setting for repoman's --echangelog option. |
| The cache formats supported in the metadata tree. There is the old "pms" format |
| and the newer/faster "md5-dict" format. Default is to detect dirs. |
| .TP |
| -.BR profile\-formats " = [pms|portage-1|portage-2]" |
| +.BR profile\-formats " = [pms|portage-1|portage-2|profile-bashrcs]" |
| Control functionality available to profiles in this repo such as which files |
| may be dirs, or the syntax available in parent files. Use "portage-2" if you're |
| unsure. The default is "portage-1-compat" mode which is meant to be compatible |
| with old profiles, but is not allowed to be opted into directly. |
| +Setting profile-bashrcs will enable the per-profile bashrc mechanism |
| +\fBpackage.bashrc\fR. |
| .RE |
| .RE |
| |
| diff --git a/pym/_emerge/EbuildBinpkg.py b/pym/_emerge/EbuildBinpkg.py |
| index 34a6aef..902639c 100644 |
| --- a/pym/_emerge/EbuildBinpkg.py |
| +++ b/pym/_emerge/EbuildBinpkg.py |
| @@ -3,14 +3,14 @@ |
| |
| from _emerge.CompositeTask import CompositeTask |
| from _emerge.EbuildPhase import EbuildPhase |
| -from portage import os |
| +from portage import os, xpak |
| |
| class EbuildBinpkg(CompositeTask): |
| """ |
| This assumes that src_install() has successfully completed. |
| """ |
| __slots__ = ('pkg', 'settings') + \ |
| - ('_binpkg_tmpfile',) |
| + ('_binpkg_tmpfile', '_symbols_tmpfile') |
| |
| def _start(self): |
| pkg = self.pkg |
| @@ -24,6 +24,12 @@ class EbuildBinpkg(CompositeTask): |
| self._binpkg_tmpfile = binpkg_tmpfile |
| self.settings["PORTAGE_BINPKG_TMPFILE"] = self._binpkg_tmpfile |
| |
| + if 'separatedebug' in self.settings.features: |
| + self._symbols_tmpfile = os.path.join(bintree.pkgdir, pkg.cpv \ |
| + + '.debug.tbz2') |
| + self.settings["PORTAGE_DEBUGSYMBOLS_TMPFILE"] = \ |
| + self._symbols_tmpfile |
| + |
| package_phase = EbuildPhase(background=self.background, |
| phase='package', scheduler=self.scheduler, |
| settings=self.settings) |
| @@ -33,15 +39,25 @@ class EbuildBinpkg(CompositeTask): |
| def _package_phase_exit(self, package_phase): |
| |
| self.settings.pop("PORTAGE_BINPKG_TMPFILE", None) |
| + self.settings.pop("PORTAGE_DEBUGSYMBOLS_TMPFILE", None) |
| if self._default_exit(package_phase) != os.EX_OK: |
| try: |
| os.unlink(self._binpkg_tmpfile) |
| except OSError: |
| pass |
| + try: |
| + os.unlink(self._symbols_tmpfile) |
| + except OSError: |
| + pass |
| self.wait() |
| return |
| |
| pkg = self.pkg |
| + if self._symbols_tmpfile and os.path.isfile(self._symbols_tmpfile): |
| + xpak_data = xpak.xpak_mem({ "CATEGORY": pkg.category, |
| + "PF": pkg.pf + "-debug", |
| + "SLOT": pkg._metadata['SLOT'] }) |
| + xpak.tbz2(self._symbols_tmpfile).recompose_mem(xpak_data) |
| bintree = pkg.root_config.trees["bintree"] |
| bintree.inject(pkg.cpv, filename=self._binpkg_tmpfile) |
| |
| diff --git a/pym/_emerge/Scheduler.py b/pym/_emerge/Scheduler.py |
| index d6db311..6e3bf1a 100644 |
| --- a/pym/_emerge/Scheduler.py |
| +++ b/pym/_emerge/Scheduler.py |
| @@ -1017,6 +1017,7 @@ class Scheduler(PollScheduler): |
| earlier_sigterm_handler = signal.signal(signal.SIGTERM, sighandler) |
| earlier_sigcont_handler = \ |
| signal.signal(signal.SIGCONT, self._sigcont_handler) |
| + signal.siginterrupt(signal.SIGCONT, False) |
| |
| try: |
| rval = self._merge() |
| diff --git a/pym/portage/cache/flat_hash.py b/pym/portage/cache/flat_hash.py |
| index 5304296..4735c86 100644 |
| --- a/pym/portage/cache/flat_hash.py |
| +++ b/pym/portage/cache/flat_hash.py |
| @@ -10,6 +10,7 @@ import errno |
| import io |
| import stat |
| import sys |
| +import tempfile |
| import os as _os |
| from portage import os |
| from portage import _encodings |
| @@ -66,48 +67,39 @@ class database(fs_template.FsBased): |
| raise cache_errors.CacheCorruption(cpv, e) |
| |
| def _setitem(self, cpv, values): |
| - s = cpv.rfind("/") |
| - fp = os.path.join(self.location,cpv[:s],".update.%i.%s" % (os.getpid(), cpv[s+1:])) |
| - try: |
| - myf = io.open(_unicode_encode(fp, |
| - encoding=_encodings['fs'], errors='strict'), |
| - mode='w', encoding=_encodings['repo.content'], |
| - errors='backslashreplace') |
| - except (IOError, OSError) as e: |
| - if errno.ENOENT == e.errno: |
| + with tempfile.NamedTemporaryFile(delete=False, dir=self.location, |
| + prefix=cpv.replace('/', '_')) as temp: |
| + temp.close() |
| + try: |
| + with io.open(temp.name, mode='w', |
| + encoding=_encodings['repo.content'], |
| + errors='backslashreplace') as myf: |
| + for k in self._write_keys: |
| + v = values.get(k) |
| + if not v: |
| + continue |
| + # NOTE: This format string requires unicode_literals, so that |
| + # k and v are coerced to unicode, in order to prevent TypeError |
| + # when writing raw bytes to TextIOWrapper with Python 2. |
| + myf.write("%s=%s\n" % (k, v)) |
| + |
| + self._ensure_access(temp.name) |
| + |
| + # Update written, we can move it. |
| + new_fp = os.path.join(self.location, cpv) |
| try: |
| - self._ensure_dirs(cpv) |
| - myf = io.open(_unicode_encode(fp, |
| - encoding=_encodings['fs'], errors='strict'), |
| - mode='w', encoding=_encodings['repo.content'], |
| - errors='backslashreplace') |
| - except (OSError, IOError) as e: |
| - raise cache_errors.CacheCorruption(cpv, e) |
| - else: |
| + os.rename(temp.name, new_fp) |
| + except OSError as e: |
| + if e.errno == errno.ENOENT: |
| + self._ensure_dirs(cpv) |
| + os.rename(temp.name, new_fp) |
| + else: |
| + raise cache_errors.CacheCorruption(cpv, e) |
| + |
| + except EnvironmentError as e: |
| + os.remove(temp.name) |
| raise cache_errors.CacheCorruption(cpv, e) |
| |
| - try: |
| - for k in self._write_keys: |
| - v = values.get(k) |
| - if not v: |
| - continue |
| - # NOTE: This format string requires unicode_literals, so that |
| - # k and v are coerced to unicode, in order to prevent TypeError |
| - # when writing raw bytes to TextIOWrapper with Python 2. |
| - myf.write("%s=%s\n" % (k, v)) |
| - finally: |
| - myf.close() |
| - self._ensure_access(fp) |
| - |
| - #update written. now we move it. |
| - |
| - new_fp = os.path.join(self.location,cpv) |
| - try: |
| - os.rename(fp, new_fp) |
| - except (OSError, IOError) as e: |
| - os.remove(fp) |
| - raise cache_errors.CacheCorruption(cpv, e) |
| - |
| def _delitem(self, cpv): |
| # import pdb;pdb.set_trace() |
| try: |
| diff --git a/pym/portage/cache/fs_template.py b/pym/portage/cache/fs_template.py |
| index de4fe4b..fa44abc 100644 |
| --- a/pym/portage/cache/fs_template.py |
| +++ b/pym/portage/cache/fs_template.py |
| @@ -10,7 +10,7 @@ from portage import os |
| from portage.proxy.lazyimport import lazyimport |
| lazyimport(globals(), |
| 'portage.exception:PortageException', |
| - 'portage.util:apply_permissions', |
| + 'portage.util:apply_permissions,ensure_dirs', |
| ) |
| del lazyimport |
| |
| @@ -61,20 +61,15 @@ class FsBased(template.database): |
| |
| for dir in path.lstrip(os.path.sep).rstrip(os.path.sep).split(os.path.sep): |
| base = os.path.join(base,dir) |
| - if not os.path.exists(base): |
| - if self._perms != -1: |
| - um = os.umask(0) |
| - try: |
| - perms = self._perms |
| - if perms == -1: |
| - perms = 0 |
| - perms |= 0o755 |
| - os.mkdir(base, perms) |
| - if self._gid != -1: |
| - os.chown(base, -1, self._gid) |
| - finally: |
| - if self._perms != -1: |
| - os.umask(um) |
| + if ensure_dirs(base): |
| + # We only call apply_permissions if ensure_dirs created |
| + # a new directory, so as not to interfere with |
| + # permissions of existing directories. |
| + mode = self._perms |
| + if mode == -1: |
| + mode = 0 |
| + mode |= 0o755 |
| + apply_permissions(base, mode=mode, gid=self._gid) |
| |
| def _prune_empty_dirs(self): |
| all_dirs = [] |
| diff --git a/pym/portage/const.py b/pym/portage/const.py |
| index aab6e8a..fa7bd66 100644 |
| --- a/pym/portage/const.py |
| +++ b/pym/portage/const.py |
| @@ -157,6 +157,7 @@ SUPPORTED_FEATURES = frozenset([ |
| "multilib-strict", |
| "network-sandbox", |
| "news", |
| + "no-env-update", |
| "noauto", |
| "noclean", |
| "nodoc", |
| @@ -172,6 +173,7 @@ SUPPORTED_FEATURES = frozenset([ |
| "python-trace", |
| "sandbox", |
| "selinux", |
| + "separatedebug", |
| "sesandbox", |
| "sfperms", |
| "sign", |
| diff --git a/pym/portage/dbapi/bintree.py b/pym/portage/dbapi/bintree.py |
| index 229ce3b..844d015 100644 |
| --- a/pym/portage/dbapi/bintree.py |
| +++ b/pym/portage/dbapi/bintree.py |
| @@ -43,6 +43,7 @@ import subprocess |
| import sys |
| import tempfile |
| import textwrap |
| +import time |
| import traceback |
| import warnings |
| from gzip import GzipFile |
| @@ -879,6 +880,7 @@ class binarytree(object): |
| if e.errno != errno.ENOENT: |
| raise |
| local_timestamp = pkgindex.header.get("TIMESTAMP", None) |
| + download_timestamp = float(pkgindex.header.get("DOWNLOAD_TIMESTAMP", 0)) |
| remote_timestamp = None |
| rmt_idx = self._new_pkgindex() |
| proc = None |
| @@ -890,6 +892,10 @@ class binarytree(object): |
| url = base_url.rstrip("/") + "/Packages" |
| f = None |
| |
| + ttl = float(pkgindex.header.get("TTL", 0)) |
| + if download_timestamp and ttl and download_timestamp + ttl > time.time(): |
| + raise UseCachedCopyOfRemoteIndex() |
| + |
| # Don't use urlopen for https, since it doesn't support |
| # certificate/hostname verification (bug #469888). |
| if parsed_url.scheme not in ('https',): |
| @@ -1022,6 +1028,7 @@ class binarytree(object): |
| pass |
| if pkgindex is rmt_idx: |
| pkgindex.modified = False # don't update the header |
| + pkgindex.header["DOWNLOAD_TIMESTAMP"] = str(long(time.time())) |
| try: |
| ensure_dirs(os.path.dirname(pkgindex_file)) |
| f = atomic_ofstream(pkgindex_file) |
| diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py |
| index 5b947dd..7b49b70 100644 |
| --- a/pym/portage/dbapi/vartree.py |
| +++ b/pym/portage/dbapi/vartree.py |
| @@ -70,6 +70,7 @@ from _emerge.MiscFunctionsProcess import MiscFunctionsProcess |
| from _emerge.SpawnProcess import SpawnProcess |
| |
| import errno |
| +import fileinput |
| import fnmatch |
| import gc |
| import grp |
| @@ -214,7 +215,7 @@ class vardbapi(dbapi): |
| """ |
| if self._lock_count: |
| self._lock_count += 1 |
| - else: |
| + elif os.environ.get("PORTAGE_LOCKS") != "false": |
| if self._lock is not None: |
| raise AssertionError("already locked") |
| # At least the parent needs to exist for the lock file. |
| @@ -230,7 +231,7 @@ class vardbapi(dbapi): |
| """ |
| if self._lock_count > 1: |
| self._lock_count -= 1 |
| - else: |
| + elif os.environ.get("PORTAGE_LOCKS") != "false": |
| if self._lock is None: |
| raise AssertionError("not locked") |
| self._lock_count = 0 |
| @@ -3663,17 +3664,15 @@ class dblink(object): |
| max_dblnk = dblnk |
| self._installed_instance = max_dblnk |
| |
| - if self.settings.get("INSTALL_MASK") or \ |
| - "nodoc" in self.settings.features or \ |
| - "noinfo" in self.settings.features or \ |
| - "noman" in self.settings.features: |
| - # Apply INSTALL_MASK before collision-protect, since it may |
| - # be useful to avoid collisions in some scenarios. |
| - phase = MiscFunctionsProcess(background=False, |
| - commands=["preinst_mask"], phase="preinst", |
| - scheduler=self._scheduler, settings=self.settings) |
| - phase.start() |
| - phase.wait() |
| + # Apply INSTALL_MASK before collision-protect, since it may |
| + # be useful to avoid collisions in some scenarios. |
| + # We cannot detect if this is needed or not here as INSTALL_MASK can be |
| + # modified by bashrc files. |
| + phase = MiscFunctionsProcess(background=False, |
| + commands=["preinst_mask"], phase="preinst", |
| + scheduler=self._scheduler, settings=self.settings) |
| + phase.start() |
| + phase.wait() |
| |
| # We check for unicode encoding issues after src_install. However, |
| # the check must be repeated here for binary packages (it's |
| @@ -3723,7 +3722,7 @@ class dblink(object): |
| break |
| |
| relative_path = parent[srcroot_len:] |
| - dirlist.append(os.path.join("/", relative_path)) |
| + dirlist.append(os.path.join(destroot, relative_path)) |
| |
| for fname in files: |
| try: |
| @@ -4301,6 +4300,19 @@ class dblink(object): |
| contents=contents, env=self.settings, |
| writemsg_level=self._display_merge, vardbapi=self.vartree.dbapi) |
| |
| + # Fix *.la files to point to libs in target_root, if they |
| + # don't do so already. |
| + re_root = self.settings["ROOT"].strip("/") |
| + if re_root: |
| + fix_files = [] |
| + for path in contents: |
| + if path.endswith(".la"): |
| + if os.path.exists(path): fix_files.append(path) |
| + if fix_files: |
| + pat = re.compile(r"([' =](?:-[IL])?/)(usr|lib|opt)") |
| + for line in fileinput.input(fix_files, inplace=1): |
| + sys.stdout.write(pat.sub(r"\1%s/\2" % re_root, line)) |
| + |
| # For gcc upgrades, preserved libs have to be removed after the |
| # the library path has been updated. |
| self._prune_plib_registry() |
| diff --git a/pym/portage/package/ebuild/_config/LocationsManager.py b/pym/portage/package/ebuild/_config/LocationsManager.py |
| index 4427f1d..8bf321c 100644 |
| --- a/pym/portage/package/ebuild/_config/LocationsManager.py |
| +++ b/pym/portage/package/ebuild/_config/LocationsManager.py |
| @@ -31,7 +31,7 @@ _PORTAGE1_DIRECTORIES = frozenset([ |
| 'use.mask', 'use.force']) |
| |
| _profile_node = collections.namedtuple('_profile_node', |
| - 'location portage1_directories user_config') |
| + 'location portage1_directories user_config profile_formats') |
| |
| _allow_parent_colon = frozenset( |
| ["portage-2"]) |
| @@ -132,7 +132,7 @@ class LocationsManager(object): |
| self.user_profile_dir = custom_prof |
| self.profiles.append(custom_prof) |
| self.profiles_complex.append( |
| - _profile_node(custom_prof, True, True)) |
| + _profile_node(custom_prof, True, True, ())) |
| del custom_prof |
| |
| self.profiles = tuple(self.profiles) |
| @@ -151,6 +151,7 @@ class LocationsManager(object): |
| allow_parent_colon = True |
| repo_loc = None |
| compat_mode = False |
| + current_formats = () |
| |
| eapi_file = os.path.join(currentPath, "eapi") |
| eapi = "0" |
| @@ -183,6 +184,8 @@ class LocationsManager(object): |
| layout_data['profile-formats'] == ('portage-1-compat',) |
| allow_parent_colon = any(x in _allow_parent_colon |
| for x in layout_data['profile-formats']) |
| + current_formats = tuple(layout_data['profile-formats']) |
| + |
| |
| if compat_mode: |
| offenders = _PORTAGE1_DIRECTORIES.intersection(os.listdir(currentPath)) |
| @@ -233,7 +236,8 @@ class LocationsManager(object): |
| |
| self.profiles.append(currentPath) |
| self.profiles_complex.append( |
| - _profile_node(currentPath, allow_directories, False)) |
| + _profile_node(currentPath, allow_directories, False, |
| + current_formats)) |
| |
| def _expand_parent_colon(self, parentsFile, parentPath, |
| repo_loc, repositories): |
| diff --git a/pym/portage/package/ebuild/_config/special_env_vars.py b/pym/portage/package/ebuild/_config/special_env_vars.py |
| index 74fedd6..55754d9 100644 |
| --- a/pym/portage/package/ebuild/_config/special_env_vars.py |
| +++ b/pym/portage/package/ebuild/_config/special_env_vars.py |
| @@ -49,10 +49,10 @@ environ_whitelist += [ |
| "FEATURES", "FILESDIR", "HOME", "MERGE_TYPE", "NOCOLOR", "PATH", |
| "PKGDIR", |
| "PKGUSE", "PKG_LOGDIR", "PKG_TMPDIR", |
| - "PORTAGE_ACTUAL_DISTDIR", "PORTAGE_ARCHLIST", |
| + "PORTAGE_ACTUAL_DISTDIR", "PORTAGE_ARCHLIST", "PORTAGE_BASHRC_FILES", |
| "PORTAGE_BASHRC", "PM_EBUILD_HOOK_DIR", |
| "PORTAGE_BINPKG_FILE", "PORTAGE_BINPKG_TAR_OPTS", |
| - "PORTAGE_BINPKG_TMPFILE", |
| + "PORTAGE_BINPKG_TMPFILE", "PORTAGE_DEBUGSYMBOLS_TMPFILE", |
| "PORTAGE_BIN_PATH", |
| "PORTAGE_BUILDDIR", "PORTAGE_BUILD_GROUP", "PORTAGE_BUILD_USER", |
| "PORTAGE_BUNZIP2_COMMAND", "PORTAGE_BZIP2_COMMAND", |
| @@ -74,9 +74,9 @@ environ_whitelist += [ |
| "PORTAGE_SIGPIPE_STATUS", |
| "PORTAGE_TMPDIR", "PORTAGE_UPDATE_ENV", "PORTAGE_USERNAME", |
| "PORTAGE_VERBOSE", "PORTAGE_WORKDIR_MODE", "PORTAGE_XATTR_EXCLUDE", |
| - "PORTDIR", "PORTDIR_OVERLAY", "PREROOTPATH", "PROFILE_PATHS", |
| + "PORTDIR", "PORTDIR_OVERLAY", "PREROOTPATH", |
| "REPLACING_VERSIONS", "REPLACED_BY_VERSION", |
| - "ROOT", "ROOTPATH", "T", "TMP", "TMPDIR", |
| + "ROOT", "ROOTPATH", "SYSROOT", "T", "TMP", "TMPDIR", |
| "USE_EXPAND", "USE_ORDER", "WORKDIR", |
| "XARGS", "__PORTAGE_TEST_HARDLINK_LOCKS", |
| ] |
| diff --git a/pym/portage/package/ebuild/config.py b/pym/portage/package/ebuild/config.py |
| index f639e14..67f95de 100644 |
| --- a/pym/portage/package/ebuild/config.py |
| +++ b/pym/portage/package/ebuild/config.py |
| @@ -254,6 +254,7 @@ class config(object): |
| self._iuse_implicit_match = clone._iuse_implicit_match |
| self._non_user_variables = clone._non_user_variables |
| self._env_d_blacklist = clone._env_d_blacklist |
| + self._pbashrc = clone._pbashrc |
| self._repo_make_defaults = clone._repo_make_defaults |
| self.usemask = clone.usemask |
| self.useforce = clone.useforce |
| @@ -316,6 +317,7 @@ class config(object): |
| self._accept_restrict = copy.deepcopy(clone._accept_restrict) |
| self._paccept_restrict = copy.deepcopy(clone._paccept_restrict) |
| self._penvdict = copy.deepcopy(clone._penvdict) |
| + self._pbashrcdict = copy.deepcopy(clone._pbashrcdict) |
| self._expand_map = copy.deepcopy(clone._expand_map) |
| |
| else: |
| @@ -661,6 +663,8 @@ class config(object): |
| self._ppropertiesdict = portage.dep.ExtendedAtomDict(dict) |
| self._paccept_restrict = portage.dep.ExtendedAtomDict(dict) |
| self._penvdict = portage.dep.ExtendedAtomDict(dict) |
| + self._pbashrcdict = {} |
| + self._pbashrc = () |
| |
| self._repo_make_defaults = {} |
| for repo in self.repositories.repos_with_profiles(): |
| @@ -742,6 +746,25 @@ class config(object): |
| for k, v in penvdict.items(): |
| self._penvdict.setdefault(k.cp, {})[k] = v |
| |
| + # package.bashrc |
| + for profile in profiles_complex: |
| + if not 'profile-bashrcs' in profile.profile_formats: |
| + continue |
| + self._pbashrcdict[profile] = \ |
| + portage.dep.ExtendedAtomDict(dict) |
| + bashrc = grabdict_package(os.path.join(profile.location, |
| + "package.bashrc"), recursive=1, allow_wildcard=True, |
| + allow_repo=True, verify_eapi=False) |
| + if not bashrc: |
| + continue |
| + |
| + for k, v in bashrc.items(): |
| + envfiles = [os.path.join(profile.location, |
| + "bashrc", |
| + envname) for envname in v] |
| + self._pbashrcdict[profile].setdefault(k.cp, {})\ |
| + .setdefault(k, []).extend(envfiles) |
| + |
| #getting categories from an external file now |
| self.categories = [grabfile(os.path.join(x, "categories")) \ |
| for x in locations_manager.profile_and_user_locations] |
| @@ -1501,6 +1524,23 @@ class config(object): |
| for x in penv_matches: |
| self._penv.extend(x) |
| |
| + bashrc_files = [] |
| + |
| + for profile in self._locations_manager.profiles_complex: |
| + profile_bashrc = os.path.join(profile.location, |
| + 'profile.bashrc') |
| + if os.path.exists(profile_bashrc): |
| + bashrc_files.append(profile_bashrc) |
| + if profile in self._pbashrcdict: |
| + cpdict = self._pbashrcdict[profile].get(cp) |
| + if cpdict: |
| + bashrc_matches = \ |
| + ordered_by_atom_specificity(cpdict, cpv_slot) |
| + for x in bashrc_matches: |
| + bashrc_files.extend(x) |
| + |
| + self._pbashrc = tuple(bashrc_files) |
| + |
| protected_pkg_keys = set(pkg_configdict) |
| protected_pkg_keys.discard('USE') |
| |
| @@ -2273,22 +2313,22 @@ class config(object): |
| if v is None: |
| continue |
| prefix = k.lower() + '_' |
| - if k in myincrementals: |
| - for x in v.split(): |
| - if x[:1] == '-': |
| - expand_use.append('-' + prefix + x[1:]) |
| - else: |
| - expand_use.append(prefix + x) |
| - else: |
| - for x in v.split(): |
| + for x in v.split(): |
| + if x[:1] == '-': |
| + expand_use.append('-' + prefix + x[1:]) |
| + else: |
| expand_use.append(prefix + x) |
| + |
| if expand_use: |
| expand_use.append(use) |
| use = ' '.join(expand_use) |
| self.make_defaults_use.append(use) |
| self.make_defaults_use = tuple(self.make_defaults_use) |
| + # Preserve both positive and negative flags here, since |
| + # negative flags may later interact with other flags pulled |
| + # in via USE_ORDER. |
| configdict_defaults['USE'] = ' '.join( |
| - stack_lists([x.split() for x in self.make_defaults_use])) |
| + filter(None, self.make_defaults_use)) |
| # Set to None so this code only runs once. |
| self._make_defaults = None |
| |
| diff --git a/pym/portage/package/ebuild/doebuild.py b/pym/portage/package/ebuild/doebuild.py |
| index 01707ae..98e5903 100644 |
| --- a/pym/portage/package/ebuild/doebuild.py |
| +++ b/pym/portage/package/ebuild/doebuild.py |
| @@ -5,6 +5,7 @@ from __future__ import unicode_literals |
| |
| __all__ = ['doebuild', 'doebuild_environment', 'spawn', 'spawnebuild'] |
| |
| +import fileinput |
| import grp |
| import gzip |
| import errno |
| @@ -335,7 +336,8 @@ def doebuild_environment(myebuild, mydo, myroot=None, settings=None, |
| mysettings["ECLASSDIR"] = mysettings["PORTDIR"]+"/eclass" |
| mysettings["SANDBOX_LOG"] = mycpv.replace("/", "_-_") |
| |
| - mysettings["PROFILE_PATHS"] = "\n".join(mysettings.profiles) |
| + mysettings["PORTAGE_BASHRC_FILES"] = "\n".join(mysettings._pbashrc) |
| + |
| mysettings["P"] = mysplit[0]+"-"+mysplit[1] |
| mysettings["PN"] = mysplit[0] |
| mysettings["PV"] = mysplit[1] |
| @@ -1628,9 +1630,10 @@ def spawnebuild(mydo, actionmap, mysettings, debug, alwaysdep=0, |
| _post_phase_cmds = { |
| |
| "install" : [ |
| + "install_hooks", |
| "install_qa_check", |
| "install_symlink_html_docs", |
| - "install_hooks"], |
| + ], |
| |
| "preinst" : [ |
| "preinst_sfperms", |
| @@ -1949,6 +1952,7 @@ def _post_src_install_uid_fix(mysettings, out): |
| destdir = mysettings["D"] |
| ed_len = len(mysettings["ED"]) |
| unicode_errors = [] |
| + fix_files = [] |
| desktop_file_validate = \ |
| portage.process.find_binary("desktop-file-validate") is not None |
| xdg_dirs = mysettings.get('XDG_DATA_DIRS', '/usr/share').split(':') |
| @@ -2075,10 +2079,12 @@ def _post_src_install_uid_fix(mysettings, out): |
| new_contents, mode='wb') |
| |
| mystat = os.lstat(fpath) |
| - if stat.S_ISREG(mystat.st_mode) and \ |
| - mystat.st_ino not in counted_inodes: |
| - counted_inodes.add(mystat.st_ino) |
| - size += mystat.st_size |
| + if stat.S_ISREG(mystat.st_mode): |
| + if fname.endswith(".la"): |
| + fix_files.append(fpath) |
| + if mystat.st_ino not in counted_inodes: |
| + counted_inodes.add(mystat.st_ino) |
| + size += mystat.st_size |
| if mystat.st_uid != portage_uid and \ |
| mystat.st_gid != portage_gid: |
| continue |
| @@ -2119,6 +2125,14 @@ def _post_src_install_uid_fix(mysettings, out): |
| f.write('%d\n' % size) |
| f.close() |
| |
| + re_root = mysettings["ROOT"].strip("/") |
| + if fix_files and re_root: |
| + # Replace references to our sysroot with references to "/" in binpkg. |
| + # Sysroot will be re-appended when the package is installed. |
| + pat = re.compile(r"([' =](-[IL])?/)%s/" % re.escape(re_root)) |
| + for line in fileinput.input(fix_files, inplace=1): |
| + sys.stdout.write(pat.sub(r"\1", line)) |
| + |
| _reapply_bsdflags_to_image(mysettings) |
| |
| def _reapply_bsdflags_to_image(mysettings): |
| diff --git a/pym/portage/repository/config.py b/pym/portage/repository/config.py |
| index 5e0d055..a3144b1 100644 |
| --- a/pym/portage/repository/config.py |
| +++ b/pym/portage/repository/config.py |
| @@ -40,7 +40,7 @@ if sys.hexversion >= 0x3000000: |
| _invalid_path_char_re = re.compile(r'[^a-zA-Z0-9._\-+:/]') |
| |
| _valid_profile_formats = frozenset( |
| - ['pms', 'portage-1', 'portage-2']) |
| + ['pms', 'portage-1', 'portage-2', 'profile-bashrcs']) |
| |
| _portage1_profiles_allow_directories = frozenset( |
| ["portage-1-compat", "portage-1", 'portage-2']) |
| @@ -233,6 +233,7 @@ class RepoConfig(object): |
| # useful when having two copies of the same repo enabled |
| # to avoid modifying profiles/repo_name in one of them |
| self.name = layout_data['repo-name'] |
| + self.missing_repo_name = False |
| |
| for value in ('allow-missing-manifest', |
| 'allow-provide-virtual', 'cache-formats', |
| diff --git a/pym/portage/tests/ebuild/test_use_expand_incremental.py b/pym/portage/tests/ebuild/test_use_expand_incremental.py |
| new file mode 100644 |
| index 0000000..a58f08c |
| --- /dev/null |
| +++ b/pym/portage/tests/ebuild/test_use_expand_incremental.py |
| @@ -0,0 +1,132 @@ |
| +# Copyright 2014 Gentoo Foundation |
| +# Distributed under the terms of the GNU General Public License v2 |
| + |
| +from __future__ import unicode_literals |
| + |
| +import io |
| + |
| +from portage import os, _encodings |
| +from portage.dep import Atom |
| +from portage.package.ebuild.config import config |
| +from portage.tests import TestCase |
| +from portage.tests.resolver.ResolverPlayground import ResolverPlayground |
| +from portage.util import ensure_dirs |
| + |
| +class UseExpandIncrementalTestCase(TestCase): |
| + |
| + def testUseExpandIncremental(self): |
| + |
| + profiles = ( |
| + ( |
| + 'base', |
| + { |
| + "eapi": ("5",), |
| + "parent": ("..",), |
| + "make.defaults": ( |
| + "INPUT_DEVICES=\"keyboard mouse\"", |
| + "PYTHON_TARGETS=\"python2_7 python3_3\"", |
| + ("USE_EXPAND=\"INPUT_DEVICES PYTHON_TARGETS " |
| + "VIDEO_CARDS\""), |
| + ) |
| + } |
| + ), |
| + ( |
| + 'default/linux', |
| + { |
| + "eapi": ("5",), |
| + "make.defaults": ( |
| + "VIDEO_CARDS=\"dummy fbdev v4l\"", |
| + ) |
| + } |
| + ), |
| + ( |
| + 'default/linux/x86', |
| + { |
| + "eapi": ("5",), |
| + "make.defaults": ( |
| + # Test negative incremental for bug 530222. |
| + "PYTHON_TARGETS=\"-python3_3\"", |
| + ), |
| + "parent": ("../../../base", |
| + "../../../mixins/python/3.4", |
| + ".." |
| + ) |
| + } |
| + ), |
| + ( |
| + 'mixins/python/3.4', |
| + { |
| + "eapi": ("5",), |
| + "make.defaults": ( |
| + "PYTHON_TARGETS=\"python3_4\"", |
| + ) |
| + } |
| + ), |
| + ) |
| + |
| + # USE_EXPAND variable settings in make.conf will cause |
| + # profile settings for the same variable to be discarded |
| + # (non-incremental behavior). PMS does not govern make.conf |
| + # behavior. |
| + user_config = { |
| + "make.conf" : ( |
| + "VIDEO_CARDS=\"intel\"", |
| + ) |
| + } |
| + |
| + ebuilds = { |
| + "x11-base/xorg-drivers-1.15": { |
| + "EAPI": "5", |
| + "IUSE": ("input_devices_keyboard input_devices_mouse " |
| + "videos_cards_dummy video_cards_fbdev " |
| + "video_cards_v4l video_cards_intel") |
| + }, |
| + "sys-apps/portage-2.2.14": { |
| + "EAPI": "5", |
| + "IUSE": ("python_targets_python2_7 " |
| + "python_targets_python3_3 python_targets_python3_4") |
| + }, |
| + } |
| + |
| + package_expected_use = ( |
| + ("x11-base/xorg-drivers-1.15", ("input_devices_keyboard", |
| + "input_devices_mouse", "video_cards_intel",)), |
| + ("sys-apps/portage-2.2.14", ("python_targets_python2_7", |
| + "python_targets_python3_4")) |
| + ) |
| + |
| + playground = ResolverPlayground(debug=False, |
| + ebuilds=ebuilds, user_config=user_config) |
| + try: |
| + repo_dir = (playground.settings.repositories. |
| + get_location_for_name("test_repo")) |
| + profile_root = os.path.join(repo_dir, "profiles") |
| + |
| + for p, data in profiles: |
| + prof_path = os.path.join(profile_root, p) |
| + ensure_dirs(prof_path) |
| + for k, v in data.items(): |
| + with io.open(os.path.join(prof_path, k), mode="w", |
| + encoding=_encodings["repo.content"]) as f: |
| + for line in v: |
| + f.write("%s\n" % line) |
| + |
| + # The config must be reloaded in order to account |
| + # for the above profile customizations. |
| + playground.reload_config() |
| + |
| + depgraph = playground.run( |
| + ["=x11-base/xorg-drivers-1.15"]).depgraph |
| + settings = config(clone=playground.settings) |
| + |
| + for cpv, expected_use in package_expected_use: |
| + pkg, existing_node = depgraph._select_package( |
| + playground.eroot, Atom("=" + cpv)) |
| + settings.setcpv(pkg) |
| + expected = frozenset(expected_use) |
| + got = frozenset(settings["PORTAGE_USE"].split()) |
| + self.assertEqual(got, expected, |
| + "%s != %s" % (got, expected)) |
| + |
| + finally: |
| + playground.cleanup() |
| diff --git a/pym/portage/tests/resolver/ResolverPlayground.py b/pym/portage/tests/resolver/ResolverPlayground.py |
| index 077e271..6fcef5c 100644 |
| --- a/pym/portage/tests/resolver/ResolverPlayground.py |
| +++ b/pym/portage/tests/resolver/ResolverPlayground.py |
| @@ -99,6 +99,16 @@ class ResolverPlayground(object): |
| |
| portage.util.noiselimit = 0 |
| |
| + def reload_config(self): |
| + """ |
| + Reload configuration from disk, which is useful if it has |
| + been modified after the constructor has been called. |
| + """ |
| + for eroot in self.trees: |
| + portdb = self.trees[eroot]["porttree"].dbapi |
| + portdb.close_caches() |
| + self.settings, self.trees = self._load_config() |
| + |
| def _get_repo_dir(self, repo): |
| """ |
| Create the repo directory if needed. |
| diff --git a/pym/portage/util/env_update.py b/pym/portage/util/env_update.py |
| index c0a93a8..f4cccc9 100644 |
| --- a/pym/portage/util/env_update.py |
| +++ b/pym/portage/util/env_update.py |
| @@ -43,6 +43,14 @@ def env_update(makelinks=1, target_root=None, prev_mtimes=None, contents=None, |
| defaults to portage.settings["ROOT"]. |
| @type target_root: String (Path) |
| """ |
| + settings = getattr(portage, 'settings', None) |
| + if settings is None: |
| + settings = config(config_root=target_root, |
| + target_root=target_root) |
| + |
| + if 'no-env-update' in settings.features: |
| + return |
| + |
| if vardbapi is None: |
| if isinstance(env, config): |
| vardbapi = vartree(settings=env).dbapi |