Improve output of the external find command (#18017)
This commit adds output to the "spack external find" command to inform users of the result of the operation. It also fixes a bug introduced in #17804 due to the fact that a function was not updated to conform to the new packages.yaml format (_get_predefined_externals).
This commit is contained in:
parent
c0342e4152
commit
31f660bd90
@ -15,6 +15,7 @@
|
|||||||
import llnl.util.tty.colify as colify
|
import llnl.util.tty.colify as colify
|
||||||
import six
|
import six
|
||||||
import spack
|
import spack
|
||||||
|
import spack.cmd
|
||||||
import spack.error
|
import spack.error
|
||||||
import spack.util.environment
|
import spack.util.environment
|
||||||
import spack.util.spack_yaml as syaml
|
import spack.util.spack_yaml as syaml
|
||||||
@ -146,7 +147,17 @@ def external_find(args):
|
|||||||
packages_to_check = spack.repo.path.all_packages()
|
packages_to_check = spack.repo.path.all_packages()
|
||||||
|
|
||||||
pkg_to_entries = _get_external_packages(packages_to_check)
|
pkg_to_entries = _get_external_packages(packages_to_check)
|
||||||
_update_pkg_config(pkg_to_entries, args.not_buildable)
|
new_entries, write_scope = _update_pkg_config(
|
||||||
|
pkg_to_entries, args.not_buildable
|
||||||
|
)
|
||||||
|
if new_entries:
|
||||||
|
path = spack.config.config.get_config_filename(write_scope, 'packages')
|
||||||
|
msg = ('The following specs have been detected on this system '
|
||||||
|
'and added to {0}')
|
||||||
|
tty.msg(msg.format(path))
|
||||||
|
spack.cmd.display_specs(new_entries)
|
||||||
|
else:
|
||||||
|
tty.msg('No new external packages detected')
|
||||||
|
|
||||||
|
|
||||||
def _group_by_prefix(paths):
|
def _group_by_prefix(paths):
|
||||||
@ -188,23 +199,24 @@ def _get_predefined_externals():
|
|||||||
pkg_config = spack.config.get('packages')
|
pkg_config = spack.config.get('packages')
|
||||||
already_defined_specs = set()
|
already_defined_specs = set()
|
||||||
for pkg_name, per_pkg_cfg in pkg_config.items():
|
for pkg_name, per_pkg_cfg in pkg_config.items():
|
||||||
paths = per_pkg_cfg.get('paths', {})
|
for item in per_pkg_cfg.get('externals', []):
|
||||||
already_defined_specs.update(spack.spec.Spec(k) for k in paths)
|
already_defined_specs.add(spack.spec.Spec(item['spec']))
|
||||||
modules = per_pkg_cfg.get('modules', {})
|
|
||||||
already_defined_specs.update(spack.spec.Spec(k) for k in modules)
|
|
||||||
return already_defined_specs
|
return already_defined_specs
|
||||||
|
|
||||||
|
|
||||||
def _update_pkg_config(pkg_to_entries, not_buildable):
|
def _update_pkg_config(pkg_to_entries, not_buildable):
|
||||||
predefined_external_specs = _get_predefined_externals()
|
predefined_external_specs = _get_predefined_externals()
|
||||||
|
|
||||||
pkg_to_cfg = {}
|
pkg_to_cfg, all_new_specs = {}, []
|
||||||
for pkg_name, ext_pkg_entries in pkg_to_entries.items():
|
for pkg_name, ext_pkg_entries in pkg_to_entries.items():
|
||||||
new_entries = list(
|
new_entries = list(
|
||||||
e for e in ext_pkg_entries
|
e for e in ext_pkg_entries
|
||||||
if (e.spec not in predefined_external_specs))
|
if (e.spec not in predefined_external_specs))
|
||||||
|
|
||||||
pkg_config = _generate_pkg_config(new_entries)
|
pkg_config = _generate_pkg_config(new_entries)
|
||||||
|
all_new_specs.extend([
|
||||||
|
spack.spec.Spec(x['spec']) for x in pkg_config.get('externals', [])
|
||||||
|
])
|
||||||
if not_buildable:
|
if not_buildable:
|
||||||
pkg_config['buildable'] = False
|
pkg_config['buildable'] = False
|
||||||
pkg_to_cfg[pkg_name] = pkg_config
|
pkg_to_cfg[pkg_name] = pkg_config
|
||||||
@ -215,6 +227,8 @@ def _update_pkg_config(pkg_to_entries, not_buildable):
|
|||||||
spack.config.merge_yaml(pkgs_cfg, pkg_to_cfg)
|
spack.config.merge_yaml(pkgs_cfg, pkg_to_cfg)
|
||||||
spack.config.set('packages', pkgs_cfg, scope=cfg_scope)
|
spack.config.set('packages', pkgs_cfg, scope=cfg_scope)
|
||||||
|
|
||||||
|
return all_new_specs, cfg_scope
|
||||||
|
|
||||||
|
|
||||||
def _get_external_packages(packages_to_check, system_path_to_exe=None):
|
def _get_external_packages(packages_to_check, system_path_to_exe=None):
|
||||||
if not system_path_to_exe:
|
if not system_path_to_exe:
|
||||||
|
@ -222,3 +222,21 @@ def _determine_variants(cls, exes, version_str):
|
|||||||
externals = packages_yaml['gcc']['externals']
|
externals = packages_yaml['gcc']['externals']
|
||||||
assert len(externals) == 1
|
assert len(externals) == 1
|
||||||
assert externals[0]['prefix'] == '/opt/gcc/bin'
|
assert externals[0]['prefix'] == '/opt/gcc/bin'
|
||||||
|
|
||||||
|
|
||||||
|
def test_new_entries_are_reported_correctly(
|
||||||
|
mock_executable, mutable_config, monkeypatch
|
||||||
|
):
|
||||||
|
# Prepare an environment to detect a fake gcc
|
||||||
|
gcc_exe = mock_executable('gcc', output="echo 4.2.1")
|
||||||
|
prefix = os.path.dirname(gcc_exe)
|
||||||
|
monkeypatch.setenv('PATH', prefix)
|
||||||
|
|
||||||
|
# The first run will find and add the external gcc
|
||||||
|
output = external('find', 'gcc')
|
||||||
|
assert 'The following specs have been' in output
|
||||||
|
|
||||||
|
# The second run should report that no new external
|
||||||
|
# has been found
|
||||||
|
output = external('find', 'gcc')
|
||||||
|
assert 'No new external packages detected' in output
|
||||||
|
Loading…
Reference in New Issue
Block a user