From 9add99f73e20f0ee9c1b40e286be45ea49a1ffa4 Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Fri, 30 Nov 2007 00:59:48 +0000 Subject: Bug #189417 - When ${T}/environment exists, isolate the ebuild environment from the calling environment. This makes it possible for the build to unset a variable that was inherited from the calling environment, and the variable will remain unset between phases. (trunk r8752:8755) svn path=/main/branches/2.1.2/; revision=8756 --- bin/ebuild.sh | 28 +++------------- bin/isolated-functions.sh | 2 +- pym/portage.py | 82 ++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 80 insertions(+), 32 deletions(-) diff --git a/bin/ebuild.sh b/bin/ebuild.sh index a5b89c9d4..f8f7377d7 100755 --- a/bin/ebuild.sh +++ b/bin/ebuild.sh @@ -1547,32 +1547,14 @@ if hasq "depend" "${EBUILD_SH_ARGS}"; then unset BIN_PATH BIN BODY FUNC_SRC fi -# Automatically try to load environment.bz2 whenever -# "${T}/environment" does not exist, except for phases -# such as nofetch that do not require ${T} to exist. -if ! hasq ${EBUILD_SH_ARGS} clean depend nofetch && \ - [ ! -f "${T}/environment" ] ; then - bzip2 -dc "${EBUILD%/*}"/environment.bz2 > \ - "${T}/environment" 2> /dev/null - if [ $? -eq 0 ] && [ -s "${T}/environment" ] ; then - preprocess_ebuild_env || \ - die "error processing '${EBUILD%/*}/environment.bz2'" - else - rm -f "${T}/environment" - fi -fi - if hasq ${EBUILD_SH_ARGS} clean ; then true elif ! hasq ${EBUILD_PHASE} depend && [ -f "${T}"/environment ] ; then - if [ "${PN}" == "portage" ] && [ -n "${EBUILD_SH_ARGS}" ] ; then - # When portage reinstalls itself, during inst/rm phases, the - # environment may have been saved by a different version of ebuild.sh, - # so it can't trusted that it's been properly filtered. Therefore, - # always preprocess the environment when ${PN} == portage. - preprocess_ebuild_env || \ - die "error processing environment" - fi + # The environment may have been extracted from environment.bz2 or + # may have come from another version of ebuild.sh or something. + # In any case, preprocess it to prevent any potential interference. + preprocess_ebuild_env || \ + die "error processing environment" # Colon separated SANDBOX_* variables need to be cumulative. for x in SANDBOX_DENY SANDBOX_READ SANDBOX_PREDICT SANDBOX_WRITE ; do eval PORTAGE_${x}=\${!x} diff --git a/bin/isolated-functions.sh b/bin/isolated-functions.sh index 70cae7097..62824b2bc 100644 --- a/bin/isolated-functions.sh +++ b/bin/isolated-functions.sh @@ -423,7 +423,7 @@ save_ebuild_env() { EBUILD_EXIT_STATUS_FILE EBUILD_MASTER_PID \ ECLASSDIR ECLASS_DEPTH ENDCOL FAKEROOTKEY FEATURES \ GOOD HILITE HOME IMAGE \ - KV LAST_E_CMD LAST_E_LEN LD_PRELOAD MOPREFIX \ + KV LAST_E_CMD LAST_E_LEN LD_PRELOAD MISC_FUNCTIONS_ARGS MOPREFIX \ NORMAL PATH PKGDIR PKGUSE PKG_LOGDIR PKG_TMPDIR \ PORTAGE_ACTUAL_DISTDIR PORTAGE_ARCHLIST PORTAGE_BASHRC \ PORTAGE_BINPKG_TMPFILE PORTAGE_BUILDDIR \ diff --git a/pym/portage.py b/pym/portage.py index c1527a4d4..b3d5baf7f 100644 --- a/pym/portage.py +++ b/pym/portage.py @@ -996,6 +996,17 @@ class config: virtuals ...etc you look in here. """ + # Preserve backupenv values that are initialized in the config + # constructor. Also, preserve XARGS since it is set by the + # portage.data module. + _environ_whitelist = frozenset([ + "FEATURES", "PORTAGE_BIN_PATH", + "PORTAGE_CONFIGROOT", "PORTAGE_DEPCACHEDIR", + "PORTAGE_GID", "PORTAGE_INST_GID", "PORTAGE_INST_UID", + "PORTAGE_PYM_PATH", "PORTDIR_OVERLAY", "ROOT", "USE_ORDER", + "XARGS", + ]) + # Filter selected variables in the config.environ() method so that # they don't needlessly propagate down into the ebuild environment. _environ_filter = [] @@ -1055,6 +1066,7 @@ class config: self.already_in_regenerate = 0 + self._filter_calling_env = False self.locked = 0 self.mycpv = None self.puse = [] @@ -1081,6 +1093,7 @@ class config: self._env_d_mtime = 0 if clone: + self._filter_calling_env = copy.deepcopy(clone._filter_calling_env) self.incrementals = copy.deepcopy(clone.incrementals) self.profile_path = copy.deepcopy(clone.profile_path) self.user_profile_dir = copy.deepcopy(clone.user_profile_dir) @@ -2511,6 +2524,9 @@ class config: "return our locally-maintained environment" mydict={} environ_filter = self._environ_filter + filter_calling_env = self._filter_calling_env + environ_whitelist = self._environ_whitelist + env_d = self.configdict["env.d"] for x in self: if x in environ_filter: continue @@ -2519,6 +2535,11 @@ class config: writemsg("!!! Non-string value in config: %s=%s\n" % \ (x, myvalue), noiselevel=-1) continue + if filter_calling_env and \ + x not in environ_whitelist: + if myvalue == env_d.get(x) or \ + myvalue == os.environ.get(x): + continue mydict[x] = myvalue if not mydict.has_key("HOME") and mydict.has_key("BUILD_PREFIX"): writemsg("*** HOME not set. Setting to "+mydict["BUILD_PREFIX"]+"\n") @@ -3561,8 +3582,15 @@ def spawnebuild(mydo,actionmap,mysettings,debug,alwaysdep=0,logfile=None): mysettings["EBUILD_PHASE"] = mydo _doebuild_exit_status_unlink( mysettings.get("EBUILD_EXIT_STATUS_FILE")) - phase_retval = spawn(actionmap[mydo]["cmd"] % mydo, mysettings, debug=debug, logfile=logfile, **kwargs) - mysettings["EBUILD_PHASE"] = "" + filter_calling_env_state = mysettings._filter_calling_env + if os.path.exists(os.path.join(mysettings["T"], "environment")): + mysettings._filter_calling_env = True + try: + phase_retval = spawn(actionmap[mydo]["cmd"] % mydo, + mysettings, debug=debug, logfile=logfile, **kwargs) + finally: + mysettings["EBUILD_PHASE"] = "" + mysettings._filter_calling_env = filter_calling_env_state msg = _doebuild_exit_status_check(mydo, mysettings) if msg: phase_retval = 1 @@ -4163,6 +4191,7 @@ def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0, builddir_lock = None tmpdir = None tmpdir_orig = None + filter_calling_env_state = mysettings._filter_calling_env try: if mydo in ("digest", "manifest", "help"): # Temporarily exempt the depend phase from manifest checks, in case @@ -4285,6 +4314,46 @@ def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0, if logfile and not os.access(os.path.dirname(logfile), os.W_OK): logfile = None if have_build_dirs: + env_file = os.path.join(mysettings["T"], "environment") + env_stat = None + saved_env = None + try: + env_stat = os.stat(env_file) + except OSError, e: + if e.errno != errno.ENOENT: + raise + del e + if not env_stat: + saved_env = os.path.join( + os.path.dirname(myebuild), "environment.bz2") + if not os.path.isfile(saved_env): + saved_env = None + if saved_env: + retval = os.system( + "bzip2 -dc '%s' > '%s'" % (saved_env, env_file)) + try: + env_stat = os.stat(env_file) + except OSError, e: + if e.errno != errno.ENOENT: + raise + del e + if os.WIFEXITED(retval) and \ + os.WEXITSTATUS(retval) == os.EX_OK and \ + env_stat and env_stat.st_size > 0: + pass + else: + writemsg("!!! Error extracting saved environment: '%s'" % \ + saved_env, noiselevel=-1) + try: + os.unlink(env_file) + except OSError, e: + if e.errno != errno.ENOENT: + raise + del e + env_stat = None + if env_stat: + mysettings._filter_calling_env = True + del env_file, env_stat, saved_env _doebuild_exit_status_unlink( mysettings.get("EBUILD_EXIT_STATUS_FILE")) else: @@ -4556,6 +4625,7 @@ def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0, return retval finally: + mysettings._filter_calling_env = filter_calling_env_state if tmpdir: mysettings["PORTAGE_TMPDIR"] = tmpdir_orig shutil.rmtree(tmpdir) @@ -9563,15 +9633,11 @@ def create_trees(config_root=None, target_root=None, trees=None): # with ROOT != "/", so we wipe out the "backupenv" for the # config that is associated with ROOT == "/" and regenerate # it's incrementals. - # Preserve backupenv values that are initialized in the config # constructor. Also, preserve XARGS since it is set by the # portage.data module. - backupenv_whitelist = set(["FEATURES", "PORTAGE_BIN_PATH", - "PORTAGE_CONFIGROOT", "PORTAGE_DEPCACHEDIR", - "PORTAGE_GID", "PORTAGE_INST_GID", "PORTAGE_INST_UID", - "PORTAGE_PYM_PATH", "PORTDIR_OVERLAY", "ROOT", "USE_ORDER", - "XARGS"]) + + backupenv_whitelist = settings._environ_whitelist backupenv = settings.configdict["backupenv"] for k, v in os.environ.iteritems(): if k in backupenv_whitelist: -- cgit v1.2.3-1-g7c22