summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/spack/cmd/install.py40
-rw-r--r--lib/spack/spack/test/cmd/install.py63
2 files changed, 78 insertions, 25 deletions
diff --git a/lib/spack/spack/cmd/install.py b/lib/spack/spack/cmd/install.py
index fc79c5d689..5524324094 100644
--- a/lib/spack/spack/cmd/install.py
+++ b/lib/spack/spack/cmd/install.py
@@ -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
- if not args.yes_to_all:
- tty.msg('The following package will be reinstalled:\n')
+ installed = list(filter(lambda x: x,
+ map(spack.store.db.query_one, specs)))
+ if not args.yes_to_all:
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):
diff --git a/lib/spack/spack/test/cmd/install.py b/lib/spack/spack/test/cmd/install.py
index 12feba9555..f3e6a4d3ed 100644
--- a/lib/spack/spack/test/cmd/install.py
+++ b/lib/spack/spack/test/cmd/install.py
@@ -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',
)