env: add --env argument to spack find
- add a common argument for `-e/--env` - modify the database to support queries on subsets of hashes - allow `spack find` to be filtered by hashes in an environment
This commit is contained in:
parent
ea7648ff84
commit
47e60d5ef8
@ -8,6 +8,7 @@
|
||||
|
||||
import spack.cmd
|
||||
import spack.config
|
||||
import spack.environment
|
||||
import spack.modules
|
||||
import spack.spec
|
||||
import spack.store
|
||||
@ -42,16 +43,23 @@ class ConstraintAction(argparse.Action):
|
||||
|
||||
To obtain the specs from a command the function must be called.
|
||||
"""
|
||||
|
||||
def __call__(self, parser, namespace, values, option_string=None):
|
||||
# Query specs from command line
|
||||
self.values = values
|
||||
namespace.constraint = values
|
||||
namespace.specs = self._specs
|
||||
|
||||
# env comes from EnvAction if --env is provided
|
||||
self.env = None if not hasattr(namespace, 'env') else namespace.env
|
||||
|
||||
def _specs(self, **kwargs):
|
||||
qspecs = spack.cmd.parse_specs(self.values)
|
||||
|
||||
# If an environment is provided, we'll restrict the search to
|
||||
# only its installed packages.
|
||||
if self.env:
|
||||
kwargs['hashes'] = set(self.env.specs_by_hash.keys())
|
||||
|
||||
# return everything for an empty query.
|
||||
if not qspecs:
|
||||
return spack.store.db.query(**kwargs)
|
||||
@ -66,6 +74,16 @@ def _specs(self, **kwargs):
|
||||
return sorted(specs.values())
|
||||
|
||||
|
||||
class EnvAction(argparse.Action):
|
||||
"""Records the environment to which a command applies."""
|
||||
def __call__(self, parser, namespace, env_name, option_string=None):
|
||||
namespace.env = spack.environment.read(env_name)
|
||||
|
||||
|
||||
_arguments['env'] = Args(
|
||||
'-e', '--env', action=EnvAction, default=None,
|
||||
help="run this command on a specific environment")
|
||||
|
||||
_arguments['constraint'] = Args(
|
||||
'constraint', nargs=argparse.REMAINDER, action=ConstraintAction,
|
||||
help='constraint to select a subset of installed packages')
|
||||
|
@ -37,7 +37,8 @@ def setup_parser(subparser):
|
||||
const='deps',
|
||||
help='show full dependency DAG of installed packages')
|
||||
|
||||
arguments.add_common_arguments(subparser, ['long', 'very_long', 'tags'])
|
||||
arguments.add_common_arguments(
|
||||
subparser, ['env', 'long', 'very_long', 'tags'])
|
||||
|
||||
subparser.add_argument('-f', '--show-flags',
|
||||
action='store_true',
|
||||
@ -49,11 +50,11 @@ def setup_parser(subparser):
|
||||
help='show full compiler specs')
|
||||
implicit_explicit = subparser.add_mutually_exclusive_group()
|
||||
implicit_explicit.add_argument(
|
||||
'-e', '--explicit',
|
||||
'-x', '--explicit',
|
||||
action='store_true',
|
||||
help='show only specs that were installed explicitly')
|
||||
implicit_explicit.add_argument(
|
||||
'-E', '--implicit',
|
||||
'-X', '--implicit',
|
||||
action='store_true',
|
||||
help='show only specs that were installed as dependencies')
|
||||
subparser.add_argument(
|
||||
|
@ -55,9 +55,7 @@ def setup_parser(subparser):
|
||||
help='prompt the list of modules associated with a constraint'
|
||||
)
|
||||
add_loads_arguments(loads_parser)
|
||||
arguments.add_common_arguments(
|
||||
loads_parser, ['constraint']
|
||||
)
|
||||
arguments.add_common_arguments(loads_parser, ['constraint'])
|
||||
|
||||
return sp
|
||||
|
||||
|
@ -851,7 +851,8 @@ def query(
|
||||
installed=True,
|
||||
explicit=any,
|
||||
start_date=None,
|
||||
end_date=None
|
||||
end_date=None,
|
||||
hashes=None
|
||||
):
|
||||
"""Run a query on the database
|
||||
|
||||
@ -885,19 +886,26 @@ def query(
|
||||
end_date (datetime, optional): filters the query discarding
|
||||
specs that have been installed after ``end_date``.
|
||||
|
||||
hashes (container): list or set of hashes that we can use to
|
||||
restrict the search
|
||||
|
||||
Returns:
|
||||
list of specs that match the query
|
||||
|
||||
"""
|
||||
# TODO: Specs are a lot like queries. Should there be a
|
||||
# TODO: wildcard spec object, and should specs have attributes
|
||||
# TODO: like installed and known that can be queried? Or are
|
||||
# TODO: these really special cases that only belong here?
|
||||
|
||||
# TODO: handling of hashes restriction is not particularly elegant.
|
||||
with self.read_transaction():
|
||||
# Just look up concrete specs with hashes; no fancy search.
|
||||
if isinstance(query_spec, spack.spec.Spec) and query_spec.concrete:
|
||||
|
||||
hash_key = query_spec.dag_hash()
|
||||
if hash_key in self._data:
|
||||
if (hash_key in self._data and
|
||||
(not hashes or hash_key in hashes)):
|
||||
return [self._data[hash_key].spec]
|
||||
else:
|
||||
return []
|
||||
@ -909,6 +917,9 @@ def query(
|
||||
end_date = end_date or datetime.datetime.max
|
||||
|
||||
for key, rec in self._data.items():
|
||||
if hashes is not None and rec.spec.dag_hash() not in hashes:
|
||||
continue
|
||||
|
||||
if installed is not any and rec.installed != installed:
|
||||
continue
|
||||
|
||||
|
@ -31,6 +31,7 @@
|
||||
import llnl.util.filesystem as fs
|
||||
import llnl.util.tty as tty
|
||||
|
||||
import spack.error
|
||||
import spack.repo
|
||||
import spack.schema.env
|
||||
import spack.util.spack_json as sjson
|
||||
@ -389,9 +390,15 @@ def repair(environment_name):
|
||||
|
||||
|
||||
def read(environment_name):
|
||||
"""Read environment state from disk."""
|
||||
# Check that env is in a consistent state on disk
|
||||
env_root = root(environment_name)
|
||||
|
||||
if not os.path.isdir(env_root):
|
||||
raise EnvError("no such environment '%s'" % environment_name)
|
||||
if not os.access(env_root, os.R_OK):
|
||||
raise EnvError("can't read environment '%s'" % environment_name)
|
||||
|
||||
# Read env.yaml file
|
||||
env_yaml = spack.config._read_config_file(
|
||||
fs.join_path(env_root, 'env.yaml'),
|
||||
@ -458,3 +465,11 @@ def prepare_config_scope(environment):
|
||||
tty.msg('Using Spack config %s scope at %s' %
|
||||
(config_name, config_dir))
|
||||
spack.config.config.push_scope(ConfigScope(config_name, config_dir))
|
||||
|
||||
|
||||
class EnvError(spack.error.SpackError):
|
||||
"""Superclass for all errors to do with Spack environments.
|
||||
|
||||
Note that this is called ``EnvError`` to distinguish it from the
|
||||
builtin ``EnvironmentError``.
|
||||
"""
|
||||
|
Loading…
Reference in New Issue
Block a user