From 233dabbd4fdcb1806e73fcedb1a12f6bdd624021 Mon Sep 17 00:00:00 2001 From: Todd Gamblin Date: Thu, 28 Oct 2021 10:46:51 -0700 Subject: bugfix: config edit should work with a malformed `spack.yaml` If you don't format `spack.yaml` correctly, `spack config edit` still fails and you have to edit your `spack.yaml` manually. - [x] Add some code to `_main()` to defer `ConfigFormatError` when loading the environment, until we know what command is being run. - [x] Make `spack config edit` use `SPACK_ENV` instead of the config scope object to find `spack.yaml`, so it can work even if the environment is bad. Co-authored-by: scheibelp --- lib/spack/spack/cmd/config.py | 17 ++++++++++++----- lib/spack/spack/main.py | 24 +++++++++++++++++++----- 2 files changed, 31 insertions(+), 10 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/cmd/config.py b/lib/spack/spack/cmd/config.py index 2dc25353ed..0dfb40c04e 100644 --- a/lib/spack/spack/cmd/config.py +++ b/lib/spack/spack/cmd/config.py @@ -170,12 +170,19 @@ def config_edit(args): With no arguments and an active environment, edit the spack.yaml for the active environment. """ - scope, section = _get_scope_and_section(args) - if not scope and not section: - tty.die('`spack config edit` requires a section argument ' - 'or an active environment.') + spack_env = os.environ.get(ev.spack_env_var) + if spack_env and not args.scope: + # Don't use the scope object for envs, as `config edit` can be called + # for a malformed environment. Use SPACK_ENV to find spack.yaml. + config_file = ev.manifest_file(spack_env) + else: + # If we aren't editing a spack.yaml file, get config path from scope. + scope, section = _get_scope_and_section(args) + if not scope and not section: + tty.die('`spack config edit` requires a section argument ' + 'or an active environment.') + config_file = spack.config.config.get_config_filename(scope, section) - config_file = spack.config.config.get_config_filename(scope, section) if args.print_file: print(config_file) else: diff --git a/lib/spack/spack/main.py b/lib/spack/spack/main.py index 651de68c49..c341271c02 100644 --- a/lib/spack/spack/main.py +++ b/lib/spack/spack/main.py @@ -740,7 +740,7 @@ def _main(argv=None): Args: argv (list or None): command line arguments, NOT including - the executable name. If None, parses from sys.argv. + the executable name. If None, parses from ``sys.argv``. """ # ------------------------------------------------------------------------ @@ -803,10 +803,17 @@ def _main(argv=None): spack.config.command_line_scopes = args.config_scopes # activate an environment if one was specified on the command line + env_format_error = None if not args.no_env: - env = spack.cmd.find_environment(args) - if env: - ev.activate(env, args.use_env_repo) + try: + env = spack.cmd.find_environment(args) + if env: + ev.activate(env, args.use_env_repo) + except spack.config.ConfigFormatError as e: + # print the context but delay this exception so that commands like + # `spack config edit` can still work with a bad environment. + e.print_context() + env_format_error = e # ------------------------------------------------------------------------ # Things that require configuration should go below here @@ -830,6 +837,13 @@ def _main(argv=None): # Re-parse with the proper sub-parser added. args, unknown = parser.parse_known_args() + # Now that we know what command this is and what its args are, determine + # whether we can continue with a bad environment and raise if not. + if env_format_error: + subcommand = getattr(args, "config_command", None) + if (cmd_name, subcommand) != ("config", "edit"): + raise env_format_error + # many operations will fail without a working directory. set_working_dir() @@ -854,7 +868,7 @@ def main(argv=None): The logic is all in ``_main()``. Args: - argv (list of str or None): command line arguments, NOT including + argv (list or None): command line arguments, NOT including the executable name. If None, parses from sys.argv. """ -- cgit v1.2.3-60-g2f50