env: make spack config edit
and spack config get
environment-aware
- with no arguments, these commands will now edit or dump the environment's `spack.yaml` file. - users may not know where named environments live - this makes it convenient for users to get to the spack.yaml configuration file for their named environment.
This commit is contained in:
parent
25f8abb963
commit
8d92fd6640
@ -3,7 +3,13 @@
|
||||
#
|
||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||
|
||||
from __future__ import print_function
|
||||
import os
|
||||
|
||||
import llnl.util.tty as tty
|
||||
|
||||
import spack.config
|
||||
import spack.environment as ev
|
||||
|
||||
from spack.util.editor import editor
|
||||
|
||||
@ -27,6 +33,7 @@ def setup_parser(subparser):
|
||||
get_parser.add_argument('section',
|
||||
help="configuration section to print. "
|
||||
"options: %(choices)s",
|
||||
nargs='?',
|
||||
metavar='SECTION',
|
||||
choices=spack.config.section_schemas)
|
||||
|
||||
@ -43,29 +50,81 @@ def setup_parser(subparser):
|
||||
help="configuration section to edit. "
|
||||
"options: %(choices)s",
|
||||
metavar='SECTION',
|
||||
nargs='?',
|
||||
choices=spack.config.section_schemas)
|
||||
edit_parser.add_argument(
|
||||
'--print-file', action='store_true',
|
||||
help="print the file name that would be edited")
|
||||
|
||||
|
||||
def _get_scope_and_section(args):
|
||||
"""Extract config scope and section from arguments."""
|
||||
scope = args.scope
|
||||
section = args.section
|
||||
|
||||
# w/no args and an active environment, point to env manifest
|
||||
if not args.section:
|
||||
env = ev.get_env(args, 'config edit', required=False)
|
||||
if env:
|
||||
scope = env.env_file_config_scope_name()
|
||||
|
||||
# set scope defaults
|
||||
elif not args.scope:
|
||||
if section == 'compilers':
|
||||
scope = spack.config.default_modify_scope()
|
||||
else:
|
||||
scope = 'user'
|
||||
|
||||
return scope, section
|
||||
|
||||
|
||||
def config_get(args):
|
||||
spack.config.config.print_section(args.section)
|
||||
"""Dump merged YAML configuration for a specific section.
|
||||
|
||||
With no arguments and an active environment, print the contents of
|
||||
the environment's manifest file (spack.yaml).
|
||||
|
||||
"""
|
||||
scope, section = _get_scope_and_section(args)
|
||||
|
||||
if scope and scope.startswith('env:'):
|
||||
config_file = spack.config.config.get_config_filename(scope, section)
|
||||
if os.path.exists(config_file):
|
||||
with open(config_file) as f:
|
||||
print(f.read())
|
||||
else:
|
||||
tty.die('environment has no %s file' % ev.manifest_name)
|
||||
|
||||
elif section is not None:
|
||||
spack.config.config.print_section(section)
|
||||
|
||||
else:
|
||||
tty.die('`spack config get` requires a section argument '
|
||||
'or an active environment.')
|
||||
|
||||
|
||||
def config_blame(args):
|
||||
"""Print out line-by-line blame of merged YAML."""
|
||||
spack.config.config.print_section(args.section, blame=True)
|
||||
|
||||
|
||||
def config_edit(args):
|
||||
if not args.scope:
|
||||
if args.section == 'compilers':
|
||||
args.scope = spack.config.default_modify_scope()
|
||||
else:
|
||||
args.scope = 'user'
|
||||
if not args.section:
|
||||
args.section = None
|
||||
"""Edit the configuration file for a specific scope and config section.
|
||||
|
||||
config = spack.config.config
|
||||
config_file = config.get_config_filename(args.scope, args.section)
|
||||
editor(config_file)
|
||||
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.')
|
||||
|
||||
config_file = spack.config.config.get_config_filename(scope, section)
|
||||
if args.print_file:
|
||||
print(config_file)
|
||||
else:
|
||||
editor(config_file)
|
||||
|
||||
|
||||
def config(parser, args):
|
||||
|
@ -483,9 +483,13 @@ def included_config_scopes(self):
|
||||
|
||||
return scopes
|
||||
|
||||
def env_file_config_scope_name(self):
|
||||
"""Name of the config scope of this environment's manifest file."""
|
||||
return 'env:%s' % self.name
|
||||
|
||||
def env_file_config_scope(self):
|
||||
"""Get the configuration scope for the environment's manifest file."""
|
||||
config_name = 'env:%s' % self.name
|
||||
config_name = self.env_file_config_scope_name()
|
||||
return spack.config.SingleFileScope(config_name,
|
||||
self.manifest_path,
|
||||
spack.schema.env.schema,
|
||||
|
93
lib/spack/spack/test/cmd/config.py
Normal file
93
lib/spack/spack/test/cmd/config.py
Normal file
@ -0,0 +1,93 @@
|
||||
# Copyright 2013-2018 Lawrence Livermore National Security, LLC and other
|
||||
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
||||
#
|
||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||
|
||||
import os
|
||||
|
||||
from llnl.util.filesystem import mkdirp
|
||||
|
||||
import spack.config
|
||||
import spack.environment as ev
|
||||
from spack.main import SpackCommand
|
||||
|
||||
config = SpackCommand('config')
|
||||
|
||||
|
||||
def test_get_config_scope(mock_config):
|
||||
assert config('get', 'compilers').strip() == 'compilers: {}'
|
||||
|
||||
|
||||
def test_get_config_scope_merged(mock_config):
|
||||
low_path = mock_config.scopes['low'].path
|
||||
high_path = mock_config.scopes['high'].path
|
||||
|
||||
mkdirp(low_path)
|
||||
mkdirp(high_path)
|
||||
|
||||
with open(os.path.join(low_path, 'repos.yaml'), 'w') as f:
|
||||
f.write('''\
|
||||
repos:
|
||||
- repo3
|
||||
''')
|
||||
|
||||
with open(os.path.join(high_path, 'repos.yaml'), 'w') as f:
|
||||
f.write('''\
|
||||
repos:
|
||||
- repo1
|
||||
- repo2
|
||||
''')
|
||||
|
||||
assert config('get', 'repos').strip() == '''repos:
|
||||
- repo1
|
||||
- repo2
|
||||
- repo3'''
|
||||
|
||||
|
||||
def test_config_edit():
|
||||
"""Ensure `spack config edit` edits the right paths."""
|
||||
dms = spack.config.default_modify_scope()
|
||||
dms_path = spack.config.config.scopes[dms].path
|
||||
user_path = spack.config.config.scopes['user'].path
|
||||
|
||||
comp_path = os.path.join(dms_path, 'compilers.yaml')
|
||||
repos_path = os.path.join(user_path, 'repos.yaml')
|
||||
|
||||
assert config('edit', '--print-file', 'compilers').strip() == comp_path
|
||||
assert config('edit', '--print-file', 'repos').strip() == repos_path
|
||||
|
||||
|
||||
def test_config_get_gets_spack_yaml(mutable_mock_env_path):
|
||||
env = ev.create('test')
|
||||
|
||||
config('get', fail_on_error=False)
|
||||
assert config.returncode == 1
|
||||
|
||||
with env:
|
||||
config('get', fail_on_error=False)
|
||||
assert config.returncode == 1
|
||||
|
||||
env.write()
|
||||
|
||||
assert 'mpileaks' not in config('get')
|
||||
|
||||
env.add('mpileaks')
|
||||
env.write()
|
||||
|
||||
assert 'mpileaks' in config('get')
|
||||
|
||||
|
||||
def test_config_edit_edits_spack_yaml(mutable_mock_env_path):
|
||||
env = ev.create('test')
|
||||
with env:
|
||||
assert config('edit', '--print-file').strip() == env.manifest_path
|
||||
|
||||
|
||||
def test_config_edit_fails_correctly_with_no_env(mutable_mock_env_path):
|
||||
output = config('edit', '--print-file', fail_on_error=False)
|
||||
assert "requires a section argument or an active environment" in output
|
||||
|
||||
|
||||
def test_config_get_fails_correctly_with_no_env(mutable_mock_env_path):
|
||||
output = config('get', fail_on_error=False)
|
||||
assert "requires a section argument or an active environment" in output
|
@ -49,20 +49,6 @@
|
||||
'build_stage:': ['patha', 'pathb']}}
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def mock_config(tmpdir):
|
||||
"""Mocks the configuration scope."""
|
||||
real_configuration = spack.config.config
|
||||
|
||||
spack.config.config = spack.config.Configuration(
|
||||
*[spack.config.ConfigScope(name, str(tmpdir.join(name)))
|
||||
for name in ['low', 'high']])
|
||||
|
||||
yield spack.config.config
|
||||
|
||||
spack.config.config = real_configuration
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def write_config_file(tmpdir):
|
||||
"""Returns a function that writes a config file."""
|
||||
|
@ -309,6 +309,20 @@ def mutable_config(tmpdir_factory, configuration_dir, config):
|
||||
spack.package_prefs.PackagePrefs.clear_caches()
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def mock_config(tmpdir):
|
||||
"""Mocks two configuration scopes: 'low' and 'high'."""
|
||||
real_configuration = spack.config.config
|
||||
|
||||
spack.config.config = spack.config.Configuration(
|
||||
*[spack.config.ConfigScope(name, str(tmpdir.join(name)))
|
||||
for name in ['low', 'high']])
|
||||
|
||||
yield spack.config.config
|
||||
|
||||
spack.config.config = real_configuration
|
||||
|
||||
|
||||
def _populate(mock_db):
|
||||
r"""Populate a mock database with packages.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user