Bug #327883 - Make EbuildBuild call the pre-clean phase prior to
authorZac Medico <zmedico@gentoo.org>
Fri, 16 Jul 2010 18:17:08 +0000 (11:17 -0700)
committerZac Medico <zmedico@gentoo.org>
Fri, 16 Jul 2010 18:17:08 +0000 (11:17 -0700)
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
pym/_emerge/EbuildExecuter.py
pym/_emerge/EbuildFetcher.py

index d42ff6f5f3bfbdeecb59b32cce3e981d281b0ba9..be6025a8281f9d51e37020443c0aff9a7465b521 100644 (file)
@@ -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 \
index adb91aa0063541ee4be95c734c8a3e2af12f7707..4496c757d2e5407bf2b43c731ddb3911e91a3a1f 100644 (file)
@@ -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
index 5059e998b68a7a0681652f80786a32b0c6b470f8..4c26710dc4ab6385608397e3858b58ec85890ef9 100644 (file)
@@ -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()