Merged from trunk 8523:8528
authorFabian Groffen <grobian@gentoo.org>
Mon, 19 Nov 2007 18:20:13 +0000 (18:20 -0000)
committerFabian Groffen <grobian@gentoo.org>
Mon, 19 Nov 2007 18:20:13 +0000 (18:20 -0000)
   | 8524    | Fix PROFILE_ONLY_VARIABLES handling in the config            |
   | zmedico | constructor so that variables are appropriately filtered     |
   |         | from "backupenv", since otherwise they can leak in from      |
   |         | there.                                                       |

   | 8525    | Use the existing RootConfig class to serve as a replacement  |
   | zmedico | for the EmergeConfig class. They both served roughly the     |
   |         | same purpose and it was messy the way that EmergeConfig      |
   |         | inherited from the portage.config class. It's better to      |
   |         | avoid inheritance here, expecially since it doesn't provide  |
   |         | anything really useful.                                      |

   | 8526    | Disable logging and ${T}/environment saving during the       |
   | zmedico | pkg_info() phase.                                            |

   | 8527    | When creating environment.bz2 at the end of dyn_compile(),   |
   | zmedico | reduce bloat by filtering out functions that are defined     |
   |         | internally by portage. This reduces the size of the          |
   |         | resulting environment.bz2 file by approximately 10 KB.       |

   | 8528    | In bash-3.2_p20+ an attempt to assign BASH_*, FUNCNAME,      |
   | zmedico | GROUPS or any readonly variable cause the shell to exit      |
   |         | while executing the "source" builtin command. To avoid this  |
   |         | problem, a new save_ebuild_env() function filters those      |
   |         | variables out and discards them. See bug #190128.            |

svn path=/main/branches/prefix/; revision=8529

bin/ebuild.sh
pym/_emerge/__init__.py
pym/portage/__init__.py

index a673505e5f30dd186cbe6bd88dbd760ec8f33264..99099c0a07f4df9ec9fdd2ceacc669e4e8e73a12 100755 (executable)
@@ -957,8 +957,8 @@ dyn_compile() {
        echo "${USE}"           > USE
        echo "${EAPI:-0}"       > EAPI
        set +f
-       set                     >  environment
-       export | sed 's:^declare -rx:declare -x:' >> environment
+
+       save_ebuild_env > environment
        bzip2 -f9 environment
 
        cp "${EBUILD}" "${PF}.ebuild"
@@ -1369,6 +1369,47 @@ remove_path_entry() {
        PATH="${stripped_path}"
 }
 
+save_ebuild_env() {
+       # In bash-3.2_p20+ an attempt to assign BASH_*, FUNCNAME, GROUPS or any
+       # readonly variable cause the shell to exit while executing the "source"
+       # builtin command. To avoid this problem, this function filters those
+       # variables out and discards them. See bug #190128.
+       local readonly_vars=$(readonly | while read line; \
+               do [[ ${line} == "declare -"*" "*"="* ]] || continue ; \
+               x=${line%%=*} ; echo ${x##* } ; done)
+       local x var_grep=""
+       for x in BASH SANDBOX ; do
+               var_grep="${var_grep}|(^|^declare[[:space:]]+-[^[:space:]]+[[:space:]]+)${x}_[_[:alnum:]]*=.*"
+       done
+       for x in ${readonly_vars} var_grep LD_PRELOAD FAKEROOTKEY FUNCNAME GROUPS ; do
+               var_grep="${var_grep}|(^|^declare[[:space:]]+-[^[:space:]]+[[:space:]]+)${x}=.*"
+       done
+       var_grep=${var_grep:1} # strip the first |
+       unset x readonly_vars
+       (
+               # There's no need to bloat environment.bz2 with internally defined
+               # functions and variables, so filter them out if possible.
+
+               unset -f dump_trace diefunc quiet_mode vecho elog_base eqawarn elog \
+                       esyslog einfo einfon ewarn eerror ebegin _eend eend KV_major \
+                       KV_minor KV_micro KV_to_int get_KV unset_colors set_colors has \
+                       hasv hasq qa_source qa_call addread addwrite adddeny addpredict \
+                       lchown lchgrp esyslog use usev useq has_version portageq \
+                       best_version use_with use_enable register_die_hook check_KV \
+                       keepdir unpack strip_duplicate_slashes econf einstall gen_wrapper \
+                       dyn_setup dyn_unpack dyn_clean into insinto exeinto docinto \
+                       insopts diropts exeopts libopts abort_handler abort_compile \
+                       abort_test abort_install dyn_compile dyn_test dyn_install \
+                       dyn_preinst dyn_help debug-print debug-print-function \
+                       debug-print-section inherit EXPORT_FUNCTIONS newdepend newrdepend \
+                       newpdepend do_newdepend remove_path_entry killparent \
+                       save_ebuild_env
+
+               set
+               export
+       ) | egrep -v -e "${var_grep}"
+}
+
 # === === === === === === === === === === === === === === === === === ===
 # === === === === === functions end, main part begins === === === === ===
 # === === === === === functions end, main part begins === === === === ===
@@ -1675,16 +1716,13 @@ done
 
 # Save the env only for relevant phases.
 if [ -n "${myarg}" ] && \
-       [ "${myarg}" != "clean" ] && \
-       [ "${myarg}" != "help" ] ; then
+       ! hasq ${myarg} clean help info ; then
        # Do not save myarg in the env, or else the above [ -n "$myarg" ] test will
        # give a false positive when ebuild.sh is sourced.
        unset myarg
        # Save current environment and touch a success file. (echo for success)
        umask 002
-       set | egrep -v -e "^SANDBOX_" -e "^LD_PRELOAD=" -e "^FAKEROOTKEY=" > "${T}/environment" 2>/dev/null
-       export | egrep -v -e "^declare -x SANDBOX_" -e "^declare -x LD_PRELOAD=" -e "^declare -x FAKEROOTKEY=" | \
-               sed 's:^declare -rx:declare -x:' >> "${T}/environment" 2>/dev/null
+       save_ebuild_env > "${T}/environment" 2>/dev/null
        chown ${PORTAGE_USER:-portage}:${PORTAGE_GROUP:-portage} "${T}/environment" &>/dev/null
        chmod g+w "${T}/environment" &>/dev/null
 fi
index f8d35544871ac9348a75e6debd3902c6effe6586..45065cb2c9f17d51d466838f698b12d5784c976b 100644 (file)
@@ -386,22 +386,6 @@ def create_depgraph_params(myopts, myaction):
                myparams.add("consistent")
        return myparams
 
-
-class EmergeConfig(portage.config):
-       def __init__(self, settings, trees=None, setconfig=None):
-               """ You have to specify one of trees or setconfig """
-               portage.config.__init__(self, clone=settings)
-               if not setconfig:
-                       setconfigpaths = [os.path.join(GLOBAL_CONFIG_PATH, "sets.conf")]
-                       setconfigpaths.append(os.path.join(settings["PORTDIR"], "sets.conf"))
-                       setconfigpaths += [os.path.join(x, "sets.conf") for x in settings["PORDIR_OVERLAY"].split()]
-                       setconfigpaths.append(os.path.join(settings["PORTAGE_CONFIGROOT"],
-                               USER_CONFIG_PATH.lstrip(os.path.sep), "sets.conf"))
-                       #setconfig = SetConfig(setconfigpaths, settings, trees)
-                       setconfig = make_default_config(settings, trees)
-               self.setconfig = setconfig
-               self.sets = self.setconfig.getSetsWithAliases()
-
 # search functionality
 class search(object):
 
@@ -414,18 +398,18 @@ class search(object):
        #
        # public interface
        #
-       def __init__(self, settings, portdb, vartree, spinner, searchdesc,
+       def __init__(self, root_config, spinner, searchdesc,
                verbose):
                """Searches the available and installed packages for the supplied search key.
                The list of available and installed packages is created at object instantiation.
                This makes successive searches faster."""
-               self.settings = settings
-               self.portdb = portdb
-               self.vartree = vartree
+               self.settings = root_config.settings
+               self.portdb = root_config.trees["porttree"].dbapi
+               self.vartree = root_config.trees["vartree"]
                self.spinner = spinner
                self.verbose = verbose
                self.searchdesc = searchdesc
-               self.setconfig = settings.setconfig
+               self.setconfig = root_config.setconfig
 
        def execute(self,searchkey):
                """Performs the search for the supplied search key"""
@@ -598,10 +582,12 @@ class search(object):
 class RootConfig(object):
        """This is used internally by depgraph to track information about a
        particular $ROOT."""
-       def __init__(self, trees):
+       def __init__(self, trees, setconfig):
                self.trees = trees
                self.settings = trees["vartree"].settings
                self.root = self.settings["ROOT"]
+               self.setconfig = setconfig
+               self.sets = self.setconfig.getSetsWithAliases()
 
 def create_world_atom(pkg_key, metadata, args_set, root_config):
        """Create a new atom for the world file if one does not exist.  If the
@@ -615,7 +601,7 @@ def create_world_atom(pkg_key, metadata, args_set, root_config):
                return None
        cp = portage.dep_getkey(arg_atom)
        new_world_atom = cp
-       sets = root_config.settings.sets
+       sets = root_config.sets
        portdb = root_config.trees["porttree"].dbapi
        vardb = root_config.trees["vartree"].dbapi
        available_slots = set(portdb.aux_get(cpv, ["SLOT"])[0] \
@@ -1190,7 +1176,10 @@ class depgraph(object):
                                clone=self.trees[myroot]["vartree"].settings)
                        self._slot_pkg_map[myroot] = {}
                        vardb = self.trees[myroot]["vartree"].dbapi
-                       self.roots[myroot] = RootConfig(self.trees[myroot])
+                       # Create a RootConfig instance that references
+                       # the FakeVartree instead of the real one.
+                       self.roots[myroot] = RootConfig(self.trees[myroot],
+                               trees[myroot]["root_config"].setconfig)
                        # This fakedbapi instance will model the state that the vdb will
                        # have after new packages have been installed.
                        fakedb = portage.fakedbapi(settings=self.pkgsettings[myroot])
@@ -1741,8 +1730,8 @@ class depgraph(object):
                """Given a list of .tbz2s, .ebuilds sets, and deps, create the
                appropriate depgraph and return a favorite list."""
                root_config = self.roots[self.target_root]
-               sets = root_config.settings.sets
-               getSetAtoms = root_config.settings.setconfig.getSetAtoms
+               sets = root_config.sets
+               getSetAtoms = root_config.setconfig.getSetAtoms
                oneshot = "--oneshot" in self.myopts or \
                        "--onlydeps" in self.myopts
                myfavorites=[]
@@ -2539,7 +2528,7 @@ class depgraph(object):
                        if not required_set_names and not self._ignored_deps:
                                continue
                        root_config = self.roots[root]
-                       setconfig = root_config.settings.setconfig
+                       setconfig = root_config.setconfig
                        args = []
                        # Reuse existing SetArg instances when available.
                        for arg in self._parent_child_digraph.root_nodes():
@@ -3625,8 +3614,8 @@ class depgraph(object):
 
                                pkg_cp = xs[0]
                                root_config = self.roots[myroot]
-                               system_set = root_config.settings.sets["system"]
-                               world_set  = root_config.settings.sets["world"]
+                               system_set = root_config.sets["system"]
+                               world_set  = root_config.sets["world"]
 
                                pkg_system = False
                                pkg_world = False
@@ -3866,7 +3855,7 @@ class depgraph(object):
                        if x in self.myopts:
                                return
                root_config = self.roots[self.target_root]
-               world_set = root_config.settings.sets["world"]
+               world_set = root_config.sets["world"]
                world_set.lock()
                world_set.load() # maybe it's changed on disk
                args_set = self._sets["args"]
@@ -4073,9 +4062,8 @@ class MergeTask(object):
                        self.edebug = 1
                self.pkgsettings = {}
                for root in trees:
-                       self.pkgsettings[root] = EmergeConfig(
-                               trees[root]["vartree"].settings,
-                               setconfig=trees[root]["vartree"].settings.setconfig)
+                       self.pkgsettings[root] = portage.config(
+                               clone=trees[root]["vartree"].settings)
                self.curval = 0
 
        def merge(self, mylist, favorites, mtimedb):
@@ -4141,10 +4129,10 @@ class MergeTask(object):
                                del x, mytype, myroot, mycpv, mystatus, quiet_config
                        del shown_verifying_msg, quiet_settings
 
-               root_config = RootConfig(self.trees[self.target_root])
-               system_set = root_config.settings.sets["system"]
+               root_config = self.trees[self.target_root]["root_config"]
+               system_set = root_config.sets["system"]
                args_set = InternalPackageSet(favorites)
-               world_set = root_config.settings.sets["world"]
+               world_set = root_config.sets["world"]
                if "--resume" not in self.myopts:
                        mymergelist = mylist
                        mtimedb["resume"]["mergelist"]=mymergelist[:]
@@ -4453,7 +4441,8 @@ class MergeTask(object):
                                        if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
                                                xsplit=portage.pkgsplit(x[2])
                                                emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
-                                               retval = unmerge(pkgsettings, self.myopts, vartree,
+                                               retval = unmerge(self.trees[myroot]["root_config"],
+                                                       self.myopts,
                                                        "clean", [xsplit[0]], ldpath_mtimes, autoclean=1)
                                                if not retval:
                                                        emergelog(xterm_titles,
@@ -4546,8 +4535,11 @@ class MergeTask(object):
                                sys.exit(0)
                return os.EX_OK
 
-def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
-       ldpath_mtimes, autoclean=0):
+def unmerge(root_config, myopts, unmerge_action,
+       unmerge_files, ldpath_mtimes, autoclean=0):
+       settings = root_config.settings
+       sets = root_config.sets
+       vartree = root_config.trees["vartree"]
        candidate_catpkgs=[]
        global_unmerge=0
        xterm_titles = "notitles" not in settings.features
@@ -4562,7 +4554,7 @@ def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
        try:
                if os.access(vdb_path, os.W_OK):
                        vdb_lock = portage.locks.lockdir(vdb_path)
-               realsyslist = settings.sets["system"].getAtoms()
+               realsyslist = sets["system"].getAtoms()
                syslist = []
                for x in realsyslist:
                        mycp = portage.dep_getkey(x)
@@ -4844,7 +4836,7 @@ def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
                                show_unmerge_failure_message(y, ebuild, retval)
                                sys.exit(retval)
                        else:
-                               settings.sets["world"].cleanPackage(vartree.dbapi, y)
+                               sets["world"].cleanPackage(vartree.dbapi, y)
                                emergelog(xterm_titles, " >>> unmerge success: "+y)
        return 1
 
@@ -6027,12 +6019,12 @@ def action_info(settings, trees, myopts, myfiles):
                                mydbapi=trees[settings["ROOT"]]["vartree"].dbapi,
                                tree="vartree")
 
-def action_search(settings, portdb, vartree, myopts, myfiles, spinner):
+def action_search(root_config, myopts, myfiles, spinner):
        if not myfiles:
                print "emerge: no search terms provided."
        else:
-               searchinstance = search(settings, portdb,
-                       vartree, spinner, "--searchdesc" in myopts,
+               searchinstance = search(root_config,
+                       spinner, "--searchdesc" in myopts,
                        "--quiet" not in myopts)
                for mysearch in myfiles:
                        try:
@@ -6081,8 +6073,10 @@ def action_depclean(settings, trees, ldpath_mtimes,
        vardb = dep_check_trees[myroot]["vartree"].dbapi
        # Constrain dependency selection to the installed packages.
        dep_check_trees[myroot]["porttree"] = dep_check_trees[myroot]["vartree"]
-       syslist = settings.setconfig.getSetAtoms("system")
-       worldlist = settings.setconfig.getSetAtoms("world")
+       root_config = trees[myroot]["root_config"]
+       setconfig = root_config.setconfig
+       syslist = setconfig.getSetAtoms("system")
+       worldlist = setconfig.getSetAtoms("world")
        args_set = InternalPackageSet()
        fakedb = portage.fakedbapi(settings=settings)
        myvarlist = vardb.cpv_all()
@@ -6331,7 +6325,7 @@ def action_depclean(settings, trees, ldpath_mtimes,
                                        good("--nodeps"))
 
        if len(cleanlist):
-               unmerge(settings, myopts, trees[settings["ROOT"]]["vartree"],
+               unmerge(root_config, myopts,
                        "unmerge", cleanlist, ldpath_mtimes)
 
        if action == "prune":
@@ -6596,8 +6590,8 @@ def action_build(settings, trees, mtimedb,
                        mtimedb.pop("resume", None)
                        if "yes" == settings.get("AUTOCLEAN"):
                                portage.writemsg_stdout(">>> Auto-cleaning packages...\n")
-                               vartree = trees[settings["ROOT"]]["vartree"]
-                               unmerge(settings, myopts, vartree, "clean", [],
+                               unmerge(trees[settings["ROOT"]]["root_config"],
+                                       myopts, "clean", [],
                                        ldpath_mtimes, autoclean=1)
                        else:
                                portage.writemsg_stdout(colorize("WARN", "WARNING:")
@@ -6726,11 +6720,10 @@ def load_emerge_config(trees=None):
                kwargs[k] = os.environ.get(envvar, None)
        trees = portage.create_trees(trees=trees, **kwargs)
 
-       for root in trees:
-               settings = trees[root]["vartree"].settings
-               settings = EmergeConfig(settings, trees=trees[root])
-               settings.lock()
-               trees[root]["vartree"].settings = settings
+       for root, root_trees in trees.iteritems():
+               settings = root_trees["vartree"].settings
+               setconfig = make_default_config(settings, root_trees)
+               root_trees["root_config"] = RootConfig(root_trees, setconfig)
 
        settings = trees["/"]["vartree"].settings
 
@@ -6920,10 +6913,12 @@ def emerge_main():
                        print colorize("BAD", "\n*** emerging by path is broken and may not always work!!!\n")
                        break
 
-       mysets = {}
        # only expand sets for actions taking package arguments
        oldargs = myfiles[:]
        if myaction in ("clean", "config", "depclean", "info", "prune", "unmerge"):
+               root_config = trees[settings["ROOT"]]["root_config"]
+               setconfig = root_config.setconfig
+               sets = root_config.sets
                newargs = []
                for a in myfiles:
                        if a in ("system", "world"):
@@ -6936,21 +6931,20 @@ def emerge_main():
                for a in myfiles:
                        if a.startswith(SETPREFIX):
                                s = a[len(SETPREFIX):]
-                               if s not in settings.sets:
+                               if s not in sets:
                                        print "emerge: there are no sets to satisfy %s." % \
                                                colorize("INFORM", s)
                                        return 1
                                # TODO: check if the current setname also resolves to a package name
                                if myaction in ["unmerge", "prune", "clean", "depclean"] and \
-                                       not settings.sets[s].supportsOperation("unmerge"):
+                                       not sets[s].supportsOperation("unmerge"):
                                        print "emerge: the given set %s does not support unmerge operations" % s
                                        return 1
-                               if not settings.setconfig.getSetAtoms(s):
+                               if not setconfig.getSetAtoms(s):
                                        print "emerge: '%s' is an empty set" % s
                                else:
-                                       newargs.extend(settings.setconfig.getSetAtoms(s))
-                                       mysets[s] = settings.sets[s]
-                               for e in settings.sets[s].errors:
+                                       newargs.extend(setconfig.getSetAtoms(s))
+                               for e in sets[s].errors:
                                        print e
                        else:
                                newargs.append(a)
@@ -7150,13 +7144,13 @@ def emerge_main():
        # SEARCH action
        elif "search"==myaction:
                validate_ebuild_environment(trees)
-               action_search(settings, portdb, trees["/"]["vartree"],
+               action_search(trees[settings["ROOT"]]["root_config"],
                        myopts, myfiles, spinner)
        elif myaction in ("clean", "unmerge") or \
                (myaction == "prune" and "--nodeps" in myopts):
                validate_ebuild_environment(trees)
-               vartree = trees[settings["ROOT"]]["vartree"]
-               if 1 == unmerge(settings, myopts, vartree, myaction, myfiles,
+               root_config = trees[settings["ROOT"]]["root_config"]
+               if 1 == unmerge(root_config, myopts, myaction, myfiles,
                        mtimedb["ldpath"]):
                        if "--pretend" not in myopts:
                                post_emerge(trees, mtimedb, os.EX_OK)
index ee01856bfa91b89e3d7337d1464de21ff72f9dbe..9c9eacf079d1bae9446ee06d3d6b4676b7013df5 100644 (file)
@@ -974,9 +974,6 @@ class config(object):
                        self._use_wildcards = copy.deepcopy(clone._use_wildcards)
                else:
 
-                       # backupenv is for calculated incremental variables.
-                       self.backupenv = os.environ.copy()
-
                        def check_var_directory(varname, var):
                                if not os.path.isdir(var):
                                        writemsg(("!!! Error: %s='%s' is not a directory. " + \
@@ -1229,15 +1226,16 @@ class config(object):
                        self.configlist.append({})
                        self.configdict["auto"]=self.configlist[-1]
 
+                       # backupenv is used for calculating incremental variables.
+                       self.backupenv = os.environ.copy()
                        self.configlist.append(self.backupenv) # XXX Why though?
                        self.configdict["backupenv"]=self.configlist[-1]
 
-                       myenv = os.environ.copy()               
                        # Don't allow the user to override certain variables in the env
                        for k in profile_only_variables:
-                               myenv.pop(k, None)
+                               self.backupenv.pop(k, None)
 
-                       self.configlist.append(myenv)
+                       self.configlist.append(self.backupenv.copy())
                        self.configdict["env"]=self.configlist[-1]
 
                        # make lookuplist for loading package.*
@@ -4189,7 +4187,7 @@ def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0,
 
                # Build directory creation isn't required for any of these.
                have_build_dirs = False
-               if mydo not in ("digest", "fetch", "help", "manifest"):
+               if mydo not in ("digest", "fetch", "help", "info", "manifest"):
                        mystatus = prepare_build_dirs(myroot, mysettings, cleanup)
                        if mystatus:
                                return mystatus