Make --skipfirst handle missing dependencies by dropping the merge tasks
authorZac Medico <zmedico@gentoo.org>
Thu, 29 May 2008 21:19:48 +0000 (21:19 -0000)
committerZac Medico <zmedico@gentoo.org>
Thu, 29 May 2008 21:19:48 +0000 (21:19 -0000)
that have missing dependencies. This involves creating an entirely new
depgraph each time that a missing dependency is discovered. This isn't
the most efficient approach but it's simple and it works well.

This new behavior can server as a fix for bug #12768 by calling emerge
--resume --skipfirst each time that emerge exits unsuccessfully. This
was possible before, but now packages with unsatisfied dependencies
will be properly identified and dropped from the list.
(trunk r10477:10482)

svn path=/main/branches/2.1.2/; revision=10483

bin/emerge

index 0ece528624797c221dc8fbc03fbb62671408828e..87e2366a5d713460e0a254d089f86e7491eccc03 100755 (executable)
@@ -5351,13 +5351,6 @@ class depgraph(object):
                if not isinstance(mergelist, list):
                        mergelist = []
 
-               if mergelist and "--skipfirst" in self.myopts:
-                       for i, task in enumerate(mergelist):
-                               if isinstance(task, list) and \
-                                       task and task[-1] == "merge":
-                                       del mergelist[i]
-                                       break
-
                fakedb = self.mydbapi
                trees = self.trees
                serialized_tasks = []
@@ -8291,11 +8284,43 @@ def action_build(settings, trees, mtimedb,
                if show_spinner:
                        print "Calculating dependencies  ",
                myparams = create_depgraph_params(myopts, myaction)
-               mydepgraph = depgraph(settings, trees,
-                       myopts, myparams, spinner)
+
+               resume_data = mtimedb["resume"]
+               mergelist = resume_data["mergelist"]
+               if mergelist and "--skipfirst" in myopts:
+                       for i, task in enumerate(mergelist):
+                               if isinstance(task, list) and \
+                                       task and task[-1] == "merge":
+                                       del mergelist[i]
+                                       break
+
+               dropped_tasks = set()
+
                success = False
                try:
-                       success = mydepgraph.loadResumeCommand(mtimedb["resume"])
+                       while True:
+                               mydepgraph = depgraph(settings, trees,
+                                       myopts, myparams, spinner)
+                               try:
+                                       success = mydepgraph.loadResumeCommand(mtimedb["resume"])
+                               except depgraph.UnsatisfiedResumeDep, e:
+                                       if "--skipfirst" not in myopts:
+                                               raise
+                                       unsatisfied_parents = set(dep.parent for dep in e.value)
+                                       pruned_mergelist = []
+                                       for task in mergelist:
+                                               if isinstance(task, list) and \
+                                                       tuple(task) in unsatisfied_parents:
+                                                       continue
+                                               pruned_mergelist.append(task)
+                                       if not pruned_mergelist:
+                                               raise
+                                       mergelist[:] = pruned_mergelist
+                                       dropped_tasks.update(unsatisfied_parents)
+                                       del e, unsatisfied_parents
+                                       continue
+                               else:
+                                       break
                except (portage_exception.PackageNotFound,
                        mydepgraph.UnsatisfiedResumeDep), e:
                        if show_spinner:
@@ -8329,7 +8354,9 @@ def action_build(settings, trees, mtimedb,
                                msg = "The resume list contains packages " + \
                                        "with dependencies that have not been " + \
                                        "installed yet. Please restart/continue " + \
-                                       "the operation manually."
+                                       "the operation manually, or use --skipfirst " + \
+                                       "to skip the first package in the list and " + \
+                                       "any other packages that may have missing dependencies."
                                for line in wrap(msg, 72):
                                        out.eerror(line)
                        elif isinstance(e, portage_exception.PackageNotFound):
@@ -8346,7 +8373,16 @@ def action_build(settings, trees, mtimedb,
                        if show_spinner:
                                print "\b\b... done!"
 
-               if not success:
+               if success:
+                       if dropped_tasks:
+                               portage.writemsg("!!! One or more packages have been " + \
+                                       "dropped due to unsatisfied dependencies:\n\n",
+                                       noiselevel=-1)
+                               for task in dropped_tasks:
+                                       portage.writemsg("  " + str(task) + "\n", noiselevel=-1)
+                               portage.writemsg("\n", noiselevel=-1)
+                       del dropped_tasks
+               else:
                        mydepgraph.display_problems()
                        if not (ask or pretend):
                                # delete the current list and also the backup