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:42:56 +0900
commitd46fbbcbfec7f44cfa3d412b70000eff633b85bb (patch)
tree2ab94501109c9ba3e624b5c385a47b2c86385896
parentcb38665143e6a93f21a08416c869f996b528459f (diff)
downloadbuildstream-d46fbbcbfec7f44cfa3d412b70000eff633b85bb.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.py28
1 files changed, 28 insertions, 0 deletions
diff --git a/buildstream/element.py b/buildstream/element.py
index 48d75274f..7c94354f5 100644
--- a/buildstream/element.py
+++ b/buildstream/element.py
@@ -38,6 +38,7 @@ from . import _yaml
from ._variables import Variables
from ._versions import BST_CORE_ARTIFACT_VERSION
from ._exceptions import BstError, LoadError, LoadErrorReason, ImplError, ErrorDomain
+from .utils import UtilError
from . import Plugin, Consistency
from . import SandboxFlags
from . import utils
@@ -162,6 +163,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 +615,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 +1186,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))