Make ProviderIndexes mergeable, so we can cache them per-repo.

This commit is contained in:
Todd Gamblin 2016-05-28 20:13:13 -05:00
parent bf028990e7
commit cf2f902b82
3 changed files with 57 additions and 8 deletions

View file

@ -224,12 +224,20 @@ def all_packages(self):
yield self.get(name) yield self.get(name)
@property
def provider_index(self):
"""Merged ProviderIndex from all Repos in the RepoPath."""
if self._provider_index is None:
self._provider_index = ProviderIndex()
for repo in reversed(self.repos):
self._provider_index.merge(repo.provider_index)
return self._provider_index
@_autospec @_autospec
def providers_for(self, vpkg_spec): def providers_for(self, vpkg_spec):
if self._provider_index is None: providers = self.provider_index.providers_for(vpkg_spec)
self._provider_index = ProviderIndex(self.all_package_names())
providers = self._provider_index.providers_for(vpkg_spec)
if not providers: if not providers:
raise UnknownPackageError(vpkg_spec.name) raise UnknownPackageError(vpkg_spec.name)
return providers return providers
@ -603,12 +611,19 @@ def purge(self):
self._instances.clear() self._instances.clear()
@property
def provider_index(self):
"""A provider index with names *specific* to this repo."""
if self._provider_index is None:
namespaced_names = ['%s.%s' % (self.namespace, n)
for n in self.all_package_names()]
self._provider_index = ProviderIndex(namespaced_names)
return self._provider_index
@_autospec @_autospec
def providers_for(self, vpkg_spec): def providers_for(self, vpkg_spec):
if self._provider_index is None: providers = self.provider_index.providers_for(vpkg_spec)
self._provider_index = ProviderIndex(self.all_package_names())
providers = self._provider_index.providers_for(vpkg_spec)
if not providers: if not providers:
raise UnknownPackageError(vpkg_spec.name) raise UnknownPackageError(vpkg_spec.name)
return providers return providers

View file

@ -41,3 +41,9 @@ def test_write_and_read(self):
q = ProviderIndex.from_yaml(istream) q = ProviderIndex.from_yaml(istream)
self.assertTrue(p == q) self.assertTrue(p == q)
def test_copy(self):
p = ProviderIndex(spack.repo.all_package_names())
q = p.copy()
self.assertTrue(p == q)

View file

@ -209,5 +209,33 @@ def from_yaml(stream):
return index return index
def merge(self, other):
"""Merge `other` ProviderIndex into this one."""
other = other.copy() # defensive copy.
for pkg in other.providers:
if pkg not in self.providers:
self.providers[pkg] = other.providers[pkg]
continue
spdict, opdict = self.providers[pkg], other.providers[pkg]
for provided_spec in opdict:
if provided_spec not in spdict:
spdict[provided_spec] = opdict[provided_spec]
continue
spdict[provided_spec] += opdict[provided_spec]
def copy(self):
"""Deep copy of this ProviderIndex."""
clone = ProviderIndex()
clone.providers = dict(
(name, dict((vpkg, set((p.copy() for p in pset)))
for vpkg, pset in pdict.items()))
for name, pdict in self.providers.items())
return clone
def __eq__(self, other): def __eq__(self, other):
return self.providers == other.providers return self.providers == other.providers