env: enforce predictable ordering when reading lockfile
Without some enforcement of spec ordering, python 2 produced different results in the affected test than did python 3. This change makes the arbitrary but reproducible decision to sort the specs by their lockfile key alphabetically.
This commit is contained in:
parent
84cfb3b7fe
commit
9de61c0197
2 changed files with 19 additions and 9 deletions
|
@ -1817,9 +1817,11 @@ def _read_lockfile_dict(self, d):
|
||||||
roots = d['roots']
|
roots = d['roots']
|
||||||
self.concretized_user_specs = [Spec(r['spec']) for r in roots]
|
self.concretized_user_specs = [Spec(r['spec']) for r in roots]
|
||||||
self.concretized_order = [r['hash'] for r in roots]
|
self.concretized_order = [r['hash'] for r in roots]
|
||||||
json_specs_by_hash = d['concrete_specs']
|
json_specs_by_hash = collections.OrderedDict()
|
||||||
|
for lockfile_key in sorted(d['concrete_specs']):
|
||||||
|
json_specs_by_hash[lockfile_key] = d['concrete_specs'][lockfile_key]
|
||||||
|
|
||||||
specs_by_hash = {}
|
specs_by_hash = collections.OrderedDict()
|
||||||
|
|
||||||
for lockfile_key, node_dict in json_specs_by_hash.items():
|
for lockfile_key, node_dict in json_specs_by_hash.items():
|
||||||
specs_by_hash[lockfile_key] = Spec.from_node_dict(node_dict)
|
specs_by_hash[lockfile_key] = Spec.from_node_dict(node_dict)
|
||||||
|
|
|
@ -2868,16 +2868,24 @@ def test_environment_query_spec_by_hash(mock_stage, mock_fetch, install_mockery)
|
||||||
def test_read_legacy_lockfile_and_reconcretize(mock_stage, mock_fetch, install_mockery):
|
def test_read_legacy_lockfile_and_reconcretize(mock_stage, mock_fetch, install_mockery):
|
||||||
"""Make sure that when we read a legacy environment lock file with a hash
|
"""Make sure that when we read a legacy environment lock file with a hash
|
||||||
conflict (one from before we switched to full hash), the behavior as to
|
conflict (one from before we switched to full hash), the behavior as to
|
||||||
which of the conflicting specs we pick is deterministic. When we read
|
which of the conflicting specs we pick is deterministic and reproducible.
|
||||||
the lockfile, we process root specs in the order they appear in 'roots',
|
When we read the lockfile, we (somewhat arbitrarily) process specs in
|
||||||
so we expect the dependencies of the last root in that list to be the
|
alphabetical order of their lockfile key. Consequently, when reading an
|
||||||
ones that appear in the environment before we forcefully re-concretize
|
old lockfile where two specs have a dag hash conflict we expect to keep the
|
||||||
the environment. After we force reconcretization, we should see all
|
second one we encounter. After we force reconcretization, we should both of
|
||||||
the dependencies again."""
|
the specs that originally conflicted present in the environment again."""
|
||||||
legacy_lockfile_path = os.path.join(
|
legacy_lockfile_path = os.path.join(
|
||||||
spack.paths.test_path, 'data', 'legacy_env', 'spack.lock'
|
spack.paths.test_path, 'data', 'legacy_env', 'spack.lock'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# In the legacy lockfile, we have two conflicting specs that differ only
|
||||||
|
# in a build-only dependency. The lockfile keys and conflicting specs
|
||||||
|
# are:
|
||||||
|
# wci7a3a -> dttop ^dtbuild1@0.5
|
||||||
|
# 5zg6wxw -> dttop ^dtbuild1@1.0
|
||||||
|
# So when we initially read the legacy lockfile, we expect to have kept
|
||||||
|
# the version of dttop that depends on dtbuild1@0.5
|
||||||
|
|
||||||
env('create', 'test', legacy_lockfile_path)
|
env('create', 'test', legacy_lockfile_path)
|
||||||
test = ev.read('test')
|
test = ev.read('test')
|
||||||
|
|
||||||
|
@ -2888,7 +2896,7 @@ def test_read_legacy_lockfile_and_reconcretize(mock_stage, mock_fetch, install_m
|
||||||
|
|
||||||
single_root = next(iter(test.specs_by_hash.values()))
|
single_root = next(iter(test.specs_by_hash.values()))
|
||||||
|
|
||||||
assert single_root['dtbuild1'].version == Version('1.0')
|
assert single_root['dtbuild1'].version == Version('0.5')
|
||||||
|
|
||||||
# Now forcefully reconcretize
|
# Now forcefully reconcretize
|
||||||
with ev.read('test'):
|
with ev.read('test'):
|
||||||
|
|
Loading…
Reference in a new issue