Merged from trunk -r12492:12520
authorFabian Groffen <grobian@gentoo.org>
Sat, 17 Jan 2009 16:56:19 +0000 (16:56 -0000)
committerFabian Groffen <grobian@gentoo.org>
Sat, 17 Jan 2009 16:56:19 +0000 (16:56 -0000)
   | 12494   | Simplify depgraph._select_pkg_from_graph() by using          |
   | zmedico | match_pkgs().                                                |

   | 12495   | Bug #254860 - Inside _expand_new_virtuals(), generate        |
   | zmedico | instances of Atom instead of plain strings, so calling code  |
   |         | can assume that only Atom instances will be returned when    |
   |         | strict mode is enabled.                                      |

   | 12496   | Use a new 'usersync' feature to control dropping of          |
   | zmedico | privileges for --sync, since it's fairly common for people   |
   |         | to have inconsistent permissions between $PORTDIR and        |
   |         | contained files/directories.                                 |

   | 12497   | Bug #254860 - Add another missing str -> atom conversion     |
   | zmedico | inside _expand_new_virtuals().                               |

   | 12498   | Bug #254825 - Improve messages that are displayed when       |
   | zmedico | manifest generation bails out due to a changed distfile      |
   |         | digest.                                                      |

   | 12499   | Inside digestgen(), don't unnecessarily call fetch() in      |
   | zmedico | cases when the there are no hashes for comparison and the    |
   |         | file already exists in $DISTDIR.                             |

   | 12500   | Bug #254825 - Add a note about the need to use `ebuild       |
   | zmedico | --force manifest` to update distfiles digests.               |

   | 12501   | In spawn(), put the full cpv in opt_name, instead of just    |
   | zmedico | $PF. Thanks to Diego Pettenò <flameeyes@g.o> for the        |
   |         | suggestion.                                                  |

   | 12502   | Make sure spawn() always initializes opt_name because later  |
   | zmedico | code assumes that it is.                                     |

   | 12503   | Add some more variables to config._env_blacklist to ensure   |
   | zmedico | that they never leak in from the calling environment.        |

   | 12514   | Fix repoman conditionals inside _expand_new_virtuals() to    |
   | zmedico | use config.local_config instead of checking for portdbapi    |
   |         | type.                                                        |

   | 12518   | Don't show the running Linux kernel version in the commit    |
   | zmedico | message, since it might leak information that would be       |
   |         | useful to attackers. Thanks to Ned Ludd <solar@g.o> for the  |
   |         | suggestion.                                                  |

   | 12519   | Drop the kernel version from the commit message for all      |
   | zmedico | platforms. Thanks to Fabian Groffen <grobian@g.o> for the    |
   |         | suggestion.                                                  |

   | 12520   | Call depgraph._set_args() inside _load_favorites(), to       |
   | zmedico | eliminate duplicate code.                                    |

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

RELEASE-NOTES
bin/repoman
man/make.conf.5
pym/_emerge/__init__.py
pym/portage/__init__.py

index b68c02d90a32bbbeb71029ff0575af07d103ca10..c5a5dc6c25b37ac699149e9b4d55be857f6669f0 100644 (file)
@@ -47,6 +47,11 @@ portage-2.1.6
   used in ACCEPT_KEYWORDS.
   For packages that don't specify any other KEYWORDS you can use the new **
   token as documented in portage(5) to disable KEYWORDS filtering completely.
+* When generating manifests, existing distfiles digests will not be updated
+  in cases when the current file in $DISTDIR does not match. In order to
+  force digests to be updated, run `ebuild --force <ebuild file> manifest`.
+  This is a safety measure which protects valid distfiles digests from being
+  accidentally replaced by invalid digests.
 
 portage-2.1.5
 ==================================
index dc1bbd6c73c09675c46821e1393b99b9671f81b5..c788f1f683cbec1e0d83c44b5f4d5263c9188291 100755 (executable)
@@ -1894,7 +1894,7 @@ else:
                sys.stderr.write("Failed to insert portage version in message!\n")
                sys.stderr.flush()
                portage_version = "Unknown"
-       unameout = platform.system() + " " + platform.release() + " "
+       unameout = platform.system() + " "
        if platform.system() in ["Darwin", "SunOS"]:
                unameout += platform.processor()
        else:
index 9a0261e2553fbe178461f25bb335d302795ca95e..83b7fa3ba896836b4202a41ade1b92e44010dd39 100644 (file)
@@ -360,6 +360,10 @@ portage:portage without a sandbox (unless \fIusersandbox\fR is also used).
 .B usersandbox
 Enable the sandbox in the compile phase, when running without root privs (\fIuserpriv\fR).
 .TP
+.B usersync
+Drop privileges to the owner of \fBPORTDIR\fR for \fBemerge(1) --sync\fR
+operations.
+.TP
 .B webrsync-gpg
 Enable GPG verification when using \fIemerge\-webrsync\fR.
 .RE
index bc7e3ecc7b859f444a6226dfd0f5885dd31922ab..711418eb3a454df1ff2563439dd6f9441e363964 100644 (file)
@@ -6265,19 +6265,12 @@ class depgraph(object):
                replacement.
                """
                graph_db = self._graph_trees[root]["porttree"].dbapi
-               matches = graph_db.match(atom)
+               matches = graph_db.match_pkgs(atom)
                if not matches:
                        return None, None
-               cpv = matches[-1] # highest match
-               slot_atom = "%s:%s" % (portage.cpv_getkey(cpv),
-                       graph_db.aux_get(cpv, ["SLOT"])[0])
-               e_pkg = self._slot_pkg_map[root].get(slot_atom)
-               if e_pkg:
-                       return e_pkg, e_pkg
-               # Since this cpv exists in the graph_db,
-               # we must have a cached Package instance.
-               cache_key = ("installed", root, cpv, "nomerge")
-               return (self._pkg_cache[cache_key], None)
+               pkg = matches[-1] # highest match
+               in_graph = self._slot_pkg_map[root].get(pkg.slot_atom)
+               return pkg, in_graph
 
        def _complete_graph(self):
                """
@@ -8610,27 +8603,7 @@ class depgraph(object):
                                args.append(AtomArg(arg=x, atom=x,
                                        root_config=root_config))
 
-               # Create the "args" package set from atoms and
-               # packages given as arguments.
-               args_set = self._sets["args"]
-               for arg in args:
-                       if not isinstance(arg, (AtomArg, PackageArg)):
-                               continue
-                       myatom = arg.atom
-                       if myatom in args_set:
-                               continue
-                       args_set.add(myatom)
-               self._set_atoms.update(chain(*self._sets.itervalues()))
-               atom_arg_map = self._atom_arg_map
-               for arg in args:
-                       for atom in arg.set:
-                               atom_key = (atom, arg.root_config.root)
-                               refs = atom_arg_map.get(atom_key)
-                               if refs is None:
-                                       refs = []
-                                       atom_arg_map[atom_key] = refs
-                                       if arg not in refs:
-                                               refs.append(arg)
+               self._set_args(args)
                return args
 
        class UnsatisfiedResumeDep(portage.exception.PortageException):
@@ -12117,7 +12090,8 @@ def action_sync(settings, trees, mtimedb, myopts, myaction):
 
        spawn_kwargs = {}
        spawn_kwargs["env"] = settings.environ()
-       if portage.data.secpass >= 2 and \
+       if 'usersync' in settings.features and \
+               portage.data.secpass >= 2 and \
                (st.st_uid != os.getuid() and st.st_mode & 0700 or \
                st.st_gid != os.getgid() and st.st_mode & 0070):
                try:
index d6aae6b692451aac4f587e04caac0b0c2f020779..98ab4594e9f0010c921e72d94404db6d0df2327a 100644 (file)
@@ -916,9 +916,12 @@ class config(object):
        """
 
        _env_blacklist = [
-               "A", "AA", "CATEGORY", "EBUILD_PHASE", "EMERGE_FROM",
-               "PF", "PKGUSE", "PORTAGE_CONFIGROOT", "PORTAGE_IUSE",
-               "PORTAGE_REPO_NAME", "PORTAGE_USE", "ROOT", "EPREFIX", "EROOT"
+               "A", "AA", "CATEGORY", "DEPEND", "DESCRIPTION", "EAPI",
+               "EBUILD_PHASE", "EMERGE_FROM", "HOMEPAGE", "INHERITED", "IUSE",
+               "KEYWORDS", "LICENSE", "PDEPEND", "PF", "PKGUSE",
+               "PORTAGE_CONFIGROOT", "PORTAGE_IUSE", "PORTAGE_REPO_NAME",
+               "PORTAGE_USE", "PROPERTIES", "PROVIDE", "RDEPEND", "RESTRICT",
+               "ROOT", "SLOT", "SRC_URI", "EPREFIX", "EROOT"
        ]
 
        _environ_whitelist = []
@@ -3052,7 +3055,11 @@ def spawn(mystring, mysettings, debug=0, free=0, droppriv=0, sesandbox=0, fakero
        else:
                check_config_instance(mysettings)
                env=mysettings.environ()
-               keywords["opt_name"]="[%s]" % mysettings["PF"]
+               if mysettings.mycpv is not None:
+                       keywords["opt_name"] = "[%s]" % mysettings.mycpv
+               else:
+                       keywords["opt_name"] = "[%s/%s]" % \
+                               (mysettings.get("CATEGORY",""), mysettings.get("PF",""))
 
        fd_pipes = keywords.get("fd_pipes")
        if fd_pipes is None:
@@ -3940,12 +3947,23 @@ def fetch(myuris, mysettings, listonly=0, fetchonly=0, locks_in_subdir=".locks",
 
                                if not can_fetch:
                                        if fetched != 2:
-                                               if fetched == 0:
+                                               try:
+                                                       mysize = os.stat(myfile_path).st_size
+                                               except OSError, e:
+                                                       if e.errno != errno.ENOENT:
+                                                               raise
+                                                       del e
+                                                       mysize = 0
+
+                                               if mysize == 0:
                                                        writemsg("!!! File %s isn't fetched but unable to get it.\n" % myfile,
                                                                noiselevel=-1)
-                                               else:
+                                               elif size is None or size > mysize:
                                                        writemsg("!!! File %s isn't fully fetched, but unable to complete it\n" % myfile,
                                                                noiselevel=-1)
+                                               else:
+                                                       writemsg(("!!! File %s is incorrect size, " + \
+                                                               "but unable to retry.\n") % myfile, noiselevel=-1)
                                                for var_name in ("FETCHCOMMAND", "RESUMECOMMAND"):
                                                        if not mysettings.get(var_name, None):
                                                                writemsg(("!!! %s is unset.  It should " + \
@@ -4252,7 +4270,12 @@ def digestgen(myarchives, mysettings, overwrite=1, manifestonly=0, myportdb=None
                for myfile in distfiles_map:
                        myhashes = dist_hashes.get(myfile)
                        if not myhashes:
-                               missing_files.append(myfile)
+                               try:
+                                       st = os.stat(os.path.join(mysettings["DISTDIR"], myfile))
+                               except OSError:
+                                       st = None
+                               if st is None or st.st_size == 0:
+                                       missing_files.append(myfile)
                                continue
                        size = myhashes.get("size")
 
@@ -4279,7 +4302,7 @@ def digestgen(myarchives, mysettings, overwrite=1, manifestonly=0, myportdb=None
                                fetch_settings = config(clone=mysettings)
                                debug = mysettings.get("PORTAGE_DEBUG") == "1"
                                for myfile in missing_files:
-                                       success = False
+                                       uris = set()
                                        for cpv in distfiles_map[myfile]:
                                                myebuild = os.path.join(mysettings["O"],
                                                        catsplit(cpv)[1] + ".ebuild")
@@ -4287,15 +4310,33 @@ def digestgen(myarchives, mysettings, overwrite=1, manifestonly=0, myportdb=None
                                                doebuild_environment(myebuild, "fetch",
                                                        mysettings["ROOT"], fetch_settings,
                                                        debug, 1, myportdb)
-                                               uri_map = myportdb.getFetchMap(cpv, mytree=mytree)
-                                               myuris = {myfile:uri_map[myfile]}
-                                               fetch_settings["A"] = myfile # for use by pkg_nofetch()
-                                               if fetch(myuris, fetch_settings):
-                                                       success = True
-                                                       break
-                                       if not success:
-                                               writemsg(("!!! File %s doesn't exist, can't update " + \
+                                               uris.update(myportdb.getFetchMap(
+                                                       cpv, mytree=mytree)[myfile])
+
+                                       fetch_settings["A"] = myfile # for use by pkg_nofetch()
+
+                                       try:
+                                               st = os.stat(os.path.join(
+                                                       mysettings["DISTDIR"],myfile))
+                                       except OSError:
+                                               st = None
+
+                                       if not fetch({myfile : uris}, fetch_settings):
+                                               writemsg(("!!! Fetch failed for %s, can't update " + \
                                                        "Manifest\n") % myfile, noiselevel=-1)
+                                               if myfile in dist_hashes and \
+                                                       st is not None and st.st_size > 0:
+                                                       # stat result is obtained before calling fetch(),
+                                                       # since fetch may rename the existing file if the
+                                                       # digest does not match.
+                                                       writemsg("!!! If you would like to " + \
+                                                               "forcefully replace the existing " + \
+                                                               "Manifest entry\n!!! for %s, use the " % \
+                                                               myfile + "following command:\n" + \
+                                                               "!!!    " + colorize("INFORM",
+                                                               "ebuild --force %s manifest" % \
+                                                               os.path.basename(myebuild)) + "\n",
+                                                               noiselevel=-1)
                                                return 0
                writemsg_stdout(">>> Creating Manifest for %s\n" % mysettings["O"])
                try:
@@ -6308,7 +6349,7 @@ def _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings, myroot="/",
        # for new-style virtuals.  Repoman should enforce this.
        dep_keys = ["RDEPEND", "DEPEND", "PDEPEND"]
        portdb = trees[myroot]["porttree"].dbapi
-       repoman = isinstance(mydbapi, portdbapi)
+       repoman = not mysettings.local_config
        if kwargs["use_binaries"]:
                portdb = trees[myroot]["bintree"].dbapi
        myvirtuals = mysettings.getvirtuals()
@@ -6380,7 +6421,7 @@ def _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings, myroot="/",
                        newsplit.append(x)
                        continue
                if not pkgs and len(mychoices) == 1:
-                       newsplit.append(x.replace(mykey, mychoices[0]))
+                       newsplit.append(portage.dep.Atom(x.replace(mykey, mychoices[0])))
                        continue
                if isblocker:
                        a = []
@@ -6390,8 +6431,7 @@ def _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings, myroot="/",
                        cpv, pv_split, db = y
                        depstring = " ".join(db.aux_get(cpv, dep_keys))
                        pkg_kwargs = kwargs.copy()
-                       if isinstance(db, portdbapi):
-                               # for repoman
+                       if repoman:
                                pass
                        else:
                                # for emerge
@@ -6411,13 +6451,14 @@ def _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings, myroot="/",
                                if len(virtual_atoms) == 1:
                                        # It wouldn't make sense to block all the components of a
                                        # compound virtual, so only a single atom block is allowed.
-                                       a.append("!" + virtual_atoms[0])
+                                       a.append(portage.dep.Atom("!" + virtual_atoms[0]))
                        else:
-                               mycheck[1].append("="+y[0]) # pull in the new-style virtual
+                               # pull in the new-style virtual
+                               mycheck[1].append(portage.dep.Atom("="+y[0]))
                                a.append(mycheck[1])
                # Plain old-style virtuals.  New-style virtuals are preferred.
                for y in mychoices:
-                       a.append(x.replace(mykey, y))
+                       a.append(portage.dep.Atom(x.replace(mykey, y, 1)))
                if isblocker and not a:
                        # Probably a compound virtual.  Pass the atom through unprocessed.
                        newsplit.append(x)