aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'portage_with_autodep/pym/portage/dbapi/porttree.py')
-rw-r--r--portage_with_autodep/pym/portage/dbapi/porttree.py694
1 files changed, 332 insertions, 362 deletions
diff --git a/portage_with_autodep/pym/portage/dbapi/porttree.py b/portage_with_autodep/pym/portage/dbapi/porttree.py
index ecf275c..c5ee770 100644
--- a/portage_with_autodep/pym/portage/dbapi/porttree.py
+++ b/portage_with_autodep/pym/portage/dbapi/porttree.py
@@ -1,4 +1,4 @@
-# Copyright 1998-2011 Gentoo Foundation
+# Copyright 1998-2012 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
__all__ = [
@@ -14,20 +14,19 @@ portage.proxy.lazyimport.lazyimport(globals(),
'portage.package.ebuild.doebuild:doebuild',
'portage.util:ensure_dirs,shlex_split,writemsg,writemsg_level',
'portage.util.listdir:listdir',
- 'portage.versions:best,catpkgsplit,_pkgsplit@pkgsplit,ver_regexp',
+ 'portage.versions:best,catpkgsplit,_pkgsplit@pkgsplit,ver_regexp,_pkg_str',
)
-from portage.cache import metadata_overlay, volatile
+from portage.cache import volatile
from portage.cache.cache_errors import CacheError
from portage.cache.mappings import Mapping
from portage.dbapi import dbapi
from portage.exception import PortageException, \
FileNotFound, InvalidAtom, InvalidDependString, InvalidPackageName
from portage.localization import _
-from portage.manifest import Manifest
-from portage import eclass_cache, auxdbkeys, \
- eapi_is_supported, dep_check, \
+from portage import eclass_cache, \
+ eapi_is_supported, \
_eapi_is_deprecated
from portage import os
from portage import _encodings
@@ -37,8 +36,6 @@ from _emerge.EbuildMetadataPhase import EbuildMetadataPhase
from _emerge.PollScheduler import PollScheduler
import os as _os
-import io
-import stat
import sys
import traceback
import warnings
@@ -47,15 +44,6 @@ if sys.hexversion >= 0x3000000:
basestring = str
long = int
-class _repo_info(object):
- __slots__ = ('name', 'path', 'eclass_db', 'portdir', 'portdir_overlay')
- def __init__(self, name, path, eclass_db):
- self.name = name
- self.path = path
- self.eclass_db = eclass_db
- self.portdir = eclass_db.porttrees[0]
- self.portdir_overlay = ' '.join(eclass_db.porttrees[1:])
-
class portdbapi(dbapi):
"""this tree will scan a portage directory located at root (passed to init)"""
portdbapi_instances = []
@@ -69,6 +57,13 @@ class portdbapi(dbapi):
def porttree_root(self):
return self.settings.repositories.mainRepoLocation()
+ @property
+ def eclassdb(self):
+ main_repo = self.repositories.mainRepo()
+ if main_repo is None:
+ return None
+ return main_repo.eclass_db
+
def __init__(self, _unused_param=None, mysettings=None):
"""
@param _unused_param: deprecated, use mysettings['PORTDIR'] instead
@@ -100,6 +95,7 @@ class portdbapi(dbapi):
# this purpose because doebuild makes many changes to the config
# instance that is passed in.
self.doebuild_settings = config(clone=self.settings)
+ self._scheduler = PollScheduler().sched_iface
self.depcachedir = os.path.realpath(self.settings.depcachedir)
if os.environ.get("SANDBOX_ON") == "1":
@@ -112,7 +108,6 @@ class portdbapi(dbapi):
":".join(filter(None, sandbox_write))
self.porttrees = list(self.settings.repositories.repoLocationList())
- self.eclassdb = eclass_cache.cache(self.settings.repositories.mainRepoLocation())
# This is used as sanity check for aux_get(). If there is no
# root eclass dir, we assume that PORTDIR is invalid or
@@ -121,86 +116,74 @@ class portdbapi(dbapi):
self._have_root_eclass_dir = os.path.isdir(
os.path.join(self.settings.repositories.mainRepoLocation(), "eclass"))
- self.metadbmodule = self.settings.load_best_module("portdbapi.metadbmodule")
-
#if the portdbapi is "frozen", then we assume that we can cache everything (that no updates to it are happening)
self.xcache = {}
self.frozen = 0
- #Create eclass dbs
- self._repo_info = {}
- eclass_dbs = {self.settings.repositories.mainRepoLocation() : self.eclassdb}
- for repo in self.repositories:
- if repo.location in self._repo_info:
- continue
-
- eclass_db = None
- for eclass_location in repo.eclass_locations:
- tree_db = eclass_dbs.get(eclass_location)
- if tree_db is None:
- tree_db = eclass_cache.cache(eclass_location)
- eclass_dbs[eclass_location] = tree_db
- if eclass_db is None:
- eclass_db = tree_db.copy()
- else:
- eclass_db.append(tree_db)
-
- self._repo_info[repo.location] = _repo_info(repo.name, repo.location, eclass_db)
-
#Keep a list of repo names, sorted by priority (highest priority first).
self._ordered_repo_name_list = tuple(reversed(self.repositories.prepos_order))
self.auxdbmodule = self.settings.load_best_module("portdbapi.auxdbmodule")
self.auxdb = {}
self._pregen_auxdb = {}
+ # If the current user doesn't have depcachedir write permission,
+ # then the depcachedir cache is kept here read-only access.
+ self._ro_auxdb = {}
self._init_cache_dirs()
- depcachedir_w_ok = os.access(self.depcachedir, os.W_OK)
- cache_kwargs = {
- 'gid' : portage_gid,
- 'perms' : 0o664
- }
-
- # XXX: REMOVE THIS ONCE UNUSED_0 IS YANKED FROM auxdbkeys
- # ~harring
- filtered_auxdbkeys = [x for x in auxdbkeys if not x.startswith("UNUSED_0")]
- filtered_auxdbkeys.sort()
+ try:
+ depcachedir_st = os.stat(self.depcachedir)
+ depcachedir_w_ok = os.access(self.depcachedir, os.W_OK)
+ except OSError:
+ depcachedir_st = None
+ depcachedir_w_ok = False
+
+ cache_kwargs = {}
+
+ depcachedir_unshared = False
+ if portage.data.secpass < 1 and \
+ depcachedir_w_ok and \
+ depcachedir_st is not None and \
+ os.getuid() == depcachedir_st.st_uid and \
+ os.getgid() == depcachedir_st.st_gid:
+ # If this user owns depcachedir and is not in the
+ # portage group, then don't bother to set permissions
+ # on cache entries. This makes it possible to run
+ # egencache without any need to be a member of the
+ # portage group.
+ depcachedir_unshared = True
+ else:
+ cache_kwargs.update({
+ 'gid' : portage_gid,
+ 'perms' : 0o664
+ })
+
# If secpass < 1, we don't want to write to the cache
# since then we won't be able to apply group permissions
# to the cache entries/directories.
- if secpass < 1 or not depcachedir_w_ok:
+ if (secpass < 1 and not depcachedir_unshared) or not depcachedir_w_ok:
for x in self.porttrees:
+ self.auxdb[x] = volatile.database(
+ self.depcachedir, x, self._known_keys,
+ **cache_kwargs)
try:
- db_ro = self.auxdbmodule(self.depcachedir, x,
- filtered_auxdbkeys, readonly=True, **cache_kwargs)
+ self._ro_auxdb[x] = self.auxdbmodule(self.depcachedir, x,
+ self._known_keys, readonly=True, **cache_kwargs)
except CacheError:
- self.auxdb[x] = volatile.database(
- self.depcachedir, x, filtered_auxdbkeys,
- **cache_kwargs)
- else:
- self.auxdb[x] = metadata_overlay.database(
- self.depcachedir, x, filtered_auxdbkeys,
- db_rw=volatile.database, db_ro=db_ro,
- **cache_kwargs)
+ pass
else:
for x in self.porttrees:
if x in self.auxdb:
continue
# location, label, auxdbkeys
self.auxdb[x] = self.auxdbmodule(
- self.depcachedir, x, filtered_auxdbkeys, **cache_kwargs)
- if self.auxdbmodule is metadata_overlay.database:
- self.auxdb[x].db_ro.ec = self._repo_info[x].eclass_db
+ self.depcachedir, x, self._known_keys, **cache_kwargs)
if "metadata-transfer" not in self.settings.features:
for x in self.porttrees:
if x in self._pregen_auxdb:
continue
- if os.path.isdir(os.path.join(x, "metadata", "cache")):
- self._pregen_auxdb[x] = self.metadbmodule(
- x, "metadata/cache", filtered_auxdbkeys, readonly=True)
- try:
- self._pregen_auxdb[x].ec = self._repo_info[x].eclass_db
- except AttributeError:
- pass
+ cache = self._create_pregen_cache(x)
+ if cache is not None:
+ self._pregen_auxdb[x] = cache
# Selectively cache metadata in order to optimize dep matching.
self._aux_cache_keys = set(
["DEPEND", "EAPI", "INHERITED", "IUSE", "KEYWORDS", "LICENSE",
@@ -210,18 +193,28 @@ class portdbapi(dbapi):
self._aux_cache = {}
self._broken_ebuilds = set()
+ def _create_pregen_cache(self, tree):
+ conf = self.repositories.get_repo_for_location(tree)
+ cache = conf.get_pregenerated_cache(
+ self._known_keys, readonly=True)
+ if cache is not None:
+ try:
+ cache.ec = self.repositories.get_repo_for_location(tree).eclass_db
+ except AttributeError:
+ pass
+ return cache
+
def _init_cache_dirs(self):
"""Create /var/cache/edb/dep and adjust permissions for the portage
group."""
dirmode = 0o2070
- filemode = 0o60
modemask = 0o2
try:
ensure_dirs(self.depcachedir, gid=portage_gid,
mode=dirmode, mask=modemask)
- except PortageException as e:
+ except PortageException:
pass
def close_caches(self):
@@ -260,7 +253,7 @@ class portdbapi(dbapi):
@param canonical_repo_path: the canonical path of a repository, as
resolved by os.path.realpath()
@type canonical_repo_path: String
- @returns: The repo_name for the corresponding repository, or None
+ @return: The repo_name for the corresponding repository, or None
if the path does not correspond a known repository
@rtype: String or None
"""
@@ -332,63 +325,33 @@ class portdbapi(dbapi):
return (filename, x)
return (None, 0)
- def _metadata_process(self, cpv, ebuild_path, repo_path):
- """
- Create an EbuildMetadataPhase instance to generate metadata for the
- give ebuild.
- @rtype: EbuildMetadataPhase
- @returns: A new EbuildMetadataPhase instance, or None if the
- metadata cache is already valid.
- """
- metadata, st, emtime = self._pull_valid_cache(cpv, ebuild_path, repo_path)
- if metadata is not None:
- return None
-
- process = EbuildMetadataPhase(cpv=cpv, ebuild_path=ebuild_path,
- ebuild_mtime=emtime, metadata_callback=self._metadata_callback,
- portdb=self, repo_path=repo_path, settings=self.doebuild_settings)
- return process
-
- def _metadata_callback(self, cpv, ebuild_path, repo_path, metadata, mtime):
-
- i = metadata
- if hasattr(metadata, "items"):
- i = iter(metadata.items())
- metadata = dict(i)
-
- if metadata.get("INHERITED", False):
- metadata["_eclasses_"] = self._repo_info[repo_path
- ].eclass_db.get_eclass_data(metadata["INHERITED"].split())
- else:
- metadata["_eclasses_"] = {}
-
- metadata.pop("INHERITED", None)
- metadata["_mtime_"] = mtime
-
- eapi = metadata.get("EAPI")
- if not eapi or not eapi.strip():
- eapi = "0"
- metadata["EAPI"] = eapi
- if not eapi_is_supported(eapi):
- for k in set(metadata).difference(("_mtime_", "_eclasses_")):
- metadata[k] = ""
- metadata["EAPI"] = "-" + eapi.lstrip("-")
+ def _write_cache(self, cpv, repo_path, metadata, ebuild_hash):
try:
- self.auxdb[repo_path][cpv] = metadata
+ cache = self.auxdb[repo_path]
+ chf = cache.validation_chf
+ metadata['_%s_' % chf] = getattr(ebuild_hash, chf)
except CacheError:
# Normally this shouldn't happen, so we'll show
# a traceback for debugging purposes.
traceback.print_exc()
- return metadata
+ cache = None
+
+ if cache is not None:
+ try:
+ cache[cpv] = metadata
+ except CacheError:
+ # Normally this shouldn't happen, so we'll show
+ # a traceback for debugging purposes.
+ traceback.print_exc()
def _pull_valid_cache(self, cpv, ebuild_path, repo_path):
try:
- # Don't use unicode-wrapped os module, for better performance.
- st = _os.stat(_unicode_encode(ebuild_path,
- encoding=_encodings['fs'], errors='strict'))
- emtime = st[stat.ST_MTIME]
- except OSError:
+ ebuild_hash = eclass_cache.hashed_path(ebuild_path)
+ # snag mtime since we use it later, and to trigger stat failure
+ # if it doesn't exist
+ ebuild_hash.mtime
+ except FileNotFound:
writemsg(_("!!! aux_get(): ebuild for " \
"'%s' does not exist at:\n") % (cpv,), noiselevel=-1)
writemsg("!!! %s\n" % ebuild_path, noiselevel=-1)
@@ -401,39 +364,39 @@ class portdbapi(dbapi):
pregen_auxdb = self._pregen_auxdb.get(repo_path)
if pregen_auxdb is not None:
auxdbs.append(pregen_auxdb)
+ ro_auxdb = self._ro_auxdb.get(repo_path)
+ if ro_auxdb is not None:
+ auxdbs.append(ro_auxdb)
auxdbs.append(self.auxdb[repo_path])
- eclass_db = self._repo_info[repo_path].eclass_db
+ eclass_db = self.repositories.get_repo_for_location(repo_path).eclass_db
- doregen = True
for auxdb in auxdbs:
try:
metadata = auxdb[cpv]
except KeyError:
- pass
+ continue
except CacheError:
- if auxdb is not pregen_auxdb:
+ if not auxdb.readonly:
try:
del auxdb[cpv]
- except KeyError:
- pass
- except CacheError:
+ except (KeyError, CacheError):
pass
- else:
- eapi = metadata.get('EAPI', '').strip()
- if not eapi:
- eapi = '0'
- if not (eapi[:1] == '-' and eapi_is_supported(eapi[1:])) and \
- emtime == metadata['_mtime_'] and \
- eclass_db.is_eclass_data_valid(metadata['_eclasses_']):
- doregen = False
-
- if not doregen:
+ continue
+ eapi = metadata.get('EAPI', '').strip()
+ if not eapi:
+ eapi = '0'
+ metadata['EAPI'] = eapi
+ if not eapi_is_supported(eapi):
+ # Since we're supposed to be able to efficiently obtain the
+ # EAPI from _parse_eapi_ebuild_head, we disregard cache entries
+ # for unsupported EAPIs.
+ continue
+ if auxdb.validate_entry(metadata, ebuild_hash, eclass_db):
break
-
- if doregen:
+ else:
metadata = None
- return (metadata, st, emtime)
+ return (metadata, ebuild_hash)
def aux_get(self, mycpv, mylist, mytree=None, myrepo=None):
"stub code for returning auxilliary db information, such as SLOT, DEPEND, etc."
@@ -445,15 +408,22 @@ class portdbapi(dbapi):
if mytree is None:
raise KeyError(myrepo)
- if not mytree:
+ if mytree is not None and len(self.porttrees) == 1 \
+ and mytree == self.porttrees[0]:
+ # mytree matches our only tree, so it's safe to
+ # ignore mytree and cache the result
+ mytree = None
+ myrepo = None
+
+ if mytree is None:
cache_me = True
- if not mytree and not self._known_keys.intersection(
+ if mytree is None and not self._known_keys.intersection(
mylist).difference(self._aux_cache_keys):
aux_cache = self._aux_cache.get(mycpv)
if aux_cache is not None:
return [aux_cache.get(x, "") for x in mylist]
cache_me = True
- global auxdbkeys, auxdbkeylen
+
try:
cat, pkg = mycpv.split("/", 1)
except ValueError:
@@ -467,60 +437,35 @@ class portdbapi(dbapi):
_("ebuild not found for '%s'") % mycpv, noiselevel=1)
raise KeyError(mycpv)
- mydata, st, emtime = self._pull_valid_cache(mycpv, myebuild, mylocation)
+ mydata, ebuild_hash = self._pull_valid_cache(mycpv, myebuild, mylocation)
doregen = mydata is None
if doregen:
if myebuild in self._broken_ebuilds:
raise KeyError(mycpv)
- self.doebuild_settings.setcpv(mycpv)
- eapi = None
-
- if eapi is None and \
- 'parse-eapi-ebuild-head' in self.doebuild_settings.features:
- eapi = portage._parse_eapi_ebuild_head(io.open(
- _unicode_encode(myebuild,
- encoding=_encodings['fs'], errors='strict'),
- mode='r', encoding=_encodings['repo.content'],
- errors='replace'))
-
- if eapi is not None:
- self.doebuild_settings.configdict['pkg']['EAPI'] = eapi
-
- if eapi is not None and not portage.eapi_is_supported(eapi):
- mydata = self._metadata_callback(
- mycpv, myebuild, mylocation, {'EAPI':eapi}, emtime)
- else:
- proc = EbuildMetadataPhase(cpv=mycpv, ebuild_path=myebuild,
- ebuild_mtime=emtime,
- metadata_callback=self._metadata_callback, portdb=self,
- repo_path=mylocation,
- scheduler=PollScheduler().sched_iface,
- settings=self.doebuild_settings)
+ proc = EbuildMetadataPhase(cpv=mycpv,
+ ebuild_hash=ebuild_hash, portdb=self,
+ repo_path=mylocation, scheduler=self._scheduler,
+ settings=self.doebuild_settings)
- proc.start()
- proc.wait()
+ proc.start()
+ proc.wait()
- if proc.returncode != os.EX_OK:
- self._broken_ebuilds.add(myebuild)
- raise KeyError(mycpv)
+ if proc.returncode != os.EX_OK:
+ self._broken_ebuilds.add(myebuild)
+ raise KeyError(mycpv)
- mydata = proc.metadata
+ mydata = proc.metadata
- # do we have a origin repository name for the current package
mydata["repository"] = self.repositories.get_name_for_location(mylocation)
- mydata["INHERITED"] = ' '.join(mydata.get("_eclasses_", []))
- mydata["_mtime_"] = st[stat.ST_MTIME]
-
+ mydata["_mtime_"] = ebuild_hash.mtime
eapi = mydata.get("EAPI")
if not eapi:
eapi = "0"
mydata["EAPI"] = eapi
- if not eapi_is_supported(eapi):
- for k in set(mydata).difference(("_mtime_", "_eclasses_")):
- mydata[k] = ""
- mydata["EAPI"] = "-" + eapi.lstrip("-")
+ if eapi_is_supported(eapi):
+ mydata["INHERITED"] = " ".join(mydata.get("_eclasses_", []))
#finally, we look at our internal cache entry and return the requested data.
returnme = [mydata.get(x, "") for x in mylist]
@@ -546,7 +491,7 @@ class portdbapi(dbapi):
@param mytree: The canonical path of the tree in which the ebuild
is located, or None for automatic lookup
@type mypkg: String
- @returns: A dict which maps each file name to a set of alternative
+ @return: A dict which maps each file name to a set of alternative
URIs.
@rtype: dict
"""
@@ -565,7 +510,7 @@ class portdbapi(dbapi):
# since callers already handle it.
raise portage.exception.InvalidDependString(
"getFetchMap(): '%s' has unsupported EAPI: '%s'" % \
- (mypkg, eapi.lstrip("-")))
+ (mypkg, eapi))
return _parse_uri_map(mypkg, {'EAPI':eapi,'SRC_URI':myuris},
use=useflags)
@@ -576,7 +521,9 @@ class portdbapi(dbapi):
if myebuild is None:
raise AssertionError(_("ebuild not found for '%s'") % mypkg)
pkgdir = os.path.dirname(myebuild)
- mf = Manifest(pkgdir, self.settings["DISTDIR"])
+ mf = self.repositories.get_repo_for_location(
+ os.path.dirname(os.path.dirname(pkgdir))).load_manifest(
+ pkgdir, self.settings["DISTDIR"])
checksums = mf.getDigests()
if not checksums:
if debug:
@@ -597,7 +544,7 @@ class portdbapi(dbapi):
mystat = None
try:
mystat = os.stat(file_path)
- except OSError as e:
+ except OSError:
pass
if mystat is None:
existing_size = 0
@@ -644,7 +591,9 @@ class portdbapi(dbapi):
if myebuild is None:
raise AssertionError(_("ebuild not found for '%s'") % mypkg)
pkgdir = os.path.dirname(myebuild)
- mf = Manifest(pkgdir, self.settings["DISTDIR"])
+ mf = self.repositories.get_repo_for_location(
+ os.path.dirname(os.path.dirname(pkgdir)))
+ mf = mf.load_manifest(pkgdir, self.settings["DISTDIR"])
mysums = mf.getDigests()
failures = {}
@@ -706,15 +655,22 @@ class portdbapi(dbapi):
return l
def cp_list(self, mycp, use_cache=1, mytree=None):
+ # NOTE: Cache can be safely shared with the match cache, since the
+ # match cache uses the result from dep_expand for the cache_key.
+ if self.frozen and mytree is not None \
+ and len(self.porttrees) == 1 \
+ and mytree == self.porttrees[0]:
+ # mytree matches our only tree, so it's safe to
+ # ignore mytree and cache the result
+ mytree = None
+
if self.frozen and mytree is None:
cachelist = self.xcache["cp-list"].get(mycp)
if cachelist is not None:
# Try to propagate this to the match-all cache here for
# repoman since he uses separate match-all caches for each
- # profile (due to old-style virtuals). Do not propagate
- # old-style virtuals since cp_list() doesn't expand them.
- if not (not cachelist and mycp.startswith("virtual/")):
- self.xcache["match-all"][mycp] = cachelist
+ # profile (due to differences in _get_implicit_iuse).
+ self.xcache["match-all"][(mycp, mycp)] = cachelist
return cachelist[:]
mysplit = mycp.split("/")
invalid_category = mysplit[0] not in self._categories
@@ -752,7 +708,7 @@ class portdbapi(dbapi):
writemsg(_("\nInvalid ebuild version: %s\n") % \
os.path.join(oroot, mycp, x), noiselevel=-1)
continue
- d[mysplit[0]+"/"+pf] = None
+ d[_pkg_str(mysplit[0]+"/"+pf)] = None
if invalid_category and d:
writemsg(_("\n!!! '%s' has a category that is not listed in " \
"%setc/portage/categories\n") % \
@@ -766,14 +722,11 @@ class portdbapi(dbapi):
if self.frozen and mytree is None:
cachelist = mylist[:]
self.xcache["cp-list"][mycp] = cachelist
- # Do not propagate old-style virtuals since
- # cp_list() doesn't expand them.
- if not (not cachelist and mycp.startswith("virtual/")):
- self.xcache["match-all"][mycp] = cachelist
+ self.xcache["match-all"][(mycp, mycp)] = cachelist
return mylist
def freeze(self):
- for x in "bestmatch-visible", "cp-list", "list-visible", "match-all", \
+ for x in "bestmatch-visible", "cp-list", "match-all", \
"match-all-cpv-only", "match-visible", "minimum-all", \
"minimum-visible":
self.xcache[x]={}
@@ -785,12 +738,12 @@ class portdbapi(dbapi):
def xmatch(self,level,origdep,mydep=None,mykey=None,mylist=None):
"caching match function; very trick stuff"
- #if no updates are being made to the tree, we can consult our xcache...
- if self.frozen:
- try:
- return self.xcache[level][origdep][:]
- except KeyError:
- pass
+ if level == "list-visible":
+ level = "match-visible"
+ warnings.warn("The 'list-visible' mode of "
+ "portage.dbapi.porttree.portdbapi.xmatch "
+ "has been renamed to match-visible",
+ DeprecationWarning, stacklevel=2)
if mydep is None:
#this stuff only runs on first call of xmatch()
@@ -798,12 +751,24 @@ class portdbapi(dbapi):
mydep = dep_expand(origdep, mydb=self, settings=self.settings)
mykey = mydep.cp
+ #if no updates are being made to the tree, we can consult our xcache...
+ cache_key = None
+ if self.frozen:
+ cache_key = (mydep, mydep.unevaluated_atom)
+ try:
+ return self.xcache[level][cache_key][:]
+ except KeyError:
+ pass
+
myval = None
mytree = None
if mydep.repo is not None:
mytree = self.treemap.get(mydep.repo)
if mytree is None:
- myval = []
+ if level.startswith("match-"):
+ myval = []
+ else:
+ myval = ""
if myval is not None:
# Unknown repo, empty result.
@@ -822,27 +787,8 @@ class portdbapi(dbapi):
myval = match_from_list(mydep,
self.cp_list(mykey, mytree=mytree))
- elif level == "list-visible":
- #a list of all visible packages, not called directly (just by xmatch())
- #myval = self.visible(self.cp_list(mykey))
-
- myval = self.gvisible(self.visible(
- self.cp_list(mykey, mytree=mytree)))
- elif level == "minimum-all":
- # Find the minimum matching version. This is optimized to
- # minimize the number of metadata accesses (improves performance
- # especially in cases where metadata needs to be generated).
- if mydep == mykey:
- cpv_iter = iter(self.cp_list(mykey, mytree=mytree))
- else:
- cpv_iter = self._iter_match(mydep,
- self.cp_list(mykey, mytree=mytree))
- try:
- myval = next(cpv_iter)
- except StopIteration:
- myval = ""
-
- elif level in ("minimum-visible", "bestmatch-visible"):
+ elif level in ("bestmatch-visible", "match-all", "match-visible",
+ "minimum-all", "minimum-visible"):
# Find the minimum matching visible version. This is optimized to
# minimize the number of metadata accesses (improves performance
# especially in cases where metadata needs to be generated).
@@ -851,158 +797,172 @@ class portdbapi(dbapi):
else:
mylist = match_from_list(mydep,
self.cp_list(mykey, mytree=mytree))
- myval = ""
- settings = self.settings
- local_config = settings.local_config
+
+ visibility_filter = level not in ("match-all", "minimum-all")
+ single_match = level not in ("match-all", "match-visible")
+ myval = []
aux_keys = list(self._aux_cache_keys)
- if level == "minimum-visible":
+ if level == "bestmatch-visible":
+ iterfunc = reversed
+ else:
iterfunc = iter
+
+ if mydep.repo is not None:
+ repos = [mydep.repo]
else:
- iterfunc = reversed
+ # We iterate over self.porttrees, since it's common to
+ # tweak this attribute in order to adjust match behavior.
+ repos = []
+ for tree in reversed(self.porttrees):
+ repos.append(self.repositories.get_name_for_location(tree))
+
for cpv in iterfunc(mylist):
- try:
- metadata = dict(zip(aux_keys,
- self.aux_get(cpv, aux_keys)))
- except KeyError:
- # ebuild masked by corruption
- continue
- if not eapi_is_supported(metadata["EAPI"]):
- continue
- if mydep.slot and mydep.slot != metadata["SLOT"]:
- continue
- if settings._getMissingKeywords(cpv, metadata):
- continue
- if settings._getMaskAtom(cpv, metadata):
- continue
- if settings._getProfileMaskAtom(cpv, metadata):
- continue
- if local_config:
- metadata["USE"] = ""
- if "?" in metadata["LICENSE"] or "?" in metadata["PROPERTIES"]:
- self.doebuild_settings.setcpv(cpv, mydb=metadata)
- metadata["USE"] = self.doebuild_settings.get("USE", "")
+ for repo in repos:
try:
- if settings._getMissingLicenses(cpv, metadata):
- continue
- if settings._getMissingProperties(cpv, metadata):
- continue
- except InvalidDependString:
+ metadata = dict(zip(aux_keys,
+ self.aux_get(cpv, aux_keys, myrepo=repo)))
+ except KeyError:
+ # ebuild not in this repo, or masked by corruption
continue
- if mydep.use:
- has_iuse = False
- for has_iuse in self._iter_match_use(mydep, [cpv]):
- break
- if not has_iuse:
+
+ if visibility_filter and not self._visible(cpv, metadata):
continue
- myval = cpv
- break
+
+ if mydep.slot is not None and \
+ mydep.slot != metadata["SLOT"]:
+ continue
+
+ if mydep.unevaluated_atom.use is not None and \
+ not self._match_use(mydep, cpv, metadata):
+ continue
+
+ myval.append(cpv)
+ # only yield a given cpv once
+ break
+
+ if myval and single_match:
+ break
+
+ if single_match:
+ if myval:
+ myval = myval[0]
+ else:
+ myval = ""
+
elif level == "bestmatch-list":
#dep match -- find best match but restrict search to sublist
- #no point in calling xmatch again since we're not caching list deps
-
+ warnings.warn("The 'bestmatch-list' mode of "
+ "portage.dbapi.porttree.portdbapi.xmatch is deprecated",
+ DeprecationWarning, stacklevel=2)
myval = best(list(self._iter_match(mydep, mylist)))
elif level == "match-list":
#dep match -- find all matches but restrict search to sublist (used in 2nd half of visible())
-
+ warnings.warn("The 'match-list' mode of "
+ "portage.dbapi.porttree.portdbapi.xmatch is deprecated",
+ DeprecationWarning, stacklevel=2)
myval = list(self._iter_match(mydep, mylist))
- elif level == "match-visible":
- #dep match -- find all visible matches
- #get all visible packages, then get the matching ones
- myval = list(self._iter_match(mydep,
- self.xmatch("list-visible", mykey, mydep=Atom(mykey), mykey=mykey)))
- elif level == "match-all":
- #match *all* visible *and* masked packages
- if mydep == mykey:
- myval = self.cp_list(mykey, mytree=mytree)
- else:
- myval = list(self._iter_match(mydep,
- self.cp_list(mykey, mytree=mytree)))
else:
raise AssertionError(
"Invalid level argument: '%s'" % level)
- if self.frozen and (level not in ["match-list", "bestmatch-list"]):
- self.xcache[level][mydep] = myval
- if origdep and origdep != mydep:
- self.xcache[level][origdep] = myval
- return myval[:]
+ if self.frozen:
+ xcache_this_level = self.xcache.get(level)
+ if xcache_this_level is not None:
+ xcache_this_level[cache_key] = myval
+ if not isinstance(myval, _pkg_str):
+ myval = myval[:]
+
+ return myval
def match(self, mydep, use_cache=1):
return self.xmatch("match-visible", mydep)
- def visible(self, mylist):
- """two functions in one. Accepts a list of cpv values and uses the package.mask *and*
- packages file to remove invisible entries, returning remaining items. This function assumes
- that all entries in mylist have the same category and package name."""
- if not mylist:
- return []
-
- db_keys = ["SLOT"]
- visible = []
- getMaskAtom = self.settings._getMaskAtom
- getProfileMaskAtom = self.settings._getProfileMaskAtom
- for cpv in mylist:
- try:
- metadata = dict(zip(db_keys, self.aux_get(cpv, db_keys)))
- except KeyError:
- # masked by corruption
- continue
- if not metadata["SLOT"]:
- continue
- if getMaskAtom(cpv, metadata):
- continue
- if getProfileMaskAtom(cpv, metadata):
- continue
- visible.append(cpv)
- return visible
-
- def gvisible(self,mylist):
- "strip out group-masked (not in current group) entries"
+ def gvisible(self, mylist):
+ warnings.warn("The 'gvisible' method of "
+ "portage.dbapi.porttree.portdbapi "
+ "is deprecated",
+ DeprecationWarning, stacklevel=2)
+ return list(self._iter_visible(iter(mylist)))
- if mylist is None:
+ def visible(self, cpv_iter):
+ warnings.warn("The 'visible' method of "
+ "portage.dbapi.porttree.portdbapi "
+ "is deprecated",
+ DeprecationWarning, stacklevel=2)
+ if cpv_iter is None:
return []
- newlist=[]
+ return list(self._iter_visible(iter(cpv_iter)))
+
+ def _iter_visible(self, cpv_iter, myrepo=None):
+ """
+ Return a new list containing only visible packages.
+ """
aux_keys = list(self._aux_cache_keys)
metadata = {}
- local_config = self.settings.local_config
- chost = self.settings.get('CHOST', '')
- accept_chost = self.settings._accept_chost
- for mycpv in mylist:
- metadata.clear()
- try:
- metadata.update(zip(aux_keys, self.aux_get(mycpv, aux_keys)))
- except KeyError:
- continue
- except PortageException as e:
- writemsg("!!! Error: aux_get('%s', %s)\n" % (mycpv, aux_keys),
- noiselevel=-1)
- writemsg("!!! %s\n" % (e,), noiselevel=-1)
- del e
- continue
- eapi = metadata["EAPI"]
- if not eapi_is_supported(eapi):
- continue
- if _eapi_is_deprecated(eapi):
- continue
- if self.settings._getMissingKeywords(mycpv, metadata):
- continue
- if local_config:
- metadata['CHOST'] = chost
- if not accept_chost(mycpv, metadata):
- continue
- metadata["USE"] = ""
- if "?" in metadata["LICENSE"] or "?" in metadata["PROPERTIES"]:
- self.doebuild_settings.setcpv(mycpv, mydb=metadata)
- metadata['USE'] = self.doebuild_settings['PORTAGE_USE']
+
+ if myrepo is not None:
+ repos = [myrepo]
+ else:
+ # We iterate over self.porttrees, since it's common to
+ # tweak this attribute in order to adjust match behavior.
+ repos = []
+ for tree in reversed(self.porttrees):
+ repos.append(self.repositories.get_name_for_location(tree))
+
+ for mycpv in cpv_iter:
+ for repo in repos:
+ metadata.clear()
try:
- if self.settings._getMissingLicenses(mycpv, metadata):
- continue
- if self.settings._getMissingProperties(mycpv, metadata):
- continue
- except InvalidDependString:
+ metadata.update(zip(aux_keys,
+ self.aux_get(mycpv, aux_keys, myrepo=repo)))
+ except KeyError:
+ continue
+ except PortageException as e:
+ writemsg("!!! Error: aux_get('%s', %s)\n" %
+ (mycpv, aux_keys), noiselevel=-1)
+ writemsg("!!! %s\n" % (e,), noiselevel=-1)
+ del e
continue
- newlist.append(mycpv)
- return newlist
+
+ if not self._visible(mycpv, metadata):
+ continue
+
+ yield mycpv
+ # only yield a given cpv once
+ break
+
+ def _visible(self, cpv, metadata):
+ eapi = metadata["EAPI"]
+ if not eapi_is_supported(eapi):
+ return False
+ if _eapi_is_deprecated(eapi):
+ return False
+ if not metadata["SLOT"]:
+ return False
+
+ settings = self.settings
+ if settings._getMaskAtom(cpv, metadata):
+ return False
+ if settings._getMissingKeywords(cpv, metadata):
+ return False
+ if settings.local_config:
+ metadata['CHOST'] = settings.get('CHOST', '')
+ if not settings._accept_chost(cpv, metadata):
+ return False
+ metadata["USE"] = ""
+ if "?" in metadata["LICENSE"] or \
+ "?" in metadata["PROPERTIES"]:
+ self.doebuild_settings.setcpv(cpv, mydb=metadata)
+ metadata['USE'] = self.doebuild_settings['PORTAGE_USE']
+ try:
+ if settings._getMissingLicenses(cpv, metadata):
+ return False
+ if settings._getMissingProperties(cpv, metadata):
+ return False
+ except InvalidDependString:
+ return False
+
+ return True
def close_portdbapi_caches():
for i in portdbapi.portdbapi_instances:
@@ -1011,7 +971,7 @@ def close_portdbapi_caches():
portage.process.atexit_register(portage.portageexit)
class portagetree(object):
- def __init__(self, root=None, virtual=None, settings=None):
+ def __init__(self, root=None, virtual=DeprecationWarning, settings=None):
"""
Constructor for a PortageTree
@@ -1034,8 +994,14 @@ class portagetree(object):
"settings['ROOT'] instead.",
DeprecationWarning, stacklevel=2)
+ if virtual is not DeprecationWarning:
+ warnings.warn("The 'virtual' parameter of the "
+ "portage.dbapi.porttree.portagetree"
+ " constructor is unused",
+ DeprecationWarning, stacklevel=2)
+
self.portroot = settings["PORTDIR"]
- self.virtual = virtual
+ self.__virtual = virtual
self.dbapi = portdbapi(mysettings=settings)
@property
@@ -1044,9 +1010,17 @@ class portagetree(object):
"portage.dbapi.porttree.portagetree" + \
" is deprecated. Use " + \
"settings['ROOT'] instead.",
- DeprecationWarning, stacklevel=2)
+ DeprecationWarning, stacklevel=3)
return self.settings['ROOT']
+ @property
+ def virtual(self):
+ warnings.warn("The 'virtual' attribute of " + \
+ "portage.dbapi.porttree.portagetree" + \
+ " is deprecated.",
+ DeprecationWarning, stacklevel=3)
+ return self.__virtual
+
def dep_bestmatch(self,mydep):
"compatibility method"
mymatch = self.dbapi.xmatch("bestmatch-visible",mydep)
@@ -1077,17 +1051,14 @@ class portagetree(object):
psplit = pkgsplit(mysplit[1])
return "/".join([self.portroot, mysplit[0], psplit[0], mysplit[1]])+".ebuild"
- def depcheck(self, mycheck, use="yes", myusesplit=None):
- return dep_check(mycheck, self.dbapi, use=use, myuse=myusesplit)
-
def getslot(self,mycatpkg):
"Get a slot for a catpkg; assume it exists."
myslot = ""
try:
myslot = self.dbapi.aux_get(mycatpkg, ["SLOT"])[0]
- except SystemExit as e:
+ except SystemExit:
raise
- except Exception as e:
+ except Exception:
pass
return myslot
@@ -1148,7 +1119,7 @@ def _parse_uri_map(cpv, metadata, use=None):
while myuris:
uri = myuris.pop()
if myuris and myuris[-1] == "->":
- operator = myuris.pop()
+ myuris.pop()
distfile = myuris.pop()
else:
distfile = os.path.basename(uri)
@@ -1163,6 +1134,5 @@ def _parse_uri_map(cpv, metadata, use=None):
uri_map[distfile] = uri_set
uri_set.add(uri)
uri = None
- operator = None
return uri_map