| ... | ... | @@ -37,7 +37,6 @@ import click | 
| 37 | 37 |  
 | 
| 38 | 38 |  from buildstream import _yaml
 | 
| 39 | 39 |  from buildstream import utils
 | 
| 40 |  | -from buildstream._frontend import cli as bst_cli
 | 
| 41 | 40 |  from buildstream._exceptions import BstError
 | 
| 42 | 41 |  
 | 
| 43 | 42 |  
 | 
| ... | ... | @@ -176,20 +175,6 @@ def ansi2html(text, palette='solarized'): | 
| 176 | 175 |      return sub
 | 
| 177 | 176 |  
 | 
| 178 | 177 |  
 | 
| 179 |  | -@contextmanager
 | 
| 180 |  | -def capture_stdout_stderr():
 | 
| 181 |  | -    from io import StringIO
 | 
| 182 |  | -
 | 
| 183 |  | -    capture = StringIO()
 | 
| 184 |  | -    oldstdout, sys.stdout = sys.stdout, capture
 | 
| 185 |  | -    oldstderr, sys.stderr = sys.stderr, capture
 | 
| 186 |  | -
 | 
| 187 |  | -    yield capture
 | 
| 188 |  | -
 | 
| 189 |  | -    sys.stdout = oldstdout
 | 
| 190 |  | -    sys.stderr = oldstderr
 | 
| 191 |  | -
 | 
| 192 |  | -
 | 
| 193 | 178 |  # workdir()
 | 
| 194 | 179 |  #
 | 
| 195 | 180 |  # Sets up a new temp directory with a config file
 | 
| ... | ... | @@ -219,7 +204,7 @@ def workdir(source_cache=None): | 
| 219 | 204 |          yield (tempdir, bst_config_file, source_cache)
 | 
| 220 | 205 |  
 | 
| 221 | 206 |  
 | 
| 222 |  | -# run_command()
 | 
|  | 207 | +# run_bst_command()
 | 
| 223 | 208 |  #
 | 
| 224 | 209 |  # Runs a command
 | 
| 225 | 210 |  #
 | 
| ... | ... | @@ -231,18 +216,33 @@ def workdir(source_cache=None): | 
| 231 | 216 |  # Returns:
 | 
| 232 | 217 |  #    (str): The colorized combined stdout/stderr of BuildStream
 | 
| 233 | 218 |  #
 | 
| 234 |  | -def run_command(config_file, directory, command):
 | 
| 235 |  | -    click.echo("Running command in directory '{}': bst {}".format(directory, command), err=True)
 | 
|  | 219 | +def run_bst_command(config_file, directory, command):
 | 
|  | 220 | +    click.echo("Running bst command in directory '{}': bst {}".format(directory, command), err=True)
 | 
| 236 | 221 |  
 | 
| 237 |  | -    args = ['--colors', '--config', config_file, '--directory', directory] + shlex.split(command)
 | 
|  | 222 | +    argv = ['python3', '-m', 'buildstream', '--colors', '--config', config_file] + shlex.split(command)
 | 
|  | 223 | +    p = subprocess.Popen(argv, cwd=directory, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
 | 
|  | 224 | +    out, _ = p.communicate()
 | 
|  | 225 | +    return out.decode('utf-8').strip()
 | 
| 238 | 226 |  
 | 
| 239 |  | -    with capture_stdout_stderr() as capture:
 | 
| 240 |  | -        bst_cli.main(args=args, prog_name=bst_cli.name)
 | 
| 241 | 227 |  
 | 
| 242 |  | -        capture.flush()
 | 
| 243 |  | -        out = capture.getvalue()
 | 
|  | 228 | +# run_shell_command()
 | 
|  | 229 | +#
 | 
|  | 230 | +# Runs a command
 | 
|  | 231 | +#
 | 
|  | 232 | +# Args:
 | 
|  | 233 | +#    directory (str): The project directory
 | 
|  | 234 | +#    command (str): A shell command
 | 
|  | 235 | +#
 | 
|  | 236 | +# Returns:
 | 
|  | 237 | +#    (str): The combined stdout/stderr of the shell command
 | 
|  | 238 | +#
 | 
|  | 239 | +def run_shell_command(directory, command):
 | 
|  | 240 | +    click.echo("Running shell command in directory '{}': {}".format(directory, command), err=True)
 | 
| 244 | 241 |  
 | 
| 245 |  | -    return out.strip()
 | 
|  | 242 | +    argv = shlex.split(command)
 | 
|  | 243 | +    p = subprocess.Popen(argv, cwd=directory, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
 | 
|  | 244 | +    out, _ = p.communicate()
 | 
|  | 245 | +    return out.decode('utf-8').strip()
 | 
| 246 | 246 |  
 | 
| 247 | 247 |  
 | 
| 248 | 248 |  # generate_html
 | 
| ... | ... | @@ -393,12 +393,18 @@ def run_session(description, tempdir, source_cache, palette, config_file, force) | 
| 393 | 393 |          # Get the command string
 | 
| 394 | 394 |          command_str = _yaml.node_get(command, str, 'command')
 | 
| 395 | 395 |  
 | 
|  | 396 | +        # Check whether this is a shell command and not a bst command
 | 
|  | 397 | +        is_shell = _yaml.node_get(command, bool, 'shell', default_value=False)
 | 
|  | 398 | +
 | 
| 396 | 399 |          # Check if there is fake output
 | 
| 397 | 400 |          command_fake_output = _yaml.node_get(command, str, 'fake-output', default_value=None)
 | 
| 398 | 401 |  
 | 
| 399 | 402 |          # Run the command, or just use the fake output
 | 
| 400 | 403 |          if command_fake_output is None:
 | 
| 401 |  | -            command_out = run_command(config_file, directory, command_str)
 | 
|  | 404 | +            if is_shell:
 | 
|  | 405 | +                command_out = run_shell_command(directory, command_str)
 | 
|  | 406 | +            else:
 | 
|  | 407 | +                command_out = run_bst_command(config_file, directory, command_str)
 | 
| 402 | 408 |          else:
 | 
| 403 | 409 |              command_out = command_fake_output
 | 
| 404 | 410 |  
 | 
| ... | ... | @@ -434,14 +440,8 @@ def run_session(description, tempdir, source_cache, palette, config_file, force) | 
| 434 | 440 |  @click.option('--palette', '-p', default='tango',
 | 
| 435 | 441 |                type=click.Choice(['solarized', 'solarized-xterm', 'tango', 'xterm', 'console']),
 | 
| 436 | 442 |                help="Selects a palette for the output style")
 | 
| 437 |  | -@click.option('--output', '-o',
 | 
| 438 |  | -              type=click.Path(file_okay=True, dir_okay=False, writable=True),
 | 
| 439 |  | -              help="A file to store the output")
 | 
| 440 |  | -@click.option('--description', '-d',
 | 
| 441 |  | -              type=click.Path(file_okay=True, dir_okay=False, readable=True),
 | 
| 442 |  | -              help="A file describing what to do")
 | 
| 443 |  | -@click.argument('command', type=click.STRING, nargs=-1)
 | 
| 444 |  | -def run_bst(directory, force, source_cache, description, palette, output, command):
 | 
|  | 443 | +@click.argument('description', click.Path(file_okay=True, dir_okay=False, readable=True))
 | 
|  | 444 | +def run_bst(directory, force, source_cache, description, palette):
 | 
| 445 | 445 |      """Run a bst command and capture stdout/stderr in html
 | 
| 446 | 446 |  
 | 
| 447 | 447 |      This command normally takes a description yaml file, see the HACKING
 | 
| ... | ... | @@ -450,45 +450,8 @@ def run_bst(directory, force, source_cache, description, palette, output, comman | 
| 450 | 450 |      if not source_cache and os.environ.get('BST_SOURCE_CACHE'):
 | 
| 451 | 451 |          source_cache = os.environ['BST_SOURCE_CACHE']
 | 
| 452 | 452 |  
 | 
| 453 |  | -    if output is not None and not check_needs_build(None, output, force=force):
 | 
| 454 |  | -        click.echo("No need to rebuild {}".format(output))
 | 
| 455 |  | -        return 0
 | 
| 456 |  | -
 | 
| 457 | 453 |      with workdir(source_cache=source_cache) as (tempdir, config_file, source_cache):
 | 
| 458 |  | -
 | 
| 459 |  | -        if description:
 | 
| 460 |  | -            run_session(description, tempdir, source_cache, palette, config_file, force)
 | 
| 461 |  | -            return 0
 | 
| 462 |  | -
 | 
| 463 |  | -        # Run a command specified on the CLI
 | 
| 464 |  | -        #
 | 
| 465 |  | -        if not directory:
 | 
| 466 |  | -            directory = os.getcwd()
 | 
| 467 |  | -        else:
 | 
| 468 |  | -            directory = os.path.abspath(directory)
 | 
| 469 |  | -            directory = os.path.realpath(directory)
 | 
| 470 |  | -
 | 
| 471 |  | -        if not command:
 | 
| 472 |  | -            command = []
 | 
| 473 |  | -        command_str = " ".join(command)
 | 
| 474 |  | -
 | 
| 475 |  | -        # Run the command
 | 
| 476 |  | -        #
 | 
| 477 |  | -        command_out = run_command(config_file, directory, command_str)
 | 
| 478 |  | -
 | 
| 479 |  | -        # Generate a nice html div for this output
 | 
| 480 |  | -        #
 | 
| 481 |  | -        converted = generate_html(command_out, directory, config_file,
 | 
| 482 |  | -                                  source_cache, tempdir, palette,
 | 
| 483 |  | -                                  command_str)
 | 
| 484 |  | -
 | 
| 485 |  | -    if output is None:
 | 
| 486 |  | -        click.echo(converted)
 | 
| 487 |  | -    else:
 | 
| 488 |  | -        outdir = os.path.dirname(output)
 | 
| 489 |  | -        os.makedirs(outdir, exist_ok=True)
 | 
| 490 |  | -        with open(output, 'wb') as f:
 | 
| 491 |  | -            f.write(converted.encode('utf-8'))
 | 
|  | 454 | +        run_session(description, tempdir, source_cache, palette, config_file, force)
 | 
| 492 | 455 |  
 | 
| 493 | 456 |      return 0
 | 
| 494 | 457 |  
 |