From a6fc3b46fc9d282e78c873f947416479257af364 Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Fri, 12 Dec 2008 00:04:21 +0000 Subject: [PATCH] Fix --getbinpkgonly behavior so that binaries from the remote server are preferred over local packages if they are not identical. Thanks to Lance Albertson for reporting. svn path=/main/trunk/; revision=12207 --- man/emerge.1 | 6 ++---- pym/_emerge/__init__.py | 17 ++++++++++++----- pym/portage/dbapi/bintree.py | 37 +++++++++++++++++++++++++++++++++++- 3 files changed, 50 insertions(+), 10 deletions(-) diff --git a/man/emerge.1 b/man/emerge.1 index f113ebd3b..4dc8f587b 100644 --- a/man/emerge.1 +++ b/man/emerge.1 @@ -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. diff --git a/pym/_emerge/__init__.py b/pym/_emerge/__init__.py index 81f0f3667..d416bb6b3 100644 --- a/pym/_emerge/__init__.py +++ b/pym/_emerge/__init__.py @@ -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 diff --git a/pym/portage/dbapi/bintree.py b/pym/portage/dbapi/bintree.py index 2b0ebd6f4..0fa2db06a 100644 --- a/pym/portage/dbapi/bintree.py +++ b/pym/portage/dbapi/bintree.py @@ -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: -- 2.26.2