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
This commit is contained in:
parent
c963bdee8b
commit
29d1bc6546
@ -23,6 +23,7 @@
|
||||
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():
|
||||
|
@ -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')
|
||||
|
@ -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:
|
||||
|
@ -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."""
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user