* Fix doebuild so "returnpid" works for preinst and postinst.
authorZac Medico <zmedico@gentoo.org>
Mon, 14 Jul 2008 06:38:30 +0000 (06:38 -0000)
committerZac Medico <zmedico@gentoo.org>
Mon, 14 Jul 2008 06:38:30 +0000 (06:38 -0000)
* Add async support for pkg_prerm and pkg_postrm.
* Add missing "treetype" parameter to dblink constructor calls.
* Fix SubProcess._wait() to check self.returncode _after_ calling
  the scheduler.

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

pym/_emerge/__init__.py
pym/portage/__init__.py
pym/portage/dbapi/vartree.py

index a68248a77c669eb095c5e454103338d0cdf90d55..c02849995e8ecb0bc5fa0dfc129e1c6b4cb9d493 100644 (file)
@@ -1931,10 +1931,10 @@ class SubProcess(AsynchronousTask):
                        self.returncode is None
 
        def _wait(self):
-               if self.returncode is not None:
-                       return self.returncode
                if self.registered:
                        self.scheduler.schedule(self._reg_id)
+               if self.returncode is not None:
+                       return self.returncode
                try:
                        wait_retval = os.waitpid(self.pid, 0)
                except OSError, e:
@@ -2720,23 +2720,51 @@ class EbuildPhase(SubProcess):
 
        def _set_returncode(self, wait_retval):
                SubProcess._set_returncode(self, wait_retval)
-               if self.phase != "clean":
-                       msg = portage._doebuild_exit_status_check(
-                               self.phase, self.settings)
-                       if msg:
-                               self.returncode = 1
-                               from textwrap import wrap
-                               from portage.elog.messages import eerror
-                               for l in wrap(msg, 72):
-                                       eerror(l, phase=self.phase, key=self.pkg.cpv)
 
                settings = self.settings
+               debug = settings.get("PORTAGE_DEBUG") == "1"
+               log_path = settings.get("PORTAGE_LOG_FILE")
+
+               if self.phase != "clean":
+                       self.returncode = portage._doebuild_exit_status_check_and_log(
+                               settings, self.phase, self.returncode)
+
                portage._post_phase_userpriv_perms(settings)
                if self.phase == "install":
                        portage._check_build_log(settings)
                        if self.returncode == os.EX_OK:
                                self.returncode = portage._post_src_install_checks(settings)
 
+               elif self.phase == "preinst":
+
+                       if self.returncode == os.EX_OK:
+                               portage._doebuild_exit_status_unlink(
+                                       settings.get("EBUILD_EXIT_STATUS_FILE"))
+                               phase_retval = portage.spawn(
+                                       " ".join(portage._post_pkg_preinst_cmd(settings)),
+                                       settings, debug=debug, free=1, logfile=log_path)
+                               phase_retval = portage._doebuild_exit_status_check_and_log(
+                                       settings, self.phase, phase_retval)
+                               if phase_retval != os.EX_OK:
+                                       writemsg("!!! post preinst failed; exiting.\n",
+                                               noiselevel=-1)
+                                       self.returncode = phase_retval
+
+               elif self.phase == "postinst":
+
+                       if self.returncode == os.EX_OK:
+                               portage._doebuild_exit_status_unlink(
+                                       settings.get("EBUILD_EXIT_STATUS_FILE"))
+                               phase_retval = portage.spawn(
+                                       " ".join(portage._post_pkg_postinst_cmd(settings)),
+                                       settings, debug=debug, free=1, logfile=log_path)
+                               phase_retval = portage._doebuild_exit_status_check_and_log(
+                                       settings, self.phase, phase_retval)
+                               if phase_retval != os.EX_OK:
+                                       writemsg("!!! post postinst failed; exiting.\n",
+                                               noiselevel=-1)
+                                       self.returncode = phase_retval
+
 class EbuildBinpkg(EbuildPhase):
        """
        This assumes that src_install() has successfully completed.
index fd4d14b2f1aa8b2828cde8fd3f675fce4c5f7186..c9586c19a881ffd728d6539cef8aba87e3eb949f 100644 (file)
@@ -4380,6 +4380,42 @@ def _post_src_install_uid_fix(mysettings):
                                mode=mystat.st_mode, stat_cached=mystat,
                                follow_links=False)
 
+def _post_pkg_preinst_cmd(mysettings):
+       """
+       Post phase logic and tasks that have been factored out of
+       ebuild.sh. Call preinst_mask last so that INSTALL_MASK can
+       can be used to wipe out any gmon.out files created during
+       previous functions (in case any tools were built with -pg
+       in CFLAGS).
+       """
+
+       portage_bin_path = mysettings["PORTAGE_BIN_PATH"]
+       misc_sh_binary = os.path.join(portage_bin_path,
+               os.path.basename(MISC_SH_BINARY))
+
+       mysettings["EBUILD_PHASE"] = ""
+       myargs = [_shell_quote(misc_sh_binary),
+               "preinst_bsdflags",
+               "preinst_sfperms", "preinst_selinux_labels",
+               "preinst_suid_scan", "preinst_mask"]
+
+       return myargs
+
+def _post_pkg_postinst_cmd(mysettings):
+       """
+       Post phase logic and tasks that have been factored out of
+       build.sh.
+       """
+
+       portage_bin_path = mysettings["PORTAGE_BIN_PATH"]
+       misc_sh_binary = os.path.join(portage_bin_path,
+               os.path.basename(MISC_SH_BINARY))
+
+       mysettings["EBUILD_PHASE"] = ""
+       myargs = [_shell_quote(misc_sh_binary), "postinst_bsdflags"]
+
+       return myargs
+
 def _spawn_misc_sh(mysettings, commands, **kwargs):
        """
        @param mysettings: the ebuild config
@@ -4822,6 +4858,18 @@ def _doebuild_exit_status_check(mydo, settings):
        "errors (bug #200313)."
        return msg
 
+def _doebuild_exit_status_check_and_log(settings, mydo, retval):
+       if retval != os.EX_OK:
+               return retval
+       msg = _doebuild_exit_status_check(mydo, settings)
+       if msg:
+               retval = 1
+               from textwrap import wrap
+               from portage.elog.messages import eerror
+               for l in wrap(msg, 72):
+                       eerror(l, phase=mydo, key=settings.mycpv)
+       return retval
+
 def _doebuild_exit_status_unlink(exit_status_file):
        """
        Double check to make sure it really doesn't exist
@@ -5277,22 +5325,18 @@ def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0,
                elif mydo == "preinst":
                        phase_retval = spawn(
                                _shell_quote(ebuild_sh_binary) + " " + mydo,
-                               mysettings, debug=debug, free=1, logfile=logfile)
+                               mysettings, debug=debug, free=1, logfile=logfile,
+                               fd_pipes=fd_pipes, returnpid=returnpid)
+
+                       if returnpid:
+                               return phase_retval
+
                        phase_retval = exit_status_check(phase_retval)
                        if phase_retval == os.EX_OK:
-                               # Post phase logic and tasks that have been factored out of
-                               # ebuild.sh. Call preinst_mask last so that INSTALL_MASK can
-                               # can be used to wipe out any gmon.out files created during
-                               # previous functions (in case any tools were built with -pg
-                               # in CFLAGS).
-                               myargs = [_shell_quote(misc_sh_binary),
-                                       "preinst_bsdflags",
-                                       "preinst_sfperms", "preinst_selinux_labels",
-                                       "preinst_suid_scan", "preinst_mask"]
                                _doebuild_exit_status_unlink(
                                        mysettings.get("EBUILD_EXIT_STATUS_FILE"))
-                               mysettings["EBUILD_PHASE"] = ""
-                               phase_retval = spawn(" ".join(myargs),
+                               phase_retval = spawn(
+                                       " ".join(_post_pkg_preinst_cmd(mysettings)),
                                        mysettings, debug=debug, free=1, logfile=logfile)
                                phase_retval = exit_status_check(phase_retval)
                                if phase_retval != os.EX_OK:
@@ -5302,16 +5346,17 @@ def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0,
                elif mydo == "postinst":
                        phase_retval = spawn(
                                _shell_quote(ebuild_sh_binary) + " " + mydo,
-                               mysettings, debug=debug, free=1, logfile=logfile)
+                               mysettings, debug=debug, free=1, logfile=logfile,
+                               fd_pipes=fd_pipes, returnpid=returnpid)
+
+                       if returnpid:
+                               return phase_retval
+
                        phase_retval = exit_status_check(phase_retval)
                        if phase_retval == os.EX_OK:
-                               # Post phase logic and tasks that have been factored out of
-                               # ebuild.sh.
-                               myargs = [_shell_quote(misc_sh_binary), "postinst_bsdflags"]
                                _doebuild_exit_status_unlink(
                                        mysettings.get("EBUILD_EXIT_STATUS_FILE"))
-                               mysettings["EBUILD_PHASE"] = ""
-                               phase_retval = spawn(" ".join(myargs),
+                               phase_retval = spawn(" ".join(_post_pkg_postinst_cmd(mysettings)),
                                        mysettings, debug=debug, free=1, logfile=logfile)
                                phase_retval = exit_status_check(phase_retval)
                                if phase_retval != os.EX_OK:
@@ -5321,7 +5366,12 @@ def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0,
                elif mydo in ("prerm", "postrm", "config", "info"):
                        retval =  spawn(
                                _shell_quote(ebuild_sh_binary) + " " + mydo,
-                               mysettings, debug=debug, free=1, logfile=logfile)
+                               mysettings, debug=debug, free=1, logfile=logfile,
+                               fd_pipes=fd_pipes, returnpid=returnpid)
+
+                       if returnpid:
+                               return retval
+
                        retval = exit_status_check(retval)
                        return retval
 
index fdb16a225eccc5a1f6d939333f0f7fe93012a892..1dfa8946a04bf9513bcf80d400151d474b473d90 100644 (file)
@@ -895,7 +895,7 @@ class vardbapi(dbapi):
        def _dblink(self, cpv):
                category, pf = catsplit(cpv)
                return dblink(category, pf, self.root,
-                       self.settings, vartree=self.vartree)
+                       self.settings, vartree=self.vartree, treetype="vartree")
 
        def removeFromContents(self, pkg, paths, relative_paths=True):
                """
@@ -1523,7 +1523,9 @@ class dblink(object):
                                if cur_cpv == self.mycpv:
                                        continue
                                others_in_slot.append(dblink(self.cat, catsplit(cur_cpv)[1],
-                                       self.vartree.root, self.settings, vartree=self.vartree))
+                                       self.vartree.root, self.settings, vartree=self.vartree,
+                                       treetype="vartree"))
+
                        retval = self._security_check([self] + others_in_slot)
                        if retval:
                                return retval
@@ -1560,6 +1562,7 @@ class dblink(object):
                                uid=portage_uid, gid=portage_gid, mode=070, mask=0)
                builddir_lock = None
                catdir_lock = None
+               scheduler = self._scheduler
                retval = -1
                try:
                        if myebuildpath:
@@ -1573,11 +1576,16 @@ class dblink(object):
                                        unlockdir(catdir_lock)
                                finally:
                                        catdir_lock = None
-                               # Eventually, we'd like to pass in the saved ebuild env here...
-                               retval = doebuild(myebuildpath, "prerm", self.myroot,
-                                       self.settings, cleanup=cleanup, use_cache=0,
-                                       mydbapi=self.vartree.dbapi, tree="vartree",
-                                       vartree=self.vartree)
+
+                               if scheduler is None:
+                                       retval = doebuild(myebuildpath, ebuild_phase, self.myroot,
+                                               self.settings, cleanup=cleanup, use_cache=0,
+                                               mydbapi=self.vartree.dbapi, tree=self.treetype,
+                                               vartree=self.vartree)
+                               else:
+                                       retval = scheduler.dblinkEbuildPhase(
+                                               self, self.vartree.dbapi, myebuildpath, ebuild_phase)
+
                                # XXX: Decide how to handle failures here.
                                if retval != os.EX_OK:
                                        writemsg("!!! FAILED prerm: %s\n" % retval, noiselevel=-1)
@@ -1592,9 +1600,13 @@ class dblink(object):
 
                        if myebuildpath:
                                ebuild_phase = "postrm"
-                               retval = doebuild(myebuildpath, "postrm", self.myroot,
-                                        self.settings, use_cache=0, tree="vartree",
-                                        mydbapi=self.vartree.dbapi, vartree=self.vartree)
+                               if scheduler is None:
+                                       retval = doebuild(myebuildpath, ebuild_phase, self.myroot,
+                                               self.settings, use_cache=0, tree=self.treetype,
+                                               mydbapi=self.vartree.dbapi, vartree=self.vartree)
+                               else:
+                                       retval = scheduler.dblinkEbuildPhase(
+                                               self, self.vartree.dbapi, myebuildpath, ebuild_phase)
 
                                # XXX: Decide how to handle failures here.
                                if retval != os.EX_OK:
@@ -1751,7 +1763,8 @@ class dblink(object):
                                        continue
                                others_in_slot.append(dblink(self.cat, catsplit(cur_cpv)[1],
                                        self.vartree.root, self.settings,
-                                       vartree=self.vartree))
+                                       vartree=self.vartree, treetype="vartree"))
+
                dest_root = normalize_path(self.vartree.root).rstrip(os.path.sep) + \
                        os.path.sep
                dest_root_len = len(dest_root) - 1
@@ -2380,7 +2393,9 @@ class dblink(object):
                        # we need it to have private ${T} etc... for things like elog.
                        others_in_slot.append(dblink(self.cat, catsplit(cur_cpv)[1],
                                self.vartree.root, config(clone=self.settings),
-                               vartree=self.vartree, scheduler=self._scheduler))
+                               vartree=self.vartree, treetype="vartree",
+                               scheduler=self._scheduler))
+
                retval = self._security_check(others_in_slot)
                if retval:
                        return retval