Move temp directory configuration to config.yaml
- Moved temp finding logic to spack.stage - Updated stage tests - Added tests for new path substaitution of $user, $spack, $tempdir
This commit is contained in:
parent
9347f86939
commit
0da639298c
@ -31,13 +31,13 @@ config:
|
||||
# You can use $tempdir to refer to the system default temp directory
|
||||
# (as returned by tempfile.gettempdir()).
|
||||
#
|
||||
# A value of $local indicates that Spack should run builds directly
|
||||
# inside its install directory without staging them in temporary space.
|
||||
# A value of $spack/var/spack/stage indicates that Spack should run
|
||||
# builds directly inside its install directory without staging them in
|
||||
# temporary space.
|
||||
build_stage:
|
||||
- /usr/workspace/*/%u
|
||||
- $tempdir
|
||||
- /nfs/tmp2/%u
|
||||
- $local
|
||||
- /nfs/tmp2/$user
|
||||
- $spack/var/spack/stage
|
||||
|
||||
|
||||
# Cache directory already downloaded source tarballs and archived
|
||||
|
@ -25,7 +25,6 @@
|
||||
import collections
|
||||
import errno
|
||||
import fileinput
|
||||
import getpass
|
||||
import glob
|
||||
import numbers
|
||||
import os
|
||||
@ -46,7 +45,6 @@
|
||||
'can_access',
|
||||
'change_sed_delimiter',
|
||||
'copy_mode',
|
||||
'expand_user',
|
||||
'filter_file',
|
||||
'find_libraries',
|
||||
'fix_darwin_install_name',
|
||||
@ -229,16 +227,6 @@ def is_exe(path):
|
||||
return os.path.isfile(path) and os.access(path, os.X_OK)
|
||||
|
||||
|
||||
def expand_user(path):
|
||||
"""Find instances of '%u' in a path and replace with the current user's
|
||||
username."""
|
||||
username = getpass.getuser()
|
||||
if not username and '%u' in path:
|
||||
tty.die("Couldn't get username to complete path '%s'" % path)
|
||||
|
||||
return path.replace('%u', username)
|
||||
|
||||
|
||||
def mkdirp(*paths):
|
||||
"""Creates a directory, as well as parent directories if needed."""
|
||||
for path in paths:
|
||||
|
@ -119,27 +119,6 @@
|
||||
# certifiates. e.g., curl should use the -k option.
|
||||
insecure = False
|
||||
|
||||
# Whether to build in tmp space or directly in the stage_path.
|
||||
# If this is true, then spack will make stage directories in
|
||||
# a tmp filesystem, and it will symlink them into stage_path.
|
||||
use_tmp_stage = True
|
||||
|
||||
# Locations to use for staging and building, in order of preference
|
||||
# Use a %u to add a username to the stage paths here, in case this
|
||||
# is a shared filesystem. Spack will use the first of these paths
|
||||
# that it can create.
|
||||
tmp_dirs = []
|
||||
_default_tmp = tempfile.gettempdir()
|
||||
_tmp_user = getpass.getuser()
|
||||
|
||||
_tmp_candidates = (_default_tmp, '/nfs/tmp2', '/tmp', '/var/tmp')
|
||||
for path in _tmp_candidates:
|
||||
# don't add a second username if it's already unique by user.
|
||||
if _tmp_user not in path:
|
||||
tmp_dirs.append(join_path(path, '%u', 'spack-stage'))
|
||||
else:
|
||||
tmp_dirs.append(join_path(path, 'spack-stage'))
|
||||
|
||||
# Whether spack should allow installation of unsafe versions of
|
||||
# software. "Unsafe" versions are ones it doesn't have a checksum
|
||||
# for.
|
||||
|
@ -44,6 +44,7 @@
|
||||
import spack.error
|
||||
import spack.spec
|
||||
from spack.provider_index import ProviderIndex
|
||||
from spack.util.path import canonicalize_path
|
||||
from spack.util.naming import *
|
||||
|
||||
#
|
||||
@ -93,19 +94,6 @@ def __getattr__(self, name):
|
||||
return getattr(self, name)
|
||||
|
||||
|
||||
def substitute_spack_prefix(path):
|
||||
"""Replaces instances of $spack with Spack's prefix."""
|
||||
return re.sub(r'^\$spack', spack.prefix, path)
|
||||
|
||||
|
||||
def canonicalize_path(path):
|
||||
"""Substitute $spack, expand user home, take abspath."""
|
||||
path = substitute_spack_prefix(path)
|
||||
path = os.path.expanduser(path)
|
||||
path = os.path.abspath(path)
|
||||
return path
|
||||
|
||||
|
||||
class RepoPath(object):
|
||||
"""A RepoPath is a list of repos that function as one.
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
import hashlib
|
||||
import shutil
|
||||
import tempfile
|
||||
import getpass
|
||||
from urlparse import urljoin
|
||||
|
||||
import llnl.util.tty as tty
|
||||
@ -41,9 +42,72 @@
|
||||
import spack.fetch_strategy as fs
|
||||
import spack.error
|
||||
from spack.version import *
|
||||
from spack.util.path import canonicalize_path
|
||||
from spack.util.crypto import prefix_bits, bit_length
|
||||
|
||||
STAGE_PREFIX = 'spack-stage-'
|
||||
_stage_prefix = 'spack-stage-'
|
||||
|
||||
|
||||
def _first_accessible_path(paths):
|
||||
"""Find a tmp dir that exists that we can access."""
|
||||
for path in paths:
|
||||
try:
|
||||
# try to create the path if it doesn't exist.
|
||||
path = canonicalize_path(path)
|
||||
mkdirp(path)
|
||||
|
||||
# ensure accessible
|
||||
if not can_access(path):
|
||||
continue
|
||||
|
||||
# return it if successful.
|
||||
return path
|
||||
|
||||
except OSError:
|
||||
tty.debug('OSError while checking temporary path: %s' % path)
|
||||
continue
|
||||
|
||||
return None
|
||||
|
||||
|
||||
# cached temporary root
|
||||
_tmp_root = None
|
||||
_use_tmp_stage = True
|
||||
|
||||
|
||||
def get_tmp_root():
|
||||
global _tmp_root, _use_tmp_stage
|
||||
|
||||
if not _use_tmp_stage:
|
||||
return None
|
||||
|
||||
if _tmp_root is None:
|
||||
config = spack.config.get_config('config')
|
||||
candidates = config['build_stage']
|
||||
if isinstance(candidates, basestring):
|
||||
candidates = [candidates]
|
||||
|
||||
path = _first_accessible_path(candidates)
|
||||
if not path:
|
||||
raise StageError("No accessible stage paths in %s", candidates)
|
||||
|
||||
# Return None to indicate we're using a local staging area.
|
||||
if path == canonicalize_path(spack.stage_path):
|
||||
_use_tmp_stage = False
|
||||
return None
|
||||
|
||||
# ensure that any temp path is unique per user, so users don't
|
||||
# fight over shared temporary space.
|
||||
user = getpass.getuser()
|
||||
if user not in path:
|
||||
path = os.path.join(path, user, 'spack-stage')
|
||||
else:
|
||||
path = os.path.join(path, 'spack-stage')
|
||||
|
||||
mkdirp(path)
|
||||
_tmp_root = path
|
||||
|
||||
return _tmp_root
|
||||
|
||||
|
||||
class Stage(object):
|
||||
@ -141,9 +205,8 @@ def __init__(
|
||||
# TODO : won't be the same as the temporary stage area in tmp_root
|
||||
self.name = name
|
||||
if name is None:
|
||||
self.name = STAGE_PREFIX + next(tempfile._get_candidate_names())
|
||||
self.name = _stage_prefix + next(tempfile._get_candidate_names())
|
||||
self.mirror_path = mirror_path
|
||||
self.tmp_root = find_tmp_root()
|
||||
|
||||
# Try to construct here a temporary name for the stage directory
|
||||
# If this is a named stage, then construct a named path.
|
||||
@ -217,10 +280,11 @@ def _need_to_create_path(self):
|
||||
|
||||
# Path looks ok, but need to check the target of the link.
|
||||
if os.path.islink(self.path):
|
||||
tmp_root = get_tmp_root()
|
||||
if tmp_root is not None:
|
||||
real_path = os.path.realpath(self.path)
|
||||
real_tmp = os.path.realpath(self.tmp_root)
|
||||
real_tmp = os.path.realpath(tmp_root)
|
||||
|
||||
if spack.use_tmp_stage:
|
||||
# If we're using a tmp dir, it's a link, and it points at the
|
||||
# right spot, then keep it.
|
||||
if (real_path.startswith(real_tmp) and
|
||||
@ -416,11 +480,11 @@ def chdir_to_source(self):
|
||||
"""
|
||||
path = self.source_path
|
||||
if not path:
|
||||
tty.die("Attempt to chdir before expanding archive.")
|
||||
raise StageError("Attempt to chdir before expanding archive.")
|
||||
else:
|
||||
os.chdir(path)
|
||||
if not os.listdir(path):
|
||||
tty.die("Archive was empty for %s" % self.name)
|
||||
raise StageError("Archive was empty for %s" % self.name)
|
||||
|
||||
def restage(self):
|
||||
"""Removes the expanded archive path if it exists, then re-expands
|
||||
@ -429,17 +493,17 @@ def restage(self):
|
||||
self.fetcher.reset()
|
||||
|
||||
def create(self):
|
||||
"""
|
||||
Creates the stage directory
|
||||
"""Creates the stage directory.
|
||||
|
||||
If self.tmp_root evaluates to False, the stage directory is
|
||||
created directly under spack.stage_path, otherwise this will
|
||||
attempt to create a stage in a temporary directory and link it
|
||||
into spack.stage_path.
|
||||
If get_tmp_root() is None, the stage directory is created
|
||||
directly under spack.stage_path, otherwise this will attempt to
|
||||
create a stage in a temporary directory and link it into
|
||||
spack.stage_path.
|
||||
|
||||
Spack will use the first writable location in spack.tmp_dirs
|
||||
to create a stage. If there is no valid location in tmp_dirs,
|
||||
fall back to making the stage inside spack.stage_path.
|
||||
|
||||
"""
|
||||
# Create the top-level stage directory
|
||||
mkdirp(spack.stage_path)
|
||||
@ -448,8 +512,10 @@ def create(self):
|
||||
# If a tmp_root exists then create a directory there and then link it
|
||||
# in the stage area, otherwise create the stage directory in self.path
|
||||
if self._need_to_create_path():
|
||||
if self.tmp_root:
|
||||
tmp_dir = tempfile.mkdtemp('', STAGE_PREFIX, self.tmp_root)
|
||||
tmp_root = get_tmp_root()
|
||||
if tmp_root is not None:
|
||||
tmp_dir = tempfile.mkdtemp('', _stage_prefix, tmp_root)
|
||||
tty.debug('link %s -> %s' % (self.path, tmp_dir))
|
||||
os.symlink(tmp_dir, self.path)
|
||||
else:
|
||||
mkdirp(self.path)
|
||||
@ -614,25 +680,6 @@ def purge():
|
||||
remove_linked_tree(stage_path)
|
||||
|
||||
|
||||
def find_tmp_root():
|
||||
if spack.use_tmp_stage:
|
||||
for tmp in spack.tmp_dirs:
|
||||
try:
|
||||
# Replace %u with username
|
||||
expanded = expand_user(tmp)
|
||||
|
||||
# try to create a directory for spack stuff
|
||||
mkdirp(expanded)
|
||||
|
||||
# return it if successful.
|
||||
return expanded
|
||||
|
||||
except OSError:
|
||||
continue
|
||||
|
||||
return None
|
||||
|
||||
|
||||
class StageError(spack.error.SpackError):
|
||||
""""Superclass for all errors encountered during staging."""
|
||||
|
||||
|
@ -24,10 +24,12 @@
|
||||
##############################################################################
|
||||
import os
|
||||
import shutil
|
||||
import getpass
|
||||
from tempfile import mkdtemp
|
||||
|
||||
import spack
|
||||
import spack.config
|
||||
from spack.util.path import canonicalize_path
|
||||
from ordereddict_backport import OrderedDict
|
||||
from spack.test.mock_packages_test import *
|
||||
|
||||
@ -217,3 +219,53 @@ def test_write_to_same_priority_file(self):
|
||||
# Same check again, to ensure consistency.
|
||||
self.check_config(a_comps, *self.a_comp_specs)
|
||||
self.check_config(b_comps, *self.b_comp_specs)
|
||||
|
||||
def check_canonical(self, var, expected):
|
||||
"""ensure things are substituted properly and canonicalized."""
|
||||
path = '/foo/bar/baz'
|
||||
|
||||
self.assertEqual(canonicalize_path(var + path),
|
||||
expected + path)
|
||||
|
||||
self.assertEqual(canonicalize_path(path + var),
|
||||
path + '/' + expected)
|
||||
|
||||
self.assertEqual(canonicalize_path(path + var + path),
|
||||
expected + path)
|
||||
|
||||
def test_substitute_config_variables(self):
|
||||
prefix = spack.prefix.lstrip('/')
|
||||
|
||||
self.assertEqual(os.path.join('/foo/bar/baz', prefix),
|
||||
canonicalize_path('/foo/bar/baz/$spack'))
|
||||
|
||||
self.assertEqual(os.path.join(spack.prefix, 'foo/bar/baz'),
|
||||
canonicalize_path('$spack/foo/bar/baz/'))
|
||||
|
||||
self.assertEqual(os.path.join('/foo/bar/baz', prefix, 'foo/bar/baz'),
|
||||
canonicalize_path('/foo/bar/baz/$spack/foo/bar/baz/'))
|
||||
|
||||
self.assertEqual(os.path.join('/foo/bar/baz', prefix),
|
||||
canonicalize_path('/foo/bar/baz/${spack}'))
|
||||
|
||||
self.assertEqual(os.path.join(spack.prefix, 'foo/bar/baz'),
|
||||
canonicalize_path('${spack}/foo/bar/baz/'))
|
||||
|
||||
self.assertEqual(
|
||||
os.path.join('/foo/bar/baz', prefix, 'foo/bar/baz'),
|
||||
canonicalize_path('/foo/bar/baz/${spack}/foo/bar/baz/'))
|
||||
|
||||
self.assertNotEqual(
|
||||
os.path.join('/foo/bar/baz', prefix, 'foo/bar/baz'),
|
||||
canonicalize_path('/foo/bar/baz/${spack/foo/bar/baz/'))
|
||||
|
||||
def test_substitute_user(self):
|
||||
user = getpass.getuser()
|
||||
self.assertEqual('/foo/bar/' + user + '/baz',
|
||||
canonicalize_path('/foo/bar/$user/baz'))
|
||||
|
||||
def test_substitute_tempdir(self):
|
||||
tempdir = tempfile.gettempdir()
|
||||
self.assertEqual(tempdir, canonicalize_path('$tempdir'))
|
||||
self.assertEqual(tempdir + '/foo/bar/baz',
|
||||
canonicalize_path('$tempdir/foo/bar/baz'))
|
||||
|
@ -180,6 +180,27 @@
|
||||
externalmodule@1.0%gcc@4.5.0: external-module
|
||||
"""
|
||||
|
||||
mock_config = """\
|
||||
config:
|
||||
install_tree: $spack/opt/spack
|
||||
build_stage:
|
||||
- $tempdir
|
||||
- /nfs/tmp2/$user
|
||||
- $spack/var/spack/stage
|
||||
source_cache: $spack/var/spack/cache
|
||||
misc_cache: ~/.spack/cache
|
||||
verify_ssl: true
|
||||
checksum: true
|
||||
dirty: false
|
||||
"""
|
||||
|
||||
# these are written out to mock config files.
|
||||
mock_configs = {
|
||||
'config.yaml': mock_config,
|
||||
'compilers.yaml': mock_compiler_config,
|
||||
'packages.yaml': mock_packages_config,
|
||||
}
|
||||
|
||||
|
||||
class MockPackagesTest(unittest.TestCase):
|
||||
|
||||
@ -199,11 +220,10 @@ def initmock(self):
|
||||
self.mock_user_config = os.path.join(self.temp_config, 'user')
|
||||
mkdirp(self.mock_site_config)
|
||||
mkdirp(self.mock_user_config)
|
||||
for confs in [('compilers.yaml', mock_compiler_config),
|
||||
('packages.yaml', mock_packages_config)]:
|
||||
conf_yaml = os.path.join(self.mock_site_config, confs[0])
|
||||
for filename, data in mock_configs.items():
|
||||
conf_yaml = os.path.join(self.mock_site_config, filename)
|
||||
with open(conf_yaml, 'w') as f:
|
||||
f.write(confs[1])
|
||||
f.write(data)
|
||||
|
||||
# TODO: Mocking this up is kind of brittle b/c ConfigScope
|
||||
# TODO: constructor modifies config_scopes. Make it cleaner.
|
||||
|
@ -27,64 +27,71 @@
|
||||
"""
|
||||
import os
|
||||
import shutil
|
||||
import unittest
|
||||
import tempfile
|
||||
from contextlib import *
|
||||
|
||||
import spack
|
||||
import spack.stage
|
||||
from llnl.util.filesystem import *
|
||||
from spack.stage import Stage
|
||||
from spack.util.executable import which
|
||||
from spack.test.mock_packages_test import *
|
||||
|
||||
test_files_dir = os.path.realpath(join_path(spack.stage_path, '.test'))
|
||||
test_tmp_path = os.path.realpath(join_path(test_files_dir, 'tmp'))
|
||||
|
||||
archive_dir = 'test-files'
|
||||
archive_name = archive_dir + '.tar.gz'
|
||||
archive_dir_path = join_path(test_files_dir, archive_dir)
|
||||
archive_url = 'file://' + join_path(test_files_dir, archive_name)
|
||||
readme_name = 'README.txt'
|
||||
test_readme = join_path(archive_dir_path, readme_name)
|
||||
readme_text = "hello world!\n"
|
||||
|
||||
stage_name = 'spack-test-stage'
|
||||
_test_tmp_path = None
|
||||
|
||||
|
||||
@contextmanager
|
||||
def use_tmp(use_tmp):
|
||||
"""Allow some test code to be executed with spack.use_tmp_stage
|
||||
set to a certain value. Context manager makes sure it's reset
|
||||
on failure.
|
||||
"""Allow some test code to be executed such that spack will either use or
|
||||
not use temporary space for stages.
|
||||
"""
|
||||
old_tmp = spack.use_tmp_stage
|
||||
spack.use_tmp_stage = use_tmp
|
||||
# mock up config
|
||||
path = _test_tmp_path if use_tmp else spack.stage_path
|
||||
spack.config.update_config(
|
||||
'config', {'build_stage': [path]}, scope='user')
|
||||
yield
|
||||
spack.use_tmp_stage = old_tmp
|
||||
|
||||
|
||||
class StageTest(unittest.TestCase):
|
||||
class StageTest(MockPackagesTest):
|
||||
|
||||
def setUp(self):
|
||||
"""This sets up a mock archive to fetch, and a mock temp space for use
|
||||
by the Stage class. It doesn't actually create the Stage -- that
|
||||
is done by individual tests.
|
||||
"""
|
||||
if os.path.exists(test_files_dir):
|
||||
shutil.rmtree(test_files_dir)
|
||||
global _test_tmp_path
|
||||
|
||||
self.test_files_dir = tempfile.mkdtemp()
|
||||
self.test_tmp_path = os.path.realpath(
|
||||
os.path.join(self.test_files_dir, 'tmp'))
|
||||
_test_tmp_path = self.test_tmp_path
|
||||
|
||||
self.archive_dir = 'test-files'
|
||||
self.archive_name = self.archive_dir + '.tar.gz'
|
||||
archive_dir_path = os.path.join(self.test_files_dir,
|
||||
self.archive_dir)
|
||||
self.archive_url = 'file://' + os.path.join(self.test_files_dir,
|
||||
self.archive_name)
|
||||
test_readme = join_path(archive_dir_path, 'README.txt')
|
||||
self.readme_text = "hello world!\n"
|
||||
|
||||
self.stage_name = 'spack-test-stage'
|
||||
|
||||
mkdirp(test_files_dir)
|
||||
mkdirp(archive_dir_path)
|
||||
mkdirp(test_tmp_path)
|
||||
mkdirp(self.test_tmp_path)
|
||||
|
||||
with open(test_readme, 'w') as readme:
|
||||
readme.write(readme_text)
|
||||
readme.write(self.readme_text)
|
||||
|
||||
with working_dir(test_files_dir):
|
||||
tar = which('tar')
|
||||
tar('czf', archive_name, archive_dir)
|
||||
with working_dir(self.test_files_dir):
|
||||
tar = which('tar', required=True)
|
||||
tar('czf', self.archive_name, self.archive_dir)
|
||||
|
||||
# Make spack use the test environment for tmp stuff.
|
||||
self.old_tmp_dirs = spack.tmp_dirs
|
||||
spack.tmp_dirs = [test_tmp_path]
|
||||
self._old_tmp_root = spack.stage._tmp_root
|
||||
self._old_use_tmp_stage = spack.stage._use_tmp_stage
|
||||
spack.stage._tmp_root = None
|
||||
spack.stage._use_tmp_stage = True
|
||||
|
||||
# record this since this test changes to directories that will
|
||||
# be removed.
|
||||
@ -92,13 +99,14 @@ def setUp(self):
|
||||
|
||||
def tearDown(self):
|
||||
"""Blows away the test environment directory."""
|
||||
shutil.rmtree(test_files_dir)
|
||||
shutil.rmtree(self.test_files_dir, ignore_errors=True)
|
||||
|
||||
# chdir back to original working dir
|
||||
os.chdir(self.working_dir)
|
||||
|
||||
# restore spack's original tmp environment
|
||||
spack.tmp_dirs = self.old_tmp_dirs
|
||||
spack.stage._tmp_root = self._old_tmp_root
|
||||
spack.stage._use_tmp_stage = self._old_use_tmp_stage
|
||||
|
||||
def get_stage_path(self, stage, stage_name):
|
||||
"""Figure out where a stage should be living. This depends on
|
||||
@ -120,7 +128,7 @@ def check_setup(self, stage, stage_name):
|
||||
# Ensure stage was created in the spack stage directory
|
||||
self.assertTrue(os.path.isdir(stage_path))
|
||||
|
||||
if spack.use_tmp_stage:
|
||||
if spack.stage.get_tmp_root():
|
||||
# Check that the stage dir is really a symlink.
|
||||
self.assertTrue(os.path.islink(stage_path))
|
||||
|
||||
@ -131,7 +139,7 @@ def check_setup(self, stage, stage_name):
|
||||
|
||||
# Make sure the directory is in the place we asked it to
|
||||
# be (see setUp and tearDown)
|
||||
self.assertTrue(target.startswith(test_tmp_path))
|
||||
self.assertTrue(target.startswith(self.test_tmp_path))
|
||||
|
||||
else:
|
||||
# Make sure the stage path is NOT a link for a non-tmp stage
|
||||
@ -139,24 +147,24 @@ def check_setup(self, stage, stage_name):
|
||||
|
||||
def check_fetch(self, stage, stage_name):
|
||||
stage_path = self.get_stage_path(stage, stage_name)
|
||||
self.assertTrue(archive_name in os.listdir(stage_path))
|
||||
self.assertEqual(join_path(stage_path, archive_name),
|
||||
self.assertTrue(self.archive_name in os.listdir(stage_path))
|
||||
self.assertEqual(join_path(stage_path, self.archive_name),
|
||||
stage.fetcher.archive_file)
|
||||
|
||||
def check_expand_archive(self, stage, stage_name):
|
||||
stage_path = self.get_stage_path(stage, stage_name)
|
||||
self.assertTrue(archive_name in os.listdir(stage_path))
|
||||
self.assertTrue(archive_dir in os.listdir(stage_path))
|
||||
self.assertTrue(self.archive_name in os.listdir(stage_path))
|
||||
self.assertTrue(self.archive_dir in os.listdir(stage_path))
|
||||
|
||||
self.assertEqual(
|
||||
join_path(stage_path, archive_dir),
|
||||
join_path(stage_path, self.archive_dir),
|
||||
stage.source_path)
|
||||
|
||||
readme = join_path(stage_path, archive_dir, readme_name)
|
||||
readme = join_path(stage_path, self.archive_dir, 'README.txt')
|
||||
self.assertTrue(os.path.isfile(readme))
|
||||
|
||||
with open(readme) as file:
|
||||
self.assertEqual(readme_text, file.read())
|
||||
self.assertEqual(self.readme_text, file.read())
|
||||
|
||||
def check_chdir(self, stage, stage_name):
|
||||
stage_path = self.get_stage_path(stage, stage_name)
|
||||
@ -165,7 +173,7 @@ def check_chdir(self, stage, stage_name):
|
||||
def check_chdir_to_source(self, stage, stage_name):
|
||||
stage_path = self.get_stage_path(stage, stage_name)
|
||||
self.assertEqual(
|
||||
join_path(os.path.realpath(stage_path), archive_dir),
|
||||
join_path(os.path.realpath(stage_path), self.archive_dir),
|
||||
os.getcwd())
|
||||
|
||||
def check_destroy(self, stage, stage_name):
|
||||
@ -176,76 +184,76 @@ def check_destroy(self, stage, stage_name):
|
||||
self.assertFalse(os.path.exists(stage_path))
|
||||
|
||||
# tmp stage needs to remove tmp dir too.
|
||||
if spack.use_tmp_stage:
|
||||
if spack.stage._use_tmp_stage:
|
||||
target = os.path.realpath(stage_path)
|
||||
self.assertFalse(os.path.exists(target))
|
||||
|
||||
def test_setup_and_destroy_name_with_tmp(self):
|
||||
with use_tmp(True):
|
||||
with Stage(archive_url, name=stage_name) as stage:
|
||||
self.check_setup(stage, stage_name)
|
||||
self.check_destroy(stage, stage_name)
|
||||
with Stage(self.archive_url, name=self.stage_name) as stage:
|
||||
self.check_setup(stage, self.stage_name)
|
||||
self.check_destroy(stage, self.stage_name)
|
||||
|
||||
def test_setup_and_destroy_name_without_tmp(self):
|
||||
with use_tmp(False):
|
||||
with Stage(archive_url, name=stage_name) as stage:
|
||||
self.check_setup(stage, stage_name)
|
||||
self.check_destroy(stage, stage_name)
|
||||
with Stage(self.archive_url, name=self.stage_name) as stage:
|
||||
self.check_setup(stage, self.stage_name)
|
||||
self.check_destroy(stage, self.stage_name)
|
||||
|
||||
def test_setup_and_destroy_no_name_with_tmp(self):
|
||||
with use_tmp(True):
|
||||
with Stage(archive_url) as stage:
|
||||
with Stage(self.archive_url) as stage:
|
||||
self.check_setup(stage, None)
|
||||
self.check_destroy(stage, None)
|
||||
|
||||
def test_setup_and_destroy_no_name_without_tmp(self):
|
||||
with use_tmp(False):
|
||||
with Stage(archive_url) as stage:
|
||||
with Stage(self.archive_url) as stage:
|
||||
self.check_setup(stage, None)
|
||||
self.check_destroy(stage, None)
|
||||
|
||||
def test_chdir(self):
|
||||
with Stage(archive_url, name=stage_name) as stage:
|
||||
with Stage(self.archive_url, name=self.stage_name) as stage:
|
||||
stage.chdir()
|
||||
self.check_setup(stage, stage_name)
|
||||
self.check_chdir(stage, stage_name)
|
||||
self.check_destroy(stage, stage_name)
|
||||
self.check_setup(stage, self.stage_name)
|
||||
self.check_chdir(stage, self.stage_name)
|
||||
self.check_destroy(stage, self.stage_name)
|
||||
|
||||
def test_fetch(self):
|
||||
with Stage(archive_url, name=stage_name) as stage:
|
||||
with Stage(self.archive_url, name=self.stage_name) as stage:
|
||||
stage.fetch()
|
||||
self.check_setup(stage, stage_name)
|
||||
self.check_chdir(stage, stage_name)
|
||||
self.check_fetch(stage, stage_name)
|
||||
self.check_destroy(stage, stage_name)
|
||||
self.check_setup(stage, self.stage_name)
|
||||
self.check_chdir(stage, self.stage_name)
|
||||
self.check_fetch(stage, self.stage_name)
|
||||
self.check_destroy(stage, self.stage_name)
|
||||
|
||||
def test_expand_archive(self):
|
||||
with Stage(archive_url, name=stage_name) as stage:
|
||||
with Stage(self.archive_url, name=self.stage_name) as stage:
|
||||
stage.fetch()
|
||||
self.check_setup(stage, stage_name)
|
||||
self.check_fetch(stage, stage_name)
|
||||
self.check_setup(stage, self.stage_name)
|
||||
self.check_fetch(stage, self.stage_name)
|
||||
stage.expand_archive()
|
||||
self.check_expand_archive(stage, stage_name)
|
||||
self.check_destroy(stage, stage_name)
|
||||
self.check_expand_archive(stage, self.stage_name)
|
||||
self.check_destroy(stage, self.stage_name)
|
||||
|
||||
def test_expand_archive_with_chdir(self):
|
||||
with Stage(archive_url, name=stage_name) as stage:
|
||||
with Stage(self.archive_url, name=self.stage_name) as stage:
|
||||
stage.fetch()
|
||||
self.check_setup(stage, stage_name)
|
||||
self.check_fetch(stage, stage_name)
|
||||
self.check_setup(stage, self.stage_name)
|
||||
self.check_fetch(stage, self.stage_name)
|
||||
stage.expand_archive()
|
||||
stage.chdir_to_source()
|
||||
self.check_expand_archive(stage, stage_name)
|
||||
self.check_chdir_to_source(stage, stage_name)
|
||||
self.check_destroy(stage, stage_name)
|
||||
self.check_expand_archive(stage, self.stage_name)
|
||||
self.check_chdir_to_source(stage, self.stage_name)
|
||||
self.check_destroy(stage, self.stage_name)
|
||||
|
||||
def test_restage(self):
|
||||
with Stage(archive_url, name=stage_name) as stage:
|
||||
with Stage(self.archive_url, name=self.stage_name) as stage:
|
||||
stage.fetch()
|
||||
stage.expand_archive()
|
||||
stage.chdir_to_source()
|
||||
self.check_expand_archive(stage, stage_name)
|
||||
self.check_chdir_to_source(stage, stage_name)
|
||||
self.check_expand_archive(stage, self.stage_name)
|
||||
self.check_chdir_to_source(stage, self.stage_name)
|
||||
|
||||
# Try to make a file in the old archive dir
|
||||
with open('foobar', 'w') as file:
|
||||
@ -255,40 +263,44 @@ def test_restage(self):
|
||||
|
||||
# Make sure the file is not there after restage.
|
||||
stage.restage()
|
||||
self.check_chdir(stage, stage_name)
|
||||
self.check_fetch(stage, stage_name)
|
||||
self.check_chdir(stage, self.stage_name)
|
||||
self.check_fetch(stage, self.stage_name)
|
||||
stage.chdir_to_source()
|
||||
self.check_chdir_to_source(stage, stage_name)
|
||||
self.check_chdir_to_source(stage, self.stage_name)
|
||||
self.assertFalse('foobar' in os.listdir(stage.source_path))
|
||||
self.check_destroy(stage, stage_name)
|
||||
self.check_destroy(stage, self.stage_name)
|
||||
|
||||
def test_no_keep_without_exceptions(self):
|
||||
with Stage(archive_url, name=stage_name, keep=False) as stage:
|
||||
with Stage(self.archive_url,
|
||||
name=self.stage_name, keep=False) as stage:
|
||||
pass
|
||||
self.check_destroy(stage, stage_name)
|
||||
self.check_destroy(stage, self.stage_name)
|
||||
|
||||
def test_keep_without_exceptions(self):
|
||||
with Stage(archive_url, name=stage_name, keep=True) as stage:
|
||||
with Stage(self.archive_url,
|
||||
name=self.stage_name, keep=True) as stage:
|
||||
pass
|
||||
path = self.get_stage_path(stage, stage_name)
|
||||
path = self.get_stage_path(stage, self.stage_name)
|
||||
self.assertTrue(os.path.isdir(path))
|
||||
|
||||
def test_no_keep_with_exceptions(self):
|
||||
try:
|
||||
with Stage(archive_url, name=stage_name, keep=False) as stage:
|
||||
with Stage(self.archive_url,
|
||||
name=self.stage_name, keep=False) as stage:
|
||||
raise Exception()
|
||||
|
||||
path = self.get_stage_path(stage, stage_name)
|
||||
path = self.get_stage_path(stage, self.stage_name)
|
||||
self.assertTrue(os.path.isdir(path))
|
||||
except:
|
||||
pass # ignore here.
|
||||
|
||||
def test_keep_exceptions(self):
|
||||
try:
|
||||
with Stage(archive_url, name=stage_name, keep=True) as stage:
|
||||
with Stage(self.archive_url,
|
||||
name=self.stage_name, keep=True) as stage:
|
||||
raise Exception()
|
||||
|
||||
path = self.get_stage_path(stage, stage_name)
|
||||
path = self.get_stage_path(stage, self.stage_name)
|
||||
self.assertTrue(os.path.isdir(path))
|
||||
except:
|
||||
pass # ignore here.
|
||||
|
68
lib/spack/spack/util/path.py
Normal file
68
lib/spack/spack/util/path.py
Normal file
@ -0,0 +1,68 @@
|
||||
##############################################################################
|
||||
# Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC.
|
||||
# Produced at the Lawrence Livermore National Laboratory.
|
||||
#
|
||||
# This file is part of Spack.
|
||||
# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
|
||||
# LLNL-CODE-647188
|
||||
#
|
||||
# For details, see https://github.com/llnl/spack
|
||||
# Please also see the LICENSE file for our notice and the LGPL.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License (as
|
||||
# published by the Free Software Foundation) version 2.1, February 1999.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and
|
||||
# conditions of the GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
##############################################################################
|
||||
"""Utilities for managing paths in Spack.
|
||||
"""
|
||||
import os
|
||||
import re
|
||||
import spack
|
||||
import getpass
|
||||
import tempfile
|
||||
|
||||
__all__ = [
|
||||
'substitute_config_variables',
|
||||
'canonicalize_path']
|
||||
|
||||
# Substitutions to perform
|
||||
replacements = {
|
||||
'spack': spack.prefix,
|
||||
'user': getpass.getuser(),
|
||||
'tempdir': tempfile.gettempdir(),
|
||||
}
|
||||
|
||||
|
||||
def substitute_config_variables(path):
|
||||
"""Substitute placeholders into paths.
|
||||
|
||||
Spack allows paths in configs to have some placeholders, as follows:
|
||||
|
||||
- $spack The Spack instance's prefix
|
||||
- $user The current user's username
|
||||
- $tempdir Default temporary directory returned by tempfile.gettempdir()
|
||||
"""
|
||||
# Look up replacements for re.sub in the replacements dict.
|
||||
def repl(match):
|
||||
m = match.group(0).strip('${}')
|
||||
return replacements.get(m, match.group(0))
|
||||
|
||||
# Replace $var or ${var}.
|
||||
return re.sub(r'(\$\w+\b|\$\{\w+\})', repl, path)
|
||||
|
||||
|
||||
def canonicalize_path(path):
|
||||
"""Substitute $spack, expand user home, take abspath."""
|
||||
path = substitute_config_variables(path)
|
||||
path = os.path.expanduser(path)
|
||||
path = os.path.abspath(path)
|
||||
return path
|
Loading…
Reference in New Issue
Block a user