environment.py: drop early exit in install (#42145)
`spack install` early exit behavior was sometimes convenient, except that it had and has bugs: 1. prior bug: we didn't mark env roots of already installed specs as explicit in the db 2. current bug: `spack install --overwrite` is ignored So this PR simplifies by letting the installer do its thing even if everything is supposedly installed.
This commit is contained in:
parent
7580ba4861
commit
ed9d495915
2 changed files with 12 additions and 57 deletions
|
@ -1803,8 +1803,8 @@ def _add_concrete_spec(self, spec, concrete, new=True):
|
|||
self.concretized_order.append(h)
|
||||
self.specs_by_hash[h] = concrete
|
||||
|
||||
def _get_overwrite_specs(self):
|
||||
# Find all dev specs that were modified.
|
||||
def _dev_specs_that_need_overwrite(self):
|
||||
"""Return the hashes of all specs that need to be reinstalled due to source code change."""
|
||||
changed_dev_specs = [
|
||||
s
|
||||
for s in traverse.traverse_nodes(
|
||||
|
@ -1862,52 +1862,21 @@ def install_all(self, **install_args):
|
|||
"""
|
||||
self.install_specs(None, **install_args)
|
||||
|
||||
def install_specs(self, specs=None, **install_args):
|
||||
tty.debug("Assessing installation status of environment packages")
|
||||
# If "spack install" is invoked repeatedly for a large environment
|
||||
# where all specs are already installed, the operation can take
|
||||
# a large amount of time due to repeatedly acquiring and releasing
|
||||
# locks. As a small optimization, drop already installed root specs.
|
||||
installed_roots, uninstalled_roots = self._partition_roots_by_install_status()
|
||||
if specs:
|
||||
specs_to_install = [s for s in specs if s not in installed_roots]
|
||||
specs_dropped = [s for s in specs if s in installed_roots]
|
||||
else:
|
||||
specs_to_install = uninstalled_roots
|
||||
specs_dropped = installed_roots
|
||||
def install_specs(self, specs: Optional[List[Spec]] = None, **install_args):
|
||||
roots = self.concrete_roots()
|
||||
specs = specs if specs is not None else roots
|
||||
|
||||
# We need to repeat the work of the installer thanks to the above optimization:
|
||||
# Already installed root specs should be marked explicitly installed in the
|
||||
# database.
|
||||
if specs_dropped:
|
||||
with spack.store.STORE.db.write_transaction(): # do all in one transaction
|
||||
for spec in specs_dropped:
|
||||
spack.store.STORE.db.update_explicit(spec, True)
|
||||
# Extend the set of specs to overwrite with modified dev specs and their parents
|
||||
install_args["overwrite"] = (
|
||||
install_args.get("overwrite", []) + self._dev_specs_that_need_overwrite()
|
||||
)
|
||||
|
||||
if not specs_to_install:
|
||||
tty.msg("All of the packages are already installed")
|
||||
else:
|
||||
tty.debug("Processing {0} uninstalled specs".format(len(specs_to_install)))
|
||||
|
||||
specs_to_overwrite = self._get_overwrite_specs()
|
||||
tty.debug("{0} specs need to be overwritten".format(len(specs_to_overwrite)))
|
||||
|
||||
install_args["overwrite"] = install_args.get("overwrite", []) + specs_to_overwrite
|
||||
|
||||
installs = []
|
||||
for spec in specs_to_install:
|
||||
pkg_install_args = install_args.copy()
|
||||
pkg_install_args["explicit"] = spec in self.roots()
|
||||
installs.append((spec.package, pkg_install_args))
|
||||
installs = [(spec.package, {**install_args, "explicit": spec in roots}) for spec in specs]
|
||||
|
||||
try:
|
||||
builder = PackageInstaller(installs)
|
||||
builder.install()
|
||||
PackageInstaller(installs).install()
|
||||
finally:
|
||||
# Ensure links are set appropriately
|
||||
for spec in specs_to_install:
|
||||
if spec.installed:
|
||||
self.new_installs.append(spec)
|
||||
self.new_installs.extend(s for s in specs if s.installed)
|
||||
|
||||
def all_specs_generator(self) -> Iterable[Spec]:
|
||||
"""Returns a generator for all concrete specs"""
|
||||
|
|
|
@ -303,20 +303,6 @@ def test_activate_adds_transitive_run_deps_to_path(install_mockery, mock_fetch,
|
|||
assert env_variables["DEPENDENCY_ENV_VAR"] == "1"
|
||||
|
||||
|
||||
def test_env_install_same_spec_twice(install_mockery, mock_fetch):
|
||||
env("create", "test")
|
||||
|
||||
e = ev.read("test")
|
||||
with e:
|
||||
# The first installation outputs the package prefix, updates the view
|
||||
out = install("--add", "cmake-client")
|
||||
assert "Updating view at" in out
|
||||
|
||||
# The second installation reports all packages already installed
|
||||
out = install("cmake-client")
|
||||
assert "already installed" in out
|
||||
|
||||
|
||||
def test_env_definition_symlink(install_mockery, mock_fetch, tmpdir):
|
||||
filepath = str(tmpdir.join("spack.yaml"))
|
||||
filepath_mid = str(tmpdir.join("spack_mid.yaml"))
|
||||
|
|
Loading…
Reference in a new issue