summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd Gamblin <tgamblin@llnl.gov>2016-05-28 20:13:13 -0500
committerTodd Gamblin <tgamblin@llnl.gov>2016-08-08 21:04:23 -0700
commitcf2f902b82a3080243eae58ca728b55189108c10 (patch)
tree967dd6f02cc3b743379cd97ac2364d1bfa43d86e
parentbf028990e70927872cf506cf88bbf5a927ced2c4 (diff)
downloadspack-cf2f902b82a3080243eae58ca728b55189108c10.tar.gz
spack-cf2f902b82a3080243eae58ca728b55189108c10.tar.bz2
spack-cf2f902b82a3080243eae58ca728b55189108c10.tar.xz
spack-cf2f902b82a3080243eae58ca728b55189108c10.zip
Make ProviderIndexes mergeable, so we can cache them per-repo.
-rw-r--r--lib/spack/spack/repository.py31
-rw-r--r--lib/spack/spack/test/virtual.py6
-rw-r--r--lib/spack/spack/virtual.py28
3 files changed, 57 insertions, 8 deletions
diff --git a/lib/spack/spack/repository.py b/lib/spack/spack/repository.py
index bf0dac6a22..6e7e95b8bc 100644
--- a/lib/spack/spack/repository.py
+++ b/lib/spack/spack/repository.py
@@ -224,12 +224,20 @@ class RepoPath(object):
yield self.get(name)
- @_autospec
- def providers_for(self, vpkg_spec):
+ @property
+ def provider_index(self):
+ """Merged ProviderIndex from all Repos in the RepoPath."""
if self._provider_index is None:
- self._provider_index = ProviderIndex(self.all_package_names())
+ self._provider_index = ProviderIndex()
+ for repo in reversed(self.repos):
+ self._provider_index.merge(repo.provider_index)
+
+ return self._provider_index
- providers = self._provider_index.providers_for(vpkg_spec)
+
+ @_autospec
+ def providers_for(self, vpkg_spec):
+ providers = self.provider_index.providers_for(vpkg_spec)
if not providers:
raise UnknownPackageError(vpkg_spec.name)
return providers
@@ -603,12 +611,19 @@ class Repo(object):
self._instances.clear()
- @_autospec
- def providers_for(self, vpkg_spec):
+ @property
+ def provider_index(self):
+ """A provider index with names *specific* to this repo."""
if self._provider_index is None:
- self._provider_index = ProviderIndex(self.all_package_names())
+ namespaced_names = ['%s.%s' % (self.namespace, n)
+ for n in self.all_package_names()]
+ self._provider_index = ProviderIndex(namespaced_names)
+ return self._provider_index
+
- providers = self._provider_index.providers_for(vpkg_spec)
+ @_autospec
+ def providers_for(self, vpkg_spec):
+ providers = self.provider_index.providers_for(vpkg_spec)
if not providers:
raise UnknownPackageError(vpkg_spec.name)
return providers
diff --git a/lib/spack/spack/test/virtual.py b/lib/spack/spack/test/virtual.py
index 7699165554..1923e7006f 100644
--- a/lib/spack/spack/test/virtual.py
+++ b/lib/spack/spack/test/virtual.py
@@ -41,3 +41,9 @@ class VirtualTest(unittest.TestCase):
q = ProviderIndex.from_yaml(istream)
self.assertTrue(p == q)
+
+
+ def test_copy(self):
+ p = ProviderIndex(spack.repo.all_package_names())
+ q = p.copy()
+ self.assertTrue(p == q)
diff --git a/lib/spack/spack/virtual.py b/lib/spack/spack/virtual.py
index bf6d8227a4..2c47921a3f 100644
--- a/lib/spack/spack/virtual.py
+++ b/lib/spack/spack/virtual.py
@@ -209,5 +209,33 @@ class ProviderIndex(object):
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):
return self.providers == other.providers