env: spack install SPEC installs into currently active environment.

- install will now add (if necessary), concretize, and install a single
  spec into the active environment.
This commit is contained in:
Todd Gamblin 2018-10-15 10:33:12 -07:00
parent 3fd9fc8994
commit 9fb37dfd76
4 changed files with 100 additions and 9 deletions

View file

@ -283,7 +283,7 @@ def env_list(args):
def env_add_setup_parser(subparser): def env_add_setup_parser(subparser):
"""add a spec to an environment""" """add a spec to an environment"""
subparser.add_argument( subparser.add_argument(
'-e', '--env', help='add spec to environment with this name') '-e', '--env', help='add spec to this environment')
subparser.add_argument( subparser.add_argument(
'specs', nargs=argparse.REMAINDER, help="spec of the package to add") 'specs', nargs=argparse.REMAINDER, help="spec of the package to add")
@ -371,7 +371,7 @@ def env_install(args):
env.write() env.write()
# install all specs in the environment # install all specs in the environment
env.install(args) env.install_all(args)
# REMOVE # REMOVE

View file

@ -150,17 +150,27 @@ def default_log_file(spec):
def install_spec(cli_args, kwargs, spec): def install_spec(cli_args, kwargs, spec):
# Do the actual installation """Do the actual installation."""
# handle active environment, if any
def install(spec, kwargs):
env = spack.environment.active
if env:
new_specs = env.install(spec, kwargs)
env.write(dump_packages=new_specs)
else:
spec.package.do_install(**kwargs)
try: try:
if cli_args.things_to_install == 'dependencies': if cli_args.things_to_install == 'dependencies':
# Install dependencies as-if they were installed # Install dependencies as-if they were installed
# for root (explicit=False in the DB) # for root (explicit=False in the DB)
kwargs['explicit'] = False kwargs['explicit'] = False
for s in spec.dependencies(): for s in spec.dependencies():
s.package.do_install(**kwargs) install(s, kwargs)
else: else:
kwargs['explicit'] = True kwargs['explicit'] = True
spec.package.do_install(**kwargs) install(spec, kwargs)
except spack.build_environment.InstallError as e: except spack.build_environment.InstallError as e:
if cli_args.show_log_on_error: if cli_args.show_log_on_error:

View file

@ -116,9 +116,29 @@ def deactivate():
""" """
global active global active
if not active: if not active:
return return
deactivate_config_scope(active)
spack.repo.path.remove(active.repo)
tty.debug("Deactivated environmennt '%s'" % active.name)
active = None
@contextmanager
def env_context(env):
"""Context manager that activates and deactivates an environment."""
old_active = active
activate(env)
yield
deactivate()
if old_active:
activate(old_active)
def root(name): def root(name):
"""Get the root directory for an environment by name.""" """Get the root directory for an environment by name."""
@ -333,7 +353,7 @@ def destroy(self):
"""Remove this environment from Spack entirely.""" """Remove this environment from Spack entirely."""
shutil.rmtree(self.path) shutil.rmtree(self.path)
def add(self, user_spec, report_existing=True): def add(self, user_spec):
"""Add a single user_spec (non-concretized) to the Environment """Add a single user_spec (non-concretized) to the Environment
Returns: Returns:
@ -342,6 +362,10 @@ def add(self, user_spec, report_existing=True):
""" """
spec = Spec(user_spec) spec = Spec(user_spec)
if not spec.name:
raise EnvError('cannot add anonymous specs to an environment!')
elif not spack.repo.path.exists(spec.name):
raise EnvError('no such package: %s' % spec.name)
existing = set(s for s in self.user_specs if s.name == spec.name) existing = set(s for s in self.user_specs if s.name == spec.name)
if not existing: if not existing:
@ -425,7 +449,45 @@ def concretize(self, force=False):
# return only the newly concretized specs # return only the newly concretized specs
return new_specs return new_specs
def install(self, args=None): def install(self, user_spec, install_args=None):
"""Install a single spec into an environment.
This will automatically concretize the single spec, but it won't
affect other as-yet unconcretized specs.
Returns:
(Spec): concrete spec if the spec was installed, None if it
was already present and installed.
"""
spec = Spec(user_spec)
# TODO: do a more sophisticated match than just by name
added = self.add(spec)
concrete = None
if added:
# newly added spec
spec = self.user_specs[-1]
concrete = spec.concretized()
h = concrete.dag_hash()
self.concretized_user_specs.append(spec)
self.concretized_order.append(h)
self.specs_by_hash[h] = concrete
else:
# spec might be in the user_specs, but not installed.
spec = next(s for s in self.user_specs if s.name == spec.name)
if spec not in self.concretized_user_specs:
concrete = spec.concretized()
self.concretized_user_specs.append(spec)
self.concretized_order.append(h)
self.specs_by_hash[h] = concrete
if concrete:
spec.package.do_install(**install_args)
def install_all(self, args=None):
"""Install all concretized specs in an environment.""" """Install all concretized specs in an environment."""
# Make sure log directory exists # Make sure log directory exists
@ -706,6 +768,12 @@ def prepare_config_scope(env):
spack.config.config.push_scope(scope) spack.config.config.push_scope(scope)
def deactivate_config_scope(env):
"""Remove any scopes from env from the global config path."""
for scope in env.config_scopes():
spack.config.config.remove_scope(scope.name)
class EnvError(spack.error.SpackError): class EnvError(spack.error.SpackError):
"""Superclass for all errors to do with Spack environments. """Superclass for all errors to do with Spack environments.

View file

@ -71,16 +71,29 @@ def test_concretize():
assert any(x.name == 'mpileaks' for x in env_specs) assert any(x.name == 'mpileaks' for x in env_specs)
def test_env_install(install_mockery, mock_fetch): def test_env_install_all(install_mockery, mock_fetch):
e = ev.Environment('test') e = ev.Environment('test')
e.add('cmake-client') e.add('cmake-client')
e.concretize() e.concretize()
e.install() e.install_all()
env_specs = e._get_environment_specs() env_specs = e._get_environment_specs()
spec = next(x for x in env_specs if x.name == 'cmake-client') spec = next(x for x in env_specs if x.name == 'cmake-client')
assert spec.package.installed assert spec.package.installed
def test_env_install(install_mockery, mock_fetch):
env('create', 'test')
install = SpackCommand('install')
with ev.env_context('test'):
install('cmake-client')
e = ev.read('test')
assert e.user_specs[0].name == 'cmake-client'
assert e.concretized_user_specs[0].name == 'cmake-client'
assert e.specs_by_hash[e.concretized_order[0]].name == 'cmake-client'
def test_remove_after_concretize(): def test_remove_after_concretize():
e = ev.Environment('test') e = ev.Environment('test')