--- pym/_emerge/__init__.py (revision 12277) +++ pym/_emerge/__init__.py (revision 12279) @@ -4307,7 +4307,7 @@ # to the graph. self._graph_trees = {} # All Package instances - self._pkg_cache = self._package_cache(self) + self._pkg_cache = {} for myroot in trees: self.trees[myroot] = {} # Create a RootConfig instance that references @@ -5706,6 +5706,12 @@ return ret ret = self._select_pkg_highest_available_imp(root, atom, onlydeps=onlydeps) self._highest_pkg_cache[cache_key] = ret + pkg, existing = ret + if pkg is not None: + settings = pkg.root_config.settings + if visible(settings, pkg) and not (pkg.installed and \ + settings._getMissingKeywords(pkg.cpv, pkg.metadata)): + pkg.root_config.visible_pkgs.cpv_inject(pkg) return ret def _select_pkg_highest_available_imp(self, root, atom, onlydeps=False): @@ -5829,7 +5835,7 @@ calculated_use = True self._pkg_cache[pkg] = pkg - if not installed or (installed and matched_packages): + if not installed or (built and matched_packages): # Only enforce visibility on installed packages # if there is at least one other visible package # available. By filtering installed masked packages @@ -5848,9 +5854,8 @@ # version is masked by KEYWORDS, but never # reinstall the same exact version only due # to a KEYWORDS mask. - if installed and matched_packages and \ - pkgsettings._getMissingKeywords( - pkg.cpv, pkg.metadata): + if built and matched_packages: + different_version = None for avail_pkg in matched_packages: if not portage.dep.cpvequal( @@ -5858,10 +5863,27 @@ different_version = avail_pkg break if different_version is not None: - # Only reinstall for KEYWORDS if - # it's not the same version. - continue + if installed and \ + pkgsettings._getMissingKeywords( + pkg.cpv, pkg.metadata): + continue + + # If the ebuild no longer exists or it's + # keywords have been dropped, reject built + # instances (installed or binary). + # If --usepkgonly is enabled, assume that + # the ebuild status should be ignored. + if not usepkgonly: + try: + pkg_eb = self._pkg( + pkg.cpv, "ebuild", root_config) + except portage.exception.PackageNotFound: + continue + else: + if not visible(pkgsettings, pkg_eb): + continue + if not pkg.built and not calculated_use: # This is avoided whenever possible because # it's expensive. @@ -5997,22 +6019,6 @@ if pkg.cp == cp] break - # If the installed version is in a different slot and it is higher than - # the highest available visible package, _iter_atoms_for_pkg() may fail - # to properly match the available package with a corresponding argument - # atom. Detect this case and correct it here. - if not selective and len(matched_packages) > 1 and \ - matched_packages[-1].installed and \ - matched_packages[-1].slot_atom != \ - matched_packages[-2].slot_atom and \ - matched_packages[-1] > matched_packages[-2]: - pkg = matched_packages[-2] - if pkg.root == self.target_root and \ - self._set_atoms.findAtomForPackage(pkg): - # Select the available package instead - # of the installed package. - matched_packages.pop() - if len(matched_packages) > 1: bestmatch = portage.best( [pkg.cpv for pkg in matched_packages]) @@ -6149,7 +6155,10 @@ db = root_config.trees[tree_type].dbapi db_keys = list(self._trees_orig[root_config.root][ tree_type].dbapi._aux_cache_keys) - metadata = izip(db_keys, db.aux_get(cpv, db_keys)) + try: + metadata = izip(db_keys, db.aux_get(cpv, db_keys)) + except KeyError: + raise portage.exception.PackageNotFound(cpv) pkg = Package(cpv=cpv, metadata=metadata, root_config=root_config, installed=installed) if type_name == "ebuild": @@ -8453,22 +8462,6 @@ metadata = self._cpv_pkg_map[cpv].metadata return [metadata.get(x, "") for x in wants] - class _package_cache(dict): - def __init__(self, depgraph): - dict.__init__(self) - self._depgraph = depgraph - - def __setitem__(self, k, v): - dict.__setitem__(self, k, v) - root_config = self._depgraph.roots[v.root] - try: - if visible(root_config.settings, v) and \ - not (v.installed and \ - v.root_config.settings._getMissingKeywords(v.cpv, v.metadata)): - root_config.visible_pkgs.cpv_inject(v) - except portage.exception.InvalidDependString: - pass - class RepoDisplay(object): def __init__(self, roots): self._shown_repos = {}