diff options
author | Massimiliano Culpo <massimiliano.culpo@gmail.com> | 2021-08-26 21:20:05 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-26 12:20:05 -0700 |
commit | 29d1bc6546def4bcd09c0a5b533de9f39a78d910 (patch) | |
tree | 576e6359be1c861e5cffbba9b6d3faf439a7de73 | |
parent | c963bdee8b8507c3eb50072ccfee275e52c778b6 (diff) | |
download | spack-29d1bc6546def4bcd09c0a5b533de9f39a78d910.tar.gz spack-29d1bc6546def4bcd09c0a5b533de9f39a78d910.tar.bz2 spack-29d1bc6546def4bcd09c0a5b533de9f39a78d910.tar.xz spack-29d1bc6546def4bcd09c0a5b533de9f39a78d910.zip |
Ensure environment are deactivated when bootstrapping (#25607)
Fixes #25603
This commit adds a new context manager to temporarily
deactivate active environments. This context manager
is used when setting up bootstrapping configuration to
make sure that the current environment is not affected
by operations on the bootstrap store.
* Preserve exit code 1 if nothing is found
* Use context manager for the environment
-rw-r--r-- | lib/spack/spack/bootstrap.py | 20 | ||||
-rw-r--r-- | lib/spack/spack/cmd/clean.py | 2 | ||||
-rw-r--r-- | lib/spack/spack/cmd/find.py | 26 | ||||
-rw-r--r-- | lib/spack/spack/environment.py | 12 | ||||
-rw-r--r-- | lib/spack/spack/test/bootstrap.py | 15 |
5 files changed, 52 insertions, 23 deletions
diff --git a/lib/spack/spack/bootstrap.py b/lib/spack/spack/bootstrap.py index 09d9c6e3a8..be48d66a21 100644 --- a/lib/spack/spack/bootstrap.py +++ b/lib/spack/spack/bootstrap.py @@ -23,6 +23,7 @@ import llnl.util.tty as tty import spack.architecture import spack.binary_distribution import spack.config +import spack.environment import spack.main import spack.paths import spack.repo @@ -421,15 +422,16 @@ def _bootstrap_config_scopes(): @contextlib.contextmanager def ensure_bootstrap_configuration(): bootstrap_store_path = store_path() - with spack.architecture.use_platform(spack.architecture.real_platform()): - with spack.repo.use_repositories(spack.paths.packages_path): - with spack.store.use_store(bootstrap_store_path): - # Default configuration scopes excluding command line - # and builtin but accounting for platform specific scopes - config_scopes = _bootstrap_config_scopes() - with spack.config.use_configuration(*config_scopes): - with spack_python_interpreter(): - yield + with spack.environment.deactivate_environment(): + with spack.architecture.use_platform(spack.architecture.real_platform()): + with spack.repo.use_repositories(spack.paths.packages_path): + with spack.store.use_store(bootstrap_store_path): + # Default configuration scopes excluding command line + # and builtin but accounting for platform specific scopes + config_scopes = _bootstrap_config_scopes() + with spack.config.use_configuration(*config_scopes): + with spack_python_interpreter(): + yield def store_path(): diff --git a/lib/spack/spack/cmd/clean.py b/lib/spack/spack/cmd/clean.py index 3b66358293..ebcf7cc862 100644 --- a/lib/spack/spack/cmd/clean.py +++ b/lib/spack/spack/cmd/clean.py @@ -104,6 +104,6 @@ def clean(parser, args): if args.bootstrap: msg = 'Removing software in "{0}"' tty.msg(msg.format(spack.bootstrap.store_path())) - with spack.store.use_store(spack.bootstrap.store_path()): + with spack.bootstrap.ensure_bootstrap_configuration(): uninstall = spack.main.SpackCommand('uninstall') uninstall('-a', '-y') diff --git a/lib/spack/spack/cmd/find.py b/lib/spack/spack/cmd/find.py index 13066578e3..8378f6ef6e 100644 --- a/lib/spack/spack/cmd/find.py +++ b/lib/spack/spack/cmd/find.py @@ -205,24 +205,24 @@ def display_env(env, args, decorator): def find(parser, args): - q_args = query_arguments(args) - # Query the current store or the internal bootstrap store if required if args.bootstrap: bootstrap_store_path = spack.bootstrap.store_path() - msg = 'Showing internal bootstrap store at "{0}"' - tty.msg(msg.format(bootstrap_store_path)) - with spack.store.use_store(bootstrap_store_path): - results = args.specs(**q_args) - else: - results = args.specs(**q_args) + with spack.bootstrap.ensure_bootstrap_configuration(): + msg = 'Showing internal bootstrap store at "{0}"' + tty.msg(msg.format(bootstrap_store_path)) + _find(parser, args) + return + _find(parser, args) - decorator = lambda s, f: f - added = set() - removed = set() + +def _find(parser, args): + q_args = query_arguments(args) + results = args.specs(**q_args) env = ev.active_environment() + decorator = lambda s, f: f if env: - decorator, added, roots, removed = setup_env(env) + decorator, _, roots, _ = setup_env(env) # use groups by default except with format. if args.groups is None: @@ -233,7 +233,7 @@ def find(parser, args): msg = "No package matches the query: {0}" msg = msg.format(' '.join(args.constraint)) tty.msg(msg) - return 1 + raise SystemExit(1) # If tags have been specified on the command line, filter by tags if args.tags: diff --git a/lib/spack/spack/environment.py b/lib/spack/spack/environment.py index 23644dabd9..aa27e5361c 100644 --- a/lib/spack/spack/environment.py +++ b/lib/spack/spack/environment.py @@ -3,6 +3,7 @@ # # SPDX-License-Identifier: (Apache-2.0 OR MIT) import collections +import contextlib import copy import os import re @@ -2144,6 +2145,17 @@ def is_latest_format(manifest): return not changed +@contextlib.contextmanager +def deactivate_environment(): + """Deactivate an active environment for the duration of the context.""" + global _active_environment + current, _active_environment = _active_environment, None + try: + yield + finally: + _active_environment = current + + class SpackEnvironmentError(spack.error.SpackError): """Superclass for all errors to do with Spack environments.""" diff --git a/lib/spack/spack/test/bootstrap.py b/lib/spack/spack/test/bootstrap.py index fccf67e569..fa5621e373 100644 --- a/lib/spack/spack/test/bootstrap.py +++ b/lib/spack/spack/test/bootstrap.py @@ -5,10 +5,17 @@ import pytest import spack.bootstrap +import spack.environment import spack.store import spack.util.path +@pytest.fixture +def active_mock_environment(mutable_config, mutable_mock_env_path): + with spack.environment.create('bootstrap-test') as env: + yield env + + @pytest.mark.regression('22294') def test_store_is_restored_correctly_after_bootstrap(mutable_config, tmpdir): # Prepare a custom store path. This should be in a writeable location @@ -49,3 +56,11 @@ def test_raising_exception_if_bootstrap_disabled(mutable_config): # Check the correct exception is raised with pytest.raises(RuntimeError, match='bootstrapping is currently disabled'): spack.bootstrap.store_path() + + +@pytest.mark.regression('25603') +def test_bootstrap_deactivates_environments(active_mock_environment): + assert spack.environment.active_environment() == active_mock_environment + with spack.bootstrap.ensure_bootstrap_configuration(): + assert spack.environment.active_environment() is None + assert spack.environment.active_environment() == active_mock_environment |