blob: e0c734c6e2fdee6221337b83360ae040ad2c8df2 [file] [log] [blame]
// Copyright 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import "dart:async";
import 'dart:io';
typedef ProcessRunner = Future<ProcessResult>
Function(String executable, List<String> arguments, {bool runInShell});
/// Wraps a function in a [Zone] with an alternative [ProcessRunner].
///
/// All [Command.run] calls in the zone will use the alternative runner.
///
/// Returns the return value of the function [body].
R overrideRun<R>(ProcessRunner run, R Function() body) {
return runZoned(body, zoneValues: {#_run: run});
}
/// A command to run an [executable] with the given [arguments].
class Command {
final String executable;
final List<String> arguments;
final bool runInShell;
const Command(this.executable, this.arguments, {this.runInShell = false});
/// Runs an [executable] with the given [arguments].
///
/// If running in a zone created by [overrideRun], it will use an alternative
/// [ProcessRunner]. Otherwise, it defaults to [Process.run].
Future<ProcessResult> run({bool raise = false}) async {
final result = await (Zone.current[#_run] as ProcessRunner? ??
Process.run)(executable, arguments, runInShell: runInShell);
if (raise && result.exitCode != 0) {
throw ProcessException(
executable,
arguments,
'Command exited ${result.exitCode}: '
'$executable ${arguments.join(' ')}\n'
'${result.stdout}\n${result.stderr}',
result.exitCode);
}
return result;
}
}