run static method

Future<ProcessResultData> run(
  1. List<String> command, {
  2. String? workingDirectory,
  3. Map<String, String>? environment,
  4. Duration? timeout = const Duration(seconds: 60),
  5. String? input,
  6. void onOutput(
    1. ProcessOutputType type,
    2. String chunk
    )?,
})

Runs command with no shell, so its arguments need no escaping. timeout kills it and throws a ProcessTimedOutException.

Implementation

static Future<ProcessResultData> run(
  List<String> command, {
  String? workingDirectory,
  Map<String, String>? environment,
  Duration? timeout = const Duration(seconds: 60),
  String? input,
  void Function(ProcessOutputType type, String chunk)? onOutput,
}) async {
  final fake = _fake;
  if (fake != null) {
    return fake._answer(command);
  }
  if (command.isEmpty) {
    throw ArgumentError.value(command, 'command', 'Empty command');
  }
  final process = await io.Process.start(
    command.first,
    command.sublist(1),
    workingDirectory: workingDirectory,
    environment: environment,
  );
  final output = StringBuffer();
  final errorOutput = StringBuffer();
  Future<void> collect(
    Stream<List<int>> stream,
    StringBuffer buffer,
    ProcessOutputType type,
  ) => stream.transform(utf8.decoder).forEach((chunk) {
    buffer.write(chunk);
    onOutput?.call(type, chunk);
  });
  final reading = Future.wait([
    collect(process.stdout, output, ProcessOutputType.stdout),
    collect(process.stderr, errorOutput, ProcessOutputType.stderr),
  ]);
  // A command may exit without reading it all (`head -n 1`): a broken pipe
  // is not a failure of this call.
  process.stdin.done.ignore();
  try {
    if (input != null) {
      process.stdin.write(input);
    }
    await process.stdin.close();
  } on io.IOException {
    // The exit code says how it went.
  }
  final int exitCode;
  try {
    exitCode = timeout == null
        ? await process.exitCode
        : await process.exitCode.timeout(timeout);
  } on TimeoutException {
    process.kill(io.ProcessSignal.sigkill);
    throw ProcessTimedOutException(command, timeout!);
  }
  await reading;
  return ProcessResultData(
    command: command,
    exitCode: exitCode,
    output: output.toString(),
    errorOutput: errorOutput.toString(),
  );
}