env: move add, remove, and concretize to top-level commands
This commit is contained in:
parent
e63b45b293
commit
8b549f664c
33
lib/spack/spack/cmd/add.py
Normal file
33
lib/spack/spack/cmd/add.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# 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 argparse
|
||||||
|
|
||||||
|
import llnl.util.tty as tty
|
||||||
|
|
||||||
|
import spack.cmd
|
||||||
|
import spack.environment as ev
|
||||||
|
|
||||||
|
|
||||||
|
description = 'add a spec to an environment'
|
||||||
|
section = "environment"
|
||||||
|
level = "long"
|
||||||
|
|
||||||
|
|
||||||
|
def setup_parser(subparser):
|
||||||
|
subparser.add_argument(
|
||||||
|
'specs', nargs=argparse.REMAINDER, help="specs of packages to add")
|
||||||
|
|
||||||
|
|
||||||
|
def add(parser, args):
|
||||||
|
env = ev.get_env(args, 'add')
|
||||||
|
|
||||||
|
for spec in spack.cmd.parse_specs(args.specs):
|
||||||
|
if not env.add(spec):
|
||||||
|
tty.msg("Package {0} was already added to {1}"
|
||||||
|
.format(spec.name, env.name))
|
||||||
|
else:
|
||||||
|
tty.msg('Adding %s to environment %s' % (spec, env.name))
|
||||||
|
env.write()
|
22
lib/spack/spack/cmd/concretize.py
Normal file
22
lib/spack/spack/cmd/concretize.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# 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 spack.environment as ev
|
||||||
|
|
||||||
|
description = 'concretize an environment and write a lockfile'
|
||||||
|
section = "environment"
|
||||||
|
level = "long"
|
||||||
|
|
||||||
|
|
||||||
|
def setup_parser(subparser):
|
||||||
|
subparser.add_argument(
|
||||||
|
'-f', '--force', action='store_true',
|
||||||
|
help="Re-concretize even if already concretized.")
|
||||||
|
|
||||||
|
|
||||||
|
def concretize(parser, args):
|
||||||
|
env = ev.get_env(args, 'concretize')
|
||||||
|
env.concretize(force=args.force)
|
||||||
|
env.write()
|
@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import argparse
|
|
||||||
|
|
||||||
import llnl.util.tty as tty
|
import llnl.util.tty as tty
|
||||||
import llnl.util.filesystem as fs
|
import llnl.util.filesystem as fs
|
||||||
@ -33,9 +32,6 @@
|
|||||||
'create',
|
'create',
|
||||||
'destroy',
|
'destroy',
|
||||||
['list', 'ls'],
|
['list', 'ls'],
|
||||||
'add',
|
|
||||||
['remove', 'rm'],
|
|
||||||
'concretize',
|
|
||||||
['status', 'st'],
|
['status', 'st'],
|
||||||
'loads',
|
'loads',
|
||||||
'stage',
|
'stage',
|
||||||
@ -270,68 +266,6 @@ def env_list(args):
|
|||||||
colify(color_names, indent=4)
|
colify(color_names, indent=4)
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# env add
|
|
||||||
#
|
|
||||||
def env_add_setup_parser(subparser):
|
|
||||||
"""add a spec to an environment"""
|
|
||||||
subparser.add_argument(
|
|
||||||
'specs', nargs=argparse.REMAINDER, help="spec of the package to add")
|
|
||||||
|
|
||||||
|
|
||||||
def env_add(args):
|
|
||||||
env = ev.get_env(args, 'env add')
|
|
||||||
|
|
||||||
for spec in spack.cmd.parse_specs(args.specs):
|
|
||||||
if not env.add(spec):
|
|
||||||
tty.msg("Package {0} was already added to {1}"
|
|
||||||
.format(spec.name, env.name))
|
|
||||||
else:
|
|
||||||
tty.msg('Adding %s to environment %s' % (spec, env.name))
|
|
||||||
env.write()
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# env remove
|
|
||||||
#
|
|
||||||
def env_remove_setup_parser(subparser):
|
|
||||||
"""remove a spec from an environment"""
|
|
||||||
subparser.add_argument(
|
|
||||||
'-a', '--all', action='store_true', dest='all',
|
|
||||||
help="Remove all specs from (clear) the environment")
|
|
||||||
subparser.add_argument(
|
|
||||||
'specs', nargs=argparse.REMAINDER, help="specs to be removed")
|
|
||||||
|
|
||||||
|
|
||||||
def env_remove(args):
|
|
||||||
env = ev.get_env(args, 'env remove <spec>')
|
|
||||||
|
|
||||||
if args.all:
|
|
||||||
env.clear()
|
|
||||||
else:
|
|
||||||
for spec in spack.cmd.parse_specs(args.specs):
|
|
||||||
tty.msg('Removing %s from environment %s' % (spec, env.name))
|
|
||||||
env.remove(spec)
|
|
||||||
env.write()
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# env concretize
|
|
||||||
#
|
|
||||||
def env_concretize_setup_parser(subparser):
|
|
||||||
"""concretize user specs and write lockfile"""
|
|
||||||
subparser.add_argument(
|
|
||||||
'env', nargs='?', help='concretize all packages for this environment')
|
|
||||||
subparser.add_argument(
|
|
||||||
'-f', '--force', action='store_true',
|
|
||||||
help="Re-concretize even if already concretized.")
|
|
||||||
|
|
||||||
|
|
||||||
def env_concretize(args):
|
|
||||||
env = ev.get_env(args, 'env concretize')
|
|
||||||
env.concretize(force=args.force)
|
|
||||||
env.write()
|
|
||||||
|
|
||||||
# REMOVE
|
# REMOVE
|
||||||
# env uninstall
|
# env uninstall
|
||||||
#
|
#
|
||||||
@ -456,7 +390,7 @@ def setup_parser(subparser):
|
|||||||
setup_parser_cmd(subsubparser)
|
setup_parser_cmd(subsubparser)
|
||||||
|
|
||||||
|
|
||||||
def env(parser, args, **kwargs):
|
def env(parser, args):
|
||||||
"""Look for a function called environment_<name> and call it."""
|
"""Look for a function called environment_<name> and call it."""
|
||||||
action = subcommand_functions[args.env_command]
|
action = subcommand_functions[args.env_command]
|
||||||
action(args)
|
action(args)
|
||||||
|
39
lib/spack/spack/cmd/remove.py
Normal file
39
lib/spack/spack/cmd/remove.py
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
# 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 argparse
|
||||||
|
|
||||||
|
import llnl.util.tty as tty
|
||||||
|
|
||||||
|
import spack.cmd
|
||||||
|
import spack.environment as ev
|
||||||
|
|
||||||
|
|
||||||
|
description = 'remove specs from an environment'
|
||||||
|
section = "environment"
|
||||||
|
level = "long"
|
||||||
|
|
||||||
|
|
||||||
|
def setup_parser(subparser):
|
||||||
|
subparser.add_argument(
|
||||||
|
'-a', '--all', action='store_true',
|
||||||
|
help="remove all specs from (clear) the environment")
|
||||||
|
subparser.add_argument(
|
||||||
|
'-f', '--force', action='store_true',
|
||||||
|
help="remove concretized spec (if any) immediately")
|
||||||
|
subparser.add_argument(
|
||||||
|
'specs', nargs=argparse.REMAINDER, help="specs to be removed")
|
||||||
|
|
||||||
|
|
||||||
|
def remove(parser, args):
|
||||||
|
env = ev.get_env(args, 'remove')
|
||||||
|
|
||||||
|
if args.all:
|
||||||
|
env.clear()
|
||||||
|
else:
|
||||||
|
for spec in spack.cmd.parse_specs(args.specs):
|
||||||
|
tty.msg('Removing %s from environment %s' % (spec, env.name))
|
||||||
|
env.remove(spec, force=args.force)
|
||||||
|
env.write()
|
@ -466,17 +466,31 @@ def add(self, user_spec):
|
|||||||
self.user_specs.append(spec)
|
self.user_specs.append(spec)
|
||||||
return bool(not existing)
|
return bool(not existing)
|
||||||
|
|
||||||
def remove(self, query_spec):
|
def remove(self, query_spec, force=False):
|
||||||
"""Remove specs from an environment that match a query_spec"""
|
"""Remove specs from an environment that match a query_spec"""
|
||||||
query_spec = Spec(query_spec)
|
query_spec = Spec(query_spec)
|
||||||
matches = [s for s in self.user_specs if s.satisfies(query_spec)]
|
|
||||||
|
# try abstract specs first
|
||||||
|
matches = []
|
||||||
|
if not query_spec.concrete:
|
||||||
|
matches = [s for s in self.user_specs if s.satisfies(query_spec)]
|
||||||
|
|
||||||
|
if not matches:
|
||||||
|
# concrete specs match against concrete specs in the env
|
||||||
|
specs_hashes = zip(
|
||||||
|
self.concretized_user_specs, self.concretized_order)
|
||||||
|
matches = [
|
||||||
|
s for s, h in specs_hashes
|
||||||
|
if s.satisfies(query_spec) or query_spec.dag_hash() == h]
|
||||||
|
|
||||||
if not matches:
|
if not matches:
|
||||||
raise EnvError("Not found: {0}".format(query_spec))
|
raise EnvError("Not found: {0}".format(query_spec))
|
||||||
|
|
||||||
for spec in matches:
|
for spec in matches:
|
||||||
self.user_specs.remove(spec)
|
if spec in self.user_specs:
|
||||||
if spec in self.concretized_user_specs:
|
self.user_specs.remove(spec)
|
||||||
|
|
||||||
|
if force and spec in self.concretized_user_specs:
|
||||||
i = self.concretized_user_specs.index(spec)
|
i = self.concretized_user_specs.index(spec)
|
||||||
del self.concretized_user_specs[i]
|
del self.concretized_user_specs[i]
|
||||||
|
|
||||||
|
@ -38,6 +38,11 @@
|
|||||||
#: names of profile statistics
|
#: names of profile statistics
|
||||||
stat_names = pstats.Stats.sort_arg_dict_default
|
stat_names = pstats.Stats.sort_arg_dict_default
|
||||||
|
|
||||||
|
#: top-level aliases for Spack commands
|
||||||
|
aliases = {
|
||||||
|
'rm': 'remove'
|
||||||
|
}
|
||||||
|
|
||||||
#: help levels in order of detail (i.e., number of commands shown)
|
#: help levels in order of detail (i.e., number of commands shown)
|
||||||
levels = ['short', 'long']
|
levels = ['short', 'long']
|
||||||
|
|
||||||
@ -174,8 +179,8 @@ def add_subcommand_group(title, commands):
|
|||||||
cmd_set = set(c for c in commands)
|
cmd_set = set(c for c in commands)
|
||||||
|
|
||||||
# make a dict of commands of interest
|
# make a dict of commands of interest
|
||||||
cmds = dict((a.metavar, a) for a in self.actions
|
cmds = dict((a.dest, a) for a in self.actions
|
||||||
if a.metavar in cmd_set)
|
if a.dest in cmd_set)
|
||||||
|
|
||||||
# add commands to a group in order, and add the group
|
# add commands to a group in order, and add the group
|
||||||
group = argparse._ArgumentGroup(self, title=title)
|
group = argparse._ArgumentGroup(self, title=title)
|
||||||
@ -271,8 +276,13 @@ def add_command(self, cmd_name):
|
|||||||
# each command module implements a parser() function, to which we
|
# each command module implements a parser() function, to which we
|
||||||
# pass its subparser for setup.
|
# pass its subparser for setup.
|
||||||
module = spack.cmd.get_module(cmd_name)
|
module = spack.cmd.get_module(cmd_name)
|
||||||
|
|
||||||
|
# build a list of aliases
|
||||||
|
alias_list = [k for k, v in aliases.items() if v == cmd_name]
|
||||||
|
|
||||||
subparser = self.subparsers.add_parser(
|
subparser = self.subparsers.add_parser(
|
||||||
cmd_name, help=module.description, description=module.description)
|
cmd_name, aliases=alias_list,
|
||||||
|
help=module.description, description=module.description)
|
||||||
module.setup_parser(subparser)
|
module.setup_parser(subparser)
|
||||||
|
|
||||||
# return the callable function for the command
|
# return the callable function for the command
|
||||||
@ -647,6 +657,8 @@ def main(argv=None):
|
|||||||
# Try to load the particular command the caller asked for. If there
|
# Try to load the particular command the caller asked for. If there
|
||||||
# is no module for it, just die.
|
# is no module for it, just die.
|
||||||
cmd_name = args.command[0]
|
cmd_name = args.command[0]
|
||||||
|
cmd_name = aliases.get(cmd_name, cmd_name)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
command = parser.add_command(cmd_name)
|
command = parser.add_command(cmd_name)
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
@ -21,9 +21,11 @@
|
|||||||
pytestmark = pytest.mark.usefixtures(
|
pytestmark = pytest.mark.usefixtures(
|
||||||
'mutable_mock_env_path', 'config', 'mutable_mock_packages')
|
'mutable_mock_env_path', 'config', 'mutable_mock_packages')
|
||||||
|
|
||||||
|
env = SpackCommand('env')
|
||||||
env = SpackCommand('env')
|
install = SpackCommand('install')
|
||||||
install = SpackCommand('install')
|
add = SpackCommand('add')
|
||||||
|
remove = SpackCommand('remove')
|
||||||
|
concretize = SpackCommand('concretize')
|
||||||
|
|
||||||
|
|
||||||
def test_add():
|
def test_add():
|
||||||
@ -137,32 +139,34 @@ def test_remove_after_concretize():
|
|||||||
e.concretize()
|
e.concretize()
|
||||||
|
|
||||||
e.remove('mpileaks')
|
e.remove('mpileaks')
|
||||||
|
assert Spec('mpileaks') not in e.user_specs
|
||||||
env_specs = e._get_environment_specs()
|
env_specs = e._get_environment_specs()
|
||||||
assert not any(x.name == 'mpileaks' for x in env_specs)
|
assert any(s.name == 'mpileaks' for s in env_specs)
|
||||||
|
|
||||||
|
e.add('mpileaks')
|
||||||
|
assert any(s.name == 'mpileaks' for s in e.user_specs)
|
||||||
|
|
||||||
|
e.remove('mpileaks', force=True)
|
||||||
|
assert Spec('mpileaks') not in e.user_specs
|
||||||
|
env_specs = e._get_environment_specs()
|
||||||
|
assert not any(s.name == 'mpileaks' for s in env_specs)
|
||||||
|
|
||||||
|
|
||||||
def test_remove_command():
|
def test_remove_command():
|
||||||
env('create', 'test')
|
env('create', 'test')
|
||||||
|
|
||||||
with ev.read('test'):
|
with ev.read('test'):
|
||||||
env('add', 'mpileaks')
|
add('mpileaks')
|
||||||
assert 'mpileaks' in env('status', 'test')
|
assert 'mpileaks' in env('status', 'test')
|
||||||
|
|
||||||
with ev.read('test'):
|
with ev.read('test'):
|
||||||
env('remove', 'mpileaks')
|
remove('mpileaks')
|
||||||
assert 'mpileaks' not in env('status', 'test')
|
assert 'mpileaks' not in env('status', 'test')
|
||||||
|
|
||||||
with ev.read('test'):
|
with ev.read('test'):
|
||||||
env('add', 'mpileaks')
|
add('mpileaks')
|
||||||
assert 'mpileaks' in env('status', 'test')
|
assert 'mpileaks' in env('status', 'test')
|
||||||
|
|
||||||
env('concretize', 'test')
|
|
||||||
assert 'mpileaks' in env('status', 'test')
|
|
||||||
|
|
||||||
with ev.read('test'):
|
|
||||||
env('remove', 'mpileaks')
|
|
||||||
assert 'mpileaks' not in env('status', 'test')
|
|
||||||
|
|
||||||
|
|
||||||
def test_environment_status():
|
def test_environment_status():
|
||||||
e = ev.create('test')
|
e = ev.create('test')
|
||||||
@ -195,7 +199,8 @@ def test_env_repo():
|
|||||||
e.add('mpileaks')
|
e.add('mpileaks')
|
||||||
e.write()
|
e.write()
|
||||||
|
|
||||||
env('concretize', 'test')
|
with ev.read('test'):
|
||||||
|
concretize()
|
||||||
|
|
||||||
package = e.repo.get('mpileaks')
|
package = e.repo.get('mpileaks')
|
||||||
assert package.name == 'mpileaks'
|
assert package.name == 'mpileaks'
|
||||||
@ -487,14 +492,12 @@ def test_env_loads(install_mockery, mock_fetch):
|
|||||||
env('create', 'test')
|
env('create', 'test')
|
||||||
|
|
||||||
with ev.read('test'):
|
with ev.read('test'):
|
||||||
env('add', 'mpileaks')
|
add('mpileaks')
|
||||||
|
concretize()
|
||||||
env('concretize', 'test')
|
|
||||||
|
|
||||||
with ev.read('test'):
|
|
||||||
install('--fake')
|
install('--fake')
|
||||||
|
|
||||||
env('loads', 'test')
|
with ev.read('test'):
|
||||||
|
env('loads', 'test')
|
||||||
|
|
||||||
e = ev.read('test')
|
e = ev.read('test')
|
||||||
|
|
||||||
@ -510,9 +513,9 @@ def test_env_loads(install_mockery, mock_fetch):
|
|||||||
def test_env_stage(mock_stage, mock_fetch, install_mockery):
|
def test_env_stage(mock_stage, mock_fetch, install_mockery):
|
||||||
env('create', 'test')
|
env('create', 'test')
|
||||||
with ev.read('test'):
|
with ev.read('test'):
|
||||||
print env('add', 'mpileaks')
|
add('mpileaks')
|
||||||
print env('add', 'zmpi')
|
add('zmpi')
|
||||||
env('concretize', 'test')
|
concretize()
|
||||||
env('stage', 'test')
|
env('stage', 'test')
|
||||||
|
|
||||||
root = str(mock_stage)
|
root = str(mock_stage)
|
||||||
@ -535,18 +538,12 @@ def test_env_commands_die_with_no_env_arg():
|
|||||||
env('destroy')
|
env('destroy')
|
||||||
|
|
||||||
# these have an optional env arg and raise errors via tty.die
|
# these have an optional env arg and raise errors via tty.die
|
||||||
with pytest.raises(spack.main.SpackCommandError):
|
|
||||||
env('concretize')
|
|
||||||
with pytest.raises(spack.main.SpackCommandError):
|
with pytest.raises(spack.main.SpackCommandError):
|
||||||
env('loads')
|
env('loads')
|
||||||
with pytest.raises(spack.main.SpackCommandError):
|
with pytest.raises(spack.main.SpackCommandError):
|
||||||
env('stage')
|
env('stage')
|
||||||
with pytest.raises(spack.main.SpackCommandError):
|
with pytest.raises(spack.main.SpackCommandError):
|
||||||
env('uninstall')
|
env('uninstall')
|
||||||
with pytest.raises(spack.main.SpackCommandError):
|
|
||||||
env('add')
|
|
||||||
with pytest.raises(spack.main.SpackCommandError):
|
|
||||||
env('remove')
|
|
||||||
|
|
||||||
# This should NOT raise an error with no environment
|
# This should NOT raise an error with no environment
|
||||||
# it just tells the user there isn't an environment
|
# it just tells the user there isn't an environment
|
||||||
|
Loading…
Reference in New Issue
Block a user