summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/spack/test/config.py35
-rw-r--r--lib/spack/spack/util/path.py36
2 files changed, 63 insertions, 8 deletions
diff --git a/lib/spack/spack/test/config.py b/lib/spack/spack/test/config.py
index b5c3dd657b..06cfd018f1 100644
--- a/lib/spack/spack/test/config.py
+++ b/lib/spack/spack/test/config.py
@@ -16,6 +16,7 @@ import pytest
import spack.paths
import spack.config
import spack.main
+import spack.environment
import spack.schema.compilers
import spack.schema.config
import spack.schema.env
@@ -267,7 +268,12 @@ def test_write_list_in_memory(mock_low_high_config):
assert config == repos_high['repos'] + repos_low['repos']
-def test_substitute_config_variables(mock_low_high_config):
+class MockEnv(object):
+ def __init__(self, path):
+ self.path = path
+
+
+def test_substitute_config_variables(mock_low_high_config, monkeypatch):
prefix = spack.paths.prefix.lstrip('/')
assert os.path.join(
@@ -298,6 +304,33 @@ def test_substitute_config_variables(mock_low_high_config):
'/foo/bar/baz', prefix, 'foo/bar/baz'
) != spack_path.canonicalize_path('/foo/bar/baz/${spack/foo/bar/baz/')
+ # $env replacement is a no-op when no environment is active
+ assert spack_path.canonicalize_path(
+ '/foo/bar/baz/$env'
+ ) == '/foo/bar/baz/$env'
+
+ # Fake an active environment and $env is replaced properly
+ fake_env_path = '/quux/quuux'
+ monkeypatch.setattr(spack.environment, 'get_env',
+ lambda x, y: MockEnv(fake_env_path))
+ assert spack_path.canonicalize_path(
+ '$env/foo/bar/baz'
+ ) == os.path.join(fake_env_path, 'foo/bar/baz')
+
+ # relative paths without source information are relative to cwd
+ assert spack_path.canonicalize_path(
+ 'foo/bar/baz'
+ ) == os.path.abspath('foo/bar/baz')
+
+ # relative paths with source information are relative to the file
+ spack.config.set(
+ 'config:module_roots', {'lmod': 'foo/bar/baz'}, scope='low')
+ spack.config.config.clear_caches()
+ path = spack.config.get('config:module_roots:lmod')
+ assert spack_path.canonicalize_path(path) == os.path.normpath(
+ os.path.join(mock_low_high_config.scopes['low'].path,
+ 'foo/bar/baz'))
+
packages_merge_low = {
'packages': {
diff --git a/lib/spack/spack/util/path.py b/lib/spack/spack/util/path.py
index 5e717cbb93..0735133b35 100644
--- a/lib/spack/spack/util/path.py
+++ b/lib/spack/spack/util/path.py
@@ -17,7 +17,7 @@ import llnl.util.tty as tty
from llnl.util.lang import memoized
import spack.paths
-
+import spack.util.spack_yaml as syaml
__all__ = [
'substitute_config_variables',
@@ -72,12 +72,22 @@ def substitute_config_variables(path):
- $spack The Spack instance's prefix
- $user The current user's username
- $tempdir Default temporary directory returned by tempfile.gettempdir()
+ - $env The active Spack environment.
These are substituted case-insensitively into the path, and users can
- use either ``$var`` or ``${var}`` syntax for the variables.
-
+ use either ``$var`` or ``${var}`` syntax for the variables. $env is only
+ replaced if there is an active environment, and should only be used in
+ environment yaml files.
"""
- # Look up replacements for re.sub in the replacements dict.
+ import spack.environment as ev # break circular
+ env = ev.get_env({}, '')
+ if env:
+ replacements.update({'env': env.path})
+ else:
+ # If a previous invocation added env, remove it
+ replacements.pop('env', None)
+
+ # Look up replacements
def repl(match):
m = match.group(0).strip('${}')
return replacements.get(m.lower(), match.group(0))
@@ -132,7 +142,19 @@ def add_padding(path, length):
def canonicalize_path(path):
"""Same as substitute_path_variables, but also take absolute path."""
- path = substitute_path_variables(path)
- path = os.path.abspath(path)
+ # Get file in which path was written in case we need to make it absolute
+ # relative to that path.
+ filename = None
+ if isinstance(path, syaml.syaml_str):
+ filename = os.path.dirname(path._start_mark.name)
+ assert path._start_mark.name == path._end_mark.name
- return path
+ path = substitute_path_variables(path)
+ if not os.path.isabs(path):
+ if filename:
+ path = os.path.join(filename, path)
+ else:
+ path = os.path.abspath(path)
+ tty.debug("Using current working directory as base for abspath")
+
+ return os.path.normpath(path)