Repository: spack/spack

Issue:
--config-scope incompatible with environments
If an environment is loaded, `--config-scope` is silently ignored.

If config scopes are intended to be incompatible with environments, an error should be raised when attempting to pass `--config-scope` to spack if an environment is activated.

### Details

In `lib/spack/spack/main.py`, `spack.config.command_line_scopes` is set equal to any config scopes passed by the `--config-scope` option.  However, this is done **after** activated environments are looked for.  In the process of looking for an activated environment, the `spack.config.config` singleton is instantiated, so later setting of `spack.config.command_line_scopes` has no effect and are, thus, ignored.

### Motivation

I have several environments that all depend on the same dozen or so external packages.  I don't want to duplicate the `packages` specification in every environment.  The external packages are shared by a group of developers, so it is more convenient for each to set the config scope to the shared directory containing `packages.yaml` than each duplicated the file in their `~/.spack`.

This is another use case where having `~/.spack` relocatable (#11919) would be convenient.  Sure, `--config-scope` could work (though it is broken as of now), but setting an environment variable to point to the user's config directory would be more convenient.

### Quick fix

Move the setting of command line scopes **before** looking for activated environments:

```
diff --git a/lib/spack/spack/main.py b/lib/spack/spack/main.py
index 05c1706..b4ca7df 100644
--- a/lib/spack/spack/main.py
+++ b/lib/spack/spack/main.py
@@ -628,16 +628,16 @@ def main(argv=None):
     parser.add_argument('command', nargs=argparse.REMAINDER)
     args, unknown = parser.parse_known_args(argv)

+    # make spack.config aware of any command line configuration scopes
+    if args.config_scopes:
+        spack.config.command_line_scopes = args.config_scopes
+
     # activate an environment if one was specified on the command line
     if not args.no_env:
         env = ev.find_environment(args)
         if env:
             ev.activate(env, args.use_env_repo)

-    # make spack.config aware of any command line configuration scopes
-    if args.config_scopes:
-        spack.config.command_line_scopes = args.config_scopes
-
     if args.print_shell_vars:
         print_setup_info(*args.print_shell_vars.split(','))
         return 0
```

--config-scope incompatible with environments
If an environment is loaded, `--config-scope` is silently ignored.

If config scopes are intended to be incompatible with environments, an error should be raised when attempting to pass `--config-scope` to spack if an environment is activated.

### Details

In `lib/spack/spack/main.py`, `spack.config.command_line_scopes` is set equal to any config scopes passed by the `--config-scope` option.  However, this is done **after** activated environments are looked for.  In the process of looking for an activated environment, the `spack.config.config` singleton is instantiated, so later setting of `spack.config.command_line_scopes` has no effect and are, thus, ignored.

### Motivation

I have several environments that all depend on the same dozen or so external packages.  I don't want to duplicate the `packages` specification in every environment.  The external packages are shared by a group of developers, so it is more convenient for each to set the config scope to the shared directory containing `packages.yaml` than each duplicated the file in their `~/.spack`.

This is another use case where having `~/.spack` relocatable (#11919) would be convenient.  Sure, `--config-scope` could work (though it is broken as of now), but setting an environment variable to point to the user's config directory would be more convenient.

### Quick fix

Move the setting of command line scopes **before** looking for activated environments:

```
diff --git a/lib/spack/spack/main.py b/lib/spack/spack/main.py
index 05c1706..b4ca7df 100644
--- a/lib/spack/spack/main.py
+++ b/lib/spack/spack/main.py
@@ -628,16 +628,16 @@ def main(argv=None):
     parser.add_argument('command', nargs=argparse.REMAINDER)
     args, unknown = parser.parse_known_args(argv)

+    # make spack.config aware of any command line configuration scopes
+    if args.config_scopes:
+        spack.config.command_line_scopes = args.config_scopes
+
     # activate an environment if one was specified on the command line
     if not args.no_env:
         env = ev.find_environment(args)
         if env:
             ev.activate(env, args.use_env_repo)

-    # make spack.config aware of any command line configuration scopes
-    if args.config_scopes:
-        spack.config.command_line_scopes = args.config_scopes
-
     if args.print_shell_vars:
         print_setup_info(*args.print_shell_vars.split(','))
         return 0
```



Discussion:
Hi,

I can confirm
* the problem described
* the patch above fixes it.

We're affected by this issue. I am a Python developer and want to help getting a fix into spack.

What can I do to help?
Hi,

I can confirm
* the problem described
* the patch above fixes it.

We're affected by this issue. I am a Python developer and want to help getting a fix into spack.

What can I do to help?

Resolving patch:
diff --git a/lib/spack/spack/main.py b/lib/spack/spack/main.py
--- a/lib/spack/spack/main.py
+++ b/lib/spack/spack/main.py
@@ -700,16 +700,16 @@ def main(argv=None):
         if stored_var_name in os.environ:
             os.environ[var] = os.environ[stored_var_name]
 
+    # make spack.config aware of any command line configuration scopes
+    if args.config_scopes:
+        spack.config.command_line_scopes = args.config_scopes
+
     # activate an environment if one was specified on the command line
     if not args.no_env:
         env = ev.find_environment(args)
         if env:
             ev.activate(env, args.use_env_repo)
 
-    # make spack.config aware of any command line configuration scopes
-    if args.config_scopes:
-        spack.config.command_line_scopes = args.config_scopes
-
     if args.print_shell_vars:
         print_setup_info(*args.print_shell_vars.split(','))
         return 0


Test patch: