From 24bd9e3039367d6eae556daa2f41d57067c6c21f Mon Sep 17 00:00:00 2001 From: Greg Becker Date: Mon, 27 Jul 2020 23:44:56 -0700 Subject: 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. --- lib/spack/spack/environment.py | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/lib/spack/spack/environment.py b/lib/spack/spack/environment.py index 151e73a0fd..99aa3963d5 100644 --- a/lib/spack/spack/environment.py +++ b/lib/spack/spack/environment.py @@ -463,8 +463,9 @@ def _eval_conditional(string): class ViewDescriptor(object): - def __init__(self, root, projections={}, select=[], exclude=[], + def __init__(self, base_path, root, projections={}, select=[], exclude=[], link=default_view_link): + self.base = base_path self.root = root self.projections = projections self.select = select @@ -494,15 +495,19 @@ class ViewDescriptor(object): return ret @staticmethod - def from_dict(d): - return ViewDescriptor(d['root'], + def from_dict(base_path, d): + return ViewDescriptor(base_path, + d['root'], d.get('projections', {}), d.get('select', []), d.get('exclude', []), d.get('link', default_view_link)) 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, projections=self.projections) @@ -548,8 +553,11 @@ class ViewDescriptor(object): # that cannot be resolved or have repos that have been removed # we always regenerate the view from scratch. We must first make # sure the root directory exists for the very first time though. - fs.mkdirp(self.root) - with fs.replace_directory_transaction(self.root): + root = 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.clean() @@ -609,9 +617,11 @@ class Environment(object): self.views = {} elif with_view is True: 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): - 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 # the manifest file @@ -682,11 +692,14 @@ class Environment(object): # enable_view can be boolean, string, or None if enable_view is True or enable_view is None: 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): - self.views = {default_view_name: ViewDescriptor(enable_view)} + self.views = {default_view_name: ViewDescriptor(self.path, + 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()) else: self.views = {} @@ -1120,7 +1133,7 @@ class Environment(object): if name in self.views: self.default_view.root = viewpath else: - self.views[name] = ViewDescriptor(viewpath) + self.views[name] = ViewDescriptor(self.path, viewpath) else: self.views.pop(name, None) @@ -1531,9 +1544,10 @@ class Environment(object): default_name = default_view_name if self.views and len(self.views) == 1 and default_name in self.views: 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 - elif self.default_view == ViewDescriptor(path): + elif self.default_view == ViewDescriptor(self.path, path): view = path else: view = dict((name, view.to_dict()) -- cgit v1.2.3-60-g2f50