summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTristan Van Berkom <tristan.vanberkom@codethink.co.uk>2018-04-11 18:06:37 +0900
committerTristan Van Berkom <tristan.vanberkom@codethink.co.uk>2018-04-11 18:11:33 +0900
commit6076969ae979a348abece53fdb26c7ab3c0db085 (patch)
tree51d52f7189b9b096a43a89ecd52e81c91357b714
parentcb38665143e6a93f21a08416c869f996b528459f (diff)
downloadbuildstream-6076969ae979a348abece53fdb26c7ab3c0db085.tar.gz
element.py: Preserve workspace state in failed build sandboxes.
As reported in regression #346, since we started mounting the workspaces we now fail to debug build failures for workspaces, the shell command no longer sees the workspaces files to debug. As the failed sysroot represents a very particular build failure, it is incorrect to attempt to remount a workspace again after a failed build, as the workspace files may have changed since the build. Instead, in the case of a build failure on a workspaced element, we copy the files from the workspace in place (while automatically preserving the mtimes and everything, as utils.safe_copy() does). When we implement failed build artifacts, this case will have to be handled in a very similar way, too. This fixes issue #346
-rw-r--r--buildstream/element.py27
1 files changed, 27 insertions, 0 deletions
diff --git a/buildstream/element.py b/buildstream/element.py
index 48d75274f..3e99d2844 100644
--- a/buildstream/element.py
+++ b/buildstream/element.py
@@ -162,6 +162,7 @@ class Element(Plugin):
self.__log_path = None # Path to dedicated log file or None
self.__splits = None
self.__whitelist_regex = None
+ self.__staged_sources_directory = None # Location where Element.stage_sources() was called
# Ensure we have loaded this class's defaults
self.__init_defaults(plugin_conf)
@@ -613,6 +614,13 @@ class Element(Plugin):
directory (str): An absolute path within the sandbox to stage the sources at
"""
+ # Hold on to the location where a plugin decided to stage sources,
+ # this will be used to reconstruct the failed sysroot properly
+ # after a failed build.
+ #
+ assert self.__staged_sources_directory is None
+ self.__staged_sources_directory = directory
+
self._stage_sources_in_sandbox(sandbox, directory)
def get_public_data(self, domain):
@@ -1177,6 +1185,25 @@ class Element(Plugin):
# If an error occurred assembling an element in a sandbox,
# then tack on the sandbox directory to the error
e.sandbox = rootdir
+
+ # If there is a workspace open on this element, it will have
+ # been mounted for sandbox invocations instead of being staged.
+ #
+ # In order to preserve the correct failure state, we need to
+ # copy over the workspace files into the appropriate directory
+ # in the sandbox.
+ #
+ workspace = self._get_workspace()
+ if workspace and self.__staged_sources_directory:
+ sandbox_root = sandbox.get_directory()
+ sandbox_path = os.path.join(sandbox_root,
+ self.__staged_sources_directory.lstrip(os.sep))
+ try:
+ utils.copy_files(workspace.path, sandbox_path)
+ except UtilError as e:
+ self.warn("Failed to preserve workspace state for failed build sysroot: {}"
+ .format(e))
+
raise
collectdir = os.path.join(sandbox_root, collect.lstrip(os.sep))