exec method
Future<Result<ShellExecResult, ExecutionError> >
exec(
- String command, {
- ShellExecOptions? options,
override
Executes a shell command. Must never throw: all failures are encoded in the returned Result.
Implementation
@override
Future<Result<ShellExecResult, ExecutionError>> exec(
String command, {
ShellExecOptions? options,
}) async {
final token = options?.cancelToken;
if (token?.isCancelled ?? false) {
return const Err(ExecutionError(ExecutionErrorCode.aborted, 'aborted'));
}
final started = await _start(command, options);
if (started.isErr) return Err(started.errorOrNull!);
final process = started.valueOrNull!;
final stdout = StringBuffer();
final stderr = StringBuffer();
ExecutionError? callbackError;
final stdoutDone = process.stdout
.transform(utf8.decoder)
.forEach(
(chunk) => _collect(
stdout,
chunk,
options?.onStdout,
process,
(error) => callbackError = error,
),
);
final stderrDone = process.stderr
.transform(utf8.decoder)
.forEach(
(chunk) => _collect(
stderr,
chunk,
options?.onStderr,
process,
(error) => callbackError = error,
),
);
Timer? timer;
var timedOut = false;
final timeout = options?.timeout;
if (timeout != null) {
timer = Timer(timeout, () {
timedOut = true;
process.kill();
});
}
void onCancel(_) {
process.kill();
}
token?.onCancel.then(onCancel);
final exitCode = await process.exitCode;
timer?.cancel();
await Future.wait([stdoutDone, stderrDone]);
return _result(
callbackError: callbackError,
timedOut: timedOut,
timeout: timeout,
cancelled: token?.isCancelled ?? false,
stdout: stdout,
stderr: stderr,
exitCode: exitCode,
);
}