summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTristan Van Berkom <tristan.vanberkom@codethink.co.uk>2018-04-10 17:32:22 +0900
committerTristan Van Berkom <tristan.vanberkom@codethink.co.uk>2018-04-10 21:01:55 +0900
commitbe6b353de6ea3d3890289fbe7a4b3d462d3ac823 (patch)
treeff2e8cadf016f8df117b938478b813d9d00f46f6
parent8da99651123c6e4d37491c4d650394c5748f7ae8 (diff)
downloadbuildstream-be6b353de6ea3d3890289fbe7a4b3d462d3ac823.tar.gz
_workspaces.py: Remove knowledge of Elements completely
This makes workspaces more cleanly separated from everything else. o Removed some methods from Workspace() o Added Element._open_workspace() to initialize workspaces on sources o Cleanup some code in the pipeline o Have the App() call Element._open_workspace() instead of Workspace.open()
-rw-r--r--buildstream/_frontend/app.py4
-rw-r--r--buildstream/_pipeline.py25
-rw-r--r--buildstream/_workspaces.py70
-rw-r--r--buildstream/element.py16
4 files changed, 50 insertions, 65 deletions
diff --git a/buildstream/_frontend/app.py b/buildstream/_frontend/app.py
index 14a8201d9..2d5842c32 100644
--- a/buildstream/_frontend/app.py
+++ b/buildstream/_frontend/app.py
@@ -427,14 +427,14 @@ class App():
except OSError as e:
raise AppError("Failed to create workspace directory: {}".format(e)) from e
- workspace = self.project.workspaces.create_workspace(target, workdir)
+ workspace = self.project.workspaces.create_workspace(target.name, workdir)
if not no_checkout:
if not force and os.listdir(directory):
raise AppError("Checkout directory is not empty: {}".format(directory))
with target.timed_activity("Staging sources to {}".format(directory)):
- workspace.open()
+ target._open_workspace()
self.project.workspaces.save_config()
self.message(MessageType.INFO, "Saved workspace configuration")
diff --git a/buildstream/_pipeline.py b/buildstream/_pipeline.py
index 98ea6fbe8..969c3f6e5 100644
--- a/buildstream/_pipeline.py
+++ b/buildstream/_pipeline.py
@@ -80,7 +80,6 @@ class Pipeline():
#
# Private members
#
- self._unused_workspaces = []
self._resolved_elements = {}
self._redundant_refs = []
self._artifacts = None
@@ -136,8 +135,6 @@ class Pipeline():
self.total_elements = len(list(self.dependencies(Scope.ALL)))
- self._initialize_workspaces()
-
# Initialize remote artifact caches. We allow the commandline to override
# the user config in some cases (for example `bst push --remote=...`).
has_remote_caches = False
@@ -305,10 +302,10 @@ class Pipeline():
# building
#
def build(self, scheduler, build_all, track_first):
- if self._unused_workspaces:
+ unused_workspaces = self._collect_unused_workspaces()
+ if unused_workspaces:
self._message(MessageType.WARN, "Unused workspaces",
- detail="\n".join([el for el, _
- in self._unused_workspaces]))
+ detail="\n".join([el for el in unused_workspaces]))
# We set up two plans; one to track elements, the other to
# build them once tracking has finished. The first plan
@@ -660,20 +657,18 @@ class Pipeline():
#
raise PipelineError("{}: {}".format(plugin, e), reason=e.reason) from e
- # _initialize_workspaces()
+ # _collect_unused_workspaces()
#
- # Initialize active workspaces, and collect a list
- # of any workspaces which are unused by the pipeline
+ # Collect a list of any workspaces which are unused by the pipeline
#
- def _initialize_workspaces(self):
- for element_name, workspace in self.project.workspaces.list():
+ def _collect_unused_workspaces(self):
+ unused_workspaces = []
+ for element_name, _ in self.project.workspaces.list():
for target in self.targets:
element = target.search(Scope.ALL, element_name)
-
if element is None:
- self._unused_workspaces.append((element_name, workspace))
- else:
- workspace.init(element)
+ unused_workspaces.append(element_name)
+ return unused_workspaces
# _initialize_remote_caches()
#
diff --git a/buildstream/_workspaces.py b/buildstream/_workspaces.py
index 7c8c516ad..6c8a7401b 100644
--- a/buildstream/_workspaces.py
+++ b/buildstream/_workspaces.py
@@ -51,9 +51,8 @@ class Workspace():
self.path = path
self.running_files = running_files if running_files is not None else {}
- self._element = None
self._project = project
- self.__key = None
+ self._key = None
@classmethod
def from_yaml_node(cls, node, project):
@@ -76,30 +75,13 @@ class Workspace():
return {key: val for key, val in self.__dict__.items()
if key in to_return and val is not None}
- # open()
- #
- # "Open" this workspace, calling the init_workspace method of all
- # its sources.
- #
- def open(self):
- for source in self._element.sources():
- source._init_workspace(self.path)
-
- # init()
- #
- # Initialize the elements and sources associated to this
- # workspace. Must be called before this object is used.
- #
- def init(self, element):
- self._element = element
-
# invalidate_key()
#
# Invalidate the workspace key, forcing a recalculation next time
# it is accessed.
#
def invalidate_key(self):
- self.__key = None
+ self._key = None
# stage()
#
@@ -109,7 +91,7 @@ class Workspace():
# directory (str) - The directory into which to stage this workspace
#
def stage(self, directory):
- fullpath = os.path.join(self._project.directory, self.path)
+ fullpath = self.get_absolute_path()
if os.path.isdir(fullpath):
utils.copy_files(fullpath, directory)
else:
@@ -122,16 +104,16 @@ class Workspace():
# dependency. Duplicate files will be ignored.
#
# Args:
- # dep (Element) - The dependency whose files to append to
+ # dep_name (str) - The dependency name whose files to append to
# files (str) - A list of files to append
#
- def add_running_files(self, dep, files):
- if dep.name in self.running_files:
+ def add_running_files(self, dep_name, files):
+ if dep_name in self.running_files:
# ruamel.py cannot serialize sets in python3.4
- to_add = set(files) - set(self.running_files[dep.name])
- self.running_files[dep.name].extend(to_add)
+ to_add = set(files) - set(self.running_files[dep_name])
+ self.running_files[dep_name].extend(to_add)
else:
- self.running_files[dep.name] = list(files)
+ self.running_files[dep_name] = list(files)
# clear_running_files()
#
@@ -164,8 +146,8 @@ class Workspace():
"Failed loading workspace. Did you remove the "
"workspace directory? {}".format(e))
- if recalculate or self.__key is None:
- fullpath = os.path.join(self._project.directory, self.path)
+ if recalculate or self._key is None:
+ fullpath = self.get_absolute_path()
# Get a list of tuples of the the project relative paths and fullpaths
if os.path.isdir(fullpath):
@@ -174,9 +156,9 @@ class Workspace():
else:
filelist = [(self.path, fullpath)]
- self.__key = [(relpath, unique_key(fullpath)) for relpath, fullpath in filelist]
+ self._key = [(relpath, unique_key(fullpath)) for relpath, fullpath in filelist]
- return self.__key
+ return self._key
# get_absolute_path():
#
@@ -196,8 +178,7 @@ class Workspace():
class Workspaces():
def __init__(self, project):
self._project = project
- workspace_config = self._load_config()
- self._workspaces = self._parse_workspace_config(workspace_config)
+ self._workspaces = self._load_config()
# _list_workspaces()
#
@@ -215,16 +196,15 @@ class Workspaces():
# Create a workspace in the given path for the given element.
#
# Args:
- # element (Element) - The element for which to create a workspace
+ # element_name (str) - The element name to create a workspace for
# path (str) - The path in which the workspace should be kept
#
- def create_workspace(self, element, path):
- self._workspaces[element.name] = Workspace(path, self._project)
- self._workspaces[element.name].init(element)
+ def create_workspace(self, element_name, path):
+ self._workspaces[element_name] = Workspace(path, self._project)
- return self._workspaces[element.name]
+ return self._workspaces[element_name]
- # _get_workspace()
+ # get_workspace()
#
# Get the path of the workspace source associated with the given
# element's source at the given index
@@ -272,16 +252,12 @@ class Workspaces():
# _load_config()
#
- # Load the workspace configuration and return a node containing
- # all open workspaces for the project
+ # Loads and parses the workspace configuration
#
# Returns:
+ # (dict) The extracted workspaces
#
- # A node containing a dict that assigns elements to their
- # workspaces. For example:
- #
- # alpha.bst: /home/me/alpha
- # bravo.bst: /home/me/bravo
+ # Raises: LoadError if there was a problem with the workspace config
#
def _load_config(self):
workspace_file = os.path.join(self._project.directory, ".bst", "workspaces.yml")
@@ -294,7 +270,7 @@ class Workspaces():
raise
- return node
+ return self._parse_workspace_config(node)
# _parse_workspace_config_format()
#
diff --git a/buildstream/element.py b/buildstream/element.py
index 767860e54..4c7b96d51 100644
--- a/buildstream/element.py
+++ b/buildstream/element.py
@@ -518,7 +518,7 @@ class Element(Plugin):
# files, since removed files will be picked up by
# build systems anyway.
to_update, _, added = self.__artifacts.diff(dep, key_old, key_new, subdir='files')
- workspace.add_running_files(dep, to_update + added)
+ workspace.add_running_files(dep.name, to_update + added)
project.workspaces.save_config()
to_update.extend(workspace.running_files[dep.name])
@@ -1350,6 +1350,20 @@ class Element(Plugin):
os.makedirs(directory, exist_ok=True)
return os.path.join(directory, logfile)
+ # _open_workspace():
+ #
+ # "Open" a workspace for this element
+ #
+ # This requires that a workspace already be created in
+ # the workspaces metadata first.
+ #
+ def _open_workspace(self):
+ workspace = self._get_workspace()
+ assert workspace is not None
+
+ for source in self.sources():
+ source._init_workspace(workspace.path)
+
# _get_workspace():
#
# Returns: