Allow spack install --overwrite
for nonexistent or multiple packages (#9201)
* Allow overwrite nonexistent and multiple packages initial implementation give one prompt to users instead of a prompt per spec testing * flake * bugfix: install overwrite check each spec against installed * python3 compliance for filter/map
This commit is contained in:
parent
7d64994cbd
commit
98e0b5b0db
@ -283,36 +283,42 @@ def install(parser, args, **kwargs):
|
||||
reporter.specs = specs
|
||||
with reporter:
|
||||
if args.overwrite:
|
||||
# If we asked to overwrite an existing spec we must ensure that:
|
||||
# 1. We have only one spec
|
||||
# 2. The spec is already installed
|
||||
assert len(specs) == 1, \
|
||||
"only one spec is allowed when overwriting an installation"
|
||||
|
||||
spec = specs[0]
|
||||
t = spack.store.db.query(spec)
|
||||
assert len(t) == 1, "to overwrite a spec you must install it first"
|
||||
|
||||
# Give the user a last chance to think about overwriting an already
|
||||
# existing installation
|
||||
installed = list(filter(lambda x: x,
|
||||
map(spack.store.db.query_one, specs)))
|
||||
if not args.yes_to_all:
|
||||
tty.msg('The following package will be reinstalled:\n')
|
||||
|
||||
display_args = {
|
||||
'long': True,
|
||||
'show_flags': True,
|
||||
'variants': True
|
||||
}
|
||||
|
||||
spack.cmd.display_specs(t, **display_args)
|
||||
if installed:
|
||||
tty.msg('The following package specs will be '
|
||||
'reinstalled:\n')
|
||||
spack.cmd.display_specs(installed, **display_args)
|
||||
|
||||
not_installed = list(filter(lambda x: x not in installed,
|
||||
specs))
|
||||
if not_installed:
|
||||
tty.msg('The following package specs are not installed and'
|
||||
' the --overwrite flag was given. The package spec'
|
||||
' will be newly installed:\n')
|
||||
spack.cmd.display_specs(not_installed, **display_args)
|
||||
|
||||
# We have some specs, so one of the above must have been true
|
||||
answer = tty.get_yes_or_no(
|
||||
'Do you want to proceed?', default=False
|
||||
)
|
||||
if not answer:
|
||||
tty.die('Reinstallation aborted.')
|
||||
|
||||
with fs.replace_directory_transaction(specs[0].prefix):
|
||||
install_spec(args, kwargs, abstract_specs[0], specs[0])
|
||||
for abstract, concrete in zip(abstract_specs, specs):
|
||||
if concrete in installed:
|
||||
with fs.replace_directory_transaction(concrete.prefix):
|
||||
install_spec(args, kwargs, abstract, concrete)
|
||||
else:
|
||||
install_spec(args, kwargs, abstract, concrete)
|
||||
|
||||
else:
|
||||
for abstract, concrete in zip(abstract_specs, specs):
|
||||
|
@ -185,14 +185,6 @@ def test_show_log_on_error(mock_packages, mock_archive, mock_fetch,
|
||||
def test_install_overwrite(
|
||||
mock_packages, mock_archive, mock_fetch, config, install_mockery
|
||||
):
|
||||
# It's not possible to overwrite something that is not yet installed
|
||||
with pytest.raises(AssertionError):
|
||||
install('--overwrite', 'libdwarf')
|
||||
|
||||
# --overwrite requires a single spec
|
||||
with pytest.raises(AssertionError):
|
||||
install('--overwrite', 'libdwarf', 'libelf')
|
||||
|
||||
# Try to install a spec and then to reinstall it.
|
||||
spec = Spec('libdwarf')
|
||||
spec.concretize()
|
||||
@ -217,6 +209,61 @@ def test_install_overwrite(
|
||||
assert fs.hash_directory(spec.prefix) != bad_md5
|
||||
|
||||
|
||||
def test_install_overwrite_not_installed(
|
||||
mock_packages, mock_archive, mock_fetch, config, install_mockery
|
||||
):
|
||||
# Try to install a spec and then to reinstall it.
|
||||
spec = Spec('libdwarf')
|
||||
spec.concretize()
|
||||
|
||||
assert not os.path.exists(spec.prefix)
|
||||
|
||||
install('--overwrite', '-y', 'libdwarf')
|
||||
assert os.path.exists(spec.prefix)
|
||||
|
||||
|
||||
def test_install_overwrite_multiple(
|
||||
mock_packages, mock_archive, mock_fetch, config, install_mockery
|
||||
):
|
||||
# Try to install a spec and then to reinstall it.
|
||||
libdwarf = Spec('libdwarf')
|
||||
libdwarf.concretize()
|
||||
|
||||
install('libdwarf')
|
||||
|
||||
cmake = Spec('cmake')
|
||||
cmake.concretize()
|
||||
|
||||
install('cmake')
|
||||
|
||||
assert os.path.exists(libdwarf.prefix)
|
||||
expected_libdwarf_md5 = fs.hash_directory(libdwarf.prefix)
|
||||
|
||||
assert os.path.exists(cmake.prefix)
|
||||
expected_cmake_md5 = fs.hash_directory(cmake.prefix)
|
||||
|
||||
# Modify the first installation to be sure the content is not the same
|
||||
# as the one after we reinstalled
|
||||
with open(os.path.join(libdwarf.prefix, 'only_in_old'), 'w') as f:
|
||||
f.write('This content is here to differentiate installations.')
|
||||
with open(os.path.join(cmake.prefix, 'only_in_old'), 'w') as f:
|
||||
f.write('This content is here to differentiate installations.')
|
||||
|
||||
bad_libdwarf_md5 = fs.hash_directory(libdwarf.prefix)
|
||||
bad_cmake_md5 = fs.hash_directory(cmake.prefix)
|
||||
|
||||
assert bad_libdwarf_md5 != expected_libdwarf_md5
|
||||
assert bad_cmake_md5 != expected_cmake_md5
|
||||
|
||||
install('--overwrite', '-y', 'libdwarf', 'cmake')
|
||||
assert os.path.exists(libdwarf.prefix)
|
||||
assert os.path.exists(cmake.prefix)
|
||||
assert fs.hash_directory(libdwarf.prefix) == expected_libdwarf_md5
|
||||
assert fs.hash_directory(cmake.prefix) == expected_cmake_md5
|
||||
assert fs.hash_directory(libdwarf.prefix) != bad_libdwarf_md5
|
||||
assert fs.hash_directory(cmake.prefix) != bad_cmake_md5
|
||||
|
||||
|
||||
@pytest.mark.usefixtures(
|
||||
'mock_packages', 'mock_archive', 'mock_fetch', 'config', 'install_mockery',
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user