Eliminate duplicate code by making EbuildProcess inherit from SpawnProcess
authorZac Medico <zmedico@gentoo.org>
Thu, 17 Jul 2008 03:52:24 +0000 (03:52 -0000)
committerZac Medico <zmedico@gentoo.org>
Thu, 17 Jul 2008 03:52:24 +0000 (03:52 -0000)
instead of SubProcess.

svn path=/main/trunk/; revision=11092

pym/_emerge/__init__.py
pym/portage/__init__.py

index 627fee373d947d0a6370e01a71f8a533cb680b7a..1373d3abb05fa86ab86662a2fba4819879afe440 100644 (file)
@@ -2041,7 +2041,7 @@ class SpawnProcess(SubProcess):
                self._files = self._files_dict()
                files = self._files
 
-               master_fd, slave_fd = os.pipe()
+               master_fd, slave_fd = self._pipe(fd_pipes)
                fcntl.fcntl(master_fd, fcntl.F_SETFL,
                        fcntl.fcntl(master_fd, fcntl.F_GETFL) | os.O_NONBLOCK)
 
@@ -2103,6 +2103,13 @@ class SpawnProcess(SubProcess):
                        PollConstants.POLLIN, output_handler)
                self._registered = True
 
+       def _pipe(self, fd_pipes):
+               """
+               @type fd_pipes: dict
+               @param fd_pipes: pipes from which to copy terminal size if desired.
+               """
+               return os.pipe()
+
        def _spawn(self, args, **kwargs):
                return portage.process.spawn(args, **kwargs)
 
@@ -2646,151 +2653,43 @@ class EbuildMetadataPhase(SubProcess):
 
                return self._registered
 
-class EbuildProcess(SubProcess):
+class EbuildProcess(SpawnProcess):
 
-       __slots__ = ("fd_pipes", "phase", "pkg",
-               "settings", "tree")
-
-       _file_names = ("log", "stdout", "ebuild")
-       _files_dict = slot_dict_class(_file_names, prefix="")
-       _bufsize = 4096
+       __slots__ = ("phase", "pkg", "settings", "tree")
 
        def _start(self):
+               self.logfile = self.settings.get("PORTAGE_LOG_FILE")
+               SpawnProcess._start(self)
+
+       def _pipe(self, fd_pipes):
+               stdout_pipe = fd_pipes.get(1)
+               got_pty, master_fd, slave_fd = \
+                       portage._create_pty_or_pipe(copy_term_size=stdout_pipe)
+               return (master_fd, slave_fd)
+
+       def _spawn(self, args, **kwargs):
+
                root_config = self.pkg.root_config
                tree = self.tree
                mydbapi = root_config.trees[tree].dbapi
                settings = self.settings
                ebuild_path = settings["EBUILD"]
                debug = settings.get("PORTAGE_DEBUG") == "1"
-               logfile = settings.get("PORTAGE_LOG_FILE")
-               master_fd = None
-               slave_fd = None
-               fd_pipes = None
-               if self.fd_pipes is not None:
-                       fd_pipes = self.fd_pipes.copy()
-               else:
-                       fd_pipes = {}
-
-               fd_pipes.setdefault(0, sys.stdin.fileno())
-               fd_pipes.setdefault(1, sys.stdout.fileno())
-               fd_pipes.setdefault(2, sys.stderr.fileno())
-
-               # flush any pending output
-               for fd in fd_pipes.itervalues():
-                       if fd == sys.stdout.fileno():
-                               sys.stdout.flush()
-                       if fd == sys.stderr.fileno():
-                               sys.stderr.flush()
-
-               fd_pipes_orig = fd_pipes.copy()
-               self._files = self._files_dict()
-               files = self._files
-               got_pty = False
-
-               portage._doebuild_exit_status_unlink(
-                       settings.get("EBUILD_EXIT_STATUS_FILE"))
 
-               if logfile:
-                       got_pty, master_fd, slave_fd = \
-                               portage._create_pty_or_pipe(copy_term_size=fd_pipes_orig[1])
-
-                       fcntl.fcntl(master_fd, fcntl.F_SETFL,
-                               fcntl.fcntl(master_fd, fcntl.F_GETFL) | os.O_NONBLOCK)
-
-                       fd_pipes[0] = fd_pipes_orig[0]
-                       fd_pipes[1] = slave_fd
-                       fd_pipes[2] = slave_fd
-
-               else:
-                       # Create a dummy pipe so the scheduler can monitor
-                       # the process from inside a poll() loop.
-                       master_fd, slave_fd = os.pipe()
-                       fcntl.fcntl(master_fd, fcntl.F_SETFL,
-                               fcntl.fcntl(master_fd, fcntl.F_GETFL) | os.O_NONBLOCK)
-                       fd_pipes[self._dummy_pipe_fd] = slave_fd
-                       if self.background:
-                               fd_pipes[1] = slave_fd
-                               fd_pipes[2] = slave_fd
-
-               retval = portage.doebuild(ebuild_path, self.phase,
+               rval = portage.doebuild(ebuild_path, self.phase,
                        root_config.root, settings, debug,
-                       mydbapi=mydbapi, tree=tree,
-                       fd_pipes=fd_pipes, returnpid=True)
-
-               os.close(slave_fd)
+                       mydbapi=mydbapi, tree=tree, **kwargs)
 
-               if isinstance(retval, int):
-                       # doebuild failed before spawning
-                       os.close(master_fd)
-                       self.returncode = retval
-                       self.wait()
-                       return
-
-               self.pid = retval[0]
-               portage.process.spawned_pids.remove(self.pid)
-
-               if logfile:
-                       files.log = open(logfile, 'a')
-                       if not self.background:
-                               files.stdout = os.fdopen(os.dup(fd_pipes_orig[1]), 'w')
-                       output_handler = self._output_handler
-               else:
-                       output_handler = self._dummy_handler
-
-               files.ebuild = os.fdopen(master_fd, 'r')
-               self._reg_id = self.scheduler.register(files.ebuild.fileno(),
-                       PollConstants.POLLIN, output_handler)
-               self._registered = True
-
-       def _output_handler(self, fd, event):
-               files = self._files
-               buf = array.array('B')
-               try:
-                       buf.fromfile(files.ebuild, self._bufsize)
-               except EOFError:
-                       pass
-               if buf:
-                       if not self.background:
-                               buf.tofile(files.stdout)
-                               files.stdout.flush()
-                       buf.tofile(files.log)
-                       files.log.flush()
-               else:
-                       self._unregister()
-                       self.wait()
-               return self._registered
-
-       def _dummy_handler(self, fd, event):
-               """
-               This method is mainly interested in detecting EOF, since
-               the only purpose of the pipe is to allow the scheduler to
-               monitor the process from inside a poll() loop.
-               """
-               files = self._files
-               buf = array.array('B')
-               try:
-                       buf.fromfile(files.ebuild, self._bufsize)
-               except EOFError:
-                       pass
-               if buf:
-                       pass
-               else:
-                       self._unregister()
-                       self.wait()
-               return self._registered
+               return rval
 
        def _set_returncode(self, wait_retval):
-               SubProcess._set_returncode(self, wait_retval)
-
-               settings = self.settings
-               debug = settings.get("PORTAGE_DEBUG") == "1"
-               log_path = settings.get("PORTAGE_LOG_FILE")
+               SpawnProcess._set_returncode(self, wait_retval)
 
                if self.phase != "clean":
                        self.returncode = portage._doebuild_exit_status_check_and_log(
-                               settings, self.phase, self.returncode)
+                               self.settings, self.phase, self.returncode)
 
-               portage._post_phase_userpriv_perms(settings)
+               portage._post_phase_userpriv_perms(self.settings)
 
 class EbuildPhase(CompositeTask):
 
index 52273bd7332cadfa37d4cae779cdab70a2ad4c00..cb21435fdadbf884c0748afb19d24fe0b32ea703 100644 (file)
@@ -3001,10 +3001,6 @@ def spawn(mystring, mysettings, debug=0, free=0, droppriv=0, sesandbox=0, fakero
                env=mysettings.environ()
                keywords["opt_name"]="[%s]" % mysettings["PF"]
 
-       if keywords.get("returnpid"):
-               # emerge handles logging externally
-               keywords.pop("logfile", None)
-
        fd_pipes = keywords.get("fd_pipes")
        if fd_pipes is None:
                fd_pipes = {
@@ -5245,8 +5241,12 @@ def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0,
                        if mystatus:
                                return mystatus
                        have_build_dirs = True
-                       # PORTAGE_LOG_FILE is set above by the prepare_build_dirs() call.
-                       logfile = mysettings.get("PORTAGE_LOG_FILE")
+
+                       # emerge handles logging externally
+                       if not returnpid:
+                               # PORTAGE_LOG_FILE is set by the
+                               # above prepare_build_dirs() call.
+                               logfile = mysettings.get("PORTAGE_LOG_FILE")
 
                if have_build_dirs:
                        env_file = os.path.join(mysettings["T"], "environment")