Merged from trunk -r14674:14696
authorFabian Groffen <grobian@gentoo.org>
Tue, 20 Oct 2009 15:26:57 +0000 (15:26 -0000)
committerFabian Groffen <grobian@gentoo.org>
Tue, 20 Oct 2009 15:26:57 +0000 (15:26 -0000)
   | 14675    | Fix messages broken in r14616. Thanks to Arfrever for       |
   | zmedico  | reporting and thanks to Jonathan Callen <abcd@g.o> for this |
   |          | patch.                                                      |

   | 14676    | Move filtering of misc bash variables from                  |
   | zmedico  | save_ebuild_env() to filter_readonly_variables(). Add       |
   |          | additional variables found in the output of `env -i bash -c |
   |          | 'declare -p'`.                                              |

   | 14677    | Add a boolean expand_nested_sets parameter to               |
   | zmedico  | SetConfig.getSetAtoms(). This will be useful for adding     |
   |          | support to the dependency graph for keeping track of        |
   |          | precisely which nested set each atom comes from.            |

   | 14678    | Revert r14677 since it doesn't interact well with the       |
   | zmedico  | 'extend', 'remove', and 'intersect' code in                 |
   |          | SetConfig.getSetAtoms().                                    |

   | 14679    | Remove support for 'extend', 'remove', and 'intersect'      |
   | zmedico  | sets.conf section attributes in SetConfig.getSetAtoms()     |
   |          | since the current implementation does not meet user         |
   |          | expectations, as mentioned in bug #253802, comment #5:      |
   |          | Package set operators currently operate on atoms, but what  |
   |          | users really need is for them to operate on the packages    |
   |          | themselves. This will allow one set to add or subtract      |
   |          | packages from another even though the sets to not use the   |
   |          | exact same atoms to refer to the given packages. I imagine  |
   |          | the way this should be done is to create a mapping of atom  |
   |          | -> package for each set, perform the intersection using the |
   |          | packages, and then map the package intersection back into a |
   |          | set of atoms.                                               |

   | 14680    | Add support for display of nested sets in --depclean and    |
   | zmedico  | --prune reverse dependency output. This also fixes a bug    |
   |          | from the 'selected' set changes which could cause the       |
   |          | system set to be disregarded in some cases.                 |

   | 14681    | Bug #259697 - Update IUSE.invalid docs for glep 56. Thanks  |
   | zmedico  | to Alec Warner <antarus@g.o> for this patch.                |

   | 14694    | drop IMAGE -- people have had years to catch up             |
   | SpankMan |                                                             |

   | 14695    | Remove the docs for the extend, remove, and intersect       |
   | zmedico  | attributes that are not supported now.                      |

   | 14696    | Fix license_groups parsing to stack the lists, so           |
   | zmedico  | license_groups from overlays extend groups from the main    |
   |          | tree instead of overwritting them. Thanks to Vlastimil      |
   |          | Babka <caster@g.o> for reporting.                           |

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

bin/ebuild.sh
bin/isolated-functions.sh
bin/repoman
doc/config/sets.docbook
pym/_emerge/actions.py
pym/_emerge/depgraph.py
pym/portage/__init__.py
pym/portage/sets/__init__.py

index 4d843d1edea6bd4eee5567be0a87489b1b979fbf..a79e9fd83bf80b79156e5e927d2978f8d9f5aae0 100755 (executable)
@@ -81,10 +81,6 @@ unset GZIP BZIP BZIP2 CDPATH GREP_OPTIONS GREP_COLOR GLOBIGNORE
 
 source "${PORTAGE_BIN_PATH}/isolated-functions.sh"  &>/dev/null
 
-# Set IMAGE for minimal backward compatibility with
-# overlays or user's bashrc, but don't export it.
-[ "${EBUILD_PHASE}" == "preinst" ] && IMAGE=${D}
-
 [[ $PORTAGE_QUIET != "" ]] && export PORTAGE_QUIET
 
 # the sandbox is disabled by default except when overridden in the relevant stages
@@ -934,7 +930,7 @@ dyn_prepare() {
 
        [ -n "$EBUILD_PHASE" ] && rm -f "$T/logging/$EBUILD_PHASE"
        ebuild_phase pre_src_prepare
-       vecho ">>> Preparing source in $srcdir ..."
+       vecho ">>> Preparing source in $PWD ..."
        ebuild_phase src_prepare
        touch "$PORTAGE_BUILDDIR"/.prepared
        vecho ">>> Source prepared."
@@ -966,7 +962,7 @@ dyn_configure() {
        [ -n "$EBUILD_PHASE" ] && rm -f "$T/logging/$EBUILD_PHASE"
        ebuild_phase pre_src_configure
 
-       vecho ">>> Configuring source in $srcdir ..."
+       vecho ">>> Configuring source in $PWD ..."
        ebuild_phase src_configure
        touch "$PORTAGE_BUILDDIR"/.configured
        vecho ">>> Source configured."
@@ -999,7 +995,7 @@ dyn_compile() {
        [ -n "$EBUILD_PHASE" ] && rm -f "$T/logging/$EBUILD_PHASE"
        ebuild_phase pre_src_compile
 
-       vecho ">>> Compiling source in ${srcdir} ..."
+       vecho ">>> Compiling source in $PWD ..."
        ebuild_phase src_compile
        touch "$PORTAGE_BUILDDIR"/.compiled
        vecho ">>> Source compiled."
@@ -1061,7 +1057,6 @@ dyn_install() {
        ebuild_phase pre_src_install
        rm -rf "${PORTAGE_BUILDDIR}/image"
        mkdir "${PORTAGE_BUILDDIR}/image"
-       local srcdir
        if [[ -d $S ]] ; then
                cd "${S}"
        elif hasq $EAPI 0 1 2; then
@@ -1656,11 +1651,15 @@ filter_readonly_variables() {
        local x filtered_vars
        local readonly_bash_vars="BASHPID DIRSTACK EUID FUNCNAME
                GROUPS PIPESTATUS PPID SHELLOPTS UID"
+       local bash_misc_vars="BASH BASH_.* COMP_WORDBREAKS HISTCMD
+               HISTFILE HOSTNAME HOSTTYPE IFS LINENO MACHTYPE OLDPWD
+               OPTERR OPTIND OSTYPE POSIXLY_CORRECT PS4 PWD RANDOM
+               SECONDS SHELL SHLVL"
        local filtered_sandbox_vars="SANDBOX_ACTIVE SANDBOX_BASHRC
                SANDBOX_DEBUG_LOG SANDBOX_DISABLED SANDBOX_LIB
                SANDBOX_LOG SANDBOX_ON"
-       filtered_vars="${readonly_bash_vars} ${READONLY_PORTAGE_VARS}
-               BASH_.* HISTFILE PATH POSIXLY_CORRECT"
+       filtered_vars="$readonly_bash_vars $bash_misc_vars
+               $READONLY_PORTAGE_VARS PATH"
        if hasq --filter-sandbox $* ; then
                filtered_vars="${filtered_vars} SANDBOX_.*"
        else
index 5987a522ba18f60733ef7204156beb06de894fbb..f1b73a7019fdf53b373bd53d2bb0e6c680699833 100755 (executable)
@@ -505,10 +505,6 @@ save_ebuild_env() {
                        fi
                fi
 
-               # misc variables set by bash
-               unset BASH HOSTTYPE IFS MACHTYPE OLDPWD \
-                       OPTERR OPTIND OSTYPE PS4 PWD SHELL SHLVL
-
                # misc variables inherited from the calling environment
                unset COLORTERM DISPLAY EDITOR LESS LESSOPEN LOGNAME LS_COLORS PAGER \
                        TERM TERMCAP USER
@@ -551,6 +547,7 @@ save_ebuild_env() {
                        source_all_bashrcs ebuild_main \
                        ebuild_phase ebuild_phase_with_hooks \
                        _ebuild_arg_to_phase _ebuild_phase_funcs default \
+                       _pipestatus \
                        ${QA_INTERCEPTORS}
 
                # portage config variables and variables set directly by portage
@@ -558,7 +555,7 @@ save_ebuild_env() {
                        DISTCC_DIR DISTDIR DOC_SYMLINKS_DIR \
                        EBUILD_EXIT_STATUS_FILE EBUILD_FORCE_TEST EBUILD_MASTER_PID \
                        ECLASSDIR ECLASS_DEPTH ENDCOL FAKEROOTKEY \
-                       GOOD HILITE HOME IMAGE \
+                       GOOD HILITE HOME \
                        LAST_E_CMD LAST_E_LEN LD_PRELOAD MISC_FUNCTIONS_ARGS MOPREFIX \
                        NOCOLOR NORMAL PKGDIR PKGUSE PKG_LOGDIR PKG_TMPDIR \
                        PORTAGE_ACTUAL_DISTDIR PORTAGE_ARCHLIST \
index 961d013a4fdee7161449f400b74630c0f072d941..68a8f799ef6659b3b3fd4fbed3d8b98c92f1ae4a 100755 (executable)
@@ -309,7 +309,7 @@ qahelp={
        "variable.readonly":"Assigning a readonly variable",
        "LIVEVCS.stable":"This ebuild is a live checkout from a VCS but has stable keywords.",
        "LIVEVCS.unmasked":"This ebuild is a live checkout from a VCS but has keywords and is not masked in the global package.mask.",
-       "IUSE.invalid":"This ebuild has a variable in IUSE that is not in the use.desc or use.local.desc file",
+       "IUSE.invalid":"This ebuild has a variable in IUSE that is not in the use.desc or its metadata.xml file",
        "IUSE.undefined":"This ebuild does not define IUSE (style guideline says to define IUSE even when empty)",
        "LICENSE.invalid":"This ebuild is listing a license that doesnt exist in portages license/ dir.",
        "KEYWORDS.invalid":"This ebuild contains KEYWORDS that are not listed in profiles/arch.list or for which no valid profile was found",
index 8f93b1df2d33641564cf059c69c778f254c999da..ec8ff9a2a83c7a22cc7e395db0ab933f44a7bcb6 100644 (file)
                        is missing)</para></listitem>
                        <listitem><para><varname>world-candidate</varname>, which determines if
                        given package should be added to the <varname>world</varname> set</para></listitem>
-                       <listitem><para><varname>extend</varname> to include the contents of other package sets</para>
-                       </listitem>
-                       <listitem><para><varname>remove</varname> to remove the contents of other package sets</para>
-                       </listitem>
-                       <listitem><para><varname>intersect</varname> to only include packages that are also 
-                       included in one or more other package sets</para></listitem>
                        </itemizedlist>
                        <para>
                        Some handler classes might require additional options for their configuration,
                        sets each section still requires the <varname>class</varname> option,
                        but to indicate that the section should generate multiple sets it's
                        also necessary to set the <varname>multiset</varname> option to 
-                       <parameter>true</parameter>. The <varname>world-candidate</varname>,
-                       <varname>extend</varname>, <varname>remove</varname> and 
-                       <varname>intersect</varname> options are also supported like with 
+                       <parameter>true</parameter>. The <varname>world-candidate</varname>
+                       option also supported like with 
                        single sets (they'll apply to all sets generated by the section).
                        </para>
                        <para>
                        class = portage.sets.dbapi.CategorySet
                        multiset = true
                        name_pattern = $category/*
-                       intersect = installed
                        </programlisting>
                        </para>
                        <!-- TODO: reference list of available set handler classes here -->
index 4f319dbf3f3e576ddf942abb2ead4c6955a16037..ec661ad86d1db51805aaed13526cadc6e676ca61 100644 (file)
@@ -630,32 +630,44 @@ def calc_depclean(settings, trees, ldpath_mtimes,
        xterm_titles = "notitles" not in settings.features
        myroot = settings["ROOT"]
        root_config = trees[myroot]["root_config"]
-       getSetAtoms = root_config.setconfig.getSetAtoms
+       psets = root_config.setconfig.psets
        vardb = trees[myroot]["vartree"].dbapi
        deselect = myopts.get('--deselect') != 'n'
 
-       required_set_names = ("world",)
+       required_set_stack = ["world"]
        required_sets = {}
        set_args = []
 
-       for s in required_set_names:
-               required_sets[s] = InternalPackageSet(
-                       initial_atoms=getSetAtoms(s))
-
-
-       # When removing packages, use a temporary version of world
-       # which excludes packages that are intended to be eligible for
+       # Recursively create InternalPackageSet instances for world
+       # and any sets nested within it.
+       while required_set_stack:
+               s = required_set_stack.pop()
+               if s in required_sets:
+                       continue
+               pset = psets.get(s)
+               if pset is not None:
+                       required_sets[s] = InternalPackageSet(
+                               initial_atoms=pset.getAtoms())
+                       for n in pset.getNonAtoms():
+                               if n.startswith(SETPREFIX):
+                                       required_set_stack.append(n[len(SETPREFIX):])
+
+       # When removing packages, use a temporary version of world 'selected'
+       # set which excludes packages that are intended to be eligible for
        # removal.
-       world_temp_set = required_sets["world"]
-       system_set = root_config.sets["system"]
+       selected_set = required_sets["selected"]
+       protected_set = InternalPackageSet()
+       protected_set_name = '____depclean_protected_set____'
+       required_sets[protected_set_name] = protected_set
+       system_set = required_sets.get("system")
 
-       if not system_set or not world_temp_set:
+       if not system_set or not selected_set:
 
                if not system_set:
                        writemsg_level("!!! You have no system list.\n",
                                level=logging.ERROR, noiselevel=-1)
 
-               if not world_temp_set:
+               if not selected_set:
                        writemsg_level("!!! You have no world file.\n",
                                        level=logging.WARNING, noiselevel=-1)
 
@@ -678,7 +690,7 @@ def calc_depclean(settings, trees, ldpath_mtimes,
                if args_set:
 
                        if deselect:
-                               world_temp_set.clear()
+                               selected_set.clear()
 
                        # Pull in everything that's installed but not matched
                        # by an argument atom since we don't want to clean any
@@ -688,23 +700,23 @@ def calc_depclean(settings, trees, ldpath_mtimes,
 
                                try:
                                        if args_set.findAtomForPackage(pkg) is None:
-                                               world_temp_set.add("=" + pkg.cpv)
+                                               protected_set.add("=" + pkg.cpv)
                                                continue
                                except portage.exception.InvalidDependString as e:
                                        show_invalid_depstring_notice(pkg,
                                                pkg.metadata["PROVIDE"], str(e))
                                        del e
-                                       world_temp_set.add("=" + pkg.cpv)
+                                       protected_set.add("=" + pkg.cpv)
                                        continue
 
        elif action == "prune":
 
                if deselect:
-                       world_temp_set.clear()
+                       selected_set.clear()
 
                # Pull in everything that's installed since we don't
                # to prune a package if something depends on it.
-               world_temp_set.update(vardb.cp_all())
+               protected_set.update(vardb.cp_all())
 
                if not args_set:
 
@@ -727,7 +739,7 @@ def calc_depclean(settings, trees, ldpath_mtimes,
                        highest_version = pkgs_for_cp[-1]
                        if pkg == highest_version:
                                # pkg is the highest version
-                               world_temp_set.add("=" + pkg.cpv)
+                               protected_set.add("=" + pkg.cpv)
                                continue
 
                        if len(pkgs_for_cp) <= 1:
@@ -737,27 +749,16 @@ def calc_depclean(settings, trees, ldpath_mtimes,
 
                        try:
                                if args_set.findAtomForPackage(pkg) is None:
-                                       world_temp_set.add("=" + pkg.cpv)
+                                       protected_set.add("=" + pkg.cpv)
                                        continue
                        except portage.exception.InvalidDependString as e:
                                show_invalid_depstring_notice(pkg,
                                        pkg.metadata["PROVIDE"], str(e))
                                del e
-                               world_temp_set.add("=" + pkg.cpv)
+                               protected_set.add("=" + pkg.cpv)
                                continue
 
-       set_args = {}
-       for s, package_set in required_sets.items():
-               set_atom = SETPREFIX + s
-               set_arg = SetArg(arg=set_atom, set=package_set,
-                       root_config=resolver._frozen_config.roots[myroot])
-               set_args[s] = set_arg
-               for atom in set_arg.set:
-                       resolver._dynamic_config._dep_stack.append(
-                               Dependency(atom=atom, root=myroot, parent=set_arg))
-                       resolver._dynamic_config.digraph.add(set_arg, None)
-
-       success = resolver._complete_graph()
+       success = resolver._complete_graph(required_sets={myroot:required_sets})
        writemsg_level("\b\b... done!\n")
 
        resolver.display_problems()
@@ -841,6 +842,13 @@ def calc_depclean(settings, trees, ldpath_mtimes,
                        return -1
 
        def create_cleanlist():
+
+               # Never display the special internal protected_set.
+               for node in graph:
+                       if isinstance(node, SetArg) and node.name == protected_set_name:
+                               graph.remove(node)
+                               break
+
                pkgs_to_remove = []
 
                if action == "depclean":
@@ -868,9 +876,6 @@ def calc_depclean(settings, trees, ldpath_mtimes,
                                                show_parents(pkg)
 
                elif action == "prune":
-                       # Prune really uses all installed instead of world. It's not
-                       # a real reverse dependency so don't display it as such.
-                       graph.remove(set_args["world"])
 
                        for atom in args_set:
                                for pkg in vardb.match_pkgs(atom):
@@ -1062,7 +1067,8 @@ def calc_depclean(settings, trees, ldpath_mtimes,
                                                return 1, [], False, 0
 
                        writemsg_level("\nCalculating dependencies  ")
-                       success = resolver._complete_graph()
+                       success = resolver._complete_graph(
+                               required_sets={myroot:required_sets})
                        writemsg_level("\b\b... done!\n")
                        resolver.display_problems()
                        if not success:
index 607f0255dcf738d4b67fd7eb094db7015b22ce79..fcda3ec65249737fc72b1d1b65ba56e39e82482c 100644 (file)
@@ -2565,7 +2565,7 @@ class depgraph(object):
                in_graph = self._dynamic_config._slot_pkg_map[root].get(pkg.slot_atom)
                return pkg, in_graph
 
-       def _complete_graph(self):
+       def _complete_graph(self, required_sets=None):
                """
                Add any deep dependencies of required sets (args, system, world) that
                have not been pulled into the graph yet. This ensures that the graph
@@ -2576,6 +2576,10 @@ class depgraph(object):
 
                Since this method can consume enough time to disturb users, it is
                currently only enabled by the --complete-graph option.
+
+               @param required_sets: contains required sets (currently only used
+                       for depclean and prune removal operations)
+               @type required_sets: dict
                """
                if "--buildpkgonly" in self._frozen_config.myopts or \
                        "recurse" not in self._dynamic_config.myparams:
@@ -2598,11 +2602,16 @@ class depgraph(object):
                        self._dynamic_config.myparams["deep"] = True
 
                for root in self._frozen_config.roots:
-                       required_set_names = self._frozen_config._required_set_names.copy()
+                       if required_sets is None or root not in required_sets:
+                               required_set_names = self._frozen_config._required_set_names.copy()
+                       else:
+                               required_set_names = set(required_sets[root])
                        if root == self._frozen_config.target_root and \
                                (already_deep or "empty" in self._dynamic_config.myparams):
                                required_set_names.difference_update(self._dynamic_config._sets)
-                       if not required_set_names and not self._dynamic_config._ignored_deps:
+                       if not required_set_names and \
+                               not self._dynamic_config._ignored_deps and \
+                               not self._dynamic_config._dep_stack:
                                continue
                        root_config = self._frozen_config.roots[root]
                        setconfig = root_config.setconfig
@@ -2618,11 +2627,16 @@ class depgraph(object):
                                        required_set_names.remove(arg.name)
                        # Create new SetArg instances only when necessary.
                        for s in required_set_names:
-                               expanded_set = InternalPackageSet(
-                                       initial_atoms=setconfig.getSetAtoms(s))
+                               if required_sets is None or root not in required_sets:
+                                       expanded_set = InternalPackageSet(
+                                               initial_atoms=setconfig.getSetAtoms(s))
+                               else:
+                                       expanded_set = required_sets[root][s]
                                atom = SETPREFIX + s
                                args.append(SetArg(arg=atom, set=expanded_set,
                                        root_config=root_config))
+                               if root == self._frozen_config.target_root:
+                                       self._dynamic_config._sets[s] = expanded_set
                        vardb = root_config.trees["vartree"].dbapi
                        for arg in args:
                                for atom in arg.set:
index e247faa7a505594637776b7f6ac8132d278138a3..11c80fccb1ae0e2319fe1449bcc8b58d62c1c032 100644 (file)
@@ -2143,9 +2143,11 @@ class config(object):
                                        self.pprovideddict[mycatpkg]=[x]
 
                        # parse licensegroups
+                       license_groups = self._license_groups
                        for x in locations:
-                               self._license_groups.update(
-                                       grabdict(os.path.join(x, "license_groups")))
+                               for k, v in grabdict(
+                                       os.path.join(x, "license_groups")).items():
+                                       license_groups.setdefault(k, []).extend(v)
 
                        # reasonable defaults; this is important as without USE_ORDER,
                        # USE will always be "" (nothing set)!
@@ -3988,7 +3990,7 @@ def spawn(mystring, mysettings, debug=0, free=0, droppriv=0, sesandbox=0, fakero
        Optiosn include:
 
        Sandbox: Sandbox means the spawned process will be limited in its ability t
-       read and write files (normally this means it is restricted to ${IMAGE}/)
+       read and write files (normally this means it is restricted to ${D}/)
        SElinux Sandbox: Enables sandboxing on SElinux
        Reduced Privileges: Drops privilages such that the process runs as portage:portage
        instead of as root.
index ab67642b87fe13912cf8c23f03b19775ff8d74c6..59c3dbfd7498501af51971b90303d2e998404081 100644 (file)
@@ -155,44 +155,21 @@ class SetConfig(object):
                        raise PackageSetNotFound(setname)
                myatoms = myset.getAtoms()
                parser = self._parser
-               extend = set()
-               remove = set()
-               intersect = set()
-               
+
                if ignorelist is None:
                        ignorelist = set()
 
-               # If sets.conf is corrupt then emerge generates
-               # fallback sets without the 'creator' attribute.
-               if setname not in ignorelist and hasattr(myset, 'creator'):
-                       if parser.has_option(myset.creator, "extend"):
-                               extend.update(parser.get(myset.creator, "extend").split())
-                       if parser.has_option(myset.creator, "remove"):
-                               remove.update(parser.get(myset.creator, "remove").split())
-                       if parser.has_option(myset.creator, "intersect"):
-                               intersect.update(parser.get(myset.creator, "intersect").split())
-                                               
                ignorelist.add(setname)
                for n in myset.getNonAtoms():
                        if n.startswith(SETPREFIX):
                                s = n[len(SETPREFIX):]
                                if s in self.psets:
-                                       extend.add(n[len(SETPREFIX):])
+                                       if s not in ignorelist:
+                                               myatoms.update(self.getSetAtoms(s,
+                                                       ignorelist=ignorelist))
                                else:
                                        raise PackageSetNotFound(s)
 
-               for s in ignorelist:
-                       extend.discard(s)
-                       remove.discard(s)
-                       intersect.discard(s)
-               
-               for s in extend:
-                       myatoms.update(self.getSetAtoms(s, ignorelist=ignorelist))
-               for s in remove:
-                       myatoms.difference_update(self.getSetAtoms(s, ignorelist=ignorelist))
-               for s in intersect:
-                       myatoms.intersection_update(self.getSetAtoms(s, ignorelist=ignorelist))
-
                return myatoms
 
 def load_default_config(settings, trees):