def _run()

in src/buildstream/sandbox/_sandboxreapi.py [0:0]


    def _run(self, command, *, flags, cwd, env):
        context = self._get_context()
        cascache = context.get_cascache()

        # set up virtual dircetory
        vdir = self.get_virtual_directory()

        if not self._has_command(command[0], env):
            raise SandboxCommandError(
                "Staged artifacts do not provide command " "'{}'".format(command[0]), reason="missing-command"
            )

        # Ensure working directory exists
        if len(cwd) > 1:
            assert cwd.startswith("/")
            vdir.open_directory(cwd[1:], create=True)

        # Ensure directories required for sandboxed execution exist
        for directory in ["dev", "proc", "tmp"]:
            vsubdir = vdir.open_directory(directory, create=True)
            if flags & _SandboxFlags.ROOT_READ_ONLY:
                vsubdir._set_subtree_read_only(False)

        # Create directories for all marked directories. This emulates
        # some of the behaviour of other sandboxes, which create these
        # to use as mount points.
        read_write_directories = []
        mount_sources = self._get_mount_sources()
        for directory in self._get_marked_directories():

            if directory in mount_sources:
                # Bind mount
                mount_point = directory.lstrip(os.path.sep)
                mount_source = mount_sources[directory]

                # Ensure mount point exists in sandbox
                if not vdir.exists(mount_point):
                    if os.path.isdir(mount_source):
                        # Mounting a directory, mount point must be a directory
                        vdir.open_directory(mount_point, create=True)
                    else:
                        # Mounting a file or device node, mount point must be a file
                        split_mount_point = mount_point.rsplit(os.path.sep, 1)
                        parent_vdir = vdir.open_directory(split_mount_point[0], create=True)
                        parent_vdir._create_empty_file(split_mount_point[1])
            else:
                # Read-write directory
                marked_vdir = vdir.open_directory(directory.lstrip(os.path.sep), create=True)
                read_write_directories.append(directory)
                if flags & _SandboxFlags.ROOT_READ_ONLY:
                    marked_vdir._set_subtree_read_only(False)

        if flags & _SandboxFlags.ROOT_READ_ONLY:
            vdir._set_subtree_read_only(True)
        else:
            # The whole sandbox is writable
            read_write_directories = [os.path.sep]

        # Generate Action proto
        input_root_digest = vdir._get_digest()
        platform = self._create_platform(flags)
        command_proto = self._create_command(command, cwd, env, read_write_directories, platform)
        command_digest = cascache.add_object(buffer=command_proto.SerializeToString())
        action = remote_execution_pb2.Action(
            command_digest=command_digest, input_root_digest=input_root_digest, platform=platform
        )

        action_result = self._execute_action(action, flags)  # pylint: disable=assignment-from-no-return

        # Get output of build
        self._process_job_output(
            cwd, action_result.output_directories, action_result.output_files, failure=action_result.exit_code != 0
        )

        # Non-zero exit code means a normal error during the build:
        # the remote execution system has worked correctly but the command failed.
        return action_result.exit_code