Always treat DIYStage as expanded (#11663)
DIYStage, used to treat a user-managed directory as a staging area, should always be considered expanded (i.e. the source has been decompressed if it was stored in an archive). This also: * Adds checks to ensure that the path used to instantiate a DIYStage refers to an existing directory. * Adds tests to check the behavior of DIYStage (including behavior added here, but it was generally untested before).
This commit is contained in:
parent
aca1bfdb6a
commit
5cf62e69ce
@ -597,6 +597,12 @@ class DIYStage(object):
|
||||
"""Simple class that allows any directory to be a spack stage."""
|
||||
|
||||
def __init__(self, path):
|
||||
if path is None:
|
||||
raise ValueError("Cannot construct DIYStage without a path.")
|
||||
elif not os.path.isdir(path):
|
||||
raise StagePathError("The stage path directory does not exist:",
|
||||
path)
|
||||
|
||||
self.archive_file = None
|
||||
self.path = path
|
||||
self.source_path = path
|
||||
@ -618,8 +624,13 @@ def check(self):
|
||||
def expand_archive(self):
|
||||
tty.msg("Using source directory: %s" % self.source_path)
|
||||
|
||||
@property
|
||||
def expanded(self):
|
||||
"""Returns True since the source_path must exist."""
|
||||
return True
|
||||
|
||||
def restage(self):
|
||||
tty.die("Cannot restage DIY stage.")
|
||||
raise RestageError("Cannot restage a DIY stage.")
|
||||
|
||||
def create(self):
|
||||
self.created = True
|
||||
@ -650,6 +661,10 @@ class StageError(spack.error.SpackError):
|
||||
""""Superclass for all errors encountered during staging."""
|
||||
|
||||
|
||||
class StagePathError(StageError):
|
||||
""""Error encountered with stage path."""
|
||||
|
||||
|
||||
class RestageError(StageError):
|
||||
""""Error encountered during restaging."""
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
import spack.util.executable
|
||||
|
||||
from spack.resource import Resource
|
||||
from spack.stage import Stage, StageComposite, ResourceStage
|
||||
from spack.stage import Stage, StageComposite, ResourceStage, DIYStage
|
||||
|
||||
# The following values are used for common fetch and stage mocking fixtures:
|
||||
_archive_base = 'test-files'
|
||||
@ -699,3 +699,59 @@ def test_stage_constructor_with_path(self, tmpdir):
|
||||
testpath = str(tmpdir)
|
||||
with Stage('file:///does-not-exist', path=testpath) as stage:
|
||||
assert stage.path == testpath
|
||||
|
||||
def test_diystage_path_none(self):
|
||||
"""Ensure DIYStage for path=None behaves as expected."""
|
||||
with pytest.raises(ValueError):
|
||||
DIYStage(None)
|
||||
|
||||
def test_diystage_path_invalid(self):
|
||||
"""Ensure DIYStage for an invalid path behaves as expected."""
|
||||
with pytest.raises(spack.stage.StagePathError):
|
||||
DIYStage('/path/does/not/exist')
|
||||
|
||||
def test_diystage_path_valid(self, tmpdir):
|
||||
"""Ensure DIYStage for a valid path behaves as expected."""
|
||||
path = str(tmpdir)
|
||||
stage = DIYStage(path)
|
||||
assert stage.path == path
|
||||
assert stage.source_path == path
|
||||
|
||||
# Order doesn't really matter for DIYStage since they are
|
||||
# basically NOOPs; however, call each since they are part
|
||||
# of the normal stage usage and to ensure full test coverage.
|
||||
stage.create() # Only sets the flag value
|
||||
assert stage.created
|
||||
|
||||
stage.cache_local() # Only outputs a message
|
||||
stage.fetch() # Only outputs a message
|
||||
stage.check() # Only outputs a message
|
||||
stage.expand_archive() # Only outputs a message
|
||||
|
||||
assert stage.expanded # The path/source_path does exist
|
||||
|
||||
with pytest.raises(spack.stage.RestageError):
|
||||
stage.restage()
|
||||
|
||||
stage.destroy() # A no-op
|
||||
assert stage.path == path # Ensure can still access attributes
|
||||
assert os.path.exists(stage.source_path) # Ensure path still exists
|
||||
|
||||
def test_diystage_preserve_file(self, tmpdir):
|
||||
"""Ensure DIYStage preserves an existing file."""
|
||||
# Write a file to the temporary directory
|
||||
fn = tmpdir.join(_readme_fn)
|
||||
fn.write(_readme_contents)
|
||||
|
||||
# Instantiate the DIYStage and ensure the above file is unchanged.
|
||||
path = str(tmpdir)
|
||||
stage = DIYStage(path)
|
||||
assert os.path.isdir(path)
|
||||
assert os.path.isfile(str(fn))
|
||||
|
||||
stage.create() # Only sets the flag value
|
||||
|
||||
readmefn = str(fn)
|
||||
assert os.path.isfile(readmefn)
|
||||
with open(readmefn) as _file:
|
||||
_file.read() == _readme_contents
|
||||
|
Loading…
Reference in New Issue
Block a user