summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/spack/cmd/env.py4
-rw-r--r--lib/spack/spack/cmd/install.py16
-rw-r--r--lib/spack/spack/environment.py72
-rw-r--r--lib/spack/spack/test/cmd/env.py17
4 files changed, 100 insertions, 9 deletions
diff --git a/lib/spack/spack/cmd/env.py b/lib/spack/spack/cmd/env.py
index df26e9ece7..a0bf91bf48 100644
--- a/lib/spack/spack/cmd/env.py
+++ b/lib/spack/spack/cmd/env.py
@@ -283,7 +283,7 @@ def env_list(args):
def env_add_setup_parser(subparser):
"""add a spec to an environment"""
subparser.add_argument(
- '-e', '--env', help='add spec to environment with this name')
+ '-e', '--env', help='add spec to this environment')
subparser.add_argument(
'specs', nargs=argparse.REMAINDER, help="spec of the package to add")
@@ -371,7 +371,7 @@ def env_install(args):
env.write()
# install all specs in the environment
- env.install(args)
+ env.install_all(args)
# REMOVE
diff --git a/lib/spack/spack/cmd/install.py b/lib/spack/spack/cmd/install.py
index c1f1d09072..a628ba85c4 100644
--- a/lib/spack/spack/cmd/install.py
+++ b/lib/spack/spack/cmd/install.py
@@ -150,17 +150,27 @@ def default_log_file(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:
if cli_args.things_to_install == 'dependencies':
# Install dependencies as-if they were installed
# for root (explicit=False in the DB)
kwargs['explicit'] = False
for s in spec.dependencies():
- s.package.do_install(**kwargs)
+ install(s, kwargs)
else:
kwargs['explicit'] = True
- spec.package.do_install(**kwargs)
+ install(spec, kwargs)
except spack.build_environment.InstallError as e:
if cli_args.show_log_on_error:
diff --git a/lib/spack/spack/environment.py b/lib/spack/spack/environment.py
index fd21ece9e1..049fdff66d 100644
--- a/lib/spack/spack/environment.py
+++ b/lib/spack/spack/environment.py
@@ -116,9 +116,29 @@ def deactivate():
"""
global active
+
if not active:
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):
"""Get the root directory for an environment by name."""
@@ -333,7 +353,7 @@ class Environment(object):
"""Remove this environment from Spack entirely."""
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
Returns:
@@ -342,6 +362,10 @@ class Environment(object):
"""
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)
if not existing:
@@ -425,7 +449,45 @@ class Environment(object):
# return only the newly concretized 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."""
# Make sure log directory exists
@@ -706,6 +768,12 @@ def prepare_config_scope(env):
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):
"""Superclass for all errors to do with Spack environments.
diff --git a/lib/spack/spack/test/cmd/env.py b/lib/spack/spack/test/cmd/env.py
index 95ab60d569..7b61f11f8b 100644
--- a/lib/spack/spack/test/cmd/env.py
+++ b/lib/spack/spack/test/cmd/env.py
@@ -71,16 +71,29 @@ def test_concretize():
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.add('cmake-client')
e.concretize()
- e.install()
+ e.install_all()
env_specs = e._get_environment_specs()
spec = next(x for x in env_specs if x.name == 'cmake-client')
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():
e = ev.Environment('test')