summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/spack/docs/workflows.rst6
-rw-r--r--lib/spack/spack/cmd/__init__.py10
-rw-r--r--lib/spack/spack/cmd/load.py10
-rw-r--r--lib/spack/spack/test/cmd/load.py15
-rwxr-xr-xshare/spack/spack-completion.bash2
5 files changed, 35 insertions, 8 deletions
diff --git a/lib/spack/docs/workflows.rst b/lib/spack/docs/workflows.rst
index 89d17e98b2..9ce664b6ca 100644
--- a/lib/spack/docs/workflows.rst
+++ b/lib/spack/docs/workflows.rst
@@ -284,8 +284,10 @@ have some drawbacks:
The ``spack load`` and ``spack module tcl loads`` commands, on the
other hand, are not very smart: if the user-supplied spec matches
more than one installed package, then ``spack module tcl loads`` will
- fail. This may change in the future. For now, the workaround is to
- be more specific on any ``spack load`` commands that fail.
+ fail. This default behavior may change in the future. For now,
+ the workaround is to either be more specific on any failing ``spack load``
+ commands or to use ``spack load --first`` to allow spack to load the
+ first matching spec.
""""""""""""""""""""""
diff --git a/lib/spack/spack/cmd/__init__.py b/lib/spack/spack/cmd/__init__.py
index 2a75a87b54..83e12004a1 100644
--- a/lib/spack/spack/cmd/__init__.py
+++ b/lib/spack/spack/cmd/__init__.py
@@ -177,7 +177,7 @@ def elide_list(line_list, max_num=10):
return line_list
-def disambiguate_spec(spec, env, local=False, installed=True):
+def disambiguate_spec(spec, env, local=False, installed=True, first=False):
"""Given a spec, figure out which installed package it refers to.
Arguments:
@@ -190,10 +190,11 @@ def disambiguate_spec(spec, env, local=False, installed=True):
database query. See ``spack.database.Database._query`` for details.
"""
hashes = env.all_hashes() if env else None
- return disambiguate_spec_from_hashes(spec, hashes, local, installed)
+ return disambiguate_spec_from_hashes(spec, hashes, local, installed, first)
-def disambiguate_spec_from_hashes(spec, hashes, local=False, installed=True):
+def disambiguate_spec_from_hashes(spec, hashes, local=False,
+ installed=True, first=False):
"""Given a spec and a list of hashes, get concrete spec the spec refers to.
Arguments:
@@ -213,6 +214,9 @@ def disambiguate_spec_from_hashes(spec, hashes, local=False, installed=True):
if not matching_specs:
tty.die("Spec '%s' matches no installed packages." % spec)
+ elif first:
+ return matching_specs[0]
+
elif len(matching_specs) > 1:
format_string = '{name}{@version}{%compiler}{arch=architecture}'
args = ["%s matches multiple packages." % spec,
diff --git a/lib/spack/spack/cmd/load.py b/lib/spack/spack/cmd/load.py
index 9a00ad1c58..3ef485941f 100644
--- a/lib/spack/spack/cmd/load.py
+++ b/lib/spack/spack/cmd/load.py
@@ -34,6 +34,14 @@ def setup_parser(subparser):
help="print csh commands to load the package")
subparser.add_argument(
+ '--first',
+ action='store_true',
+ default=False,
+ dest='load_first',
+ help="load the first match if multiple packages match the spec"
+ )
+
+ subparser.add_argument(
'--only',
default='package,dependencies',
dest='things_to_load',
@@ -47,7 +55,7 @@ the dependencies"""
def load(parser, args):
env = ev.get_env(args, 'load')
- specs = [spack.cmd.disambiguate_spec(spec, env)
+ specs = [spack.cmd.disambiguate_spec(spec, env, first=args.load_first)
for spec in spack.cmd.parse_specs(args.specs)]
if not args.shell:
diff --git a/lib/spack/spack/test/cmd/load.py b/lib/spack/spack/test/cmd/load.py
index a10b99d45b..e6664a9d39 100644
--- a/lib/spack/spack/test/cmd/load.py
+++ b/lib/spack/spack/test/cmd/load.py
@@ -3,7 +3,8 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os
-from spack.main import SpackCommand
+import pytest
+from spack.main import SpackCommand, SpackCommandError
import spack.spec
import spack.user_environment as uenv
@@ -83,6 +84,18 @@ def test_load_includes_run_env(install_mockery, mock_fetch, mock_archive,
assert 'setenv FOOBAR mpileaks' in csh_out
+def test_load_first(install_mockery, mock_fetch, mock_archive, mock_packages):
+ """Test with and without the --first option"""
+ install('libelf@0.8.12')
+ install('libelf@0.8.13')
+ # Now there are two versions of libelf
+ with pytest.raises(SpackCommandError):
+ # This should cause an error due to multiple versions
+ load('--sh', 'libelf')
+ # Using --first should avoid the error condition
+ load('--sh', '--first', 'libelf')
+
+
def test_load_fails_no_shell(install_mockery, mock_fetch, mock_archive,
mock_packages):
"""Test that spack load prints an error message without a shell."""
diff --git a/share/spack/spack-completion.bash b/share/spack/spack-completion.bash
index 6df546e89f..a4d59220fa 100755
--- a/share/spack/spack-completion.bash
+++ b/share/spack/spack-completion.bash
@@ -984,7 +984,7 @@ _spack_list() {
_spack_load() {
if $list_options
then
- SPACK_COMPREPLY="-h --help -r --dependencies --sh --csh --only"
+ SPACK_COMPREPLY="-h --help -r --dependencies --sh --csh --first --only"
else
_installed_packages
fi