From 84e8783a421238e9982e28800c7b71b4892515e1 Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Sat, 26 Mar 2011 01:18:12 -0700 Subject: [PATCH] MergeProcess: relocate portage reinstall code This code goes inside _start since it needs to execute in the parent process. --- pym/portage/dbapi/_MergeProcess.py | 67 +++++++++++++++++++++++++++++- pym/portage/dbapi/vartree.py | 61 +-------------------------- 2 files changed, 67 insertions(+), 61 deletions(-) diff --git a/pym/portage/dbapi/_MergeProcess.py b/pym/portage/dbapi/_MergeProcess.py index 10d8873ec..43111cb16 100644 --- a/pym/portage/dbapi/_MergeProcess.py +++ b/pym/portage/dbapi/_MergeProcess.py @@ -1,14 +1,20 @@ # Copyright 2010-2011 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 +import shutil import signal +import tempfile import traceback import errno import fcntl import portage from portage import os, StringIO, _unicode_decode +from portage.const import PORTAGE_PACKAGE_ATOM +from portage.dep import match_from_list import portage.elog.messages +from portage.elog import _preload_elog_modules +from portage.util import ensure_dirs from _emerge.PollConstants import PollConstants from _emerge.SpawnProcess import SpawnProcess @@ -23,6 +29,60 @@ class MergeProcess(SpawnProcess): 'mydbapi', 'prev_mtimes', '_elog_reader_fd', '_elog_reg_id', '_buf', '_elog_keys') + def _start(self): + self._handle_self_reinstall() + super(MergeProcess, self)._start() + + def _handle_self_reinstall(self): + """ + If portage is reinstalling itself, create temporary + copies of PORTAGE_BIN_PATH and PORTAGE_PYM_PATH in order + to avoid relying on the new versions which may be + incompatible. Register an atexit hook to clean up the + temporary directories. Pre-load elog modules here since + we won't be able to later if they get unmerged (happens + when namespace changes). + """ + + settings = self.settings + cpv = settings.mycpv + reinstall_self = False + if self.settings["ROOT"] == "/" and \ + match_from_list(PORTAGE_PACKAGE_ATOM, [cpv]): + inherited = frozenset(self.settings.get('INHERITED', '').split()) + if not self.vartree.dbapi.cpv_exists(cpv) or \ + '9999' in cpv or \ + 'git' in inherited or \ + 'git-2' in inherited: + reinstall_self = True + + if reinstall_self: + # Load lazily referenced portage submodules into memory, + # so imports won't fail during portage upgrade/downgrade. + _preload_elog_modules(self.settings) + portage.proxy.lazyimport._preload_portage_submodules() + + # Make the temp directory inside $PORTAGE_TMPDIR/portage, since + # it's common for /tmp and /var/tmp to be mounted with the + # "noexec" option (see bug #346899). + build_prefix = os.path.join(settings["PORTAGE_TMPDIR"], "portage") + ensure_dirs(build_prefix) + base_path_tmp = tempfile.mkdtemp( + "", "._portage_reinstall_.", build_prefix) + portage.process.atexit_register(shutil.rmtree, base_path_tmp) + dir_perms = 0o755 + for subdir in "bin", "pym": + var_name = "PORTAGE_%s_PATH" % subdir.upper() + var_orig = settings[var_name] + var_new = os.path.join(base_path_tmp, subdir) + settings[var_name] = var_new + settings.backup_changes(var_name) + shutil.copytree(var_orig, var_new, symlinks=True) + os.chmod(var_new, dir_perms) + portage._bin_path = settings['PORTAGE_BIN_PATH'] + portage._pym_path = settings['PORTAGE_PYM_PATH'] + os.chmod(base_path_tmp, dir_perms) + def _elog_output_handler(self, fd, event): output = None if event & PollConstants.POLLIN: @@ -51,7 +111,6 @@ class MergeProcess(SpawnProcess): dblink.merge(). """ - files = self._files elog_reader_fd, elog_writer_fd = os.pipe() fcntl.fcntl(elog_reader_fd, fcntl.F_SETFL, fcntl.fcntl(elog_reader_fd, fcntl.F_GETFL) | os.O_NONBLOCK) @@ -69,7 +128,13 @@ class MergeProcess(SpawnProcess): self._elog_reader_fd = elog_reader_fd self._buf = "" self._elog_keys = set() + + # invalidate relevant vardbapi caches + if self.vartree.dbapi._categories is not None: + self.vartree.dbapi._categories = None self.vartree.dbapi._pkgs_changed = True + self.vartree.dbapi._clear_pkg_cache(mylink) + portage.process.spawned_pids.append(pid) return [pid] diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py index 98f578f43..f8ce3310a 100644 --- a/pym/portage/dbapi/vartree.py +++ b/pym/portage/dbapi/vartree.py @@ -14,7 +14,7 @@ portage.proxy.lazyimport.lazyimport(globals(), 'portage.dep:dep_getkey,isjustname,match_from_list,' + \ 'use_reduce,_slot_re', 'portage.elog:collect_ebuild_messages,collect_messages,' + \ - 'elog_process,_merge_logentries,_preload_elog_modules', + 'elog_process,_merge_logentries', 'portage.locks:lockdir,unlockdir', 'portage.output:bold,colorize', 'portage.package.ebuild.doebuild:doebuild_environment,' + \ @@ -3824,65 +3824,6 @@ class dblink(object): showMessage(zing + " " + mydest + "\n") def merge(self, mergeroot, inforoot, myroot=None, myebuild=None, cleanup=0, - mydbapi=None, prev_mtimes=None): - """ - If portage is reinstalling itself, create temporary - copies of PORTAGE_BIN_PATH and PORTAGE_PYM_PATH in order - to avoid relying on the new versions which may be - incompatible. Register an atexit hook to clean up the - temporary directories. Pre-load elog modules here since - we won't be able to later if they get unmerged (happens - when namespace changes). - - @param myroot: ignored, self._eroot is used instead - """ - myroot = None - if self.vartree.dbapi._categories is not None: - self.vartree.dbapi._categories = None - reinstall_self = False - if self.myroot == "/" and \ - match_from_list(PORTAGE_PACKAGE_ATOM, [self.mycpv]): - inherited = frozenset(self.settings.get('INHERITED', '').split()) - if not self.vartree.dbapi.cpv_exists(self.mycpv) or \ - '9999' in self.mycpv or \ - 'git' in inherited or \ - 'git-2' in inherited: - reinstall_self = True - - if reinstall_self: - # Load lazily referenced portage submodules into memory, - # so imports won't fail during portage upgrade/downgrade. - portage.proxy.lazyimport._preload_portage_submodules() - settings = self.settings - - # Make the temp directory inside $PORTAGE_TMPDIR/portage, since - # it's common for /tmp and /var/tmp to be mounted with the - # "noexec" option (see bug #346899). - build_prefix = os.path.join(settings["PORTAGE_TMPDIR"], "portage") - ensure_dirs(build_prefix) - base_path_tmp = tempfile.mkdtemp( - "", "._portage_reinstall_.", build_prefix) - portage.process.atexit_register(shutil.rmtree, base_path_tmp) - dir_perms = 0o755 - for subdir in "bin", "pym": - var_name = "PORTAGE_%s_PATH" % subdir.upper() - var_orig = settings[var_name] - var_new = os.path.join(base_path_tmp, subdir) - settings[var_name] = var_new - settings.backup_changes(var_name) - shutil.copytree(var_orig, var_new, symlinks=True) - os.chmod(var_new, dir_perms) - portage._bin_path = settings['PORTAGE_BIN_PATH'] - portage._pym_path = settings['PORTAGE_PYM_PATH'] - os.chmod(base_path_tmp, dir_perms) - # This serves so pre-load the modules. - _preload_elog_modules(self.settings) - - return self._merge(mergeroot, inforoot, - myebuild=myebuild, cleanup=cleanup, - mydbapi=mydbapi, prev_mtimes=prev_mtimes) - - def _merge(self, mergeroot, inforoot, myroot=None, myebuild=None, cleanup=0, mydbapi=None, prev_mtimes=None): """ @param myroot: ignored, self._eroot is used instead -- 2.26.2