From 51483738aeebe26a120ad30d2c9c662f01e26ff4 Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Mon, 16 Aug 2010 08:16:08 -0700 Subject: Split out parts of doebuild() so that EbuildProcess can bypass it and call the spawn() function directly. --- pym/_emerge/EbuildBuild.py | 17 ++- pym/_emerge/EbuildExecuter.py | 22 ++- pym/_emerge/EbuildProcess.py | 37 ++--- pym/portage/package/ebuild/doebuild.py | 258 +++++++++++++++++---------------- 4 files changed, 185 insertions(+), 149 deletions(-) (limited to 'pym') diff --git a/pym/_emerge/EbuildBuild.py b/pym/_emerge/EbuildBuild.py index be6025a82..f0fdcbdbf 100644 --- a/pym/_emerge/EbuildBuild.py +++ b/pym/_emerge/EbuildBuild.py @@ -1,4 +1,4 @@ -# Copyright 1999-2009 Gentoo Foundation +# Copyright 1999-2010 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 from _emerge.EbuildExecuter import EbuildExecuter @@ -17,6 +17,8 @@ from portage import _encodings from portage import _unicode_encode import codecs from portage.output import colorize +from portage.package.ebuild.doebuild import _check_temp_dir + class EbuildBuild(CompositeTask): __slots__ = ("args_set", "config_pool", "find_blockers", @@ -26,11 +28,16 @@ class EbuildBuild(CompositeTask): def _start(self): - logger = self.logger - opts = self.opts pkg = self.pkg settings = self.settings - world_atom = self.world_atom + + rval = _check_temp_dir(settings) + if rval != os.EX_OK: + self.returncode = rval + self._current_task = None + self.wait() + return + root_config = pkg.root_config tree = "porttree" self._tree = tree @@ -176,7 +183,6 @@ class EbuildBuild(CompositeTask): self.wait() return - opts = self.opts buildpkg = self._buildpkg if not buildpkg: @@ -259,7 +265,6 @@ class EbuildBuild(CompositeTask): and neither fetchonly nor buildpkgonly mode are enabled. """ - find_blockers = self.find_blockers ldpath_mtimes = self.ldpath_mtimes logger = self.logger pkg = self.pkg diff --git a/pym/_emerge/EbuildExecuter.py b/pym/_emerge/EbuildExecuter.py index 90cf401a7..7abcbb77e 100644 --- a/pym/_emerge/EbuildExecuter.py +++ b/pym/_emerge/EbuildExecuter.py @@ -1,4 +1,4 @@ -# Copyright 1999-2009 Gentoo Foundation +# Copyright 1999-2010 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 from _emerge.EbuildPhase import EbuildPhase @@ -7,6 +7,8 @@ from _emerge.CompositeTask import CompositeTask import portage from portage import os from portage.eapi import eapi_has_src_prepare_and_src_configure +from portage.package.ebuild.doebuild import _prepare_env_file, \ + _prepare_fake_distdir class EbuildExecuter(CompositeTask): @@ -30,8 +32,24 @@ class EbuildExecuter(CompositeTask): scheduler = self.scheduler settings = self.settings cleanup = 0 - portage.prepare_build_dirs(pkg.root, settings, cleanup) + rval = _prepare_env_file(settings) + if rval != os.EX_OK: + self.returncode = rval + self._current_task = None + self.wait() + return + + portdb = pkg.root_config.trees['porttree'].dbapi + ebuild_path = settings['EBUILD'] + mytree = os.path.dirname(os.path.dirname( + os.path.dirname(ebuild_path))) + alist = portdb.getFetchMap(pkg.cpv, + useflags=pkg.use.enabled, mytree=mytree) + aalist = portdb.getFetchMap(pkg.cpv, mytree=mytree) + settings.configdict["pkg"]["A"] = " ".join(alist) + settings.configdict["pkg"]["AA"] = " ".join(aalist) + _prepare_fake_distdir(settings, alist) setup_phase = EbuildPhase(background=self.background, pkg=pkg, phase="setup", scheduler=scheduler, diff --git a/pym/_emerge/EbuildProcess.py b/pym/_emerge/EbuildProcess.py index c643c3bd2..bd0e0d6fc 100644 --- a/pym/_emerge/EbuildProcess.py +++ b/pym/_emerge/EbuildProcess.py @@ -1,10 +1,13 @@ -# Copyright 1999-2009 Gentoo Foundation +# Copyright 1999-2010 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 from _emerge.AbstractEbuildProcess import AbstractEbuildProcess +from portage import _shell_quote from portage import os -from portage.package.ebuild.doebuild import doebuild, \ - _post_phase_userpriv_perms +from portage.const import EBUILD_SH_BINARY +from portage.package.ebuild.doebuild import _post_phase_userpriv_perms +from portage.package.ebuild.doebuild import spawn as doebuild_spawn +from portage.package.ebuild.doebuild import _spawn_actionmap class EbuildProcess(AbstractEbuildProcess): @@ -19,21 +22,19 @@ class EbuildProcess(AbstractEbuildProcess): AbstractEbuildProcess._start(self) def _spawn(self, args, **kwargs): - - root_config = self.pkg.root_config - tree = self.tree - mydbapi = root_config.trees[tree].dbapi - vartree = root_config.trees["vartree"] - settings = self.settings - ebuild_path = settings["EBUILD"] - debug = settings.get("PORTAGE_DEBUG") == "1" - - - rval = doebuild(ebuild_path, self.phase, - root_config.root, settings, debug, - mydbapi=mydbapi, tree=tree, vartree=vartree, **kwargs) - - return rval + self.settings["EBUILD_PHASE"] = self.phase + actionmap = _spawn_actionmap(self.settings) + if self.phase in actionmap: + kwargs.update(actionmap[self.phase]["args"]) + cmd = actionmap[self.phase]["cmd"] % self.phase + else: + cmd = "%s %s" % (_shell_quote(os.path.join( + self.settings["PORTAGE_BIN_PATH"], + os.path.basename(EBUILD_SH_BINARY))), self.phase) + try: + return doebuild_spawn(cmd, self.settings, **kwargs) + finally: + self.settings.pop("EBUILD_PHASE", None) def _set_returncode(self, wait_retval): AbstractEbuildProcess._set_returncode(self, wait_retval) diff --git a/pym/portage/package/ebuild/doebuild.py b/pym/portage/package/ebuild/doebuild.py index 90f65c4d9..bcac378d4 100644 --- a/pym/portage/package/ebuild/doebuild.py +++ b/pym/portage/package/ebuild/doebuild.py @@ -542,40 +542,9 @@ def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0, if rval != os.EX_OK: return rval - if "PORTAGE_TMPDIR" not in mysettings or \ - not os.path.isdir(mysettings["PORTAGE_TMPDIR"]): - writemsg(_("The directory specified in your " - "PORTAGE_TMPDIR variable, '%s',\n" - "does not exist. Please create this directory or " - "correct your PORTAGE_TMPDIR setting.\n") % mysettings.get("PORTAGE_TMPDIR", ""), noiselevel=-1) - return 1 - - # as some people use a separate PORTAGE_TMPDIR mount - # we prefer that as the checks below would otherwise be pointless - # for those people. - if os.path.exists(os.path.join(mysettings["PORTAGE_TMPDIR"], "portage")): - checkdir = os.path.join(mysettings["PORTAGE_TMPDIR"], "portage") - else: - checkdir = mysettings["PORTAGE_TMPDIR"] - - if not os.access(checkdir, os.W_OK): - writemsg(_("%s is not writable.\n" - "Likely cause is that you've mounted it as readonly.\n") % checkdir, - noiselevel=-1) - return 1 - else: - fd = tempfile.NamedTemporaryFile(prefix="exectest-", dir=checkdir) - os.chmod(fd.name, 0o755) - if not os.access(fd.name, os.X_OK): - writemsg(_("Can not execute files in %s\n" - "Likely cause is that you've mounted it with one of the\n" - "following mount options: 'noexec', 'user', 'users'\n\n" - "Please make sure that portage can execute files in this directory.\n") % checkdir, - noiselevel=-1) - fd.close() - return 1 - fd.close() - del checkdir + rval = _check_temp_dir(mysettings) + if rval != os.EX_OK: + return rval if mydo == "unmerge": return unmerge(mysettings["CATEGORY"], @@ -601,66 +570,9 @@ def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0, logfile = mysettings.get("PORTAGE_LOG_FILE") if have_build_dirs: - env_file = os.path.join(mysettings["T"], "environment") - env_stat = None - saved_env = None - try: - env_stat = os.stat(env_file) - except OSError as e: - if e.errno != errno.ENOENT: - raise - del e - if not env_stat: - saved_env = os.path.join( - os.path.dirname(myebuild), "environment.bz2") - if not os.path.isfile(saved_env): - saved_env = None - if saved_env: - retval = os.system( - "bzip2 -dc %s > %s" % \ - (_shell_quote(saved_env), - _shell_quote(env_file))) - try: - env_stat = os.stat(env_file) - except OSError as e: - if e.errno != errno.ENOENT: - raise - del e - if os.WIFEXITED(retval) and \ - os.WEXITSTATUS(retval) == os.EX_OK and \ - env_stat and env_stat.st_size > 0: - # This is a signal to ebuild.sh, so that it knows to filter - # out things like SANDBOX_{DENY,PREDICT,READ,WRITE} that - # would be preserved between normal phases. - open(_unicode_encode(env_file + '.raw'), 'w') - else: - writemsg(_("!!! Error extracting saved " - "environment: '%s'\n") % \ - saved_env, noiselevel=-1) - try: - os.unlink(env_file) - except OSError as e: - if e.errno != errno.ENOENT: - raise - del e - env_stat = None - if env_stat: - pass - else: - for var in ("ARCH", ): - value = mysettings.get(var) - if value and value.strip(): - continue - msg = _("%(var)s is not set... " - "Are you missing the '%(configroot)setc/make.profile' symlink? " - "Is the symlink correct? " - "Is your portage tree complete?") % \ - {"var": var, "configroot": mysettings["PORTAGE_CONFIGROOT"]} - for line in wrap(msg, 70): - eerror(line, phase="setup", key=mysettings.mycpv) - elog_process(mysettings.mycpv, mysettings) - return 1 - del env_file, env_stat, saved_env + rval = _prepare_env_file(mysettings) + if rval != os.EX_OK: + return rval # if any of these are being called, handle them -- running them out of # the sandbox -- and stop now. @@ -807,35 +719,7 @@ def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0, # remove PORTAGE_ACTUAL_DISTDIR once cvs/svn is supported via SRC_URI if (mydo != "setup" and "noauto" not in features) or mydo == "unpack": - orig_distdir = mysettings["DISTDIR"] - mysettings["PORTAGE_ACTUAL_DISTDIR"] = orig_distdir - edpath = mysettings["DISTDIR"] = \ - os.path.join(mysettings["PORTAGE_BUILDDIR"], "distdir") - portage.util.ensure_dirs(edpath, gid=portage_gid, mode=0o755) - - # Remove any unexpected files or directories. - for x in os.listdir(edpath): - symlink_path = os.path.join(edpath, x) - st = os.lstat(symlink_path) - if x in alist and stat.S_ISLNK(st.st_mode): - continue - if stat.S_ISDIR(st.st_mode): - shutil.rmtree(symlink_path) - else: - os.unlink(symlink_path) - - # Check for existing symlinks and recreate if necessary. - for x in alist: - symlink_path = os.path.join(edpath, x) - target = os.path.join(orig_distdir, x) - try: - link_target = os.readlink(symlink_path) - except OSError: - os.symlink(target, symlink_path) - else: - if link_target != target: - os.unlink(symlink_path) - os.symlink(target, symlink_path) + _prepare_fake_distdir(mysettings, alist) #initial dep checks complete; time to process main commands actionmap = _spawn_actionmap(mysettings) @@ -923,6 +807,134 @@ def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0, # and the exemption is no longer needed. portage._doebuild_manifest_exempt_depend -= 1 +def _check_temp_dir(settings): + if "PORTAGE_TMPDIR" not in settings or \ + not os.path.isdir(settings["PORTAGE_TMPDIR"]): + writemsg(_("The directory specified in your " + "PORTAGE_TMPDIR variable, '%s',\n" + "does not exist. Please create this directory or " + "correct your PORTAGE_TMPDIR setting.\n") % \ + settings.get("PORTAGE_TMPDIR", ""), noiselevel=-1) + return 1 + + # as some people use a separate PORTAGE_TMPDIR mount + # we prefer that as the checks below would otherwise be pointless + # for those people. + if os.path.exists(os.path.join(settings["PORTAGE_TMPDIR"], "portage")): + checkdir = os.path.join(settings["PORTAGE_TMPDIR"], "portage") + else: + checkdir = settings["PORTAGE_TMPDIR"] + + if not os.access(checkdir, os.W_OK): + writemsg(_("%s is not writable.\n" + "Likely cause is that you've mounted it as readonly.\n") % checkdir, + noiselevel=-1) + return 1 + + else: + fd = tempfile.NamedTemporaryFile(prefix="exectest-", dir=checkdir) + os.chmod(fd.name, 0o755) + if not os.access(fd.name, os.X_OK): + writemsg(_("Can not execute files in %s\n" + "Likely cause is that you've mounted it with one of the\n" + "following mount options: 'noexec', 'user', 'users'\n\n" + "Please make sure that portage can execute files in this directory.\n") % checkdir, + noiselevel=-1) + return 1 + + return os.EX_OK + +def _prepare_env_file(settings): + env_file = os.path.join(settings["T"], "environment") + env_stat = None + saved_env = None + try: + env_stat = os.stat(env_file) + except OSError as e: + if e.errno != errno.ENOENT: + raise + if not env_stat: + saved_env = os.path.join( + os.path.dirname(settings['EBUILD']), "environment.bz2") + if not os.path.isfile(saved_env): + saved_env = None + if saved_env: + retval = os.system( + "bzip2 -dc %s > %s" % \ + (_shell_quote(saved_env), + _shell_quote(env_file))) + try: + env_stat = os.stat(env_file) + except OSError as e: + if e.errno != errno.ENOENT: + raise + if os.WIFEXITED(retval) and \ + os.WEXITSTATUS(retval) == os.EX_OK and \ + env_stat and env_stat.st_size > 0: + # This is a signal to ebuild.sh, so that it knows to filter + # out things like SANDBOX_{DENY,PREDICT,READ,WRITE} that + # would be preserved between normal phases. + open(_unicode_encode(env_file + '.raw'), 'w') + else: + writemsg(_("!!! Error extracting saved " + "environment: '%s'\n") % \ + saved_env, noiselevel=-1) + try: + os.unlink(env_file) + except OSError as e: + if e.errno != errno.ENOENT: + raise + env_stat = None + if env_stat is not None: + pass + else: + for var in ("ARCH", ): + value = settings.get(var) + if value and value.strip(): + continue + msg = _("%(var)s is not set... " + "Are you missing the '%(configroot)setc/make.profile' symlink? " + "Is the symlink correct? " + "Is your portage tree complete?") % \ + {"var": var, "configroot": settings["PORTAGE_CONFIGROOT"]} + for line in wrap(msg, 70): + eerror(line, phase="setup", key=settings.mycpv) + elog_process(settings.mycpv, settings) + return 1 + + return os.EX_OK + +def _prepare_fake_distdir(settings, alist): + orig_distdir = settings["DISTDIR"] + settings["PORTAGE_ACTUAL_DISTDIR"] = orig_distdir + edpath = settings["DISTDIR"] = \ + os.path.join(settings["PORTAGE_BUILDDIR"], "distdir") + portage.util.ensure_dirs(edpath, gid=portage_gid, mode=0o755) + + # Remove any unexpected files or directories. + for x in os.listdir(edpath): + symlink_path = os.path.join(edpath, x) + st = os.lstat(symlink_path) + if x in alist and stat.S_ISLNK(st.st_mode): + continue + if stat.S_ISDIR(st.st_mode): + shutil.rmtree(symlink_path) + else: + os.unlink(symlink_path) + + # Check for existing symlinks and recreate if necessary. + for x in alist: + symlink_path = os.path.join(edpath, x) + target = os.path.join(orig_distdir, x) + try: + link_target = os.readlink(symlink_path) + except OSError: + os.symlink(target, symlink_path) + else: + if link_target != target: + os.unlink(symlink_path) + os.symlink(target, symlink_path) + def _spawn_actionmap(settings): features = settings.features restrict = settings["PORTAGE_RESTRICT"].split() -- cgit v1.2.3-1-g7c22