summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2008-06-27 07:49:57 +0000
committerZac Medico <zmedico@gentoo.org>2008-06-27 07:49:57 +0000
commitbf2604c94ce49f0476579fa24397e12f3272ef4e (patch)
tree1eb2de96fb9062c2554352c8400685a54d5c2e91
parent4b817e3e24903a1fa1959947347ad0dc48a2d59f (diff)
downloadportage-bf2604c94ce49f0476579fa24397e12f3272ef4e.tar.gz
portage-bf2604c94ce49f0476579fa24397e12f3272ef4e.tar.bz2
portage-bf2604c94ce49f0476579fa24397e12f3272ef4e.zip
Bug #12768 - Add a --keep-going option. This uses the same resume_depgraph()
function that's called for emerge --resume operations. Given the remaining tasks, depedencies are recalculated and any tasks with unsatisfied dependencies are automatically dropped. svn path=/main/trunk/; revision=10811
-rw-r--r--pym/_emerge/__init__.py110
1 files changed, 96 insertions, 14 deletions
diff --git a/pym/_emerge/__init__.py b/pym/_emerge/__init__.py
index 0247219dc..16d408b93 100644
--- a/pym/_emerge/__init__.py
+++ b/pym/_emerge/__init__.py
@@ -197,6 +197,7 @@ options=[
"--fetchonly", "--fetch-all-uri",
"--getbinpkg", "--getbinpkgonly",
"--help", "--ignore-default-opts",
+"--keep-going",
"--noconfmem",
"--newuse", "--nocolor",
"--nodeps", "--noreplace",
@@ -5871,11 +5872,16 @@ class MergeTask(object):
"--fetchonly", "--fetch-all-uri",
"--nodeps", "--pretend"])
- def __init__(self, settings, trees, myopts):
+ def __init__(self, settings, trees, mtimedb, myopts,
+ spinner, mergelist, favorites):
self.settings = settings
self.target_root = settings["ROOT"]
self.trees = trees
self.myopts = myopts
+ self._spinner = spinner
+ self._mtimedb = mtimedb
+ self._mergelist = mergelist
+ self._favorites = favorites
self.edebug = 0
if settings.get("PORTAGE_DEBUG", "") == "1":
self.edebug = 1
@@ -5924,14 +5930,85 @@ class MergeTask(object):
return blocker_dblinks
- def merge(self, mylist, favorites, mtimedb):
- try:
- return self._merge(mylist, favorites, mtimedb)
- finally:
- if self._spawned_pids:
- from portage import process
- process.spawned_pids.extend(self._spawned_pids)
- self._spawned_pids = []
+ def merge(self):
+
+ keep_going = "--keep-going" in self.myopts
+
+ while True:
+ try:
+ rval = self._merge()
+ finally:
+ spawned_pids = self._spawned_pids
+ while spawned_pids:
+ pid = spawned_pids.pop()
+ try:
+ if os.waitpid(pid, os.WNOHANG) == (0, 0):
+ os.kill(pid, signal.SIGTERM)
+ os.waitpid(pid, 0)
+ except OSError:
+ pass # cleaned up elsewhere.
+
+ if rval == os.EX_OK or not keep_going:
+ break
+ mtimedb = self._mtimedb
+ if "resume" not in mtimedb:
+ break
+ mergelist = self._mtimedb["resume"].get("mergelist")
+ if not mergelist:
+ break
+ if mergelist[0][-1] != "merge":
+ break
+ # Skip the first one because it failed to build or install.
+ del mergelist[0]
+ if not mergelist:
+ break
+ mylist = self._calc_resume_list()
+ if not mylist:
+ break
+ self.curval += 1
+ self._mergelist = mylist
+
+ return rval
+
+ def _calc_resume_list(self):
+ """
+ Use the current resume list to calculate a new one,
+ dropping any packages with unsatisfied deps.
+ """
+ print colorize("GOOD", "*** Resuming merge...")
+
+ show_spinner = "--quiet" not in self.myopts and \
+ "--nodeps" not in self.myopts
+
+ if show_spinner:
+ print "Calculating dependencies ",
+
+ myparams = create_depgraph_params(self.myopts, None)
+ success, mydepgraph, dropped_tasks = resume_depgraph(
+ self.settings, self.trees, self._mtimedb, self.myopts,
+ myparams, self._spinner, skip_unsatisfied=True)
+
+ if show_spinner:
+ print "\b\b... done!"
+
+ if not success:
+ mydepgraph.display_problems()
+ return None
+
+ if dropped_tasks:
+ portage.writemsg("!!! One or more packages have been " + \
+ "dropped due to\n" + \
+ "!!! masking or unsatisfied dependencies:\n\n",
+ noiselevel=-1)
+ for task in dropped_tasks:
+ portage.writemsg(" " + str(task) + "\n", noiselevel=-1)
+ portage.writemsg("\n", noiselevel=-1)
+
+ mylist = mydepgraph.altlist()
+ mydepgraph.break_refs(mylist)
+ del mydepgraph
+ clear_caches(self.trees)
+ return mylist
def _poll_child_processes(self):
"""
@@ -5952,7 +6029,10 @@ class MergeTask(object):
pass
spawned_pids.remove(pid)
- def _merge(self, mylist, favorites, mtimedb):
+ def _merge(self):
+ mylist = self._mergelist
+ favorites = self._favorites
+ mtimedb = self._mtimedb
from portage.elog import elog_process
from portage.elog.filtering import filter_mergephases
buildpkgonly = "--buildpkgonly" in self.myopts
@@ -8805,7 +8885,6 @@ def action_build(settings, trees, mtimedb,
if ("--resume" in myopts):
favorites=mtimedb["resume"]["favorites"]
- mergetask = MergeTask(settings, trees, myopts)
if "PORTAGE_PARALLEL_FETCHONLY" in settings:
""" parallel-fetch uses --resume --fetchonly and we don't want
it to write the mtimedb"""
@@ -8816,7 +8895,9 @@ def action_build(settings, trees, mtimedb,
del mydepgraph
clear_caches(trees)
- retval = mergetask.merge(mymergelist, favorites, mtimedb)
+ mergetask = MergeTask(settings, trees, mtimedb, myopts,
+ spinner, mymergelist, favorites)
+ retval = mergetask.merge()
merge_count = mergetask.curval
else:
if "resume" in mtimedb and \
@@ -8860,8 +8941,9 @@ def action_build(settings, trees, mtimedb,
del mydepgraph
clear_caches(trees)
- mergetask = MergeTask(settings, trees, myopts)
- retval = mergetask.merge(pkglist, favorites, mtimedb)
+ mergetask = MergeTask(settings, trees, mtimedb, myopts,
+ spinner, pkglist, favorites)
+ retval = mergetask.merge()
merge_count = mergetask.curval
if retval == os.EX_OK and not (buildpkgonly or fetchonly or pretend):