diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/spack/spack/environment.py | 24 | ||||
-rw-r--r-- | lib/spack/spack/spec.py | 5 | ||||
-rw-r--r-- | lib/spack/spack/test/env.py | 38 |
3 files changed, 57 insertions, 10 deletions
diff --git a/lib/spack/spack/environment.py b/lib/spack/spack/environment.py index f4406d0aa2..fae23335fc 100644 --- a/lib/spack/spack/environment.py +++ b/lib/spack/spack/environment.py @@ -85,7 +85,7 @@ spack: valid_environment_name_re = r'^\w[\w-]*$' #: version of the lockfile format. Must increase monotonically. -lockfile_format_version = 2 +lockfile_format_version = 3 # Magic names # The name of the standalone spec list in the manifest yaml @@ -1695,12 +1695,12 @@ class Environment(object): concrete_specs = {} for spec in self.specs_by_hash.values(): for s in spec.traverse(): - dag_hash_all = s.build_hash() - if dag_hash_all not in concrete_specs: + build_hash = s.build_hash() + if build_hash not in concrete_specs: spec_dict = s.to_node_dict(hash=ht.build_hash) # Assumes no legacy formats, since this was just created. spec_dict[ht.dag_hash.name] = s.dag_hash() - concrete_specs[dag_hash_all] = spec_dict + concrete_specs[build_hash] = spec_dict hash_spec_list = zip( self.concretized_order, self.concretized_user_specs) @@ -1711,6 +1711,7 @@ class Environment(object): '_meta': { 'file-type': 'spack-lockfile', 'lockfile-version': lockfile_format_version, + 'specfile-version': spack.spec.specfile_format_version }, # users specs + hashes are the 'roots' of the environment @@ -1741,13 +1742,18 @@ class Environment(object): root_hashes = set(self.concretized_order) specs_by_hash = {} - for dag_hash, node_dict in json_specs_by_hash.items(): - specs_by_hash[dag_hash] = Spec.from_node_dict(node_dict) - - for dag_hash, node_dict in json_specs_by_hash.items(): + for build_hash, node_dict in json_specs_by_hash.items(): + spec = Spec.from_node_dict(node_dict) + if d['_meta']['lockfile-version'] > 1: + # Build hash is stored as a key, but not as part of the node dict + # To ensure build hashes are not recomputed, we reattach here + setattr(spec, ht.build_hash.attr, build_hash) + specs_by_hash[build_hash] = spec + + for build_hash, node_dict in json_specs_by_hash.items(): for _, dep_hash, deptypes, _ in ( Spec.dependencies_from_node_dict(node_dict)): - specs_by_hash[dag_hash]._add_dependency( + specs_by_hash[build_hash]._add_dependency( specs_by_hash[dep_hash], deptypes) # If we are reading an older lockfile format (which uses dag hashes diff --git a/lib/spack/spack/spec.py b/lib/spack/spack/spec.py index f5a7f1386a..567a8215fb 100644 --- a/lib/spack/spack/spec.py +++ b/lib/spack/spack/spec.py @@ -186,6 +186,9 @@ default_format = '{name}{@version}' default_format += '{%compiler.name}{@compiler.version}{compiler_flags}' default_format += '{variants}{arch=architecture}' +#: specfile format version. Must increase monotonically +specfile_format_version = 2 + def colorize_spec(spec): """Returns a spec colorized according to the colors specified in @@ -1798,7 +1801,7 @@ class Spec(object): if node_hash not in hash_set: node_list.append(node) hash_set.add(node_hash) - meta_dict = syaml.syaml_dict([('version', 2)]) + meta_dict = syaml.syaml_dict([('version', specfile_format_version)]) inner_dict = syaml.syaml_dict([('_meta', meta_dict), ('nodes', node_list)]) spec_dict = syaml.syaml_dict([('spec', inner_dict)]) return spec_dict diff --git a/lib/spack/spack/test/env.py b/lib/spack/spack/test/env.py new file mode 100644 index 0000000000..023c621445 --- /dev/null +++ b/lib/spack/spack/test/env.py @@ -0,0 +1,38 @@ +# Copyright 2013-2021 Lawrence Livermore National Security, LLC and other +# Spack Project Developers. See the top-level COPYRIGHT file for details. +# +# SPDX-License-Identifier: (Apache-2.0 OR MIT) + +"""Test environment internals without CLI""" + +import spack.environment as ev +import spack.spec + + +def test_hash_change_no_rehash_concrete(tmpdir, mock_packages, config): + # create an environment + env_path = tmpdir.mkdir('env_dir').strpath + env = ev.Environment(env_path) + env.write() + + # add a spec with a rewritten build hash + spec = spack.spec.Spec('mpileaks') + env.add(spec) + env.concretize() + + # rewrite the hash + old_hash = env.concretized_order[0] + new_hash = 'abc' + env.specs_by_hash[old_hash]._build_hash = new_hash + env.concretized_order[0] = new_hash + env.specs_by_hash[new_hash] = env.specs_by_hash[old_hash] + del env.specs_by_hash[old_hash] + env.write() + + # Read environment + read_in = ev.Environment(env_path) + + # Ensure read hashes are used (rewritten hash seen on read) + assert read_in.concretized_order + assert read_in.concretized_order[0] in read_in.specs_by_hash + assert read_in.specs_by_hash[read_in.concretized_order[0]]._build_hash == new_hash |