From 1bbf3db3ea38d036b1ca536daea7433074c65fb7 Mon Sep 17 00:00:00 2001 From: Fabian Groffen Date: Tue, 23 Dec 2008 18:37:53 +0000 Subject: [PATCH] Merged from trunk -r12277:12282 | 12278 | Bug #252167 - If the ebuild no longer exists or it's | | zmedico | keywords have been dropped, reject built instances | | | (installed or binary). If --usepkgonly is enabled, assume | | | that the ebuild status should be ignored. | | 12279 | Simplify the code from bug #218854. Also, ensure that the | | zmedico | set of visible packages thats used by | | | depgraph._iter_atoms_for_pkg() is consistent with the | | | packages that have been selected by | | | depgraph._select_pkg_highest_available(). This should | | | correct potential inconstencies introduced by the package | | | selection changes from bug #252167. | | 12280 | Bug #252243 - Fix binarytree.prevent_collision() so that it | | zmedico | won't create a circular symlink if there happens to be a | | | symlink in $PKGDIR/All for some reason. | | 12281 | Fix typo. | | zmedico | | | 12282 | When removing entries with duplicate paths inside | | zmedico | binarytree.inject(), handle path collisions in $PKGDIR/All | | | when CPV is not identical. | svn path=/main/branches/prefix/; revision=12284 --- pym/_emerge/__init__.py | 75 ++++++++++++++++-------------------- pym/portage/dbapi/bintree.py | 32 ++++++++++----- 2 files changed, 57 insertions(+), 50 deletions(-) diff --git a/pym/_emerge/__init__.py b/pym/_emerge/__init__.py index e1d5a7010..ad4f9342b 100644 --- a/pym/_emerge/__init__.py +++ b/pym/_emerge/__init__.py @@ -4334,7 +4334,7 @@ class depgraph(object): # 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 @@ -5737,6 +5737,12 @@ class depgraph(object): 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): @@ -5860,7 +5866,7 @@ class depgraph(object): 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 @@ -5879,9 +5885,8 @@ class depgraph(object): # 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( @@ -5889,9 +5894,26 @@ class depgraph(object): 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 @@ -6028,22 +6050,6 @@ class depgraph(object): 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]) @@ -6180,7 +6186,10 @@ class depgraph(object): 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": @@ -8489,22 +8498,6 @@ class depgraph(object): 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 = {} diff --git a/pym/portage/dbapi/bintree.py b/pym/portage/dbapi/bintree.py index 51012fb3e..f8485f340 100644 --- a/pym/portage/dbapi/bintree.py +++ b/pym/portage/dbapi/bintree.py @@ -329,7 +329,21 @@ class binarytree(object): myfile = mypkg + ".tbz2" mypath = os.path.join("All", myfile) dest_path = os.path.join(self.pkgdir, mypath) - if os.path.exists(dest_path): + + try: + st = os.lstat(dest_path) + except OSError: + st = None + else: + if stat.S_ISLNK(st.st_mode): + st = None + try: + os.unlink(dest_path) + except OSError: + if os.path.exists(dest_path): + raise + + if st is not None: # For invalid packages, other_cat could be None. other_cat = portage.xpak.tbz2(dest_path).getfile("CATEGORY") if other_cat: @@ -337,11 +351,7 @@ class binarytree(object): other_cpv = other_cat + "/" + mypkg self._move_from_all(other_cpv) self.inject(other_cpv) - """The file may or may not exist. Move it if necessary and update - internal state for future calls to getname().""" self._move_to_all(cpv) - if os.path.exists(full_path): - self.inject(cpv) def _ensure_dir(self, path): """ @@ -368,6 +378,7 @@ class binarytree(object): for future getname() calls.""" mycat, mypkg = catsplit(cpv) myfile = mypkg + ".tbz2" + self._pkg_paths[cpv] = os.path.join("All", myfile) src_path = os.path.join(self.pkgdir, mycat, myfile) try: mystat = os.lstat(src_path) @@ -378,7 +389,7 @@ class binarytree(object): dest_path = os.path.join(self.pkgdir, "All", myfile) _movefile(src_path, dest_path, mysettings=self.settings) self._create_symlink(cpv) - self._pkg_paths[cpv] = os.path.join("All", myfile) + self.inject(cpv) def _move_from_all(self, cpv): """Move a package from ${PKGDIR}/All/${PF}.tbz2 to @@ -860,11 +871,14 @@ class binarytree(object): return # If found, remove package(s) with duplicate path. + path = d.get("PATH") for i in xrange(len(pkgindex.packages) - 1, -1, -1): d2 = pkgindex.packages[i] - if d2["CPV"] != cpv: - continue - if d2.get("PATH", "") == d.get("PATH", ""): + if path is not None and path == d2.get("PATH"): + # Handle path collisions in $PKGDIR/All + # when CPV is not identical. + del pkgindex.packages[i] + elif cpv == d2.get("CPV") and path == d2.get("PATH"): del pkgindex.packages[i] pkgindex.packages.append(d) -- 2.26.2