summaryrefslogtreecommitdiffstats
path: root/pym/_emerge/PackageUninstall.py
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2011-05-23 22:31:20 -0700
committerZac Medico <zmedico@gentoo.org>2011-05-23 22:31:20 -0700
commitf0f1bbe8fa9d3f698cbe529d2a11eec1ce437119 (patch)
tree0a8298a7bc680c26557fb64a92564a3fc40d992f /pym/_emerge/PackageUninstall.py
parent2610641d07aa6af21c132d438995838c516a67f2 (diff)
downloadportage-f0f1bbe8fa9d3f698cbe529d2a11eec1ce437119.tar.gz
portage-f0f1bbe8fa9d3f698cbe529d2a11eec1ce437119.tar.bz2
portage-f0f1bbe8fa9d3f698cbe529d2a11eec1ce437119.zip
PackageUninstall: make async with MergeProcess
This fixes another ebuild-locks issue like the one fixed in commit a81460175a441897282b0540cefff8060f2b92dc, but this time we use a subprocess to ensure that the ebuild-locks for pkg_prerm and pkg_postrm do not interfere with pkg_setup ebuild-locks held by the main process.
Diffstat (limited to 'pym/_emerge/PackageUninstall.py')
-rw-r--r--pym/_emerge/PackageUninstall.py57
1 files changed, 49 insertions, 8 deletions
diff --git a/pym/_emerge/PackageUninstall.py b/pym/_emerge/PackageUninstall.py
index 0e9130713..0829f50b7 100644
--- a/pym/_emerge/PackageUninstall.py
+++ b/pym/_emerge/PackageUninstall.py
@@ -4,17 +4,45 @@
import logging
import portage
from portage import os
+from portage.dbapi._MergeProcess import MergeProcess
+from portage.exception import UnsupportedAPIException
+from _emerge.EbuildBuildDir import EbuildBuildDir
from _emerge.emergelog import emergelog
from _emerge.CompositeTask import CompositeTask
from _emerge.unmerge import _unmerge_display
class PackageUninstall(CompositeTask):
+ """
+ Uninstall a package asynchronously in a subprocess. When
+ both parallel-install and ebuild-locks FEATURES are enabled,
+ it is essential for the ebuild-locks code to execute in a
+ subprocess, since the portage.locks module does not behave
+ as desired if we try to lock the same file multiple times
+ concurrently from the same process.
+ """
__slots__ = ("world_atom", "ldpath_mtimes", "opts",
- "pkg", "settings")
+ "pkg", "settings", "_builddir_lock")
def _start(self):
+ self.settings.setcpv(self.pkg)
+ vardb = self.pkg.root_config.trees["vartree"].dbapi
+ dbdir = vardb.getpath(self.pkg.cpv)
+ cat, pf = portage.catsplit(self.pkg.cpv)
+ myebuildpath = os.path.join(dbdir, pf + ".ebuild")
+
+ try:
+ portage.doebuild_environment(myebuildpath, "prerm",
+ settings=self.settings, db=vardb)
+ except UnsupportedAPIException:
+ # This is safe to ignore since this function is
+ # guaranteed to set PORTAGE_BUILDDIR even though
+ # it raises UnsupportedAPIException. The error
+ # will be logged when it prevents the pkg_prerm
+ # and pkg_postrm phases from executing.
+ pass
+
retval, pkgmap = _unmerge_display(self.pkg.root_config,
self.opts, "unmerge", [self.pkg.cpv], clean_delay=0,
writemsg_level=self._writemsg_level)
@@ -29,18 +57,31 @@ class PackageUninstall(CompositeTask):
self._emergelog("=== Unmerging... (%s)" % (self.pkg.cpv,))
cat, pf = portage.catsplit(self.pkg.cpv)
- retval = portage.unmerge(cat, pf, settings=self.settings,
- vartree=self.pkg.root_config.trees["vartree"],
- ldpath_mtimes=self.ldpath_mtimes,
- scheduler=self.scheduler)
- if retval != os.EX_OK:
+ self._builddir_lock = EbuildBuildDir(
+ scheduler=self.scheduler, settings=self.settings)
+ self._builddir_lock.lock()
+
+ portage.prepare_build_dirs(
+ settings=self.settings, cleanup=True)
+
+ unmerge_task = MergeProcess(
+ mycat=cat, mypkg=pf, settings=self.settings,
+ treetype="vartree", vartree=self.pkg.root_config.trees["vartree"],
+ scheduler=self.scheduler, background=self.background,
+ mydbapi=self.pkg.root_config.trees["vartree"].dbapi,
+ prev_mtimes=self.ldpath_mtimes,
+ logfile=self.settings.get("PORTAGE_LOG_FILE"), unmerge=True)
+
+ self._start_task(unmerge_task, self._unmerge_exit)
+
+ def _unmerge_exit(self, unmerge_task):
+ if self._final_exit(unmerge_task) != os.EX_OK:
self._emergelog(" !!! unmerge FAILURE: %s" % (self.pkg.cpv,))
else:
self._emergelog(" >>> unmerge success: %s" % (self.pkg.cpv,))
self.world_atom(self.pkg)
-
- self.returncode = retval
+ self._builddir_lock.unlock()
self.wait()
def _emergelog(self, msg):