From: Fabian Groffen Date: Thu, 14 Dec 2006 15:03:58 +0000 (-0000) Subject: Merged from trunk 5284:5294 X-Git-Url: http://git.tremily.us/gitweb.cgi?a=commitdiff_plain;h=cb05cd27d03a70e7a3f3ca1a2404eb56774d4a96;p=portage.git Merged from trunk 5284:5294 For bug #157897, handle the case of multiple versions within a single package slot have been pulled into the dependency graph. If possible, the package that has already been pulled in will be reused. Otherwise, an error message will advise the user to mask an unwanted version. handle --cols when displaying blockers (SpankMan) For bug #157897, add slot collision handling in depgraph.create(), since create() is called from places other than select_dep(). Update the comment about depgraph.pkg_node_map since it now maps all nodes added to the graph. Use depgraph.pkg_node_map so simplify comparison against existing nodes at the beginning of depgraph.create(). Fix the --onlydeps conditional logic in depgraph.create(). These aren't real nodes and shouldn't be added to the digraph, etc... Remove redundant priority handling since that's always handled in select_dep() for nodes that have parents. Remove pointless unpacking of the parent node. Make --columns blockers output more consistent when --quiet is not enabled. svn path=/main/branches/prefix/; revision=5295 --- diff --git a/bin/emerge b/bin/emerge index 50be592eb..171e1bc15 100755 --- a/bin/emerge +++ b/bin/emerge @@ -803,7 +803,7 @@ class depgraph: self.edebug = 1 self.spinner = spinner self.pkgsettings = {} - # Maps cpv to digraph node for "merge" nodes only. + # Maps cpv to digraph node for all nodes added to the graph. self.pkg_node_map = {} # Maps slot atom to digraph node for all nodes added to the graph. self._slot_node_map = {} @@ -849,6 +849,46 @@ class depgraph: self._altlist_cache = {} self._pprovided_args = [] + def _show_slot_collision_notice(self, packages): + """Show an informational message advising the user to mask one of the + the packages. In some cases it may be possible to resolve this + automatically, but support for backtracking (removal nodes that have + already been selected) will be required in order to handle all possible + cases.""" + + from formatter import AbstractFormatter, DumbWriter + f = AbstractFormatter(DumbWriter(maxcol=72)) + + print "\n!!! Multiple versions within a single " + \ + "package slot have been " + print "!!! pulled into the dependency graph:" + print + for cpv in packages: + print " ", cpv + print + + msg = [] + msg.append("It may be possible to solve this problem ") + msg.append("by using package.mask to prevent one of ") + msg.append("those packages from being selected. ") + msg.append("However, it is also possible that conflicting ") + msg.append("dependencies exist such that they are impossible to ") + msg.append("satisfy simultaneously. If such a conflict exists in ") + msg.append("the dependencies of two different packages, then those ") + msg.append("packages can not be installed simultaneously.") + + for x in msg: + f.add_flowing_data(x) + f.end_paragraph(1) + + msg = [] + msg.append("For more information, see MASKED PACKAGES ") + msg.append("section in the emerge man page or refer ") + msg.append("to the Gentoo Handbook.") + for x in msg: + f.add_flowing_data(x) + f.end_paragraph(1) + def create(self, mybigkey, myparent=None, addme=1, myuse=None, priority=DepPriority(), rev_dep=False, arg=None): """ @@ -862,25 +902,20 @@ class depgraph: #IUSE-aware emerge -> USE DEP aware depgraph #"no downgrade" emerge """ - jbigkey = tuple(chain(mybigkey, ["merge"])) mytype, myroot, mykey = mybigkey - if self.digraph.hasnode(jbigkey): - if addme and jbigkey != myparent: + existing_node = None + if addme: + existing_node = self.pkg_node_map[myroot].get(mykey) + if existing_node: + if existing_node != myparent: # Refuse to make a node depend on itself so that the we don't # don't create a bogus circular dependency in self.altlist(). if rev_dep and myparent: - ptype, proot, pkey, pstatus = myparent - self.digraph.addnode(myparent, jbigkey, priority=priority) + self.digraph.addnode(myparent, existing_node, + priority=priority) else: - self.digraph.addnode(jbigkey, myparent, priority=priority) - return 1 - jbigkey = tuple(chain(mybigkey, ["nomerge"])) - if self.digraph.hasnode(jbigkey): - if rev_dep and myparent: - ptype, proot, pkey, pstatus = myparent - self.digraph.addnode(myparent, jbigkey, priority=priority) - else: - self.digraph.addnode(jbigkey, myparent, priority=priority) + self.digraph.addnode(existing_node, myparent, + priority=priority) return 1 self.spinner.update() @@ -906,7 +941,6 @@ class depgraph: if myuse is None: self.pkgsettings[myroot].setcpv(mykey, mydb=portdb) myuse = self.pkgsettings[myroot]["USE"].split() - self.useFlags[myroot][mykey] = myuse merging=1 if mytype == "installed": @@ -944,30 +978,45 @@ class depgraph: else: mybigkey.append("nomerge") - if merging == 0 and vardbapi.cpv_exists(mykey): - myuse = vardbapi.aux_get(mykey, ["USE"])[0].split() - self.useFlags[myroot][mykey] = myuse + if addme: + metadata = dict(izip(self._mydbapi_keys, + mydbapi.aux_get(mykey, self._mydbapi_keys))) + if merging == 0 and vardbapi.cpv_exists(mykey): + metadata["USE"] = vardbapi.aux_get(mykey, ["USE"])[0] + myuse = metadata["USE"].split() + metadata["SLOT"] = vardbapi.aux_get(mykey, ["SLOT"])[0] + slot_atom = "%s:%s" % (portage.dep_getkey(mykey), metadata["SLOT"]) + existing_node = self._slot_node_map[myroot].get( + slot_atom, None) + if existing_node: + e_type, myroot, e_cpv, e_status = existing_node + if mykey == e_cpv: + # The existing node can be reused. + if rev_dep and myparent: + ptype, proot, pkey, pstatus = myparent + self.digraph.addnode(myparent, existing_node, + priority=priority) + else: + self.digraph.addnode(existing_node, myparent, + priority=priority) + return 1 + else: + self._show_slot_collision_notice((mykey, e_cpv)) + return 0 - """ At this point, we have either hit a blocker and returned, found the package in the - depgraph already and returned, or we are here. Whether we are merging or not; we must - add the package to the depgraph; so we do that here. """ - jbigkey = tuple(mybigkey) - if rev_dep and myparent: - ptype, proot, pkey, pstatus = myparent - self.digraph.addnode(myparent, jbigkey, - priority=priority) - else: - self.digraph.addnode(jbigkey, myparent, - priority=priority) - - metadata = dict(izip(self._mydbapi_keys, - mydbapi.aux_get(mykey, self._mydbapi_keys))) - slot_atom = "%s:%s" % (portage.dep_getkey(mykey), metadata["SLOT"]) - self._slot_node_map[myroot][slot_atom] = jbigkey - if mybigkey[-1] == "merge": + jbigkey = tuple(mybigkey) + self._slot_node_map[myroot][slot_atom] = jbigkey self.pkg_node_map[myroot][mykey] = jbigkey + self.useFlags[myroot][mykey] = myuse self.mydbapi[myroot].cpv_inject(mykey, metadata=metadata) + if rev_dep and myparent: + self.digraph.addnode(myparent, jbigkey, + priority=priority) + else: + self.digraph.addnode(jbigkey, myparent, + priority=priority) + """ This section determines whether we go deeper into dependencies or not. We want to go deeper on a few occasions: Installing package A, we need to make sure package A's deps are met. @@ -1437,6 +1486,21 @@ class depgraph: # ordered by type preference ("ebuild" type is the last resort) selected_pkg = matched_packages[0] + pkgtype, myroot, mycpv, myuse = selected_pkg + mydbapi = self.trees[myroot][self.pkg_tree_map[pkgtype]].dbapi + slot_atom = "%s:%s" % (portage.dep_getkey(mycpv), + mydbapi.aux_get(mycpv, ["SLOT"])[0]) + existing_node = self._slot_node_map[myroot].get( + slot_atom, None) + if existing_node: + e_type, myroot, e_cpv, e_status = existing_node + if portage.match_from_list(x, [e_cpv]): + # The existing node can be reused. + selected_pkg = [e_type, myroot, e_cpv, + self.useFlags[myroot][e_cpv]] + else: + self._show_slot_collision_notice((mycpv, e_cpv)) + return 0 if myparent: #we are a dependency, so we want to be unconditionally added @@ -1978,7 +2042,10 @@ class depgraph: counters.blocks += 1 resolved = portage.key_expand( pkg_key, mydb=vardb, settings=pkgsettings) - print "["+x[0]+" "+addl+"]",red(resolved), + if "--columns" in self.myopts and "--quiet" in self.myopts: + print addl,red(resolved), + else: + print "["+x[0]+" "+addl+"]",red(resolved), block_parents = self.blocker_parents[tuple(x)] block_parents = set([pnode[2] for pnode in block_parents]) block_parents = ", ".join(block_parents)