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:
Greg Becker 2019-01-24 12:10:32 -08:00 committed by GitHub
parent 7d64994cbd
commit 98e0b5b0db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 77 additions and 24 deletions

View File

@ -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):

View File

@ -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',
)