diff --git a/dev/devicelab/lib/framework/utils.dart b/dev/devicelab/lib/framework/utils.dart index 5fbc03637cb..41383ca9641 100644 --- a/dev/devicelab/lib/framework/utils.dart +++ b/dev/devicelab/lib/framework/utils.dart @@ -324,8 +324,39 @@ Future exec( bool canFail = false, // as in, whether failures are ok. False means that they are fatal. String workingDirectory, }) async { - final Process process = await startProcess(executable, arguments, environment: environment, workingDirectory: workingDirectory); - await forwardStandardStreams(process); + return _execute( + executable, + arguments, + environment: environment, + canFail : canFail, + workingDirectory: workingDirectory, + ); +} + +Future _execute( + String executable, + List arguments, { + Map environment, + bool canFail = false, // as in, whether failures are ok. False means that they are fatal. + String workingDirectory, + StringBuffer output, // if not null, the stdout will be written here + StringBuffer stderr, // if not null, the stderr will be written here + bool printStdout = true, + bool printStderr = true, +}) async { + final Process process = await startProcess( + executable, + arguments, + environment: environment, + workingDirectory: workingDirectory, + ); + await forwardStandardStreams( + process, + output: output, + stderr: stderr, + printStdout: printStdout, + printStderr: printStderr, + ); final int exitCode = await process.exitCode; if (exitCode != 0 && !canFail) @@ -335,26 +366,42 @@ Future exec( } /// Forwards standard out and standard error from [process] to this process' -/// respective outputs. +/// respective outputs. Also writes stdout to [output] and stderr to [stderr] +/// if they are not null. /// /// Returns a future that completes when both out and error streams a closed. -Future forwardStandardStreams(Process process) { +Future forwardStandardStreams( + Process process, { + StringBuffer output, + StringBuffer stderr, + bool printStdout = true, + bool printStderr = true, + }) { final Completer stdoutDone = Completer(); final Completer stderrDone = Completer(); process.stdout .transform(utf8.decoder) .transform(const LineSplitter()) .listen((String line) { - print('stdout: $line'); + if (printStdout) { + print('stdout: $line'); + } + output?.writeln(line); }, onDone: () { stdoutDone.complete(); }); process.stderr .transform(utf8.decoder) .transform(const LineSplitter()) .listen((String line) { - print('stderr: $line'); + if (printStderr) { + print('stderr: $line'); + } + stderr?.writeln(line); }, onDone: () { stderrDone.complete(); }); - return Future.wait(>[stdoutDone.future, stderrDone.future]); + return Future.wait(>[ + stdoutDone.future, + stderrDone.future, + ]); } /// Executes a command and returns its standard output as a String. @@ -370,36 +417,18 @@ Future eval( bool printStdout = true, bool printStderr = true, }) async { - final Process process = await startProcess(executable, arguments, environment: environment, workingDirectory: workingDirectory); - final StringBuffer output = StringBuffer(); - final Completer stdoutDone = Completer(); - final Completer stderrDone = Completer(); - process.stdout - .transform(utf8.decoder) - .transform(const LineSplitter()) - .listen((String line) { - if (printStdout) { - print('stdout: $line'); - } - output.writeln(line); - }, onDone: () { stdoutDone.complete(); }); - process.stderr - .transform(utf8.decoder) - .transform(const LineSplitter()) - .listen((String line) { - if (printStderr) { - print('stderr: $line'); - } - stderr?.writeln(line); - }, onDone: () { stderrDone.complete(); }); - - await Future.wait(>[stdoutDone.future, stderrDone.future]); - final int exitCode = await process.exitCode; - - if (exitCode != 0 && !canFail) - fail('Executable "$executable" failed with exit code $exitCode.'); - + await _execute( + executable, + arguments, + environment: environment, + canFail: canFail, + workingDirectory: workingDirectory, + output: output, + stderr: stderr, + printStdout: printStdout, + printStderr: printStderr, + ); return output.toString().trimRight(); }