Commit bf5c26ff authored by Jürg Billeter's avatar Jürg Billeter
Browse files

sandbox: Add queue() and run_queue() methods for command batching

parent 5d3f039f
Loading
Loading
Loading
Loading
+52 −0
Original line number Diff line number Diff line
@@ -29,6 +29,8 @@ See also: :ref:`sandboxing`.
"""

import os
from collections import namedtuple

from .._exceptions import ImplError, BstError
from ..storage._filebaseddirectory import FileBasedDirectory
from ..storage._casbaseddirectory import CasBasedDirectory
@@ -114,6 +116,9 @@ class Sandbox():
        # directory via get_directory.
        self._never_cache_vdirs = False

        # Queued commands
        self._queue = []

    def get_directory(self):
        """Fetches the sandbox root directory

@@ -228,6 +233,53 @@ class Sandbox():
        raise ImplError("Sandbox of type '{}' does not implement run()"
                        .format(type(self).__name__))

    def queue(self, command, *, start_callback=None, complete_callback=None):
        """Queue a command to be run in the sandbox.

        If the command fails, commands queued later will not be executed.
        The callbacks are not guaranteed to be invoked in real time.

        Args:
            command (list): The command to run in the sandboxed environment, as a list
                            of strings starting with the binary to run.
            start_callback (callable): Called when the command starts.
            complete_callback (callble): Called when the command completes
                                         with the exit code as argument.
        """
        entry = namedtuple('QueueEntry', ['command', 'start_callback', 'complete_callback'])
        entry.command = command
        entry.start_callback = start_callback
        entry.complete_callback = complete_callback
        self._queue.append(entry)

    def run_queue(self, flags, *, cwd=None, env=None):
        """Run a command in the sandbox.

        Args:
            flags (:class:`.SandboxFlags`): The flags for running this command.
            cwd (str): The sandbox relative working directory in which to run the command.
            env (dict): A dictionary of string key, value pairs to set as environment
                        variables inside the sandbox environment.

        Raises:
            (:class:`.ProgramNotFoundError`): If a host tool which the given sandbox
                                              implementation requires is not found.

        .. note::

           The optional *cwd* argument will default to the value set with
           :func:`~buildstream.sandbox.Sandbox.set_work_directory`
        """
        queue = self._queue
        self._queue = []

        for entry in queue:
            entry.start_callback()
            exit_code = self.run(entry.command, flags, cwd=cwd, env=env)
            entry.complete_callback(exit_code)
            if exit_code != 0:
                break

    ################################################
    #               Private methods                #
    ################################################