Index: bin/emerge =================================================================== --- bin/emerge (revision 7237) +++ bin/emerge (revision 7238) @@ -1083,6 +1083,8 @@ self.pkg_node_map = {} # Maps slot atom to digraph node for all nodes added to the graph. self._slot_node_map = {} + # Maps nodes to the reasons they were selected for reinstallation. + self._reinstall_nodes = {} self.mydbapi = {} self._mydbapi_keys = ["SLOT", "DEPEND", "RDEPEND", "PDEPEND", "USE", "IUSE", "PROVIDE", "RESTRICT"] @@ -1204,18 +1206,23 @@ def _reinstall_for_flags(self, forced_flags, orig_use, orig_iuse, cur_use, cur_iuse): + """Return a set of flags that trigger reinstallation, or None if there + are no such flags.""" if "--newuse" in self.myopts: - if orig_iuse.symmetric_difference( - cur_iuse).difference(forced_flags): - return True - elif orig_iuse.intersection(orig_use) != \ - cur_iuse.intersection(cur_use): - return True + flags = orig_iuse.symmetric_difference( + cur_iuse).difference(forced_flags) + if flags: + return flags + flags = orig_iuse.intersection(orig_use).symmetric_difference( + cur_iuse.intersection(cur_use)) + if flags: + return flags elif "changed-use" == self.myopts.get("--reinstall"): - if orig_iuse.intersection(orig_use) != \ - cur_iuse.intersection(cur_use): - return True - return False + flags = orig_iuse.intersection(orig_use).symmetric_difference( + cur_iuse.intersection(cur_use)) + if flags: + return flags + return None def create(self, mybigkey, myparent=None, addme=1, myuse=None, priority=DepPriority(), rev_dep=False, arg=None): @@ -1286,6 +1293,7 @@ return 0 del e + reinstall_for_flags = None merging=1 if mytype == "installed": merging = 0 @@ -1299,6 +1307,7 @@ If the package has new iuse flags or different use flags then if --newuse is specified, we need to merge the package. """ if merging == 0 and \ + myroot == self.target_root and \ ("--newuse" in self.myopts or "--reinstall" in self.myopts) and \ vardbapi.cpv_exists(mykey): @@ -1310,8 +1319,9 @@ 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( - forced_flags, old_use, old_iuse, myuse, iuses): + reinstall_for_flags = self._reinstall_for_flags( + forced_flags, old_use, old_iuse, myuse, iuses) + if reinstall_for_flags: merging = 1 if addme and merging == 1: @@ -1379,6 +1389,8 @@ self._slot_node_map[myroot][slot_atom] = jbigkey self.pkg_node_map[myroot][mykey] = jbigkey self.useFlags[myroot][mykey] = myuse + if reinstall_for_flags: + self._reinstall_nodes[jbigkey] = reinstall_for_flags if rev_dep and myparent: self.digraph.addnode(myparent, jbigkey, @@ -2874,7 +2886,8 @@ use_expand_hidden = \ pkgsettings["USE_EXPAND_HIDDEN"].lower().split() - def map_to_use_expand(myvals, forcedFlags=False): + def map_to_use_expand(myvals, forcedFlags=False, + removeHidden=True): ret = {} forced = {} for exp in use_expand: @@ -2889,13 +2902,32 @@ ret["USE"] = myvals forced["USE"] = [val for val in myvals \ if val in forced_flags] - for exp in use_expand_hidden: - if exp in ret: - del ret[exp] + if removeHidden: + for exp in use_expand_hidden: + ret.pop(exp, None) if forcedFlags: return ret, forced return ret + # Prevent USE_EXPAND_HIDDEN flags from being hidden if they + # are the only thing that triggered reinstallation. + reinst_flags_map = None + reinstall_for_flags = self._reinstall_nodes.get(pkg_node) + if reinstall_for_flags: + reinst_flags_map = map_to_use_expand( + list(reinstall_for_flags), removeHidden=False) + if reinst_flags_map["USE"]: + reinst_flags_map = None + else: + for k in reinst_flags_map.keys(): + if not reinst_flags_map[k]: + del reinst_flags_map[k] + if reinst_flags_map and \ + not set(reinst_flags_map).difference( + use_expand_hidden): + use_expand_hidden = set(use_expand_hidden).difference( + reinst_flags_map) + cur_iuse_map, iuse_forced = \ map_to_use_expand(cur_iuse, forcedFlags=True) cur_use_map = map_to_use_expand(cur_use)