diff --git a/lib/spack/spack/environment.py b/lib/spack/spack/environment.py index bc2126af4c..478aee7328 100644 --- a/lib/spack/spack/environment.py +++ b/lib/spack/spack/environment.py @@ -680,6 +680,8 @@ def add(self, user_spec, list_name='specs'): list_to_change.add(str(spec)) index = list(self.read_specs.keys()).index(list_name) + # read_specs is an OrderedDict, all list entries after the modified + # list may refer to the modified list. Update stale references for i, (name, speclist) in enumerate( list(self.read_specs.items())[index + 1:], index + 1): new_reference = dict((n, self.read_specs[n]) @@ -711,10 +713,24 @@ def remove(self, query_spec, list_name='specs', force=False): raise SpackEnvironmentError( "Not found: {0}".format(query_spec)) + old_specs = set(self.user_specs) for spec in matches: if spec in list_to_change: list_to_change.remove(spec) + # read_specs is an OrderedDict, all list entries after the modified + # list may refer to the modified list. Update stale references + index = list(self.read_specs.keys()).index(list_name) + for i, (name, speclist) in enumerate( + list(self.read_specs.items())[index + 1:], index + 1): + new_reference = dict((n, self.read_specs[n]) + for n in list(self.read_specs.keys())[:i]) + speclist.update_reference(new_reference) + + # If force, update stale concretized specs + # Only check specs removed by this operation + new_specs = set(self.user_specs) + for spec in old_specs - new_specs: if force and spec in self.concretized_user_specs: i = self.concretized_user_specs.index(spec) del self.concretized_user_specs[i] @@ -723,13 +739,6 @@ def remove(self, query_spec, list_name='specs', force=False): del self.concretized_order[i] del self.specs_by_hash[dag_hash] - index = list(self.read_specs.keys()).index(list_name) - for i, (name, speclist) in enumerate( - list(self.read_specs.items())[index + 1:], index + 1): - new_reference = dict((n, self.read_specs[n]) - for n in list(self.read_specs.keys())[:i]) - speclist.update_reference(new_reference) - def concretize(self, force=False): """Concretize user_specs in this environment. diff --git a/lib/spack/spack/test/cmd/env.py b/lib/spack/spack/test/cmd/env.py index d770739db7..fdf89f522c 100644 --- a/lib/spack/spack/test/cmd/env.py +++ b/lib/spack/spack/test/cmd/env.py @@ -846,12 +846,12 @@ def test_stack_yaml_remove_from_list_force(tmpdir): remove('-f', '-l', 'packages', 'mpileaks') find_output = find('-c') - print find_output - assert False - test = ev.read('test') + assert 'mpileaks' not in find_output - assert Spec('mpileaks') not in test.user_specs - assert Spec('callpath') in test.user_specs + test = ev.read('test') + assert len(test.user_specs) == 2 + assert Spec('callpath ^zmpi') in test.user_specs + assert Spec('callpath ^mpich') in test.user_specs def test_stack_yaml_attempt_remove_from_matrix(tmpdir):