diff options
Diffstat (limited to 'lib/spack/spack/environment/environment.py')
-rw-r--r-- | lib/spack/spack/environment/environment.py | 46 |
1 files changed, 35 insertions, 11 deletions
diff --git a/lib/spack/spack/environment/environment.py b/lib/spack/spack/environment/environment.py index 813ffca0b6..cabb255e23 100644 --- a/lib/spack/spack/environment/environment.py +++ b/lib/spack/spack/environment/environment.py @@ -62,8 +62,8 @@ spack_env_var = "SPACK_ENV" _active_environment = None -#: path where environments are stored in the spack tree -env_path = os.path.join(spack.paths.var_path, "environments") +#: default path where environments are stored in the spack tree +default_env_path = os.path.join(spack.paths.var_path, "environments") #: Name of the input yaml file for an environment @@ -78,6 +78,26 @@ lockfile_name = "spack.lock" env_subdir_name = ".spack-env" +def env_root_path(): + """Override default root path if the user specified it""" + return spack.util.path.canonicalize_path( + spack.config.get("config:environments_root", default=default_env_path) + ) + + +def check_disallowed_env_config_mods(scopes): + for scope in scopes: + with spack.config.use_configuration(scope): + if spack.config.get("config:environments_root"): + raise SpackEnvironmentError( + "Spack environments are prohibited from modifying 'config:environments_root' " + "because it can make the definition of the environment ill-posed. Please " + "remove from your environment and place it in a permanent scope such as " + "defaults, system, site, etc." + ) + return scopes + + def default_manifest_yaml(): """default spack.yaml file to put in new environments""" return """\ @@ -214,7 +234,7 @@ def active_environment(): def _root(name): """Non-validating version of root(), to be used internally.""" - return os.path.join(env_path, name) + return os.path.join(env_root_path(), name) def root(name): @@ -249,10 +269,12 @@ def read(name): def create(name, init_file=None, with_view=None, keep_relative=False): - """Create a named environment in Spack.""" + """Create a managed environment in Spack.""" + if not os.path.isdir(env_root_path()): + fs.mkdirp(env_root_path()) validate_env_name(name) if exists(name): - raise SpackEnvironmentError("'%s': environment already exists" % name) + raise SpackEnvironmentError("'%s': environment already exists at %s" % (name, root(name))) return Environment(root(name), init_file, with_view, keep_relative) @@ -266,10 +288,10 @@ def all_environment_names(): """List the names of environments that currently exist.""" # just return empty if the env path does not exist. A read-only # operation like list should not try to create a directory. - if not os.path.exists(env_path): + if not os.path.exists(env_root_path()): return [] - candidates = sorted(os.listdir(env_path)) + candidates = sorted(os.listdir(env_root_path())) names = [] for candidate in candidates: yaml_path = os.path.join(_root(candidate), manifest_name) @@ -279,7 +301,7 @@ def all_environment_names(): def all_environments(): - """Generator for all named Environments.""" + """Generator for all managed Environments.""" for name in all_environment_names(): yield read(name) @@ -859,14 +881,14 @@ class Environment(object): @property def internal(self): """Whether this environment is managed by Spack.""" - return self.path.startswith(env_path) + return self.path.startswith(env_root_path()) @property def name(self): """Human-readable representation of the environment. This is the path for directory environments, and just the name - for named environments. + for managed environments. """ if self.internal: return os.path.basename(self.path) @@ -1044,7 +1066,9 @@ class Environment(object): def config_scopes(self): """A list of all configuration scopes for this environment.""" - return self.included_config_scopes() + [self.env_file_config_scope()] + return check_disallowed_env_config_mods( + self.included_config_scopes() + [self.env_file_config_scope()] + ) def destroy(self): """Remove this environment from Spack entirely.""" |