Allow spack remove -f and spack uninstall to work on matrices (#17222)

* Allow `spack remove -f` and `spack uninstall` to work on matrices

Allow Environment.remove(force=True) to remove the concrete spec from the environment
even when the user spec cannot be removed because it is in a matrix.
This commit is contained in:
Greg Becker 2020-06-26 09:57:22 -05:00 committed by GitHub
parent c401c63156
commit ec108dbebd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 55 additions and 10 deletions

View File

@ -892,13 +892,23 @@ def remove(self, query_spec, list_name=user_speclist_name, force=False):
old_specs = set(self.user_specs)
for spec in matches:
if spec in list_to_change:
list_to_change.remove(spec)
self.update_stale_references(list_name)
try:
list_to_change.remove(spec)
self.update_stale_references(list_name)
new_specs = set(self.user_specs)
except spack.spec_list.SpecListError:
# define new specs list
new_specs = set(self.user_specs)
msg = "Spec '%s' is part of a spec matrix and " % spec
msg += "cannot be removed from list '%s'." % list_to_change
if force:
msg += " It will be removed from the concrete specs."
# Mock new specs so we can remove this spec from
# concrete spec lists
new_specs.remove(spec)
tty.warn(msg)
# 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)

View File

@ -19,7 +19,6 @@
from spack.main import SpackCommand
from spack.stage import stage_prefix
from spack.spec_list import SpecListError
from spack.util.mock_package import MockPackageMultiRepo
import spack.util.spack_json as sjson
from spack.util.path import substitute_path_variables
@ -1234,7 +1233,7 @@ def test_stack_yaml_remove_from_list_force(tmpdir):
assert Spec('callpath ^mpich') in test.user_specs
def test_stack_yaml_attempt_remove_from_matrix(tmpdir):
def test_stack_yaml_remove_from_matrix_no_effect(tmpdir):
filename = str(tmpdir.join('spack.yaml'))
with open(filename, 'w') as f:
f.write("""\
@ -1249,9 +1248,45 @@ def test_stack_yaml_attempt_remove_from_matrix(tmpdir):
""")
with tmpdir.as_cwd():
env('create', 'test', './spack.yaml')
with pytest.raises(SpecListError):
with ev.read('test'):
remove('-l', 'packages', 'mpileaks')
with ev.read('test') as e:
before = e.user_specs.specs
remove('-l', 'packages', 'mpileaks')
after = e.user_specs.specs
assert before == after
def test_stack_yaml_force_remove_from_matrix(tmpdir):
filename = str(tmpdir.join('spack.yaml'))
with open(filename, 'w') as f:
f.write("""\
env:
definitions:
- packages:
- matrix:
- [mpileaks, callpath]
- [target=be]
specs:
- $packages
""")
with tmpdir.as_cwd():
env('create', 'test', './spack.yaml')
with ev.read('test') as e:
concretize()
before_user = e.user_specs.specs
before_conc = e.concretized_user_specs
remove('-f', '-l', 'packages', 'mpileaks')
after_user = e.user_specs.specs
after_conc = e.concretized_user_specs
assert before_user == after_user
mpileaks_spec = Spec('mpileaks target=be')
assert mpileaks_spec in before_conc
assert mpileaks_spec not in after_conc
def test_stack_concretize_extraneous_deps(tmpdir, config, mock_packages):