diff --git a/lib/spack/spack/hash_types.py b/lib/spack/spack/hash_types.py index 01e31bb465..e4a238a93b 100644 --- a/lib/spack/spack/hash_types.py +++ b/lib/spack/spack/hash_types.py @@ -18,19 +18,22 @@ class SpecHashDescriptor(object): We currently use different hashes for different use cases. """ - def __init__(self, deptype=('link', 'run'), package_hash=False): + def __init__(self, deptype=('link', 'run'), package_hash=False, attr=None): self.deptype = dp.canonical_deptype(deptype) self.package_hash = package_hash + self.attr = attr #: Default Hash descriptor, used by Spec.dag_hash() and stored in the DB. -dag_hash = SpecHashDescriptor(deptype=('link', 'run'), package_hash=False) +dag_hash = SpecHashDescriptor(deptype=('link', 'run'), package_hash=False, + attr='_hash') #: Hash descriptor that includes build dependencies. build_hash = SpecHashDescriptor( - deptype=('build', 'link', 'run'), package_hash=False) + deptype=('build', 'link', 'run'), package_hash=False, attr='_build_hash') #: Full hash used in build pipelines to determine when to rebuild packages. -full_hash = SpecHashDescriptor(deptype=('link', 'run'), package_hash=True) +full_hash = SpecHashDescriptor(deptype=('link', 'run'), package_hash=True, + attr='_full_hash') diff --git a/lib/spack/spack/spec.py b/lib/spack/spack/spec.py index 009775acf4..6636f15c51 100644 --- a/lib/spack/spack/spec.py +++ b/lib/spack/spack/spec.py @@ -1305,7 +1305,7 @@ def _spec_hash(self, hash): return b32_hash - def _cached_hash(self, length, attr, hash): + def _cached_hash(self, hash, length=None): """Helper function for storing a cached hash on the spec. This will run _spec_hash() with the deptype and package_hash @@ -1315,13 +1315,16 @@ def _cached_hash(self, length, attr, hash): Arguments: hash (SpecHashDescriptor): type of hash to generate. """ - hash_string = getattr(self, attr, None) + if not hash.attr: + return self._spec_hash(hash)[:length] + + hash_string = getattr(self, hash.attr, None) if hash_string: return hash_string[:length] else: hash_string = self._spec_hash(hash) if self.concrete: - setattr(self, attr, hash_string) + setattr(self, hash.attr, hash_string) return hash_string[:length] @@ -1333,7 +1336,7 @@ def dag_hash(self, length=None): revise this to include more detailed provenance when the concretizer can more aggressievly reuse installed dependencies. """ - return self._cached_hash(length, '_hash', ht.dag_hash) + return self._cached_hash(ht.dag_hash, length) def build_hash(self, length=None): """Hash used to store specs in environments. @@ -1341,7 +1344,7 @@ def build_hash(self, length=None): This hash includes build dependencies, and we need to preserve them to be able to rebuild an entire environment for a user. """ - return self._cached_hash(length, '_build_hash', ht.build_hash) + return self._cached_hash(ht.build_hash, length) def full_hash(self, length=None): """Hash to determine when to rebuild packages in the build pipeline. @@ -1352,7 +1355,7 @@ def full_hash(self, length=None): TODO: investigate whether to include build deps here. """ - return self._cached_hash(length, '_full_hash', ht.full_hash) + return self._cached_hash(ht.full_hash, length) def dag_hash_bit_prefix(self, bits): """Get the first bits of the DAG hash as an integer type.""" @@ -1456,7 +1459,7 @@ def to_node_dict(self, hash=ht.dag_hash): d['dependencies'] = syaml_dict([ (name, syaml_dict([ - ('hash', dspec.spec._spec_hash(hash)), + ('hash', dspec.spec._cached_hash(hash)), ('type', sorted(str(s) for s in dspec.deptypes))]) ) for name, dspec in sorted(deps.items()) ])