diff options
Diffstat (limited to 'lib/portage/dbapi/bintree.py')
-rw-r--r-- | lib/portage/dbapi/bintree.py | 44 |
1 files changed, 33 insertions, 11 deletions
diff --git a/lib/portage/dbapi/bintree.py b/lib/portage/dbapi/bintree.py index 180e48c3b..ab09b42bc 100644 --- a/lib/portage/dbapi/bintree.py +++ b/lib/portage/dbapi/bintree.py @@ -31,6 +31,7 @@ from portage.exception import AlarmSignal, InvalidPackageName, \ ParseError, PortageException from portage.localization import _ from portage.package.ebuild.profile_iuse import iter_iuse_vars +from portage.util.file_copy import copyfile from portage.util.futures import asyncio from portage.util.futures.compat_coroutine import coroutine from portage.util.futures.executor.fork import ForkExecutor @@ -483,6 +484,17 @@ class binarytree: myoldpkg = catsplit(mycpv)[1] mynewpkg = catsplit(mynewcpv)[1] + # If this update has already been applied to the same + # package build then silently continue. + applied = False + for maybe_applied in self.dbapi.match('={}'.format(mynewcpv)): + if maybe_applied.build_time == mycpv.build_time: + applied = True + break + + if applied: + continue + if (mynewpkg != myoldpkg) and self.dbapi.cpv_exists(mynewcpv): writemsg(_("!!! Cannot update binary: Destination exists.\n"), noiselevel=-1) @@ -513,24 +525,34 @@ class binarytree: mydata[_unicode_encode(mynewpkg + '.ebuild', encoding=_encodings['repo.content'])] = ebuild_data - mytbz2.recompose_mem(portage.xpak.xpak_mem(mydata)) - - self.dbapi.cpv_remove(mycpv) - del self._pkg_paths[self.dbapi._instance_key(mycpv)] metadata = self.dbapi._aux_cache_slot_dict() for k in self.dbapi._aux_cache_keys: v = mydata.get(_unicode_encode(k)) if v is not None: v = _unicode_decode(v) metadata[k] = " ".join(v.split()) + + # Create a copy of the old version of the package and + # apply the update to it. Leave behind the old version, + # assuming that it will be deleted by eclean-pkg when its + # time comes. mynewcpv = _pkg_str(mynewcpv, metadata=metadata, db=self.dbapi) - new_path = self.getname(mynewcpv) - self._pkg_paths[ - self.dbapi._instance_key(mynewcpv)] = new_path[len(self.pkgdir)+1:] - if new_path != tbz2path: - self._ensure_dir(os.path.dirname(new_path)) - _movefile(tbz2path, new_path, mysettings=self.settings) - self.inject(mynewcpv) + update_path = self.getname(mynewcpv, allocate_new=True) + ".partial" + self._ensure_dir(os.path.dirname(update_path)) + update_path_lock = None + try: + update_path_lock = lockfile(update_path, wantnewlockfile=True) + copyfile(tbz2path, update_path) + mytbz2 = portage.xpak.tbz2(update_path) + mytbz2.recompose_mem(portage.xpak.xpak_mem(mydata)) + self.inject(mynewcpv, filename=update_path) + finally: + if update_path_lock is not None: + try: + os.unlink(update_path) + except OSError: + pass + unlockfile(update_path_lock) return moves |