# 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
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):
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
# 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(
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
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])
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":
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 = {}
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:
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):
"""
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)
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
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)