* Check for masked packages in the --resume merge list and bail
authorZac Medico <zmedico@gentoo.org>
Sat, 3 May 2008 02:31:39 +0000 (02:31 -0000)
committerZac Medico <zmedico@gentoo.org>
Sat, 3 May 2008 02:31:39 +0000 (02:31 -0000)
  out in that case (bug #199408).

* In depgraph.loadResumeCommand(), create a dependency graph from
  the resume list. This ensures that the merge list has it's
  dependencies satisfied. It also enables --tree display together
  with --resume.

* Fix --resume mode to check for unsatisfied blockers and bail out when
  necessary.

* Add --nodeps to the parallel-fetch --resume options since recalculation of
  deps is a a waste here.

* Delete the resume list(s) if there is an unsatisfied block.

(trunk r10113:10117)

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

bin/emerge

index 07984f6c5a7d902431414ec0542fa78f0c5fae5e..23d9981bc42a6f3aac05abd8752d0877956d94af 100755 (executable)
@@ -4878,6 +4878,9 @@ class depgraph(object):
                """
                self._sets["args"].update(resume_data.get("favorites", []))
                mergelist = resume_data.get("mergelist", [])
+               favorites = resume_data.get("favorites")
+               if not isinstance(favorites, list):
+                       favorites = []
 
                if mergelist and "--skipfirst" in self.myopts:
                        for i, task in enumerate(mergelist):
@@ -4917,10 +4920,50 @@ class depgraph(object):
                                operation=action, root=myroot,
                                type_name=pkg_type)
                        self._pkg_cache[pkg] = pkg
+
+                       root_config = self.roots[pkg.root]
+                       if "merge" == pkg.operation and \
+                               not visible(root_config.settings, pkg):
+                               self._unsatisfied_deps_for_display.append(
+                                       ((pkg.root, "="+pkg.cpv), {"myparent":None}))
+
                        fakedb[myroot].cpv_inject(pkg)
                        serialized_tasks.append(pkg)
                        self.spinner.update()
-               self._serialized_tasks_cache = serialized_tasks
+
+               if self._unsatisfied_deps_for_display:
+                       return False
+
+               if not serialized_tasks or "--nodeps" in self.myopts:
+                       self._serialized_tasks_cache = serialized_tasks
+               else:
+                       favorites_set = InternalPackageSet(atom for atom in favorites \
+                               if isinstance(atom, basestring) and portage.isvalidatom(atom))
+                       for node in serialized_tasks:
+                               if isinstance(node, Package) and \
+                                       node.operation == "merge" and \
+                                       favorites_set.findAtomForPackage(node.cpv, node.metadata):
+                                       self._set_nodes.add(node)
+
+                       self._select_package = self._select_pkg_from_graph
+                       for task in serialized_tasks:
+                               if isinstance(task, Package) and \
+                                       task.operation == "merge":
+                                       self._add_pkg(task, None)
+                       if not self._create_graph():
+                               return False
+                       self._serialized_tasks_cache = None
+                       try:
+                               self.altlist()
+                       except self._unknown_internal_error:
+                               return False
+
+                       for node in self.digraph.root_nodes():
+                               if isinstance(node, Package) and \
+                                       node.operation == "merge":
+                                       # Give hint to the --tree display.
+                                       self._set_nodes.add(node)
+               return True
 
        class _internal_exception(portage_exception.PortageException):
                def __init__(self, value=""):
@@ -5310,7 +5353,7 @@ class MergeTask(object):
 
                mymergelist = mylist
                myfeat = self.settings.features[:]
-               bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
+               bad_resume_opts = set(["--ask", "--changelog", "--skipfirst",
                        "--resume"])
                if "parallel-fetch" in myfeat and \
                        not ("--pretend" in self.myopts or \
@@ -5332,7 +5375,8 @@ class MergeTask(object):
                                fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs"
                                fetch_env["PORTAGE_NICENESS"] = "0"
                                fetch_env["PORTAGE_PARALLEL_FETCHONLY"] = "1"
-                               fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
+                               fetch_args = [sys.argv[0], "--resume",
+                                       "--fetchonly", "--nodeps"]
                                resume_opts = self.myopts.copy()
                                # For automatic resume, we need to prevent
                                # any of bad_resume_opts from leaking in
@@ -7604,6 +7648,10 @@ def action_build(settings, trees, mtimedb,
                        mysettings.lock()
                        del myroot, mysettings
 
+               favorites = mtimedb["resume"].get("favorites")
+               if not isinstance(favorites, list):
+                       favorites = []
+
                # "myopts" is a list for backward compatibility.
                resume_opts = mtimedb["resume"].get("myopts", [])
                if isinstance(resume_opts, list):
@@ -7616,8 +7664,9 @@ def action_build(settings, trees, mtimedb,
                myparams = create_depgraph_params(myopts, myaction)
                mydepgraph = depgraph(settings, trees,
                        myopts, myparams, spinner)
+               success = False
                try:
-                       mydepgraph.loadResumeCommand(mtimedb["resume"])
+                       success = mydepgraph.loadResumeCommand(mtimedb["resume"])
                except portage_exception.PackageNotFound:
                        if show_spinner:
                                print
@@ -7627,14 +7676,36 @@ def action_build(settings, trees, mtimedb,
                        out.eerror("       available to be emerged. Please restart/continue")
                        out.eerror("       the merge operation manually.")
 
+               if show_spinner:
+                       print "\b\b... done!"
+
+               unsatisfied_block = False
+               if success:
+                       mymergelist = mydepgraph.altlist()
+                       if mymergelist and \
+                               (isinstance(mymergelist[-1], Blocker) and \
+                               not mymergelist[-1].satisfied):
+                               if not fetchonly and not pretend:
+                                       unsatisfied_block = True
+                                       mydepgraph.display(
+                                               mydepgraph.altlist(reversed=tree),
+                                               favorites=favorites)
+                                       print "\n!!! Error: The above package list contains packages which cannot be installed"
+                                       print   "!!!        at the same time on the same system."
+                                       if not quiet:
+                                               show_blocker_docs_link()
+
+               if not success:
+                       mydepgraph.display_problems()
+
+               if unsatisfied_block or not success:
                        # delete the current list and also the backup
                        # since it's probably stale too.
                        for k in ("resume", "resume_backup"):
                                mtimedb.pop(k, None)
                        mtimedb.commit()
+
                        return 1
-               if show_spinner:
-                       print "\b\b... done!"
        else:
                if ("--resume" in myopts):
                        print darkgreen("emerge: It seems we have nothing to resume...")
@@ -7670,7 +7741,9 @@ def action_build(settings, trees, mtimedb,
                                print colorize("INFORM", "emerge: It seems we have nothing to resume...")
                                return os.EX_OK
                        favorites = mtimedb["resume"]["favorites"]
-                       retval = mydepgraph.display(mymergelist, favorites=favorites)
+                       retval = mydepgraph.display(
+                               mydepgraph.altlist(reversed=tree),
+                               favorites=favorites)
                        if retval != os.EX_OK:
                                return retval
                        prompt="Would you like to resume merging these packages?"
@@ -7726,7 +7799,9 @@ def action_build(settings, trees, mtimedb,
                                print colorize("INFORM", "emerge: It seems we have nothing to resume...")
                                return os.EX_OK
                        favorites = mtimedb["resume"]["favorites"]
-                       retval = mydepgraph.display(mymergelist, favorites=favorites)
+                       retval = mydepgraph.display(
+                               mydepgraph.altlist(reversed=tree),
+                               favorites=favorites)
                        if retval != os.EX_OK:
                                return retval
                else:
@@ -8249,11 +8324,6 @@ def emerge_main():
                        import portage_debug
                        portage_debug.set_trace(True)
 
-       if ("--resume" in myopts):
-               if "--tree" in myopts:
-                       print "* --tree is currently broken with --resume. Disabling..."
-                       del myopts["--tree"]
-
        if not ("--quiet" in myopts):
                if not sys.stdout.isatty() or ("--nospinner" in myopts):
                        spinner.update = spinner.update_basic