summaryrefslogtreecommitdiffstats
path: root/pym/portage/dbapi/_MergeProcess.py
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2011-03-26 01:18:12 -0700
committerZac Medico <zmedico@gentoo.org>2011-03-26 01:18:12 -0700
commit84e8783a421238e9982e28800c7b71b4892515e1 (patch)
treebb21de314985c3099dda09cb10ee0d5050efb853 /pym/portage/dbapi/_MergeProcess.py
parenta1a23d2bc25a324b24c180dc982d9442229dc9eb (diff)
downloadportage-84e8783a421238e9982e28800c7b71b4892515e1.tar.gz
portage-84e8783a421238e9982e28800c7b71b4892515e1.tar.bz2
portage-84e8783a421238e9982e28800c7b71b4892515e1.zip
MergeProcess: relocate portage reinstall code
This code goes inside _start since it needs to execute in the parent process.
Diffstat (limited to 'pym/portage/dbapi/_MergeProcess.py')
-rw-r--r--pym/portage/dbapi/_MergeProcess.py67
1 files changed, 66 insertions, 1 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]