spack deconcretize
command (#38803)
We have two ways to concretize now: * `spack concretize` concretizes only the root specs that are not concrete in the environment. * `spack concretize -f` eliminates all cached concretization data and reconcretizes the *entire* environment. This PR adds `spack deconcretize`, which eliminates cached concretization data for a spec. This allows users greater control over what is preserved from their `spack.lock` file and what is reused when not using `spack concretize -f`. If you want to update a spec installed in your environment, you can call `spack deconcretize` on it, and that spec and any relevant dependents will be removed from the lock file. `spack concretize` has two options: * `--root`: limits deconcretized specs to *specific* roots in the environment. You can use this to deconcretize exactly one root in a `unify: false` environment. i.e., if `foo` root is a dependent of `bar`, both roots, `spack deconcretize bar` will *not* deconcretize `foo`. * `--all`: deconcretize *all* specs that match the input spec. By default `spack deconcretize` will complain about multiple matches, like `spack uninstall`.
This commit is contained in:
parent
f6dc557764
commit
09e9bb5c3d
8 changed files with 265 additions and 26 deletions
30
lib/spack/spack/cmd/common/confirmation.py
Normal file
30
lib/spack/spack/cmd/common/confirmation.py
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
# Copyright 2013-2023 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 sys
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
import llnl.util.tty as tty
|
||||||
|
|
||||||
|
import spack.cmd
|
||||||
|
|
||||||
|
display_args = {"long": True, "show_flags": False, "variants": False, "indent": 4}
|
||||||
|
|
||||||
|
|
||||||
|
def confirm_action(specs: List[spack.spec.Spec], participle: str, noun: str):
|
||||||
|
"""Display the list of specs to be acted on and ask for confirmation.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
specs: specs to be removed
|
||||||
|
participle: action expressed as a participle, e.g. "uninstalled"
|
||||||
|
noun: action expressed as a noun, e.g. "uninstallation"
|
||||||
|
"""
|
||||||
|
tty.msg(f"The following {len(specs)} packages will be {participle}:\n")
|
||||||
|
spack.cmd.display_specs(specs, **display_args)
|
||||||
|
print("")
|
||||||
|
answer = tty.get_yes_or_no("Do you want to proceed?", default=False)
|
||||||
|
if not answer:
|
||||||
|
tty.msg(f"Aborting {noun}")
|
||||||
|
sys.exit(0)
|
103
lib/spack/spack/cmd/deconcretize.py
Normal file
103
lib/spack/spack/cmd/deconcretize.py
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
# Copyright 2013-2023 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 argparse
|
||||||
|
import sys
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
import llnl.util.tty as tty
|
||||||
|
|
||||||
|
import spack.cmd
|
||||||
|
import spack.cmd.common.arguments as arguments
|
||||||
|
import spack.cmd.common.confirmation as confirmation
|
||||||
|
import spack.environment as ev
|
||||||
|
import spack.spec
|
||||||
|
|
||||||
|
description = "remove specs from the concretized lockfile of an environment"
|
||||||
|
section = "environments"
|
||||||
|
level = "long"
|
||||||
|
|
||||||
|
# Arguments for display_specs when we find ambiguity
|
||||||
|
display_args = {"long": True, "show_flags": False, "variants": False, "indent": 4}
|
||||||
|
|
||||||
|
|
||||||
|
def setup_parser(subparser):
|
||||||
|
subparser.add_argument(
|
||||||
|
"--root", action="store_true", help="deconcretize only specific environment roots"
|
||||||
|
)
|
||||||
|
arguments.add_common_arguments(subparser, ["yes_to_all", "specs"])
|
||||||
|
subparser.add_argument(
|
||||||
|
"-a",
|
||||||
|
"--all",
|
||||||
|
action="store_true",
|
||||||
|
dest="all",
|
||||||
|
help="deconcretize ALL specs that match each supplied spec",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_deconcretize_list(
|
||||||
|
args: argparse.Namespace, specs: List[spack.spec.Spec], env: ev.Environment
|
||||||
|
) -> List[spack.spec.Spec]:
|
||||||
|
"""
|
||||||
|
Get list of environment roots to deconcretize
|
||||||
|
"""
|
||||||
|
env_specs = [s for _, s in env.concretized_specs()]
|
||||||
|
to_deconcretize = []
|
||||||
|
errors = []
|
||||||
|
|
||||||
|
for s in specs:
|
||||||
|
if args.root:
|
||||||
|
# find all roots matching given spec
|
||||||
|
to_deconc = [e for e in env_specs if e.satisfies(s)]
|
||||||
|
else:
|
||||||
|
# find all roots matching or depending on a matching spec
|
||||||
|
to_deconc = [e for e in env_specs if any(d.satisfies(s) for d in e.traverse())]
|
||||||
|
|
||||||
|
if len(to_deconc) < 1:
|
||||||
|
tty.warn(f"No matching specs to deconcretize for {s}")
|
||||||
|
|
||||||
|
elif len(to_deconc) > 1 and not args.all:
|
||||||
|
errors.append((s, to_deconc))
|
||||||
|
|
||||||
|
to_deconcretize.extend(to_deconc)
|
||||||
|
|
||||||
|
if errors:
|
||||||
|
for spec, matching in errors:
|
||||||
|
tty.error(f"{spec} matches multiple concrete specs:")
|
||||||
|
sys.stderr.write("\n")
|
||||||
|
spack.cmd.display_specs(matching, output=sys.stderr, **display_args)
|
||||||
|
sys.stderr.write("\n")
|
||||||
|
sys.stderr.flush()
|
||||||
|
tty.die("Use '--all' to deconcretize all matching specs, or be more specific")
|
||||||
|
|
||||||
|
return to_deconcretize
|
||||||
|
|
||||||
|
|
||||||
|
def deconcretize_specs(args, specs):
|
||||||
|
env = spack.cmd.require_active_env(cmd_name="deconcretize")
|
||||||
|
|
||||||
|
if args.specs:
|
||||||
|
deconcretize_list = get_deconcretize_list(args, specs, env)
|
||||||
|
else:
|
||||||
|
deconcretize_list = [s for _, s in env.concretized_specs()]
|
||||||
|
|
||||||
|
if not args.yes_to_all:
|
||||||
|
confirmation.confirm_action(deconcretize_list, "deconcretized", "deconcretization")
|
||||||
|
|
||||||
|
with env.write_transaction():
|
||||||
|
for spec in deconcretize_list:
|
||||||
|
env.deconcretize(spec)
|
||||||
|
env.write()
|
||||||
|
|
||||||
|
|
||||||
|
def deconcretize(parser, args):
|
||||||
|
if not args.specs and not args.all:
|
||||||
|
tty.die(
|
||||||
|
"deconcretize requires at least one spec argument.",
|
||||||
|
" Use `spack deconcretize --all` to deconcretize ALL specs.",
|
||||||
|
)
|
||||||
|
|
||||||
|
specs = spack.cmd.parse_specs(args.specs) if args.specs else [any]
|
||||||
|
deconcretize_specs(args, specs)
|
|
@ -6,6 +6,7 @@
|
||||||
import llnl.util.tty as tty
|
import llnl.util.tty as tty
|
||||||
|
|
||||||
import spack.cmd.common.arguments
|
import spack.cmd.common.arguments
|
||||||
|
import spack.cmd.common.confirmation
|
||||||
import spack.cmd.uninstall
|
import spack.cmd.uninstall
|
||||||
import spack.environment as ev
|
import spack.environment as ev
|
||||||
import spack.store
|
import spack.store
|
||||||
|
@ -41,6 +42,6 @@ def gc(parser, args):
|
||||||
return
|
return
|
||||||
|
|
||||||
if not args.yes_to_all:
|
if not args.yes_to_all:
|
||||||
spack.cmd.uninstall.confirm_removal(specs)
|
spack.cmd.common.confirmation.confirm_action(specs, "uninstalled", "uninstallation")
|
||||||
|
|
||||||
spack.cmd.uninstall.do_uninstall(specs, force=False)
|
spack.cmd.uninstall.do_uninstall(specs, force=False)
|
||||||
|
|
|
@ -11,10 +11,9 @@
|
||||||
|
|
||||||
import spack.cmd
|
import spack.cmd
|
||||||
import spack.cmd.common.arguments as arguments
|
import spack.cmd.common.arguments as arguments
|
||||||
|
import spack.cmd.common.confirmation as confirmation
|
||||||
import spack.environment as ev
|
import spack.environment as ev
|
||||||
import spack.error
|
|
||||||
import spack.package_base
|
import spack.package_base
|
||||||
import spack.repo
|
|
||||||
import spack.spec
|
import spack.spec
|
||||||
import spack.store
|
import spack.store
|
||||||
import spack.traverse as traverse
|
import spack.traverse as traverse
|
||||||
|
@ -278,7 +277,7 @@ def uninstall_specs(args, specs):
|
||||||
return
|
return
|
||||||
|
|
||||||
if not args.yes_to_all:
|
if not args.yes_to_all:
|
||||||
confirm_removal(uninstall_list)
|
confirmation.confirm_action(uninstall_list, "uninstalled", "uninstallation")
|
||||||
|
|
||||||
# Uninstall everything on the list
|
# Uninstall everything on the list
|
||||||
do_uninstall(uninstall_list, args.force)
|
do_uninstall(uninstall_list, args.force)
|
||||||
|
@ -292,21 +291,6 @@ def uninstall_specs(args, specs):
|
||||||
env.regenerate_views()
|
env.regenerate_views()
|
||||||
|
|
||||||
|
|
||||||
def confirm_removal(specs: List[spack.spec.Spec]):
|
|
||||||
"""Display the list of specs to be removed and ask for confirmation.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
specs: specs to be removed
|
|
||||||
"""
|
|
||||||
tty.msg("The following {} packages will be uninstalled:\n".format(len(specs)))
|
|
||||||
spack.cmd.display_specs(specs, **display_args)
|
|
||||||
print("")
|
|
||||||
answer = tty.get_yes_or_no("Do you want to proceed?", default=False)
|
|
||||||
if not answer:
|
|
||||||
tty.msg("Aborting uninstallation")
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
|
|
||||||
def uninstall(parser, args):
|
def uninstall(parser, args):
|
||||||
if not args.specs and not args.all:
|
if not args.specs and not args.all:
|
||||||
tty.die(
|
tty.die(
|
||||||
|
|
|
@ -1358,7 +1358,7 @@ def concretize(self, force=False, tests=False):
|
||||||
|
|
||||||
# Remove concrete specs that no longer correlate to a user spec
|
# Remove concrete specs that no longer correlate to a user spec
|
||||||
for spec in set(self.concretized_user_specs) - set(self.user_specs):
|
for spec in set(self.concretized_user_specs) - set(self.user_specs):
|
||||||
self.deconcretize(spec)
|
self.deconcretize(spec, concrete=False)
|
||||||
|
|
||||||
# Pick the right concretization strategy
|
# Pick the right concretization strategy
|
||||||
if self.unify == "when_possible":
|
if self.unify == "when_possible":
|
||||||
|
@ -1373,15 +1373,36 @@ def concretize(self, force=False, tests=False):
|
||||||
msg = "concretization strategy not implemented [{0}]"
|
msg = "concretization strategy not implemented [{0}]"
|
||||||
raise SpackEnvironmentError(msg.format(self.unify))
|
raise SpackEnvironmentError(msg.format(self.unify))
|
||||||
|
|
||||||
def deconcretize(self, spec):
|
def deconcretize(self, spec: spack.spec.Spec, concrete: bool = True):
|
||||||
|
"""
|
||||||
|
Remove specified spec from environment concretization
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
spec: Spec to deconcretize. This must be a root of the environment
|
||||||
|
concrete: If True, find all instances of spec as concrete in the environemnt.
|
||||||
|
If False, find a single instance of the abstract spec as root of the environment.
|
||||||
|
"""
|
||||||
# spec has to be a root of the environment
|
# spec has to be a root of the environment
|
||||||
index = self.concretized_user_specs.index(spec)
|
if concrete:
|
||||||
dag_hash = self.concretized_order.pop(index)
|
dag_hash = spec.dag_hash()
|
||||||
del self.concretized_user_specs[index]
|
|
||||||
|
pairs = zip(self.concretized_user_specs, self.concretized_order)
|
||||||
|
filtered = [(spec, h) for spec, h in pairs if h != dag_hash]
|
||||||
|
# Cannot use zip and unpack two values; it fails if filtered is empty
|
||||||
|
self.concretized_user_specs = [s for s, _ in filtered]
|
||||||
|
self.concretized_order = [h for _, h in filtered]
|
||||||
|
else:
|
||||||
|
index = self.concretized_user_specs.index(spec)
|
||||||
|
dag_hash = self.concretized_order.pop(index)
|
||||||
|
|
||||||
|
del self.concretized_user_specs[index]
|
||||||
|
|
||||||
# If this was the only user spec that concretized to this concrete spec, remove it
|
# If this was the only user spec that concretized to this concrete spec, remove it
|
||||||
if dag_hash not in self.concretized_order:
|
if dag_hash not in self.concretized_order:
|
||||||
del self.specs_by_hash[dag_hash]
|
# if we deconcretized a dependency that doesn't correspond to a root, it
|
||||||
|
# won't be here.
|
||||||
|
if dag_hash in self.specs_by_hash:
|
||||||
|
del self.specs_by_hash[dag_hash]
|
||||||
|
|
||||||
def _get_specs_to_concretize(
|
def _get_specs_to_concretize(
|
||||||
self,
|
self,
|
||||||
|
|
78
lib/spack/spack/test/cmd/deconcretize.py
Normal file
78
lib/spack/spack/test/cmd/deconcretize.py
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
# Copyright 2013-2023 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 pytest
|
||||||
|
|
||||||
|
import spack.environment as ev
|
||||||
|
from spack.main import SpackCommand, SpackCommandError
|
||||||
|
|
||||||
|
deconcretize = SpackCommand("deconcretize")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="function")
|
||||||
|
def test_env(mutable_mock_env_path, config, mock_packages):
|
||||||
|
ev.create("test")
|
||||||
|
with ev.read("test") as e:
|
||||||
|
e.add("a@2.0 foobar=bar ^b@1.0")
|
||||||
|
e.add("a@1.0 foobar=bar ^b@0.9")
|
||||||
|
e.concretize()
|
||||||
|
e.write()
|
||||||
|
|
||||||
|
|
||||||
|
def test_deconcretize_dep(test_env):
|
||||||
|
with ev.read("test") as e:
|
||||||
|
deconcretize("-y", "b@1.0")
|
||||||
|
specs = [s for s, _ in e.concretized_specs()]
|
||||||
|
|
||||||
|
assert len(specs) == 1
|
||||||
|
assert specs[0].satisfies("a@1.0")
|
||||||
|
|
||||||
|
|
||||||
|
def test_deconcretize_all_dep(test_env):
|
||||||
|
with ev.read("test") as e:
|
||||||
|
with pytest.raises(SpackCommandError):
|
||||||
|
deconcretize("-y", "b")
|
||||||
|
deconcretize("-y", "--all", "b")
|
||||||
|
specs = [s for s, _ in e.concretized_specs()]
|
||||||
|
|
||||||
|
assert len(specs) == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_deconcretize_root(test_env):
|
||||||
|
with ev.read("test") as e:
|
||||||
|
output = deconcretize("-y", "--root", "b@1.0")
|
||||||
|
assert "No matching specs to deconcretize" in output
|
||||||
|
assert len(e.concretized_order) == 2
|
||||||
|
|
||||||
|
deconcretize("-y", "--root", "a@2.0")
|
||||||
|
specs = [s for s, _ in e.concretized_specs()]
|
||||||
|
|
||||||
|
assert len(specs) == 1
|
||||||
|
assert specs[0].satisfies("a@1.0")
|
||||||
|
|
||||||
|
|
||||||
|
def test_deconcretize_all_root(test_env):
|
||||||
|
with ev.read("test") as e:
|
||||||
|
with pytest.raises(SpackCommandError):
|
||||||
|
deconcretize("-y", "--root", "a")
|
||||||
|
|
||||||
|
output = deconcretize("-y", "--root", "--all", "b")
|
||||||
|
assert "No matching specs to deconcretize" in output
|
||||||
|
assert len(e.concretized_order) == 2
|
||||||
|
|
||||||
|
deconcretize("-y", "--root", "--all", "a")
|
||||||
|
specs = [s for s, _ in e.concretized_specs()]
|
||||||
|
|
||||||
|
assert len(specs) == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_deconcretize_all(test_env):
|
||||||
|
with ev.read("test") as e:
|
||||||
|
with pytest.raises(SpackCommandError):
|
||||||
|
deconcretize()
|
||||||
|
deconcretize("-y", "--all")
|
||||||
|
specs = [s for s, _ in e.concretized_specs()]
|
||||||
|
|
||||||
|
assert len(specs) == 0
|
|
@ -401,7 +401,7 @@ _spack() {
|
||||||
then
|
then
|
||||||
SPACK_COMPREPLY="-h --help -H --all-help --color -c --config -C --config-scope -d --debug --timestamp --pdb -e --env -D --env-dir -E --no-env --use-env-repo -k --insecure -l --enable-locks -L --disable-locks -m --mock -b --bootstrap -p --profile --sorted-profile --lines -v --verbose --stacktrace --backtrace -V --version --print-shell-vars"
|
SPACK_COMPREPLY="-h --help -H --all-help --color -c --config -C --config-scope -d --debug --timestamp --pdb -e --env -D --env-dir -E --no-env --use-env-repo -k --insecure -l --enable-locks -L --disable-locks -m --mock -b --bootstrap -p --profile --sorted-profile --lines -v --verbose --stacktrace --backtrace -V --version --print-shell-vars"
|
||||||
else
|
else
|
||||||
SPACK_COMPREPLY="add arch audit blame bootstrap build-env buildcache cd change checksum ci clean clone commands compiler compilers concretize concretise config containerize containerise create debug dependencies dependents deprecate dev-build develop diff docs edit env extensions external fetch find gc gpg graph help info install license list load location log-parse maintainers make-installer mark mirror module patch pkg providers pydoc python reindex remove rm repo resource restage solve spec stage style tags test test-env tutorial undevelop uninstall unit-test unload url verify versions view"
|
SPACK_COMPREPLY="add arch audit blame bootstrap build-env buildcache cd change checksum ci clean clone commands compiler compilers concretize concretise config containerize containerise create debug deconcretize dependencies dependents deprecate dev-build develop diff docs edit env extensions external fetch find gc gpg graph help info install license list load location log-parse maintainers make-installer mark mirror module patch pkg providers pydoc python reindex remove rm repo resource restage solve spec stage style tags test test-env tutorial undevelop uninstall unit-test unload url verify versions view"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -937,6 +937,15 @@ _spack_debug_report() {
|
||||||
SPACK_COMPREPLY="-h --help"
|
SPACK_COMPREPLY="-h --help"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_spack_deconcretize() {
|
||||||
|
if $list_options
|
||||||
|
then
|
||||||
|
SPACK_COMPREPLY="-h --help --root -y --yes-to-all -a --all"
|
||||||
|
else
|
||||||
|
_all_packages
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
_spack_dependencies() {
|
_spack_dependencies() {
|
||||||
if $list_options
|
if $list_options
|
||||||
then
|
then
|
||||||
|
|
|
@ -371,6 +371,7 @@ complete -c spack -n '__fish_spack_using_command_pos 0 ' -f -a containerize -d '
|
||||||
complete -c spack -n '__fish_spack_using_command_pos 0 ' -f -a containerise -d 'creates recipes to build images for different container runtimes'
|
complete -c spack -n '__fish_spack_using_command_pos 0 ' -f -a containerise -d 'creates recipes to build images for different container runtimes'
|
||||||
complete -c spack -n '__fish_spack_using_command_pos 0 ' -f -a create -d 'create a new package file'
|
complete -c spack -n '__fish_spack_using_command_pos 0 ' -f -a create -d 'create a new package file'
|
||||||
complete -c spack -n '__fish_spack_using_command_pos 0 ' -f -a debug -d 'debugging commands for troubleshooting Spack'
|
complete -c spack -n '__fish_spack_using_command_pos 0 ' -f -a debug -d 'debugging commands for troubleshooting Spack'
|
||||||
|
complete -c spack -n '__fish_spack_using_command_pos 0 ' -f -a deconcretize -d 'remove specs from the concretized lockfile of an environment'
|
||||||
complete -c spack -n '__fish_spack_using_command_pos 0 ' -f -a dependencies -d 'show dependencies of a package'
|
complete -c spack -n '__fish_spack_using_command_pos 0 ' -f -a dependencies -d 'show dependencies of a package'
|
||||||
complete -c spack -n '__fish_spack_using_command_pos 0 ' -f -a dependents -d 'show packages that depend on another'
|
complete -c spack -n '__fish_spack_using_command_pos 0 ' -f -a dependents -d 'show packages that depend on another'
|
||||||
complete -c spack -n '__fish_spack_using_command_pos 0 ' -f -a deprecate -d 'replace one package with another via symlinks'
|
complete -c spack -n '__fish_spack_using_command_pos 0 ' -f -a deprecate -d 'replace one package with another via symlinks'
|
||||||
|
@ -1290,6 +1291,18 @@ set -g __fish_spack_optspecs_spack_debug_report h/help
|
||||||
complete -c spack -n '__fish_spack_using_command debug report' -s h -l help -f -a help
|
complete -c spack -n '__fish_spack_using_command debug report' -s h -l help -f -a help
|
||||||
complete -c spack -n '__fish_spack_using_command debug report' -s h -l help -d 'show this help message and exit'
|
complete -c spack -n '__fish_spack_using_command debug report' -s h -l help -d 'show this help message and exit'
|
||||||
|
|
||||||
|
# spack deconcretize
|
||||||
|
set -g __fish_spack_optspecs_spack_deconcretize h/help root y/yes-to-all a/all
|
||||||
|
complete -c spack -n '__fish_spack_using_command_pos_remainder 0 deconcretize' -f -k -a '(__fish_spack_specs)'
|
||||||
|
complete -c spack -n '__fish_spack_using_command deconcretize' -s h -l help -f -a help
|
||||||
|
complete -c spack -n '__fish_spack_using_command deconcretize' -s h -l help -d 'show this help message and exit'
|
||||||
|
complete -c spack -n '__fish_spack_using_command deconcretize' -l root -f -a root
|
||||||
|
complete -c spack -n '__fish_spack_using_command deconcretize' -l root -d 'deconcretize only specific environment roots'
|
||||||
|
complete -c spack -n '__fish_spack_using_command deconcretize' -s y -l yes-to-all -f -a yes_to_all
|
||||||
|
complete -c spack -n '__fish_spack_using_command deconcretize' -s y -l yes-to-all -d 'assume "yes" is the answer to every confirmation request'
|
||||||
|
complete -c spack -n '__fish_spack_using_command deconcretize' -s a -l all -f -a all
|
||||||
|
complete -c spack -n '__fish_spack_using_command deconcretize' -s a -l all -d 'deconcretize ALL specs that match each supplied spec'
|
||||||
|
|
||||||
# spack dependencies
|
# spack dependencies
|
||||||
set -g __fish_spack_optspecs_spack_dependencies h/help i/installed t/transitive deptype= V/no-expand-virtuals
|
set -g __fish_spack_optspecs_spack_dependencies h/help i/installed t/transitive deptype= V/no-expand-virtuals
|
||||||
complete -c spack -n '__fish_spack_using_command_pos_remainder 0 dependencies' -f -k -a '(__fish_spack_specs)'
|
complete -c spack -n '__fish_spack_using_command_pos_remainder 0 dependencies' -f -k -a '(__fish_spack_specs)'
|
||||||
|
|
Loading…
Reference in a new issue