summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--man/emerge.16
-rw-r--r--pym/_emerge/__init__.py17
-rw-r--r--pym/portage/dbapi/bintree.py37
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: