From 9d088f74ab50a6609b5c433997597acda412b239 Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Fri, 16 Jul 2010 11:17:08 -0700 Subject: [PATCH] Bug #327883 - Make EbuildBuild call the pre-clean phase prior to EbuildFetcher, in order to avoid re-use/removal of a build log from a previously failed build. This involves moving the pre-clean phase from EbuildExecuter to EbuildBuild, and moving build dir handling from EbuildFetcher to EbuildBuild. --- pym/_emerge/EbuildBuild.py | 63 ++++++++++++++++------------ pym/_emerge/EbuildExecuter.py | 12 ------ pym/_emerge/EbuildFetcher.py | 77 ++++++++++++++--------------------- 3 files changed, 67 insertions(+), 85 deletions(-) diff --git a/pym/_emerge/EbuildBuild.py b/pym/_emerge/EbuildBuild.py index d42ff6f5f..be6025a82 100644 --- a/pym/_emerge/EbuildBuild.py +++ b/pym/_emerge/EbuildBuild.py @@ -83,32 +83,54 @@ class EbuildBuild(CompositeTask): self.wait() return + self._build_dir = EbuildBuildDir(pkg=pkg, settings=settings) + self._build_dir.lock() + + # Cleaning needs to happen before fetch, since the build dir + # is used for log handling. + msg = " === (%s of %s) Cleaning (%s::%s)" % \ + (self.pkg_count.curval, self.pkg_count.maxval, + self.pkg.cpv, self._ebuild_path) + short_msg = "emerge: (%s of %s) %s Clean" % \ + (self.pkg_count.curval, self.pkg_count.maxval, self.pkg.cpv) + self.logger.log(msg, short_msg=short_msg) + + pre_clean_phase = EbuildPhase(background=self.background, + pkg=self.pkg, phase='clean', + scheduler=self.scheduler, settings=self.settings, + tree=self._tree) + self._start_task(pre_clean_phase, self._pre_clean_exit) + + def _pre_clean_exit(self, pre_clean_phase): + if self._final_exit(pre_clean_phase) != os.EX_OK: + self._unlock_builddir() + self.wait() + return + + # for log handling + portage.prepare_build_dirs(self.pkg.root, self.settings, 1) + fetcher = EbuildFetcher(config_pool=self.config_pool, - fetchall=opts.fetch_all_uri, - fetchonly=opts.fetchonly, + fetchall=self.opts.fetch_all_uri, + fetchonly=self.opts.fetchonly, background=self.background, - pkg=pkg, scheduler=self.scheduler) + logfile=self.settings.get('PORTAGE_LOG_FILE'), + pkg=self.pkg, scheduler=self.scheduler) self._start_task(fetcher, self._fetch_exit) def _fetch_exit(self, fetcher): - opts = self.opts - pkg = self.pkg - - fetch_failed = False - if opts.fetchonly: - fetch_failed = self._final_exit(fetcher) != os.EX_OK - else: - fetch_failed = self._default_exit(fetcher) != os.EX_OK - if fetch_failed and fetcher.logfile is not None and \ - os.path.exists(fetcher.logfile): - self.settings["PORTAGE_LOG_FILE"] = fetcher.logfile + portage.elog.elog_process(self.pkg.cpv, self.settings) - if fetch_failed or opts.fetchonly: + if self._default_exit(fetcher) != os.EX_OK: + self._unlock_builddir() self.wait() return + # discard successful fetch log + self._build_dir.clean_log() + pkg = self.pkg logger = self.logger opts = self.opts pkg_count = self.pkg_count @@ -118,17 +140,6 @@ class EbuildBuild(CompositeTask): ebuild_path = self._ebuild_path system_set = pkg.root_config.sets["system"] - self._build_dir = EbuildBuildDir(pkg=pkg, settings=settings) - self._build_dir.lock() - - # Cleaning is triggered before the setup - # phase, in portage.doebuild(). - msg = " === (%s of %s) Cleaning (%s::%s)" % \ - (pkg_count.curval, pkg_count.maxval, pkg.cpv, ebuild_path) - short_msg = "emerge: (%s of %s) %s Clean" % \ - (pkg_count.curval, pkg_count.maxval, pkg.cpv) - logger.log(msg, short_msg=short_msg) - #buildsyspkg: Check if we need to _force_ binary package creation self._issyspkg = "buildsyspkg" in features and \ system_set.findAtomForPackage(pkg) and \ diff --git a/pym/_emerge/EbuildExecuter.py b/pym/_emerge/EbuildExecuter.py index adb91aa00..4496c757d 100644 --- a/pym/_emerge/EbuildExecuter.py +++ b/pym/_emerge/EbuildExecuter.py @@ -25,18 +25,6 @@ class EbuildExecuter(CompositeTask): def _start(self): self._tree = "porttree" - pkg = self.pkg - phase = "clean" - clean_phase = EbuildPhase(background=self.background, pkg=pkg, phase=phase, - scheduler=self.scheduler, settings=self.settings, tree=self._tree) - self._start_task(clean_phase, self._clean_phase_exit) - - def _clean_phase_exit(self, clean_phase): - - if self._default_exit(clean_phase) != os.EX_OK: - self.wait() - return - pkg = self.pkg scheduler = self.scheduler settings = self.settings diff --git a/pym/_emerge/EbuildFetcher.py b/pym/_emerge/EbuildFetcher.py index 5059e998b..4c26710dc 100644 --- a/pym/_emerge/EbuildFetcher.py +++ b/pym/_emerge/EbuildFetcher.py @@ -8,14 +8,15 @@ import portage from portage import os from portage import _encodings from portage import _unicode_encode +from portage import _unicode_decode import codecs from portage.elog.messages import eerror +from portage.util import writemsg_stdout from portage.util._pty import _create_pty_or_pipe class EbuildFetcher(SpawnProcess): - __slots__ = ("config_pool", "fetchonly", "fetchall", "pkg", "prefetch") + \ - ("_build_dir",) + __slots__ = ("config_pool", "fetchonly", "fetchall", "pkg", "prefetch") def _start(self): @@ -28,26 +29,12 @@ class EbuildFetcher(SpawnProcess): settings.setcpv(self.pkg) if self.prefetch and \ self._prefetch_size_ok(portdb, settings, ebuild_path): + self._settings = None self.config_pool.deallocate(settings) self.returncode = os.EX_OK self.wait() return - # In prefetch mode, logging goes to emerge-fetch.log and the builddir - # should not be touched since otherwise it could interfere with - # another instance of the same cpv concurrently being built for a - # different $ROOT (currently, builds only cooperate with prefetchers - # that are spawned for the same $ROOT). - if not self.prefetch: - self._build_dir = EbuildBuildDir(pkg=self.pkg, settings=settings) - self._build_dir.lock() - self._build_dir.clean_log() - cleanup=1 - # This initializes PORTAGE_LOG_FILE. - portage.prepare_build_dirs(self.pkg.root, self._build_dir.settings, cleanup) - if self.logfile is None: - self.logfile = settings.get("PORTAGE_LOG_FILE") - phase = "fetch" if self.fetchall: phase = "fetchall" @@ -75,6 +62,10 @@ class EbuildFetcher(SpawnProcess): if debug: fetch_args.append("--debug") + # Free settings now since we only have a local reference. + self.config_pool.deallocate(settings) + settings = None + if not self.background and nocolor not in ('yes', 'true'): # Force consistent color output, in case we are capturing fetch # output through a normal pipe due to unavailability of ptys. @@ -82,9 +73,6 @@ class EbuildFetcher(SpawnProcess): self.args = fetch_args self.env = fetch_env - if self._build_dir is None: - # Free settings now since we only have a local reference. - self.config_pool.deallocate(settings) SpawnProcess._start(self) def _prefetch_size_ok(self, portdb, settings, ebuild_path): @@ -151,30 +139,25 @@ class EbuildFetcher(SpawnProcess): SpawnProcess._set_returncode(self, wait_retval) # Collect elog messages that might have been # created by the pkg_nofetch phase. - if self._build_dir is not None: - # Skip elog messages for prefetch, in order to avoid duplicates. - if not self.prefetch and self.returncode != os.EX_OK: - elog_out = None - if self.logfile is not None: - if self.background: - elog_out = codecs.open(_unicode_encode(self.logfile, - encoding=_encodings['fs'], errors='strict'), - mode='a', encoding=_encodings['content'], errors='replace') - msg = "Fetch failed for '%s'" % (self.pkg.cpv,) - if self.logfile is not None: - msg += ", Log file:" - eerror(msg, phase="unpack", key=self.pkg.cpv, out=elog_out) - if self.logfile is not None: - eerror(" '%s'" % (self.logfile,), - phase="unpack", key=self.pkg.cpv, out=elog_out) - if elog_out is not None: - elog_out.close() - if not self.prefetch: - portage.elog.elog_process(self.pkg.cpv, self._build_dir.settings) - features = self._build_dir.settings.features - if self.returncode == os.EX_OK: - self._build_dir.clean_log() - self._build_dir.unlock() - self.config_pool.deallocate(self._build_dir.settings) - self._build_dir = None - + # Skip elog messages for prefetch, in order to avoid duplicates. + if not self.prefetch and self.returncode != os.EX_OK: + out = portage.StringIO() + msg = "Fetch failed for '%s'" % (self.pkg.cpv,) + if self.logfile is not None: + msg += ", Log file:" + eerror(msg, phase="unpack", key=self.pkg.cpv, out=out) + if self.logfile is not None: + eerror(" '%s'" % (self.logfile,), + phase="unpack", key=self.pkg.cpv, out=out) + msg = _unicode_decode(out.getvalue(), + encoding=_encodings['content'], errors='replace') + if msg: + if not self.background: + writemsg_stdout(msg, noiselevel=-1) + if self.logfile is not None: + log_file = codecs.open(_unicode_encode(self.logfile, + encoding=_encodings['fs'], errors='strict'), + mode='a', encoding=_encodings['content'], + errors='backslashreplace') + log_file.write(msg) + log_file.close() -- 2.26.2