Fix --getbinpkgonly behavior so that binaries from the remote server are
authorZac Medico <zmedico@gentoo.org>
Fri, 12 Dec 2008 00:04:21 +0000 (00:04 -0000)
committerZac Medico <zmedico@gentoo.org>
Fri, 12 Dec 2008 00:04:21 +0000 (00:04 -0000)
preferred over local packages if they are not identical. Thanks to Lance
Albertson <ramereth@g.o> for reporting.

svn path=/main/trunk/; revision=12207

man/emerge.1
pym/_emerge/__init__.py
pym/portage/dbapi/bintree.py

index f113ebd3b59bc417b519e156b4c5a62b3c4a3e65..4dc8f587bf4a9c8eddf24e834747b65cdbf62341 100644 (file)
@@ -320,10 +320,8 @@ list.  This option implies \fB\-k\fR.  (Use \fB\-gK\fR for binary\-only
 merging.)
 .TP
 .BR "\-\-getbinpkgonly " (\fB\-G\fR)
-This option is identical to \fB\-g\fR, as above, except it will not use ANY 
-information from the local machine.  All binaries will be downloaded from the 
-remote server without consulting packages existing in the local packages 
-directory.
+This option is identical to \fB\-g\fR, as above, except binaries from the
+remote server are preferred over local packages if they are not identical.
 .TP
 .BR "\-\-ignore-default-opts"
 Causes \fIEMERGE_DEFAULT_OPTS\fR (see \fBmake.conf\fR(5)) to be ignored.
index 81f0f3667024feabaaea60a0c429a07c19a7e5f9..d416bb6b36e91741037bed73ecc97595091011f6 100644 (file)
@@ -3409,7 +3409,18 @@ class BinpkgFetcher(SpawnProcess):
                settings = bintree.settings
                use_locks = "distlocks" in settings.features
                pkg_path = self.pkg_path
-               resume = os.path.exists(pkg_path)
+
+               portage.util.ensure_dirs(os.path.dirname(pkg_path))
+               if use_locks:
+                       self.lock()
+               exists = os.path.exists(pkg_path)
+               resume = exists and os.path.basename(pkg_path) in bintree.invalids
+               if not resume:
+                       # Remove existing file or broken symlink.
+                       try:
+                               os.unlink(pkg_path)
+                       except OSError:
+                               pass
 
                # urljoin doesn't work correctly with
                # unrecognized protocols like sftp
@@ -3441,10 +3452,6 @@ class BinpkgFetcher(SpawnProcess):
                fetch_args = [portage.util.varexpand(x, mydict=fcmd_vars) \
                        for x in shlex.split(fcmd)]
 
-               portage.util.ensure_dirs(os.path.dirname(pkg_path))
-               if use_locks:
-                       self.lock()
-
                if self.fd_pipes is None:
                        self.fd_pipes = {}
                fd_pipes = self.fd_pipes
index 2b0ebd6f4b26a0d789c49168db86212bf8603b5c..0fa2db06af30bcd134bcf58a74767a26714961c7 100644 (file)
@@ -407,7 +407,7 @@ class binarytree(object):
                if (not os.path.isdir(self.pkgdir) and not getbinpkgs):
                        return 0
 
-               if not getbinpkgsonly:
+               if True:
                        pkg_paths = {}
                        self._pkg_paths = pkg_paths
                        dirs = listdir(self.pkgdir, dirsonly=True, EmptyOnError=True)
@@ -689,6 +689,32 @@ class binarytree(object):
                                for cpv in self._remotepkgs:
                                        self.dbapi.cpv_inject(cpv)
                                self.populated = 1
+                               if getbinpkgsonly:
+                                       # Remote package instances override local package
+                                       # if they are not identical.
+                                       hash_names = ["SIZE"] + self._pkgindex_hashes
+                                       for cpv, local_metadata in metadata.iteritems():
+                                               remote_metadata = self._remotepkgs.get(cpv)
+                                               if remote_metadata is None:
+                                                       continue
+                                               # Use digests to compare identity.
+                                               identical = True
+                                               for hash_name in hash_names:
+                                                       local_value = local_metadata.get(hash_name)
+                                                       if local_value is None:
+                                                               continue
+                                                       remote_value = remote_metadata.get(hash_name)
+                                                       if remote_value is None:
+                                                               continue
+                                                       if local_value != remote_value:
+                                                               identical = False
+                                                               break
+                                               if identical:
+                                                       del self._remotepkgs[cpv]
+                               else:
+                                       # Local package instances override remote instances.
+                                       for cpv in metadata:
+                                               self._remotepkgs.pop(cpv, None)
                                return
                        self._remotepkgs = {}
                        try:
@@ -835,6 +861,11 @@ class binarytree(object):
                        if pkgindex_lock:
                                unlockfile(pkgindex_lock)
 
+               if self._remotepkgs is not None:
+                       # When a remote package is downloaded and injected,
+                       # update state so self.isremote() returns False.
+                       self._remotepkgs.pop(cpv, None)
+
        def _pkgindex_entry(self, cpv):
                """
                Performs checksums and evaluates USE flag conditionals.
@@ -975,6 +1006,10 @@ class binarytree(object):
                downloaded (or it is only partially downloaded)."""
                if self._remotepkgs is None or pkgname not in self._remotepkgs:
                        return False
+               if self._remote_has_index:
+                       # Presence in self._remotepkgs implies that it's remote. When a
+                       # package is downloaded, state is updated by self.inject().
+                       return True
                pkg_path = self.getname(pkgname)
                if os.path.exists(pkg_path) and \
                        os.path.basename(pkg_path) not in self.invalids: