From cae1f42e8368a64dd4a36d2f7bc5987cf0553caa Mon Sep 17 00:00:00 2001 From: Fabian Groffen Date: Thu, 28 Jun 2007 09:28:07 +0000 Subject: [PATCH] Merged from trunk 7054:7078 +------------------------------------------------------------------------+ | 7055 | Format $EBUILD_OVERLAY_ECLASSES output more like it was | | zmedico | before. | |---------+--------------------------------------------------------------| | 7057 | Fix quoting. | | zmedico | | |---------+--------------------------------------------------------------| | 7059 | For bug #142473, account for $ROOT when deciding if a | | zmedico | package is part of world or not. | |---------+--------------------------------------------------------------| | 7061 | Instead of just a list, use a cat/pkg dict for matching | | zmedico | packages against args in the depgraph. | |---------+--------------------------------------------------------------| | 7063 | Improve tracking of correspondence between arguments and | | zmedico | packages in the depgraph. | |---------+--------------------------------------------------------------| | 7064 | Cache aux_get() metadata in depgraph.create() and use | | zmedico | PROVIDE for matching packages to arguments. | |---------+--------------------------------------------------------------| | 7065 | Just use a containment test for matching pprovided args | | zmedico | since it works correctly and match_to_list() isn't | | | appropriate for this. | |---------+--------------------------------------------------------------| | 7067 | Discard "nomerge" nodes to speed up depgraph.altlist() since | | zmedico | those nodes aren't used and the --tree algorithm does a good | | | job of regenerating them when appropriate. | |---------+--------------------------------------------------------------| | 7069 | For bug #144333, make the --reinstall option a single choice | | zmedico | type. | |---------+--------------------------------------------------------------| | 7071 | When filling in "nomerge" nodes for --tree display, stop at | | zmedico | a node that is an argument or a direct member of a set that | | | has been specified as an argument (system or world). | |---------+--------------------------------------------------------------| | 7073 | For bug #183431, catch a ParseError caused by a corrupt | | zmedico | profile and dump an error message. This allows emerge to | | | continue with actions that don't require a valid profile, | | | such as --sync. | |---------+--------------------------------------------------------------| | 7075 | For bug #142473, add 2 additional color classes for system | | zmedico | packages and packages matched by arguments. | |---------+--------------------------------------------------------------| | 7076 | Don't colorize system package when in "world" mode. | | zmedico | | |---------+--------------------------------------------------------------| | 7078 | Remove unused worldlist variable. | | zmedico | | +------------------------------------------------------------------------+ svn path=/main/branches/prefix/; revision=7080 --- bin/isolated-functions.sh | 8 +- pym/emerge/__init__.py | 158 ++++++++++++++++++++++++++++++-------- pym/portage/__init__.py | 9 ++- pym/portage/output.py | 4 + 4 files changed, 146 insertions(+), 33 deletions(-) diff --git a/bin/isolated-functions.sh b/bin/isolated-functions.sh index 594c4e8ec..15fc17580 100755 --- a/bin/isolated-functions.sh +++ b/bin/isolated-functions.sh @@ -54,9 +54,13 @@ diefunc() { [ -n "${PORTAGE_LOG_FILE}" ] && \ eerror "A complete build log is located at '${PORTAGE_LOG_FILE}'." if [ -n "${EBUILD_OVERLAY_ECLASSES}" ] ; then - eerror "This ebuild used eclasses from overlays: ${EBUILD_OVERLAY_ECLASSES}" + eerror "This ebuild used the following eclasses from overlays:" + local x + for x in ${EBUILD_OVERLAY_ECLASSES} ; do + eerror " ${x}" + done fi - if [ ${EBUILD#${PORTDIR}/} == ${EBUILD} ] ; then + if [ "${EBUILD#${PORTDIR}/}" == "${EBUILD}" ] ; then local overlay=${EBUILD%/*} overlay=${overlay%/*} overlay=${overlay%/*} diff --git a/pym/emerge/__init__.py b/pym/emerge/__init__.py index 4e03f60ae..0495c3a41 100644 --- a/pym/emerge/__init__.py +++ b/pym/emerge/__init__.py @@ -936,7 +936,8 @@ class depgraph(object): # Maps slot atom to digraph node for all nodes added to the graph. self._slot_node_map = {} self.mydbapi = {} - self._mydbapi_keys = ["SLOT", "DEPEND", "RDEPEND", "PDEPEND"] + self._mydbapi_keys = ["SLOT", "DEPEND", "RDEPEND", "PDEPEND", + "USE", "IUSE", "PROVIDE"] self.useFlags = {} self.trees = {} for myroot in trees: @@ -979,7 +980,10 @@ class depgraph(object): self._parent_child_digraph = digraph() self.orderedkeys=[] self.outdatedpackages=[] - self.args_keys = [] + self._args_atoms = {} + self._args_nodes = set() + self._sets = {} + self._sets_nodes = {} self.blocker_digraph = digraph() self.blocker_parents = {} self._unresolved_blocker_parents = {} @@ -1052,7 +1056,7 @@ class depgraph(object): elif org_iuse.intersection(orig_use) != \ cur_iuse.intersection(cur_use): return True - elif "changed-use" in self.myopts.get("--reinstall","").split(","): + elif "changed-use" == self.myopts.get("--reinstall"): if org_iuse.intersection(orig_use) != \ cur_iuse.intersection(cur_use): return True @@ -1110,14 +1114,22 @@ class depgraph(object): # directive, otherwise we add a "merge" directive. mydbapi = self.trees[myroot][self.pkg_tree_map[mytype]].dbapi + metadata = dict(izip(self._mydbapi_keys, + mydbapi.aux_get(mykey, self._mydbapi_keys))) + if mytype == "ebuild": + pkgsettings.setcpv(mykey, mydb=portdb) + metadata["USE"] = pkgsettings["USE"] + myuse = pkgsettings["USE"].split() if not arg and myroot == self.target_root: - cpv_slot = "%s:%s" % (mykey, mydbapi.aux_get(mykey, ["SLOT"])[0]) - arg = portage.best_match_to_list(cpv_slot, self.args_keys) - - if myuse is None: - self.pkgsettings[myroot].setcpv(mykey, mydb=portdb) - myuse = self.pkgsettings[myroot]["USE"].split() + try: + arg = self._find_atom_for_pkg(self._args_atoms, mykey, metadata) + except portage.exception.InvalidDependString, e: + if mytype != "installed": + show_invalid_depstring_notice(tuple(mybigkey+["merge"]), + metadata["PROVIDE"], str(e)) + return 0 + del e merging=1 if mytype == "installed": @@ -1140,8 +1152,7 @@ class depgraph(object): forced_flags.update(pkgsettings.useforce) forced_flags.update(pkgsettings.usemask) old_use = vardbapi.aux_get(mykey, ["USE"])[0].split() - iuses = set(filter_iuse_defaults( - mydbapi.aux_get(mykey, ["IUSE"])[0].split())) + iuses = set(filter_iuse_defaults(metadata["IUSE"].split())) old_iuse = set(filter_iuse_defaults( vardbapi.aux_get(mykey, ["IUSE"])[0].split())) if self._reinstall_for_flags( @@ -1155,16 +1166,15 @@ class depgraph(object): jbigkey = tuple(mybigkey) if addme: - metadata = dict(izip(self._mydbapi_keys, - mydbapi.aux_get(mykey, self._mydbapi_keys))) if merging == 0 and vardbapi.cpv_exists(mykey) and \ mytype != "installed": + mytype = "installed" mybigkey[0] = "installed" mydbapi = vardbapi jbigkey = tuple(mybigkey) metadata = dict(izip(self._mydbapi_keys, mydbapi.aux_get(mykey, self._mydbapi_keys))) - myuse = mydbapi.aux_get(mykey, ["USE"])[0].split() + myuse = metadata["USE"].split() slot_atom = "%s:%s" % (portage.dep_getkey(mykey), metadata["SLOT"]) existing_node = self._slot_node_map[myroot].get( slot_atom, None) @@ -1222,6 +1232,20 @@ class depgraph(object): self.digraph.addnode(jbigkey, myparent, priority=priority) + if arg: + self._args_nodes.add(jbigkey) + try: + for set_name, pkg_set in self._sets.iteritems(): + atom = self._find_atom_for_pkg(pkg_set, mykey, metadata) + if atom: + self._sets_nodes[set_name].add(jbigkey) + except portage.exception.InvalidDependString, e: + if mytype != "installed": + show_invalid_depstring_notice(jbigkey, + metadata["PROVIDE"], str(e)) + return 0 + del e + # Do this even when addme is False (--onlydeps) so that the # parent/child relationship is always known in case # self._show_slot_collision_notice() needs to be called later. @@ -1245,9 +1269,8 @@ class depgraph(object): edepend={} depkeys = ["DEPEND","RDEPEND","PDEPEND"] - depvalues = mydbapi.aux_get(mykey, depkeys) - for i in xrange(len(depkeys)): - edepend[depkeys[i]] = depvalues[i] + for k in depkeys: + edepend[k] = metadata[k] if mytype == "ebuild": if "--buildpkgonly" in self.myopts: @@ -1444,7 +1467,9 @@ class depgraph(object): """ These are used inside self.create() in order to ensure packages that happen to match arguments are not incorrectly marked as nomerge.""" - self.args_keys = [x[1] for x in arg_atoms] + for myarg, myatom in arg_atoms: + self._args_atoms.setdefault( + portage.dep_getkey(myatom), []).append(myatom) for myarg, myatom in arg_atoms: try: self.mysd = self.select_dep(myroot, myatom, arg=myarg) @@ -1548,11 +1573,12 @@ class depgraph(object): return 0 mymerge = mycheck[1] - if not mymerge and arg and \ - portage.best_match_to_list(depstring, self.args_keys): + if not mymerge and arg: # A provided package has been specified on the command line. The # package will not be merged and a warning will be displayed. - self._pprovided_args.append(arg) + cp = portage.dep_getkey(depstring) + if cp in self._args_atoms and depstring in self._args_atoms[cp]: + self._pprovided_args.append(arg) if myparent: # The parent is added after it's own dep_check call so that it @@ -2044,6 +2070,9 @@ class depgraph(object): self._altlist_cache[reversed] = retlist[:] return retlist mygraph=self.digraph.copy() + for node in mygraph.order[:]: + if node[-1] == "nomerge": + mygraph.remove(node) self._merge_order_bias(mygraph) myblockers = self.blocker_digraph.copy() retlist=[] @@ -2222,13 +2251,24 @@ class depgraph(object): matches = portdb.gvisible(portdb.visible(mylist)) return [x for x in mylist \ if x in matches or not portdb.cpv_exists(x)] + def create_cp_dict(atom_list): + cp_dict = {} + for atom in atom_list: + cp_dict.setdefault(portage.dep_getkey(atom), []).append(atom) + return cp_dict world_problems = False if mode=="system": mylist = getlist(self.settings, "system") + self._sets["system"] = create_cp_dict(mylist) + self._sets_nodes["system"] = set() else: #world mode worldlist = getlist(self.settings, "world") + self._sets["world"] = create_cp_dict(worldlist) + self._sets_nodes["world"] = set() mylist = getlist(self.settings, "system") + self._sets["system"] = create_cp_dict(mylist) + self._sets_nodes["system"] = set() worlddict=genericdict(worldlist) for x in worlddict: @@ -2299,7 +2339,11 @@ class depgraph(object): if available: newlist.append(myslot_atom) mylist = newlist - + + for myatom in mylist: + self._args_atoms.setdefault( + portage.dep_getkey(myatom), []).append(myatom) + missing_atoms = [] for mydep in mylist: try: @@ -2325,6 +2369,31 @@ class depgraph(object): return 1 + def _find_atom_for_pkg(self, pkg_set, cpv, metadata): + """Return the best match for a given package from the arguments, or + None if there are no matches. This matches virtual arguments against + the PROVIDE metadata. This can raise an InvalidDependString exception + if an error occurs while parsing PROVIDE.""" + cpv_slot = "%s:%s" % (cpv, metadata["SLOT"]) + cp = portage.dep_getkey(cpv) + atoms = pkg_set.get(cp) + if atoms: + best_match = portage.best_match_to_list(cpv_slot, atoms) + if best_match: + return best_match + provides = portage.flatten(portage.dep.use_reduce( + portage.dep.paren_reduce(metadata["PROVIDE"]), + uselist=metadata["USE"].split())) + for provide in provides: + provided_cp = portage.dep_getkey(provide) + atoms = pkg_set.get(provided_cp) + if atoms: + transformed_atoms = [atom.replace(provided_cp, cp) for atom in atoms] + best_match = portage.best_match_to_list(cpv_slot, transformed_atoms) + if best_match: + return atoms[transformed_atoms.index(best_match)] + return None + def display(self,mylist,verbosity=None): if verbosity is None: verbosity = ("--quiet" in self.myopts and 1 or \ @@ -2432,7 +2501,12 @@ class depgraph(object): traversed_nodes = set() # prevent endless circles traversed_nodes.add(graph_key) def add_parents(current_node, ordered): - parent_nodes = mygraph.parent_nodes(current_node) + parent_nodes = None + # Do not traverse to parents if this node is an + # an argument or a direct member of a set that has + # been specified as an argument (system or world). + if current_node not in self._args_nodes: + parent_nodes = mygraph.parent_nodes(current_node) if parent_nodes: child_nodes = set(mygraph.child_nodes(current_node)) selected_parent = None @@ -2493,7 +2567,6 @@ class depgraph(object): # files to fetch list - avoids counting a same file twice # in size display (verbose mode) myfetchlist=[] - worldlist = set(getlist(self.settings, "world")) for mylist_index in xrange(len(mylist)): x, depth, ordered = mylist[mylist_index] @@ -2765,17 +2838,40 @@ class depgraph(object): myoldbest=blue("["+myoldbest+"]") pkg_cp = xs[0] - pkg_world = pkg_cp in worldlist + pkg_arg = False + pkg_world = False + pkg_system = False + pkg_node = tuple(x) + if pkg_node in self._args_nodes: + pkg_arg = True + world_nodes = self._sets_nodes.get("world") + if world_nodes and pkg_node in world_nodes: + pkg_world = True + if world_nodes is None: + # Don't colorize system package when in "world" mode. + system_nodes = self._sets_nodes.get("system") + if system_nodes and pkg_node in system_nodes: + pkg_system = True def pkgprint(pkg): if pkg_merge: - if pkg_world: - return colorize("PKG_MERGE_WORLD", pkg) + if pkg_arg: + if pkg_world: + return colorize("PKG_MERGE_WORLD", pkg) + elif pkg_system: + return colorize("PKG_MERGE_SYSTEM", pkg) + else: + return colorize("PKG_MERGE_ARG", pkg) else: return colorize("PKG_MERGE", pkg) else: - if pkg_world: - return colorize("PKG_NOMERGE_WORLD", pkg) + if pkg_arg: + if pkg_world: + return colorize("PKG_NOMERGE_WORLD", pkg) + elif pkg_system: + return colorize("PKG_NOMERGE_SYSTEM", pkg) + else: + return colorize("PKG_NOMERGE_ARG", pkg) else: return colorize("PKG_NOMERGE", pkg) @@ -5335,7 +5431,9 @@ def parse_opts(tmpcmdline, silent=False): "choices":("y", "n") }, "--reinstall": { - "help":"specify conditions to trigger package reinstallation" + "help":"specify conditions to trigger package reinstallation", + "type":"choice", + "choices":["changed-use"] } } diff --git a/pym/portage/__init__.py b/pym/portage/__init__.py index c5cb97f64..79f3d6124 100644 --- a/pym/portage/__init__.py +++ b/pym/portage/__init__.py @@ -1021,7 +1021,14 @@ class config(object): "Parent '%s' not found: '%s'" % \ (parentPath, parentsFile)) self.profiles.append(currentPath) - addProfile(os.path.realpath(self.profile_path)) + try: + addProfile(os.path.realpath(self.profile_path)) + except portage.exception.ParseError, e: + writemsg("!!! Unable to parse profile: '%s'\n" % \ + self.profile_path, noiselevel=-1) + writemsg("!!! ParseError: %s\n" % str(e), noiselevel=-1) + del e + self.profiles = [] if local_config: custom_prof = os.path.join( config_root, CUSTOM_PROFILE_PATH.lstrip(os.path.sep)) diff --git a/pym/portage/output.py b/pym/portage/output.py index 008a10fc7..49a2fd995 100644 --- a/pym/portage/output.py +++ b/pym/portage/output.py @@ -130,8 +130,12 @@ codes["UNMERGE_WARN"] = codes["red"] codes["SECURITY_WARN"] = codes["red"] codes["MERGE_LIST_PROGRESS"] = codes["yellow"] codes["PKG_MERGE"] = codes["darkgreen"] +codes["PKG_MERGE_ARG"] = codes["darkgreen"] +codes["PKG_MERGE_SYSTEM"] = codes["green"] codes["PKG_MERGE_WORLD"] = codes["green"] codes["PKG_NOMERGE"] = codes["darkblue"] +codes["PKG_NOMERGE_ARG"] = codes["darkblue"] +codes["PKG_NOMERGE_SYSTEM"] = codes["blue"] codes["PKG_NOMERGE_WORLD"] = codes["blue"] def parse_color_map(): -- 2.26.2