Create abstraction layer for dart:io's Process commands (#7100)
With this change, they're run via instance methods on an object
obtained through the context. This will allow us to substitute
that object in tests with replay/record versions to allow us to
mock out the os-layer in tests.
diff --git a/packages/flutter_tools/lib/src/android/android_device.dart b/packages/flutter_tools/lib/src/android/android_device.dart
index e8f9452..bf86f76 100644
--- a/packages/flutter_tools/lib/src/android/android_device.dart
+++ b/packages/flutter_tools/lib/src/android/android_device.dart
@@ -11,6 +11,7 @@
import '../base/os.dart';
import '../base/logger.dart';
import '../base/process.dart';
+import '../base/process_manager.dart';
import '../build_info.dart';
import '../commands/build_apk.dart';
import '../device.dart';
@@ -59,7 +60,7 @@
try {
// We pass an encoding of LATIN1 so that we don't try and interpret the
// `adb shell getprop` result as UTF8.
- ProcessResult result = Process.runSync(
+ ProcessResult result = processManager.runSync(
propCommand.first,
propCommand.sublist(1),
stdoutEncoding: LATIN1
diff --git a/packages/flutter_tools/lib/src/android/android_workflow.dart b/packages/flutter_tools/lib/src/android/android_workflow.dart
index 05bc39a..58f77db 100644
--- a/packages/flutter_tools/lib/src/android/android_workflow.dart
+++ b/packages/flutter_tools/lib/src/android/android_workflow.dart
@@ -6,6 +6,7 @@
import 'dart:io';
import '../base/os.dart';
+import '../base/process_manager.dart';
import '../doctor.dart';
import '../globals.dart';
import 'android_sdk.dart';
@@ -70,7 +71,7 @@
try {
printTrace('java -version');
- ProcessResult result = Process.runSync('java', <String>['-version']);
+ ProcessResult result = processManager.runSync('java', <String>['-version']);
if (result.exitCode == 0) {
javaVersion = result.stderr;
List<String> versionLines = javaVersion.split('\n');
diff --git a/packages/flutter_tools/lib/src/base/os.dart b/packages/flutter_tools/lib/src/base/os.dart
index f709d4d..01c46d3 100644
--- a/packages/flutter_tools/lib/src/base/os.dart
+++ b/packages/flutter_tools/lib/src/base/os.dart
@@ -10,6 +10,7 @@
import 'context.dart';
import 'process.dart';
+import 'process_manager.dart';
/// Returns [OperatingSystemUtils] active in the current app context (i.e. zone).
OperatingSystemUtils get os => context[OperatingSystemUtils];
@@ -49,14 +50,14 @@
@override
ProcessResult makeExecutable(File file) {
- return Process.runSync('chmod', <String>['a+x', file.path]);
+ return processManager.runSync('chmod', <String>['a+x', file.path]);
}
/// Return the path to the given executable, or `null` if `which` was not able
/// to locate the binary.
@override
File which(String execName) {
- ProcessResult result = Process.runSync('which', <String>[execName]);
+ ProcessResult result = processManager.runSync('which', <String>[execName]);
if (result.exitCode != 0)
return null;
String path = result.stdout.trim().split('\n').first.trim();
@@ -87,7 +88,7 @@
@override
File which(String execName) {
- ProcessResult result = Process.runSync('where', <String>[execName]);
+ ProcessResult result = processManager.runSync('where', <String>[execName]);
if (result.exitCode != 0)
return null;
return new File(result.stdout.trim().split('\n').first.trim());
diff --git a/packages/flutter_tools/lib/src/base/process.dart b/packages/flutter_tools/lib/src/base/process.dart
index 104db6c..8b20f90 100644
--- a/packages/flutter_tools/lib/src/base/process.dart
+++ b/packages/flutter_tools/lib/src/base/process.dart
@@ -6,6 +6,7 @@
import 'dart:convert';
import 'dart:io';
+import 'process_manager.dart';
import '../globals.dart';
typedef String StringConverter(String string);
@@ -44,7 +45,7 @@
_traceCommand(cmd, workingDirectory: workingDirectory);
String executable = cmd[0];
List<String> arguments = cmd.length > 1 ? cmd.sublist(1) : <String>[];
- Process process = await Process.start(
+ Process process = await processManager.start(
executable,
arguments,
workingDirectory: workingDirectory,
@@ -108,13 +109,13 @@
Future<Process> proc = runDetached(cmd);
return new Future<Null>.delayed(timeout, () async {
printTrace('Intentionally killing ${cmd[0]}');
- Process.killPid((await proc).pid);
+ processManager.killPid((await proc).pid);
});
}
Future<Process> runDetached(List<String> cmd) {
_traceCommand(cmd);
- Future<Process> proc = Process.start(
+ Future<Process> proc = processManager.start(
cmd[0], cmd.getRange(1, cmd.length).toList(),
mode: ProcessStartMode.DETACHED
);
@@ -126,7 +127,7 @@
bool allowReentrantFlutter: false
}) async {
_traceCommand(cmd, workingDirectory: workingDirectory);
- ProcessResult results = await Process.run(
+ ProcessResult results = await processManager.run(
cmd[0],
cmd.getRange(1, cmd.length).toList(),
workingDirectory: workingDirectory,
@@ -140,7 +141,7 @@
bool exitsHappy(List<String> cli) {
_traceCommand(cli);
try {
- return Process.runSync(cli.first, cli.sublist(1)).exitCode == 0;
+ return processManager.runSync(cli.first, cli.sublist(1)).exitCode == 0;
} catch (error) {
return false;
}
@@ -203,7 +204,7 @@
bool hideStdout: false,
}) {
_traceCommand(cmd, workingDirectory: workingDirectory);
- ProcessResult results = Process.runSync(
+ ProcessResult results = processManager.runSync(
cmd[0],
cmd.getRange(1, cmd.length).toList(),
workingDirectory: workingDirectory,
diff --git a/packages/flutter_tools/lib/src/base/process_manager.dart b/packages/flutter_tools/lib/src/base/process_manager.dart
new file mode 100644
index 0000000..0cfc1f5
--- /dev/null
+++ b/packages/flutter_tools/lib/src/base/process_manager.dart
@@ -0,0 +1,66 @@
+// Copyright 2016 The Chromium Authors. 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:convert';
+import 'dart:io';
+
+import 'context.dart';
+
+ProcessManager get processManager => context[ProcessManager];
+
+class ProcessManager {
+ Future<Process> start(
+ String executable,
+ List<String> arguments,
+ {String workingDirectory,
+ Map<String, String> environment,
+ ProcessStartMode mode: ProcessStartMode.NORMAL}) {
+ return Process.start(
+ executable,
+ arguments,
+ workingDirectory: workingDirectory,
+ environment: environment,
+ mode: mode,
+ );
+ }
+
+ Future<ProcessResult> run(
+ String executable,
+ List<String> arguments,
+ {String workingDirectory,
+ Map<String, String> environment,
+ Encoding stdoutEncoding: SYSTEM_ENCODING,
+ Encoding stderrEncoding: SYSTEM_ENCODING}) {
+ return Process.run(
+ executable,
+ arguments,
+ workingDirectory: workingDirectory,
+ environment: environment,
+ stdoutEncoding: stdoutEncoding,
+ stderrEncoding: stderrEncoding,
+ );
+ }
+
+ ProcessResult runSync(
+ String executable,
+ List<String> arguments,
+ {String workingDirectory,
+ Map<String, String> environment,
+ Encoding stdoutEncoding: SYSTEM_ENCODING,
+ Encoding stderrEncoding: SYSTEM_ENCODING}) {
+ return Process.runSync(
+ executable,
+ arguments,
+ workingDirectory: workingDirectory,
+ environment: environment,
+ stdoutEncoding: stdoutEncoding,
+ stderrEncoding: stderrEncoding,
+ );
+ }
+
+ bool killPid(int pid, [ProcessSignal signal = ProcessSignal.SIGTERM]) {
+ return Process.killPid(pid, signal);
+ }
+}
diff --git a/packages/flutter_tools/lib/src/commands/analyze_continuously.dart b/packages/flutter_tools/lib/src/commands/analyze_continuously.dart
index b04d6f4..b8e5534 100644
--- a/packages/flutter_tools/lib/src/commands/analyze_continuously.dart
+++ b/packages/flutter_tools/lib/src/commands/analyze_continuously.dart
@@ -11,6 +11,7 @@
import '../base/common.dart';
import '../base/logger.dart';
+import '../base/process_manager.dart';
import '../base/utils.dart';
import '../cache.dart';
import '../dart/sdk.dart';
@@ -159,7 +160,7 @@
List<String> args = <String>[snapshot, '--sdk', sdk];
printTrace('dart ${args.join(' ')}');
- _process = await Process.start(path.join(dartSdkPath, 'bin', 'dart'), args);
+ _process = await processManager.start(path.join(dartSdkPath, 'bin', 'dart'), args);
_process.exitCode.whenComplete(() => _process = null);
Stream<String> errorStream = _process.stderr.transform(UTF8.decoder).transform(const LineSplitter());
diff --git a/packages/flutter_tools/lib/src/commands/test.dart b/packages/flutter_tools/lib/src/commands/test.dart
index cf421cd..f83f7a0 100644
--- a/packages/flutter_tools/lib/src/commands/test.dart
+++ b/packages/flutter_tools/lib/src/commands/test.dart
@@ -10,6 +10,7 @@
import '../base/common.dart';
import '../base/logger.dart';
+import '../base/process_manager.dart';
import '../base/os.dart';
import '../cache.dart';
import '../dart/package_map.dart';
@@ -126,7 +127,7 @@
Directory tempDir = Directory.systemTemp.createTempSync('flutter_tools');
try {
File sourceFile = coverageFile.copySync(path.join(tempDir.path, 'lcov.source.info'));
- ProcessResult result = Process.runSync('lcov', <String>[
+ ProcessResult result = processManager.runSync('lcov', <String>[
'--add-tracefile', baseCoverageData,
'--add-tracefile', sourceFile.path,
'--output-file', coverageFile.path,
diff --git a/packages/flutter_tools/lib/src/ios/devices.dart b/packages/flutter_tools/lib/src/ios/devices.dart
index d2aa790..9e05e19 100644
--- a/packages/flutter_tools/lib/src/ios/devices.dart
+++ b/packages/flutter_tools/lib/src/ios/devices.dart
@@ -9,6 +9,7 @@
import '../application_package.dart';
import '../base/os.dart';
import '../base/process.dart';
+import '../base/process_manager.dart';
import '../build_info.dart';
import '../device.dart';
import '../doctor.dart';
@@ -514,7 +515,7 @@
Process process = forwardedPort.context;
if (process != null) {
- Process.killPid(process.pid);
+ processManager.killPid(process.pid);
} else {
printError("Forwarded port did not have a valid process");
}
diff --git a/packages/flutter_tools/lib/src/ios/mac.dart b/packages/flutter_tools/lib/src/ios/mac.dart
index f727f38..b7eead4 100644
--- a/packages/flutter_tools/lib/src/ios/mac.dart
+++ b/packages/flutter_tools/lib/src/ios/mac.dart
@@ -11,6 +11,7 @@
import '../application_package.dart';
import '../base/context.dart';
import '../base/process.dart';
+import '../base/process_manager.dart';
import '../build_info.dart';
import '../flx.dart' as flx;
import '../globals.dart';
@@ -39,7 +40,7 @@
} else {
try {
printTrace('xcrun clang');
- ProcessResult result = Process.runSync('/usr/bin/xcrun', <String>['clang']);
+ ProcessResult result = processManager.runSync('/usr/bin/xcrun', <String>['clang']);
if (result.stdout != null && result.stdout.contains('license'))
_eulaSigned = false;
diff --git a/packages/flutter_tools/lib/src/ios/simulators.dart b/packages/flutter_tools/lib/src/ios/simulators.dart
index d0bae71..3c30dca 100644
--- a/packages/flutter_tools/lib/src/ios/simulators.dart
+++ b/packages/flutter_tools/lib/src/ios/simulators.dart
@@ -13,6 +13,7 @@
import '../base/common.dart';
import '../base/context.dart';
import '../base/process.dart';
+import '../base/process_manager.dart';
import '../build_info.dart';
import '../device.dart';
import '../flx.dart' as flx;
@@ -190,7 +191,7 @@
List<String> args = <String>['simctl', 'list', '--json', section.name];
printTrace('$_xcrunPath ${args.join(' ')}');
- ProcessResult results = Process.runSync(_xcrunPath, args);
+ ProcessResult results = processManager.runSync(_xcrunPath, args);
if (results.exitCode != 0) {
printError('Error executing simctl: ${results.exitCode}\n${results.stderr}');
return <String, Map<String, dynamic>>{};
diff --git a/packages/flutter_tools/lib/src/test/flutter_platform.dart b/packages/flutter_tools/lib/src/test/flutter_platform.dart
index 680df4c..6e85424 100644
--- a/packages/flutter_tools/lib/src/test/flutter_platform.dart
+++ b/packages/flutter_tools/lib/src/test/flutter_platform.dart
@@ -15,6 +15,7 @@
import 'package:test/src/runner/plugin/platform.dart'; // ignore: implementation_imports
import 'package:test/src/runner/plugin/hack_register_platform.dart' as hack; // ignore: implementation_imports
+import '../base/process_manager.dart';
import '../dart/package_map.dart';
import '../globals.dart';
import 'coverage_collector.dart';
@@ -74,7 +75,7 @@
'FLUTTER_TEST': 'true',
'FONTCONFIG_FILE': _fontConfigFile.path,
};
- return Process.start(executable, arguments, environment: environment);
+ return processManager.start(executable, arguments, environment: environment);
}
void _attachStandardStreams(Process process) {
diff --git a/packages/flutter_tools/lib/src/version.dart b/packages/flutter_tools/lib/src/version.dart
index 4ff3859..953d41e 100644
--- a/packages/flutter_tools/lib/src/version.dart
+++ b/packages/flutter_tools/lib/src/version.dart
@@ -5,6 +5,7 @@
import 'dart:io';
import 'base/process.dart';
+import 'base/process_manager.dart';
import 'cache.dart';
final Set<String> kKnownBranchNames = new Set<String>.from(<String>[
@@ -102,7 +103,7 @@
}
String _runSync(String executable, List<String> arguments, String cwd) {
- ProcessResult results = Process.runSync(executable, arguments, workingDirectory: cwd);
+ ProcessResult results = processManager.runSync(executable, arguments, workingDirectory: cwd);
return results.exitCode == 0 ? results.stdout.trim() : '';
}