env: all commands that disambiguate specs should be env-aware

- some commands were missed in the rollout of spack environments

- this makes all commands that need to disambiguate specs restrict the
  disambiguation to installed packages in the active environment, as
  users would expect
This commit is contained in:
Todd Gamblin 2018-12-14 10:28:30 -08:00
parent 84b33523ec
commit 207c37759c
19 changed files with 55 additions and 26 deletions

View File

@ -158,8 +158,16 @@ def elide_list(line_list, max_num=10):
return line_list return line_list
def disambiguate_spec(spec): def disambiguate_spec(spec, env):
matching_specs = spack.store.db.query(spec) """Given a spec, figure out which installed package it refers to.
Arguments:
spec (spack.spec.Spec): a spec to disambiguate
env (spack.environment.Environment): a spack environment,
if one is active, or None if no environment is active
"""
hashes = env.all_hashes() if env else None
matching_specs = spack.store.db.query(spec, hashes=hashes)
if not matching_specs: if not matching_specs:
tty.die("Spec '%s' matches no installed packages." % spec) tty.die("Spec '%s' matches no installed packages." % spec)

View File

@ -8,6 +8,7 @@
import llnl.util.tty as tty import llnl.util.tty as tty
import spack.cmd import spack.cmd
import spack.environment as ev
from spack.filesystem_view import YamlFilesystemView from spack.filesystem_view import YamlFilesystemView
description = "activate a package extension" description = "activate a package extension"
@ -32,7 +33,8 @@ def activate(parser, args):
if len(specs) != 1: if len(specs) != 1:
tty.die("activate requires one spec. %d given." % len(specs)) tty.die("activate requires one spec. %d given." % len(specs))
spec = spack.cmd.disambiguate_spec(specs[0]) env = ev.get_env(args, 'activate')
spec = spack.cmd.disambiguate_spec(specs[0], env)
if not spec.package.is_extension: if not spec.package.is_extension:
tty.die("%s is not an extension." % spec.name) tty.die("%s is not an extension." % spec.name)

View File

@ -22,7 +22,7 @@ def setup_parser(subparser):
def add(parser, args): def add(parser, args):
env = ev.get_env(args, 'add') env = ev.get_env(args, 'add', required=True)
for spec in spack.cmd.parse_specs(args.specs): for spec in spack.cmd.parse_specs(args.specs):
if not env.add(spec): if not env.add(spec):

View File

@ -8,6 +8,7 @@
import llnl.util.tty as tty import llnl.util.tty as tty
import spack.cmd import spack.cmd
import spack.environment as ev
import spack.repo import spack.repo
import spack.store import spack.store
import spack.spec import spack.spec
@ -81,7 +82,8 @@ def setup_parser(subparser):
dlkeys.set_defaults(func=getkeys) dlkeys.set_defaults(func=getkeys)
def find_matching_specs(pkgs, allow_multiple_matches=False, force=False): def find_matching_specs(
pkgs, allow_multiple_matches=False, force=False, env=None):
"""Returns a list of specs matching the not necessarily """Returns a list of specs matching the not necessarily
concretized specs given from cli concretized specs given from cli
@ -92,12 +94,14 @@ def find_matching_specs(pkgs, allow_multiple_matches=False, force=False):
Return: Return:
list of specs list of specs
""" """
hashes = env.all_hashes() if env else None
# List of specs that match expressions given via command line # List of specs that match expressions given via command line
specs_from_cli = [] specs_from_cli = []
has_errors = False has_errors = False
specs = spack.cmd.parse_specs(pkgs) specs = spack.cmd.parse_specs(pkgs)
for spec in specs: for spec in specs:
matching = spack.store.db.query(spec) matching = spack.store.db.query(spec, hashes=hashes)
# For each spec provided, make sure it refers to only one package. # For each spec provided, make sure it refers to only one package.
# Fail and ask user to be unambiguous if it doesn't # Fail and ask user to be unambiguous if it doesn't
if not allow_multiple_matches and len(matching) > 1: if not allow_multiple_matches and len(matching) > 1:
@ -179,7 +183,10 @@ def createtarball(args):
if args.key: if args.key:
signkey = args.key signkey = args.key
matches = find_matching_specs(pkgs, False, False) # restrict matching to current environment if one is active
env = ev.get_env(args, 'buildcache create')
matches = find_matching_specs(pkgs, False, False, env=env)
for match in matches: for match in matches:
if match.external or match.virtual: if match.external or match.virtual:
tty.msg('skipping external or virtual spec %s' % tty.msg('skipping external or virtual spec %s' %

View File

@ -17,6 +17,6 @@ def setup_parser(subparser):
def concretize(parser, args): def concretize(parser, args):
env = ev.get_env(args, 'concretize') env = ev.get_env(args, 'concretize', required=True)
env.concretize(force=args.force) env.concretize(force=args.force)
env.write() env.write()

View File

@ -64,7 +64,7 @@ def _get_scope_and_section(args):
# w/no args and an active environment, point to env manifest # w/no args and an active environment, point to env manifest
if not args.section: if not args.section:
env = ev.get_env(args, 'config edit', required=False) env = ev.get_env(args, 'config edit')
if env: if env:
scope = env.env_file_config_scope_name() scope = env.env_file_config_scope_name()

View File

@ -7,6 +7,7 @@
import llnl.util.tty as tty import llnl.util.tty as tty
import spack.cmd import spack.cmd
import spack.environment as ev
import spack.store import spack.store
from spack.filesystem_view import YamlFilesystemView from spack.filesystem_view import YamlFilesystemView
from spack.graph import topological_sort from spack.graph import topological_sort
@ -37,7 +38,8 @@ def deactivate(parser, args):
if len(specs) != 1: if len(specs) != 1:
tty.die("deactivate requires one spec. %d given." % len(specs)) tty.die("deactivate requires one spec. %d given." % len(specs))
spec = spack.cmd.disambiguate_spec(specs[0]) env = ev.get_env(args, 'deactivate')
spec = spack.cmd.disambiguate_spec(specs[0], env)
pkg = spec.package pkg = spec.package
if args.view: if args.view:

View File

@ -8,6 +8,7 @@
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.tty.colify import colify from llnl.util.tty.colify import colify
import spack.environment as ev
import spack.store import spack.store
import spack.repo import spack.repo
import spack.cmd import spack.cmd
@ -38,7 +39,8 @@ def dependencies(parser, args):
tty.die("spack dependencies takes only one spec.") tty.die("spack dependencies takes only one spec.")
if args.installed: if args.installed:
spec = spack.cmd.disambiguate_spec(specs[0]) env = ev.get_env(args, 'dependencies')
spec = spack.cmd.disambiguate_spec(specs[0], env)
tty.msg("Dependencies of %s" % spec.format('$_$@$%@$/', color=True)) tty.msg("Dependencies of %s" % spec.format('$_$@$%@$/', color=True))
deps = spack.store.db.installed_relatives( deps = spack.store.db.installed_relatives(

View File

@ -8,6 +8,7 @@
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.tty.colify import colify from llnl.util.tty.colify import colify
import spack.environment as ev
import spack.repo import spack.repo
import spack.store import spack.store
import spack.cmd import spack.cmd
@ -81,7 +82,8 @@ def dependents(parser, args):
tty.die("spack dependents takes only one spec.") tty.die("spack dependents takes only one spec.")
if args.installed: if args.installed:
spec = spack.cmd.disambiguate_spec(specs[0]) env = ev.get_env(args, 'dependents')
spec = spack.cmd.disambiguate_spec(specs[0], env)
tty.msg("Dependents of %s" % spec.cformat('$_$@$%@$/')) tty.msg("Dependents of %s" % spec.cformat('$_$@$%@$/'))
deps = spack.store.db.installed_relatives( deps = spack.store.db.installed_relatives(

View File

@ -280,7 +280,7 @@ def env_status_setup_parser(subparser):
def env_status(args): def env_status(args):
env = ev.get_env(args, 'env status', required=False) env = ev.get_env(args, 'env status')
if env: if env:
if env.path == os.getcwd(): if env.path == os.getcwd():
tty.msg('Using %s in current directory: %s' tty.msg('Using %s in current directory: %s'
@ -305,7 +305,7 @@ def env_loads_setup_parser(subparser):
def env_loads(args): def env_loads(args):
env = ev.get_env(args, 'env loads') env = ev.get_env(args, 'env loads', required=True)
# Set the module types that have been selected # Set the module types that have been selected
module_type = args.module_type module_type = args.module_type

View File

@ -8,6 +8,7 @@
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.tty.colify import colify from llnl.util.tty.colify import colify
import spack.environment as ev
import spack.cmd import spack.cmd
import spack.cmd.find import spack.cmd.find
import spack.repo import spack.repo
@ -75,7 +76,8 @@ def extensions(parser, args):
if not spec[0].package.extendable: if not spec[0].package.extendable:
tty.die("%s is not an extendable package." % spec[0].name) tty.die("%s is not an extendable package." % spec[0].name)
spec = spack.cmd.disambiguate_spec(spec[0]) env = ev.get_env(args, 'extensions')
spec = spack.cmd.disambiguate_spec(spec[0], env)
if not spec.package.extendable: if not spec.package.extendable:
tty.die("%s does not have extensions." % spec.short_spec) tty.die("%s does not have extensions." % spec.short_spec)

View File

@ -151,7 +151,7 @@ def find(parser, args):
added = set() added = set()
removed = set() removed = set()
env = ev.get_env(args, 'find', required=False) env = ev.get_env(args, 'find')
if env: if env:
decorator, added, roots, removed = setup_env(env) decorator, added, roots, removed = setup_env(env)

View File

@ -160,7 +160,7 @@ def install_spec(cli_args, kwargs, abstract_spec, spec):
# handle active environment, if any # handle active environment, if any
def install(spec, kwargs): def install(spec, kwargs):
env = ev.get_env(cli_args, 'install', required=False) env = ev.get_env(cli_args, 'install')
if env: if env:
env.install(abstract_spec, spec, **kwargs) env.install(abstract_spec, spec, **kwargs)
env.write() env.write()
@ -194,7 +194,7 @@ def install(parser, args, **kwargs):
if not args.package and not args.specfiles: if not args.package and not args.specfiles:
# if there are no args but an active environment or spack.yaml file # if there are no args but an active environment or spack.yaml file
# then install the packages from it. # then install the packages from it.
env = ev.get_env(args, 'install', required=False) env = ev.get_env(args, 'install')
if env: if env:
if not args.only_concrete: if not args.only_concrete:
env.concretize() env.concretize()

View File

@ -9,6 +9,7 @@
import argparse import argparse
import llnl.util.tty as tty import llnl.util.tty as tty
import spack.environment as ev
import spack.cmd import spack.cmd
import spack.environment import spack.environment
import spack.paths import spack.paths
@ -86,7 +87,8 @@ def location(parser, args):
if args.install_dir: if args.install_dir:
# install_dir command matches against installed specs. # install_dir command matches against installed specs.
spec = spack.cmd.disambiguate_spec(specs[0]) env = ev.get_env(args, 'location')
spec = spack.cmd.disambiguate_spec(specs[0], env)
print(spec.prefix) print(spec.prefix)
else: else:

View File

@ -28,7 +28,7 @@ def setup_parser(subparser):
def remove(parser, args): def remove(parser, args):
env = ev.get_env(args, 'remove') env = ev.get_env(args, 'remove', required=True)
if args.all: if args.all:
env.clear() env.clear()

View File

@ -29,7 +29,7 @@ def setup_parser(subparser):
def stage(parser, args): def stage(parser, args):
if not args.specs: if not args.specs:
env = ev.get_env(args, 'stage', required=False) env = ev.get_env(args, 'stage')
if env: if env:
tty.msg("Staging specs from environment %s" % env.name) tty.msg("Staging specs from environment %s" % env.name)
for spec in env.specs_by_hash.values(): for spec in env.specs_by_hash.values():

View File

@ -301,7 +301,7 @@ def get_uninstall_list(args, specs, env):
def uninstall_specs(args, specs): def uninstall_specs(args, specs):
env = ev.get_env(args, 'uninstall', required=False) env = ev.get_env(args, 'uninstall')
uninstall_list, remove_list = get_uninstall_list(args, specs, env) uninstall_list, remove_list = get_uninstall_list(args, specs, env)
anything_to_do = set(uninstall_list).union(set(remove_list)) anything_to_do = set(uninstall_list).union(set(remove_list))

View File

@ -38,6 +38,7 @@
import llnl.util.tty as tty import llnl.util.tty as tty
from llnl.util.link_tree import MergeConflictError from llnl.util.link_tree import MergeConflictError
import spack.environment as ev
import spack.cmd import spack.cmd
import spack.store import spack.store
from spack.filesystem_view import YamlFilesystemView from spack.filesystem_view import YamlFilesystemView
@ -172,7 +173,8 @@ def view(parser, args):
elif args.action in actions_link: elif args.action in actions_link:
# only link commands need to disambiguate specs # only link commands need to disambiguate specs
specs = [spack.cmd.disambiguate_spec(s) for s in specs] env = ev.get_env(args, 'view link')
specs = [spack.cmd.disambiguate_spec(s, env) for s in specs]
elif args.action in actions_status: elif args.action in actions_status:
# no specs implies all # no specs implies all

View File

@ -184,7 +184,7 @@ def find_environment(args):
raise SpackEnvironmentError('no environment in %s' % env) raise SpackEnvironmentError('no environment in %s' % env)
def get_env(args, cmd_name, required=True): def get_env(args, cmd_name, required=False):
"""Used by commands to get the active environment. """Used by commands to get the active environment.
This first checks for an ``env`` argument, then looks at the This first checks for an ``env`` argument, then looks at the
@ -202,8 +202,8 @@ def get_env(args, cmd_name, required=True):
Arguments: Arguments:
args (Namespace): argparse namespace wtih command arguments args (Namespace): argparse namespace wtih command arguments
cmd_name (str): name of calling command cmd_name (str): name of calling command
required (bool): if ``False``, return ``None`` if no environment required (bool): if ``True``, raise an exception when no environment
is found instead of raising an exception. is found; if ``False``, just return ``None``
Returns: Returns:
(Environment): if there is an arg or active environment (Environment): if there is an arg or active environment