bugfix: allow relative view paths (#17721)

Relative paths in views have been broken since #17608 or earlier.

- [x] Fix by passing base path of the environment into the `ViewDescriptor`.
      Relative paths are calculated from this path.
This commit is contained in:
Greg Becker 2020-07-27 23:44:56 -07:00 committed by Todd Gamblin
parent 0efb8ef412
commit 24bd9e3039

View File

@ -463,8 +463,9 @@ def _eval_conditional(string):
class ViewDescriptor(object): class ViewDescriptor(object):
def __init__(self, root, projections={}, select=[], exclude=[], def __init__(self, base_path, root, projections={}, select=[], exclude=[],
link=default_view_link): link=default_view_link):
self.base = base_path
self.root = root self.root = root
self.projections = projections self.projections = projections
self.select = select self.select = select
@ -494,15 +495,19 @@ def to_dict(self):
return ret return ret
@staticmethod @staticmethod
def from_dict(d): def from_dict(base_path, d):
return ViewDescriptor(d['root'], return ViewDescriptor(base_path,
d['root'],
d.get('projections', {}), d.get('projections', {}),
d.get('select', []), d.get('select', []),
d.get('exclude', []), d.get('exclude', []),
d.get('link', default_view_link)) d.get('link', default_view_link))
def view(self): def view(self):
return YamlFilesystemView(self.root, spack.store.layout, root = self.root
if not os.path.isabs(root):
root = os.path.normpath(os.path.join(self.base, self.root))
return YamlFilesystemView(root, spack.store.layout,
ignore_conflicts=True, ignore_conflicts=True,
projections=self.projections) projections=self.projections)
@ -548,8 +553,11 @@ def regenerate(self, all_specs, roots):
# that cannot be resolved or have repos that have been removed # that cannot be resolved or have repos that have been removed
# we always regenerate the view from scratch. We must first make # we always regenerate the view from scratch. We must first make
# sure the root directory exists for the very first time though. # sure the root directory exists for the very first time though.
fs.mkdirp(self.root) root = self.root
with fs.replace_directory_transaction(self.root): if not os.path.isabs(root):
root = os.path.normpath(os.path.join(self.base, self.root))
fs.mkdirp(root)
with fs.replace_directory_transaction(root):
view = self.view() view = self.view()
view.clean() view.clean()
@ -609,9 +617,11 @@ def __init__(self, path, init_file=None, with_view=None):
self.views = {} self.views = {}
elif with_view is True: elif with_view is True:
self.views = { self.views = {
default_view_name: ViewDescriptor(self.view_path_default)} default_view_name: ViewDescriptor(self.path,
self.view_path_default)}
elif isinstance(with_view, six.string_types): elif isinstance(with_view, six.string_types):
self.views = {default_view_name: ViewDescriptor(with_view)} self.views = {default_view_name: ViewDescriptor(self.path,
with_view)}
# If with_view is None, then defer to the view settings determined by # If with_view is None, then defer to the view settings determined by
# the manifest file # the manifest file
@ -682,11 +692,14 @@ def _read_manifest(self, f, raw_yaml=None):
# enable_view can be boolean, string, or None # enable_view can be boolean, string, or None
if enable_view is True or enable_view is None: if enable_view is True or enable_view is None:
self.views = { self.views = {
default_view_name: ViewDescriptor(self.view_path_default)} default_view_name: ViewDescriptor(self.path,
self.view_path_default)}
elif isinstance(enable_view, six.string_types): elif isinstance(enable_view, six.string_types):
self.views = {default_view_name: ViewDescriptor(enable_view)} self.views = {default_view_name: ViewDescriptor(self.path,
enable_view)}
elif enable_view: elif enable_view:
self.views = dict((name, ViewDescriptor.from_dict(values)) path = self.path
self.views = dict((name, ViewDescriptor.from_dict(path, values))
for name, values in enable_view.items()) for name, values in enable_view.items())
else: else:
self.views = {} self.views = {}
@ -1120,7 +1133,7 @@ def update_default_view(self, viewpath):
if name in self.views: if name in self.views:
self.default_view.root = viewpath self.default_view.root = viewpath
else: else:
self.views[name] = ViewDescriptor(viewpath) self.views[name] = ViewDescriptor(self.path, viewpath)
else: else:
self.views.pop(name, None) self.views.pop(name, None)
@ -1531,9 +1544,10 @@ def write(self, regenerate_views=True):
default_name = default_view_name default_name = default_view_name
if self.views and len(self.views) == 1 and default_name in self.views: if self.views and len(self.views) == 1 and default_name in self.views:
path = self.default_view.root path = self.default_view.root
if self.default_view == ViewDescriptor(self.view_path_default): if self.default_view == ViewDescriptor(self.path,
self.view_path_default):
view = True view = True
elif self.default_view == ViewDescriptor(path): elif self.default_view == ViewDescriptor(self.path, path):
view = path view = path
else: else:
view = dict((name, view.to_dict()) view = dict((name, view.to_dict())