MergeProcess: relocate portage reinstall code
authorZac Medico <zmedico@gentoo.org>
Sat, 26 Mar 2011 08:18:12 +0000 (01:18 -0700)
committerZac Medico <zmedico@gentoo.org>
Sat, 26 Mar 2011 08:18:12 +0000 (01:18 -0700)
This code goes inside _start since it needs to execute in the parent
process.

pym/portage/dbapi/_MergeProcess.py
pym/portage/dbapi/vartree.py

index 10d8873ec773d461030313c7b0c10e34861e73a2..43111cb16af0a6ac584f9bcc468f19b4d3f11358 100644 (file)
@@ -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]
 
index 98f578f4395658e9418f032a4dc77f3547788a6d..f8ce3310a6beb569f6737253446699a28fbdb05d 100644 (file)
@@ -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