Merged from trunk 7209:7242
authorFabian Groffen <grobian@gentoo.org>
Fri, 13 Jul 2007 17:59:44 +0000 (17:59 -0000)
committerFabian Groffen <grobian@gentoo.org>
Fri, 13 Jul 2007 17:59:44 +0000 (17:59 -0000)
   +------------------------------------------------------------------------+
   | 7210    | - remove readable bits for debug files if the souce ELF is   |
   | solar   | setXid                                                       |
   |---------+--------------------------------------------------------------|
   | 7211    | - be quiet about overlays profiles/repo_name entry when      |
   | solar   | --quiet mode is used                                         |
   |---------+--------------------------------------------------------------|
   | 7212    | Remove the repo_name warning in the portdbapi constructor    |
   | zmedico | since we don't want to see a warning every time the portage  |
   |         | module is imported.                                          |
   |---------+--------------------------------------------------------------|
   | 7214    | For bug #184806, account for the fact the metadata is not    |
   | zmedico | cached for slot_collision_nodes.                             |
   |---------+--------------------------------------------------------------|
   | 7216    | For bug #184604, make env-update write $ in front of quoted  |
   | zmedico | values when appropriate.                                     |
   |---------+--------------------------------------------------------------|
   | 7218    | For bug #184843, allow USE_EXPAND variables to pass through  |
   | zmedico | if none of their flags are in IUSE. This allows packages     |
   |         | that support LINGUAS but don't declare it in IUSE to use the |
   |         | variable outside of the USE_EXPAND context.                  |
   |---------+--------------------------------------------------------------|
   | 7220    | For bug #184679, handle ENOTDIR by finding the non-directory |
   | zmedico | parent and testing that for collision instead.               |
   |---------+--------------------------------------------------------------|
   | 7222    | For bug #184687, skip the huge --depclean warning when       |
   | zmedico | --quiet mode is enabled.                                     |
   |---------+--------------------------------------------------------------|
   | 7224    | Fix typo.                                                    |
   | zmedico |                                                              |
   |---------+--------------------------------------------------------------|
   | 7226    | Fix another case similar to bug #184806 that can occur with  |
   | zmedico | --onlydeps.                                                  |
   |---------+--------------------------------------------------------------|
   | 7228    | Fix typo.                                                    |
   | zmedico |                                                              |
   |---------+--------------------------------------------------------------|
   | 7230    | Use set.discard() instead of remove() to avoid a potential   |
   | zmedico | KeyError.                                                    |
   |---------+--------------------------------------------------------------|
   | 7237    | For bug #184983, prevent USE_EXPAND_HIDDEN flags from being  |
   | zmedico | hidden if they are the only thing that triggered             |
   |         | reinstallation.                                              |
   |---------+--------------------------------------------------------------|
   | 7239    | Make depgraph._reinstall_for_flags() always return all       |
   | zmedico | revelant flags.                                              |
   |---------+--------------------------------------------------------------|
   | 7241    | Fix the case where the currently installed package is from a |
   | zmedico | repo that is no longer in the overlay (oldrepo is None       |
   |         | rather than an empty string).                                |
   |---------+--------------------------------------------------------------|
   | 7242    | Add "reset" to the list of attributes.                       |
   | zmedico |                                                              |
   +------------------------------------------------------------------------+

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

bin/prepstrip
man/color.map.5
pym/emerge/__init__.py
pym/portage/__init__.py
pym/portage/dbapi/porttree.py
pym/portage/dbapi/vartree.py
pym/portage/output.py

index df187c127204e7bcb0d28445399092880c4152b5..68418b5f2d81c3425fb57e688bb2b9b3ba9c6be1 100755 (executable)
@@ -50,6 +50,8 @@ save_elf_debug() {
        mkdir -p $(dirname "${y}")
        ${OBJCOPY} --only-keep-debug "${x}" "${y}"
        ${OBJCOPY} --add-gnu-debuglink="${y}" "${x}"
+       [ -g "${x}" ] && chmod go-r "${y}"
+       [ -u "${x}" ] && chmod go-r "${y}"
        chmod a-x,o-w "${y}"
 }
 
index 7a0f1b2ec63dc7dbd78d4fffc550749366debdd2..bf63bbaedeafd7c1d8befcdd149be7c45c3dcfab 100644 (file)
@@ -123,6 +123,8 @@ Defines color used for warnings.
 .B Other attributes
 .RS
 .TP
+.B reset
+.TP
 .B bold
 .TP
 .B faint
index 6966b79288e989c79bec9e8ca207ff762019242a..20bb8dac2dfaa00d0c2783b75d722c31142df04a 100644 (file)
@@ -352,9 +352,9 @@ def create_depgraph_params(myopts, myaction):
                myparams.add("selective")
        if "--emptytree" in myopts:
                myparams.add("empty")
-               myparams.remove("selective")
+               myparams.discard("selective")
        if "--nodeps" in myopts:
-               myparams.remove("recurse")
+               myparams.discard("recurse")
        if "--deep" in myopts:
                myparams.add("deep")
        return myparams
@@ -1083,6 +1083,8 @@ class depgraph(object):
                self.pkg_node_map = {}
                # Maps slot atom to digraph node for all nodes added to the graph.
                self._slot_node_map = {}
+               # Maps nodes to the reasons they were selected for reinstallation.
+               self._reinstall_nodes = {}
                self.mydbapi = {}
                self._mydbapi_keys = ["SLOT", "DEPEND", "RDEPEND", "PDEPEND",
                        "USE", "IUSE", "PROVIDE", "RESTRICT", "repository"]
@@ -1204,18 +1206,21 @@ class depgraph(object):
 
        def _reinstall_for_flags(self, forced_flags,
                orig_use, orig_iuse, cur_use, cur_iuse):
+               """Return a set of flags that trigger reinstallation, or None if there
+               are no such flags."""
                if "--newuse" in self.myopts:
-                       if orig_iuse.symmetric_difference(
-                               cur_iuse).difference(forced_flags):
-                               return True
-                       elif orig_iuse.intersection(orig_use) != \
-                               cur_iuse.intersection(cur_use):
-                               return True
+                       flags = orig_iuse.symmetric_difference(
+                               cur_iuse).difference(forced_flags)
+                       flags.update(orig_iuse.intersection(orig_use).symmetric_difference(
+                               cur_iuse.intersection(cur_use)))
+                       if flags:
+                               return flags
                elif "changed-use" == self.myopts.get("--reinstall"):
-                       if orig_iuse.intersection(orig_use) != \
-                               cur_iuse.intersection(cur_use):
-                               return True
-               return False
+                       flags = orig_iuse.intersection(orig_use).symmetric_difference(
+                               cur_iuse.intersection(cur_use))
+                       if flags:
+                               return flags
+               return None
 
        def create(self, mybigkey, myparent=None, addme=1, myuse=None,
                priority=DepPriority(), rev_dep=False, arg=None):
@@ -1286,6 +1291,7 @@ class depgraph(object):
                                        return 0
                                del e
 
+               reinstall_for_flags = None
                merging=1
                if mytype == "installed":
                        merging = 0
@@ -1299,6 +1305,7 @@ class depgraph(object):
                            If the package has new iuse flags or different use flags then if
                            --newuse is specified, we need to merge the package. """
                        if merging == 0 and \
+                               myroot == self.target_root and \
                                ("--newuse" in self.myopts or
                                "--reinstall" in self.myopts) and \
                                vardbapi.cpv_exists(mykey):
@@ -1310,8 +1317,9 @@ class depgraph(object):
                                iuses = set(filter_iuse_defaults(metadata["IUSE"].split()))
                                old_iuse = set(filter_iuse_defaults(
                                        vardbapi.aux_get(mykey, ["IUSE"])[0].split()))
-                               if self._reinstall_for_flags(
-                                       forced_flags, old_use, old_iuse, myuse, iuses):
+                               reinstall_for_flags = self._reinstall_for_flags(
+                                       forced_flags, old_use, old_iuse, myuse, iuses)
+                               if reinstall_for_flags:
                                        merging = 1
 
                if addme and merging == 1:
@@ -1379,6 +1387,8 @@ class depgraph(object):
                                self._slot_node_map[myroot][slot_atom] = jbigkey
                                self.pkg_node_map[myroot][mykey] = jbigkey
                                self.useFlags[myroot][mykey] = myuse
+                               if reinstall_for_flags:
+                                       self._reinstall_nodes[jbigkey] = reinstall_for_flags
 
                        if rev_dep and myparent:
                                self.digraph.addnode(myparent, jbigkey,
@@ -1748,6 +1758,9 @@ class depgraph(object):
                                # Update old-style virtuals if this package provides any.
                                # These are needed for dep_virtual calls inside dep_check.
                                p_db = self.mydbapi[p_root] # contains cached metadata
+                               if myparent in self._slot_collision_nodes:
+                                       # The metadata isn't cached due to the slot collision.
+                                       p_db = self.trees[p_root][self.pkg_tree_map[p_type]].dbapi
                                try:
                                        self.pkgsettings[p_root].setinst(p_key, p_db)
                                        # For consistency, also update the global virtuals.
@@ -2740,6 +2753,7 @@ class depgraph(object):
 
                for mylist_index in xrange(len(mylist)):
                        x, depth, ordered = mylist[mylist_index]
+                       pkg_node = tuple(x)
                        pkg_type = x[0]
                        myroot = x[1]
                        pkg_key = x[2]
@@ -2771,14 +2785,18 @@ class depgraph(object):
                                        addl += bad(" (is blocking %s)") % block_parents
                                blockers.append(addl)
                        else:
-                               mydbapi = self.trees[myroot][self.pkg_tree_map[pkg_type]].dbapi
                                pkg_status = x[3]
                                pkg_merge = ordered and pkg_status != "nomerge"
                                binary_package = pkg_type != "ebuild"
+                               if pkg_node in self._slot_collision_nodes or \
+                                       (pkg_status == "nomerge" and pkg_type != "installed"):
+                                       # The metadata isn't cached due to a slot collision or
+                                       # --onlydeps.
+                                       mydbapi = self.trees[myroot][self.pkg_tree_map[pkg_type]].dbapi
+                               else:
+                                       mydbapi = self.mydbapi[myroot] # contains cached metadata
                                metadata = dict(izip(self._mydbapi_keys,
-                                       self.mydbapi[myroot].aux_get(
-                                       pkg_key, self._mydbapi_keys)))
-                               mydbapi = self.mydbapi[myroot] # use the cached metadata
+                                       mydbapi.aux_get(pkg_key, self._mydbapi_keys)))
                                if pkg_key not in self.useFlags[myroot]:
                                        """If this is a --resume then the USE flags need to be
                                        fetched from the appropriate locations here."""
@@ -2896,7 +2914,8 @@ class depgraph(object):
                                        use_expand_hidden = \
                                                pkgsettings["USE_EXPAND_HIDDEN"].lower().split()
 
-                                       def map_to_use_expand(myvals, forcedFlags=False):
+                                       def map_to_use_expand(myvals, forcedFlags=False,
+                                               removeHidden=True):
                                                ret = {}
                                                forced = {}
                                                for exp in use_expand:
@@ -2911,13 +2930,32 @@ class depgraph(object):
                                                ret["USE"] = myvals
                                                forced["USE"] = [val for val in myvals \
                                                        if val in forced_flags]
-                                               for exp in use_expand_hidden:
-                                                       if exp in ret:
-                                                               del ret[exp]
+                                               if removeHidden:
+                                                       for exp in use_expand_hidden:
+                                                               ret.pop(exp, None)
                                                if forcedFlags:
                                                        return ret, forced
                                                return ret
 
+                                       # Prevent USE_EXPAND_HIDDEN flags from being hidden if they
+                                       # are the only thing that triggered reinstallation.
+                                       reinst_flags_map = None
+                                       reinstall_for_flags = self._reinstall_nodes.get(pkg_node)
+                                       if reinstall_for_flags:
+                                               reinst_flags_map = map_to_use_expand(
+                                                       list(reinstall_for_flags), removeHidden=False)
+                                               if reinst_flags_map["USE"]:
+                                                       reinst_flags_map = None
+                                               else:
+                                                       for k in reinst_flags_map.keys():
+                                                               if not reinst_flags_map[k]:
+                                                                       del reinst_flags_map[k]
+                                       if reinst_flags_map and \
+                                               not set(reinst_flags_map).difference(
+                                               use_expand_hidden):
+                                               use_expand_hidden = set(use_expand_hidden).difference(
+                                                       reinst_flags_map)
+
                                        cur_iuse_map, iuse_forced = \
                                                map_to_use_expand(cur_iuse, forcedFlags=True)
                                        cur_use_map = map_to_use_expand(cur_use)
@@ -2978,7 +3016,7 @@ class depgraph(object):
                                                        newrepoindex += 1
                                                
                                                # assing lookup indexes
-                                               if oldrepo == "":
+                                               if not oldrepo:
                                                        oldrepoindex = "?"
                                                elif oldrepo == pkgsettings["PORTDIR"]:
                                                        oldrepoindex = "0"
@@ -5275,23 +5313,26 @@ def action_depclean(settings, trees, ldpath_mtimes,
        # Kill packages that aren't explicitly merged or are required as a
        # dependency of another package. World file is explicit.
 
-       warn_prefix = colorize("BAD", "*** WARNING ***  ")
-       print
-       print warn_prefix + "Depclean may break link level dependencies.  Thus, it is"
-       print warn_prefix + "recommended to use a tool such as " + good("`revdep-rebuild`") + " (from"
-       print warn_prefix + "app-portage/gentoolkit) in order to detect such breakage."
-       print warn_prefix
-       print warn_prefix + "Also study the list of packages to be cleaned for any obvious"
-       print warn_prefix + "mistakes. Packages that are part of the world set will always"
-       print warn_prefix + "be kept.  They can be manually added to this set with"
-       print warn_prefix + good("`emerge --noreplace <atom>`") + ".  Packages that are listed in"
-       print warn_prefix + "package.provided (see portage(5)) will be removed by"
-       print warn_prefix + "depclean, even if they are part of the world set."
-       print warn_prefix
-       print warn_prefix + "As a safety measure, depclean will not remove any packages"
-       print warn_prefix + "unless *all* required dependencies have been resolved.  As a"
-       print warn_prefix + "consequence, it is often necessary to run "
-       print warn_prefix + good("`emerge --update --newuse --deep world`") + " prior to depclean."
+       msg = []
+       msg.append("Depclean may break link level dependencies.  Thus, it is\n")
+       msg.append("recommended to use a tool such as " + good("`revdep-rebuild`") + " (from\n")
+       msg.append("app-portage/gentoolkit) in order to detect such breakage.\n")
+       msg.append("\n")
+       msg.append("Also study the list of packages to be cleaned for any obvious\n")
+       msg.append("mistakes. Packages that are part of the world set will always\n")
+       msg.append("be kept.  They can be manually added to this set with\n")
+       msg.append(good("`emerge --noreplace <atom>`") + ".  Packages that are listed in\n")
+       msg.append("package.provided (see portage(5)) will be removed by\n")
+       msg.append("depclean, even if they are part of the world set.\n")
+       msg.append("\n")
+       msg.append("As a safety measure, depclean will not remove any packages\n")
+       msg.append("unless *all* required dependencies have been resolved.  As a\n")
+       msg.append("consequence, it is often necessary to run\n")
+       msg.append(good("`emerge --update --newuse --deep world`") + " prior to depclean.\n")
+
+       portage.writemsg_stdout("\n")
+       for x in msg:
+               portage.writemsg_stdout(colorize("BAD", "*** WARNING ***  ") + x)
 
        xterm_titles = "notitles" not in settings.features
        myroot = settings["ROOT"]
index 6515df00cdb198e40e5688c1d8d330ff21ff61ed..a6a39c895c70d2cc04dd34e979a560d718126bc5 100644 (file)
@@ -706,8 +706,12 @@ def env_update(makelinks=1, target_root=None, prev_mtimes=None, contents=None,
 
        env_keys = [ x for x in env if x != "LDPATH" ]
        env_keys.sort()
-       for x in env_keys:
-               outfile.write("export %s='%s'\n" % (x, env[x]))
+       for k in env_keys:
+               v = env[k]
+               if v.startswith('$') and not v.startswith('${'):
+                       outfile.write("export %s=$'%s'\n" % (k, v[1:]))
+               else:
+                       outfile.write("export %s='%s'\n" % (k, v))
        outfile.close()
 
        #create /etc/csh.env for (t)csh support
@@ -2080,34 +2084,49 @@ class config(object):
                        # like LINGUAS.
                        var_split = [ x for x in var_split if x in expand_flags ]
                        var_split.extend(expand_flags.difference(var_split))
-                       if (var_split or var in self) and \
-                               "*" not in var_split:
+                       has_wildcard = "*" in var_split
+                       if has_wildcard:
+                               var_split = [ x for x in var_split if x != "*" ]
+                       has_iuse = False
+                       for x in iuse:
+                               if x.startswith(prefix):
+                                       has_iuse = True
+                                       break
+                       if has_wildcard:
+                               # * means to enable everything in IUSE that's not masked
+                               if has_iuse:
+                                       for x in iuse:
+                                               if x.startswith(prefix) and x not in self.usemask:
+                                                       suffix = x[prefix_len:]
+                                                       if suffix in var_split:
+                                                               continue
+                                                       var_split.append(suffix)
+                                                       usesplit.append(x)
+                               else:
+                                       # If there is a wildcard and no matching flags in IUSE then
+                                       # LINGUAS should be unset so that all .mo files are
+                                       # installed.
+                                       var_split = []
+                       if var_split:
+                               self[var] = " ".join(var_split)
+                       else:
                                # Don't export empty USE_EXPAND vars unless the user config
                                # exports them as empty.  This is required for vars such as
                                # LINGUAS, where unset and empty have different meanings.
-                               self[var] = " ".join(var_split)
-                       elif "*" in var_split:
-                               # * means to enable everything in IUSE that's not masked
-                               filtered_split = []
-                               for x in var_split:
-                                       if x == "*":
-                                               continue
-                                       if (prefix + x) in iuse:
-                                               filtered_split.append(x)
-                               var_split = filtered_split
-                               for x in iuse:
-                                       if x.startswith(prefix) and x not in self.usemask:
-                                               suffix = x[prefix_len:]
-                                               if suffix in var_split:
-                                                       continue
-                                               var_split.append(suffix)
-                                               usesplit.append(x)
-                               if var_split:
-                                       self[var] = " ".join(var_split)
-                               elif var in self:
+                               if has_wildcard:
                                        # ebuild.sh will see this and unset the variable so
                                        # that things like LINGUAS work properly
                                        self[var] = "*"
+                               else:
+                                       if has_iuse:
+                                               self[var] = ""
+                                       else:
+                                               # It's not in IUSE, so just allow the variable content
+                                               # to pass through if it is defined somewhere.  This
+                                               # allows packages that support LINGUAS but don't
+                                               # declare it in IUSE to use the variable outside of the
+                                               # USE_EXPAND context.
+                                               pass
 
                # Pre-Pend ARCH variable to USE settings so '-*' in env doesn't kill arch.
                if self.configdict["defaults"].has_key("ARCH"):
index 128e5b166a71911bf4eca438c221df402a664b3b..34eff92a7e583fc42ff4150426d2d184576403a5 100644 (file)
@@ -91,8 +91,9 @@ class portdbapi(dbapi):
                                repo_name = open(repo_name_path, 'r').readline().strip()
                                self.treemap[repo_name] = path
                        except (OSError,IOError):
-                               writemsg("Note: The repository at %s does not have a profiles/repo_name entry.\n" % path \
-                                               + "      This can reduce the functionality of the repository in some cases.\n")
+                               # warn about missing repo_name at some other time, since we
+                               # don't want to see a warning every time the portage module is
+                               # imported.
                                pass
                
                self.auxdbmodule = self.mysettings.load_best_module("portdbapi.auxdbmodule")
index ad16e766190dcb4ef8aabdb8db1e001dc2433a3a..f90c970a61ed92f67834f6469dd89afb57442c22 100644 (file)
@@ -1440,7 +1440,8 @@ class dblink(object):
                        stopmerge = False
                        i=0
                        collisions = []
-
+                       destroot = normalize_path(destroot).rstrip(os.path.sep) + \
+                               os.path.sep
                        print green("*")+" checking "+str(len(mycontents))+" files for package collisions"
                        for f in mycontents:
                                nocheck = False
@@ -1460,10 +1461,34 @@ class dblink(object):
                                try:
                                        dest_lstat = os.lstat(dest_path)
                                except EnvironmentError, e:
-                                       if e.errno != errno.ENOENT:
+                                       if e.errno == errno.ENOENT:
+                                               del e
+                                               continue
+                                       elif e.errno == errno.ENOTDIR:
+                                               del e
+                                               # A non-directory is in a location where this package
+                                               # expects to have a directory.
+                                               dest_lstat = None
+                                               parent_path = dest_path
+                                               while len(parent_path) > len(destroot):
+                                                       parent_path = os.path.dirname(parent_path)
+                                                       try:
+                                                               dest_lstat = os.lstat(parent_path)
+                                                               break
+                                                       except EnvironmentError, e:
+                                                               if e.errno != errno.ENOTDIR:
+                                                                       raise
+                                                               del e
+                                               if not dest_lstat:
+                                                       raise AssertionError(
+                                                               "unable to find non-directory " + \
+                                                               "parent for '%s'" % dest_path)
+                                               dest_path = parent_path
+                                               f = os.path.sep + dest_path[len(destroot):]
+                                               if f in collisions:
+                                                       continue
+                                       else:
                                                raise
-                                       del e
-                                       continue
                                if f[0] != "/":
                                        f="/"+f
                                isowned = False
index 384625bea14a6055387a868c690349f200e29de4..26a5c4f08ae60d6337f48c0162598d47d64be60e 100644 (file)
@@ -129,7 +129,8 @@ codes["bg_lightgray"]  = esc_seq + "47m"
 
 codes["bg_darkyellow"] = codes["bg_brown"]
 
-# Colors from /sbin/functions.sh
+# Colors from /etc/init.d/functions.sh
+codes["NORMAL"]     = esc_seq + "0m"
 codes["GOOD"]       = codes["green"]
 codes["WARN"]       = codes["yellow"]
 codes["BAD"]        = codes["red"]