Commit d46fbbcb authored by Tristan Van Berkom's avatar Tristan Van Berkom
Browse files

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
parent cb386651
Loading
Loading
Loading
Loading
+28 −0
Original line number Diff line number Diff line
@@ -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))