Unverified Commit 73c10e8c authored by Zachary Anderson's avatar Zachary Anderson Committed by GitHub

[flutter_tool] process.dart cleanup (#39899)

parent 3712ea63
......@@ -9,8 +9,7 @@ import 'package:meta/meta.dart';
import '../android/android_sdk.dart';
import '../android/android_workflow.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/process_manager.dart';
import '../base/process.dart';
import '../device.dart';
import '../emulator.dart';
import 'android_sdk.dart';
......@@ -50,13 +49,10 @@ class AndroidEmulator extends Emulator {
@override
Future<void> launch() async {
final Future<void> launchResult =
processManager.run(<String>[getEmulatorPath(), '-avd', id])
.then((ProcessResult runResult) {
if (runResult.exitCode != 0) {
throw '${runResult.stdout}\n${runResult.stderr}'.trimRight();
}
});
final Future<void> launchResult = processUtils.run(
<String>[getEmulatorPath(), '-avd', id],
throwOnError: true,
);
// The emulator continues running on a successful launch, so if it hasn't
// quit within 3 seconds we assume that's a success and just return. This
// means that on a slow machine, a failure that takes more than three
......@@ -75,7 +71,8 @@ List<AndroidEmulator> getEmulatorAvds() {
return <AndroidEmulator>[];
}
final String listAvdsOutput = processManager.runSync(<String>[emulatorPath, '-list-avds']).stdout;
final String listAvdsOutput = processUtils.runSync(
<String>[emulatorPath, '-list-avds']).stdout.trim();
final List<AndroidEmulator> emulators = <AndroidEmulator>[];
if (listAvdsOutput != null) {
......
......@@ -7,7 +7,6 @@ import 'package:meta/meta.dart';
import '../base/common.dart';
import '../base/context.dart';
import '../base/file_system.dart';
import '../base/io.dart' show ProcessResult;
import '../base/os.dart';
import '../base/platform.dart';
import '../base/process.dart';
......@@ -526,9 +525,9 @@ class AndroidSdk {
/// First try Java bundled with Android Studio, then sniff JAVA_HOME, then fallback to PATH.
static String findJavaBinary() {
if (android_studio.javaPath != null)
if (android_studio.javaPath != null) {
return fs.path.join(android_studio.javaPath, 'bin', 'java');
}
final String javaHomeEnv = platform.environment[_javaHomeEnvironmentVariable];
if (javaHomeEnv != null) {
......@@ -540,7 +539,11 @@ class AndroidSdk {
// See: http://stackoverflow.com/questions/14292698/how-do-i-check-if-the-java-jdk-is-installed-on-mac.
if (platform.isMacOS) {
try {
final String javaHomeOutput = runCheckedSync(<String>['/usr/libexec/java_home'], hideStdout: true);
final String javaHomeOutput = processUtils.runSync(
<String>['/usr/libexec/java_home'],
throwOnError: true,
hideStdout: true,
).stdout.trim();
if (javaHomeOutput != null) {
final List<String> javaHomeOutputSplit = javaHomeOutput.split('\n');
if ((javaHomeOutputSplit != null) && (javaHomeOutputSplit.isNotEmpty)) {
......@@ -575,7 +578,10 @@ class AndroidSdk {
String get sdkManagerVersion {
if (!processManager.canRun(sdkManagerPath))
throwToolExit('Android sdkmanager not found. Update to the latest Android SDK to resolve this.');
final ProcessResult result = processManager.runSync(<String>[sdkManagerPath, '--version'], environment: sdkManagerEnv);
final RunResult result = processUtils.runSync(
<String>[sdkManagerPath, '--version'],
environment: sdkManagerEnv,
);
if (result.exitCode != 0) {
printTrace('sdkmanager --version failed: exitCode: ${result.exitCode} stdout: ${result.stdout} stderr: ${result.stderr}');
return null;
......
......@@ -5,8 +5,8 @@
import '../base/common.dart';
import '../base/context.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/platform.dart';
import '../base/process.dart';
import '../base/process_manager.dart';
import '../base/version.dart';
import '../globals.dart';
......@@ -290,7 +290,7 @@ class AndroidStudio implements Comparable<AndroidStudio> {
if (!processManager.canRun(javaExecutable)) {
_validationMessages.add('Unable to find bundled Java version.');
} else {
final ProcessResult result = processManager.runSync(<String>[javaExecutable, '-version']);
final RunResult result = processUtils.runSync(<String>[javaExecutable, '-version']);
if (result.exitCode == 0) {
final List<String> versionLines = result.stderr.split('\n');
final String javaVersion = versionLines.length >= 2 ? versionLines[1] : versionLines[0];
......
......@@ -259,7 +259,7 @@ class AndroidLicenseValidator extends DoctorValidator {
}
try {
final Process process = await runCommand(
final Process process = await processUtils.start(
<String>[androidSdk.sdkManagerPath, '--licenses'],
environment: androidSdk.sdkManagerEnv,
);
......@@ -302,7 +302,7 @@ class AndroidLicenseValidator extends DoctorValidator {
}
try {
final Process process = await runCommand(
final Process process = await processUtils.start(
<String>[androidSdk.sdkManagerPath, '--licenses'],
environment: androidSdk.sdkManagerEnv,
);
......
......@@ -145,8 +145,9 @@ Future<void> checkGradleDependencies() async {
final Status progress = logger.startProgress('Ensuring gradle dependencies are up to date...', timeout: timeoutConfiguration.slowOperation);
final FlutterProject flutterProject = FlutterProject.current();
final String gradlew = await gradleUtils.getExecutable(flutterProject);
await runCheckedAsync(
await processUtils.run(
<String>[gradlew, 'dependencies'],
throwOnError: true,
workingDirectory: flutterProject.android.hostAppGradleRoot.path,
environment: _gradleEnv,
);
......@@ -234,13 +235,15 @@ Future<GradleProject> _readGradleProject({bool isLibrary = false}) async {
// Get the properties and tasks from Gradle, so we can determinate the `buildDir`,
// flavors and build types defined in the project. If gradle fails, then check if the failure is due to t
try {
final RunResult propertiesRunResult = await runCheckedAsync(
final RunResult propertiesRunResult = await processUtils.run(
<String>[gradlew, isLibrary ? 'properties' : 'app:properties'],
throwOnError: true,
workingDirectory: hostAppGradleRoot.path,
environment: _gradleEnv,
);
final RunResult tasksRunResult = await runCheckedAsync(
final RunResult tasksRunResult = await processUtils.run(
<String>[gradlew, isLibrary ? 'tasks': 'app:tasks', '--all', '--console=auto'],
throwOnError: true,
workingDirectory: hostAppGradleRoot.path,
environment: _gradleEnv,
);
......@@ -306,22 +309,29 @@ Future<String> _initializeGradle(FlutterProject project) async {
injectGradleWrapperIfNeeded(android);
final String gradle = _locateGradlewExecutable(android);
if (gradle == null)
if (gradle == null) {
status.stop();
throwToolExit('Unable to locate gradlew script');
}
printTrace('Using gradle from $gradle.');
// Validates the Gradle executable by asking for its version.
// Makes Gradle Wrapper download and install Gradle distribution, if needed.
try {
await runCheckedAsync(<String>[gradle, '-v'], environment: _gradleEnv);
} catch (e) {
if (e is ProcessException &&
e.toString().contains('java.io.FileNotFoundException: https://downloads.gradle.org') ||
e.toString().contains('java.io.IOException: Unable to tunnel through proxy')) {
await processUtils.run(
<String>[gradle, '-v'],
throwOnError: true,
environment: _gradleEnv,
);
} on ProcessException catch (e) {
final String error = e.toString();
if (error.contains('java.io.FileNotFoundException: https://downloads.gradle.org') ||
error.contains('java.io.IOException: Unable to tunnel through proxy')) {
throwToolExit('$gradle threw an error while trying to update itself.\n$e');
}
rethrow;
} finally {
status.stop();
}
status.stop();
return gradle;
}
......@@ -595,7 +605,7 @@ Future<void> buildGradleAar({
int exitCode = 1;
try {
exitCode = await runCommandAndStreamOutput(
exitCode = await processUtils.stream(
command,
workingDirectory: project.android.hostAppGradleRoot.path,
allowReentrantFlutter: true,
......@@ -633,7 +643,7 @@ Future<void> _buildGradleProjectV1(FlutterProject project) async {
multilineOutput: true,
);
final Stopwatch sw = Stopwatch()..start();
final int exitCode = await runCommandAndStreamOutput(
final int exitCode = await processUtils.stream(
<String>[fs.file(gradlew).absolute.path, 'build'],
workingDirectory: project.android.hostAppGradleRoot.path,
allowReentrantFlutter: true,
......@@ -756,7 +766,7 @@ Future<void> _buildGradleProjectV2(
final Stopwatch sw = Stopwatch()..start();
int exitCode = 1;
try {
exitCode = await runCommandAndStreamOutput(
exitCode = await processUtils.stream(
command,
workingDirectory: flutterProject.android.hostAppGradleRoot.path,
allowReentrantFlutter: true,
......
......@@ -13,6 +13,7 @@ import 'android/gradle.dart';
import 'base/common.dart';
import 'base/context.dart';
import 'base/file_system.dart';
import 'base/io.dart';
import 'base/os.dart' show os;
import 'base/process.dart';
import 'base/user_messages.dart';
......@@ -115,14 +116,17 @@ class AndroidApk extends ApplicationPackage {
String apptStdout;
try {
apptStdout = runCheckedSync(<String>[
aaptPath,
'dump',
'xmltree',
apk.path,
'AndroidManifest.xml',
]);
} catch (error) {
apptStdout = processUtils.runSync(
<String>[
aaptPath,
'dump',
'xmltree',
apk.path,
'AndroidManifest.xml',
],
throwOnError: true,
).stdout.trim();
} on ProcessException catch (error) {
printError('Failed to extract manifest from APK: $error.');
return null;
}
......
......@@ -69,7 +69,10 @@ class GenSnapshot {
outputFilter = (String line) => line != kStripWarning ? line : null;
}
return runCommandAndStreamOutput(<String>[snapshotterPath, ...args], mapFunction: outputFilter);
return processUtils.stream(
<String>[snapshotterPath, ...args],
mapFunction: outputFilter,
);
}
}
......
......@@ -154,30 +154,45 @@ class _PosixUtils extends OperatingSystemUtils {
@override
void zip(Directory data, File zipFile) {
runSync(<String>['zip', '-r', '-q', zipFile.path, '.'], workingDirectory: data.path);
processUtils.runSync(
<String>['zip', '-r', '-q', zipFile.path, '.'],
workingDirectory: data.path,
throwOnError: true,
);
}
// unzip -o -q zipfile -d dest
@override
void unzip(File file, Directory targetDirectory) {
runSync(<String>['unzip', '-o', '-q', file.path, '-d', targetDirectory.path]);
processUtils.runSync(
<String>['unzip', '-o', '-q', file.path, '-d', targetDirectory.path],
throwOnError: true,
);
}
@override
bool verifyZip(File zipFile) => exitsHappy(<String>['zip', '-T', zipFile.path]);
bool verifyZip(File zipFile) =>
processUtils.exitsHappySync(<String>['zip', '-T', zipFile.path]);
// tar -xzf tarball -C dest
@override
void unpack(File gzippedTarFile, Directory targetDirectory) {
runSync(<String>['tar', '-xzf', gzippedTarFile.path, '-C', targetDirectory.path]);
processUtils.runSync(
<String>['tar', '-xzf', gzippedTarFile.path, '-C', targetDirectory.path],
throwOnError: true,
);
}
@override
bool verifyGzip(File gzippedFile) => exitsHappy(<String>['gzip', '-t', gzippedFile.path]);
bool verifyGzip(File gzippedFile) =>
processUtils.exitsHappySync(<String>['gzip', '-t', gzippedFile.path]);
@override
File makePipe(String path) {
runSync(<String>['mkfifo', path]);
processUtils.runSync(
<String>['mkfifo', path],
throwOnError: true,
);
return fs.file(path);
}
......@@ -187,12 +202,12 @@ class _PosixUtils extends OperatingSystemUtils {
String get name {
if (_name == null) {
if (platform.isMacOS) {
final List<ProcessResult> results = <ProcessResult>[
processManager.runSync(<String>['sw_vers', '-productName']),
processManager.runSync(<String>['sw_vers', '-productVersion']),
processManager.runSync(<String>['sw_vers', '-buildVersion']),
final List<RunResult> results = <RunResult>[
processUtils.runSync(<String>['sw_vers', '-productName']),
processUtils.runSync(<String>['sw_vers', '-productVersion']),
processUtils.runSync(<String>['sw_vers', '-buildVersion']),
];
if (results.every((ProcessResult result) => result.exitCode == 0)) {
if (results.every((RunResult result) => result.exitCode == 0)) {
_name = '${results[0].stdout.trim()} ${results[1].stdout
.trim()} ${results[2].stdout.trim()}';
}
......
......@@ -9,6 +9,7 @@ import '../base/build.dart';
import '../base/common.dart';
import '../base/context.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/logger.dart';
import '../base/process.dart';
import '../base/version.dart';
......@@ -142,14 +143,18 @@ class BuildAotCommand extends BuildSubCommand with TargetPlatformBasedDevelopmen
// Merge arch-specific App.frameworks into a multi-arch App.framework.
if ((await Future.wait<int>(exitCodes.values)).every((int buildExitCode) => buildExitCode == 0)) {
final Iterable<String> dylibs = iosBuilds.values.map<String>((String outputDir) => fs.path.join(outputDir, 'App.framework', 'App'));
final Iterable<String> dylibs = iosBuilds.values.map<String>(
(String outputDir) => fs.path.join(outputDir, 'App.framework', 'App'));
fs.directory(fs.path.join(outputPath, 'App.framework'))..createSync();
await runCheckedAsync(<String>[
'lipo',
...dylibs,
'-create',
'-output', fs.path.join(outputPath, 'App.framework', 'App'),
]);
await processUtils.run(
<String>[
'lipo',
...dylibs,
'-create',
'-output', fs.path.join(outputPath, 'App.framework', 'App'),
],
throwOnError: true,
);
} else {
status?.cancel();
exitCodes.forEach((DarwinArch iosArch, Future<int> exitCodeFuture) async {
......@@ -173,10 +178,10 @@ class BuildAotCommand extends BuildSubCommand with TargetPlatformBasedDevelopmen
throwToolExit('Snapshotting exited with non-zero exit code: $snapshotExitCode');
}
}
} on String catch (error) {
// Catch the String exceptions thrown from the `runCheckedSync` methods below.
} on ProcessException catch (error) {
// Catch the String exceptions thrown from the `runSync` methods below.
status?.cancel();
printError(error);
printError(error.toString());
return null;
}
status?.stop();
......
......@@ -61,7 +61,7 @@ class ChannelCommand extends FlutterCommand {
showAll = showAll || currentChannel != currentBranch;
printStatus('Flutter channels:');
final int result = await runCommandAndStreamOutput(
final int result = await processUtils.stream(
<String>['git', 'branch', '-r'],
workingDirectory: Cache.flutterRoot,
mapFunction: (String line) {
......@@ -111,28 +111,28 @@ class ChannelCommand extends FlutterCommand {
static Future<void> _checkout(String branchName) async {
// Get latest refs from upstream.
int result = await runCommandAndStreamOutput(
int result = await processUtils.stream(
<String>['git', 'fetch'],
workingDirectory: Cache.flutterRoot,
prefix: 'git: ',
);
if (result == 0) {
result = await runCommandAndStreamOutput(
result = await processUtils.stream(
<String>['git', 'show-ref', '--verify', '--quiet', 'refs/heads/$branchName'],
workingDirectory: Cache.flutterRoot,
prefix: 'git: ',
);
if (result == 0) {
// branch already exists, try just switching to it
result = await runCommandAndStreamOutput(
result = await processUtils.stream(
<String>['git', 'checkout', branchName, '--'],
workingDirectory: Cache.flutterRoot,
prefix: 'git: ',
);
} else {
// branch does not exist, we have to create it
result = await runCommandAndStreamOutput(
result = await processUtils.stream(
<String>['git', 'checkout', '--track', '-b', branchName, 'origin/$branchName'],
workingDirectory: Cache.flutterRoot,
prefix: 'git: ',
......
......@@ -292,7 +292,7 @@ Future<void> _runTests(List<String> testArgs, String observatoryUri) async {
PackageMap.globalPackagesPath = fs.path.normalize(fs.path.absolute(PackageMap.globalPackagesPath));
final String dartVmPath = fs.path.join(dartSdkPath, 'bin', 'dart');
final int result = await runCommandAndStreamOutput(
final int result = await processUtils.stream(
<String>[
dartVmPath,
...dartVmFlags,
......
......@@ -76,9 +76,10 @@ class FormatCommand extends FlutterCommand {
...argResults.rest,
];
final int result = await runCommandAndStreamOutput(command);
if (result != 0)
final int result = await processUtils.stream(command);
if (result != 0) {
throwToolExit('Formatting failed: $result', exitCode: result);
}
return null;
}
......
......@@ -5,8 +5,7 @@
import '../artifacts.dart';
import '../base/common.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/process_manager.dart';
import '../base/process.dart';
import '../build_info.dart';
import '../cache.dart';
import '../globals.dart';
......@@ -284,7 +283,7 @@ class ArtifactUnpacker {
_deleteFrameworkIfPresent(
fs.path.join(targetDirectory, fs.path.basename(frameworkPath)));
final ProcessResult result = processManager
final RunResult result = processUtils
.runSync(<String>['cp', '-R', frameworkPath, targetDirectory]);
if (result.exitCode != 0) {
throw Exception(
......
......@@ -121,7 +121,7 @@ class UpgradeCommandRunner {
}
Future<void> flutterUpgradeContinue() async {
final int code = await runCommandAndStreamOutput(
final int code = await processUtils.stream(
<String>[
fs.path.join('bin', 'flutter'),
'upgrade',
......@@ -146,9 +146,11 @@ class UpgradeCommandRunner {
Future<bool> hasUncomittedChanges() async {
try {
final RunResult result = await runCheckedAsync(<String>[
'git', 'status', '-s'
], workingDirectory: Cache.flutterRoot);
final RunResult result = await processUtils.run(
<String>['git', 'status', '-s'],
throwOnError: true,
workingDirectory: Cache.flutterRoot,
);
return result.stdout.trim().isNotEmpty;
} on ProcessException catch (error) {
throwToolExit(
......@@ -167,9 +169,11 @@ class UpgradeCommandRunner {
/// Exits tool if there is no upstream.
Future<void> verifyUpstreamConfigured() async {
try {
await runCheckedAsync(<String>[
'git', 'rev-parse', '@{u}',
], workingDirectory: Cache.flutterRoot);
await processUtils.run(
<String>[ 'git', 'rev-parse', '@{u}'],
throwOnError: true,
workingDirectory: Cache.flutterRoot,
);
} catch (e) {
throwToolExit(
'Unable to upgrade Flutter: no origin repository configured. '
......@@ -191,9 +195,11 @@ class UpgradeCommandRunner {
tag = 'v${gitTagVersion.x}.${gitTagVersion.y}.${gitTagVersion.z}';
}
try {
await runCheckedAsync(<String>[
'git', 'reset', '--hard', tag,
], workingDirectory: Cache.flutterRoot);
await processUtils.run(
<String>['git', 'reset', '--hard', tag],
throwOnError: true,
workingDirectory: Cache.flutterRoot,
);
} on ProcessException catch (error) {
throwToolExit(
'Unable to upgrade Flutter: The tool could not update to the version $tag. '
......@@ -218,7 +224,7 @@ class UpgradeCommandRunner {
/// If there haven't been any hot fixes or local changes, this is equivalent
/// to a fast-forward.
Future<void> attemptFastForward() async {
final int code = await runCommandAndStreamOutput(
final int code = await processUtils.stream(
<String>['git', 'pull', '--ff'],
workingDirectory: Cache.flutterRoot,
mapFunction: (String line) => matchesGitLine(line) ? null : line,
......@@ -236,7 +242,7 @@ class UpgradeCommandRunner {
Future<void> precacheArtifacts() async {
printStatus('');
printStatus('Upgrading engine...');
final int code = await runCommandAndStreamOutput(
final int code = await processUtils.stream(
<String>[
fs.path.join('bin', 'flutter'), '--no-color', '--no-version-check', 'precache',
],
......@@ -263,7 +269,7 @@ class UpgradeCommandRunner {
Future<void> runDoctor() async {
printStatus('');
printStatus('Running flutter doctor...');
await runCommandAndStreamOutput(
await processUtils.stream(
<String>[
fs.path.join('bin', 'flutter'), '--no-version-check', 'doctor',
],
......
......@@ -37,8 +37,9 @@ class VersionCommand extends FlutterCommand {
Future<List<String>> getTags() async {
RunResult runResult;
try {
runResult = await runCheckedAsync(
runResult = await processUtils.run(
<String>['git', 'tag', '-l', 'v*', '--sort=-creatordate'],
throwOnError: true,
workingDirectory: Cache.flutterRoot,
);
} on ProcessException catch (error) {
......@@ -83,8 +84,9 @@ class VersionCommand extends FlutterCommand {
}
try {
await runCheckedAsync(
await processUtils.run(
<String>['git', 'checkout', 'v$version'],
throwOnError: true,
workingDirectory: Cache.flutterRoot,
);
} catch (e) {
......@@ -101,7 +103,7 @@ class VersionCommand extends FlutterCommand {
// if necessary.
printStatus('');
printStatus('Downloading engine...');
int code = await runCommandAndStreamOutput(<String>[
int code = await processUtils.stream(<String>[
fs.path.join('bin', 'flutter'),
'--no-color',
'precache',
......@@ -128,7 +130,7 @@ class VersionCommand extends FlutterCommand {
// Run a doctor check in case system requirements have changed.
printStatus('');
printStatus('Running flutter doctor...');
code = await runCommandAndStreamOutput(
code = await processUtils.stream(
<String>[
fs.path.join('bin', 'flutter'),
'doctor',
......
......@@ -19,6 +19,7 @@ import 'base/io.dart';
import 'base/logger.dart';
import 'base/os.dart';
import 'base/platform.dart';
import 'base/process.dart';
import 'base/time.dart';
import 'base/user_messages.dart';
import 'base/utils.dart';
......@@ -101,6 +102,7 @@ Future<T> runInContext<T>(
Logger: () => platform.isWindows ? WindowsStdoutLogger() : StdoutLogger(),
MacOSWorkflow: () => const MacOSWorkflow(),
OperatingSystemUtils: () => OperatingSystemUtils(),
ProcessUtils: () => ProcessUtils(),
SimControl: () => SimControl(),
Stdio: () => const Stdio(),
SystemClock: () => const SystemClock(),
......
......@@ -8,6 +8,7 @@ import 'package:meta/meta.dart';
import '../base/common.dart';
import '../base/file_system.dart';
import '../base/io.dart' as io;
import '../base/logger.dart';
import '../base/platform.dart';
import '../base/process.dart';
......@@ -156,22 +157,25 @@ Future<void> pub(
int code;
while (true) {
attempts += 1;
code = await runCommandAndStreamOutput(
code = await processUtils.stream(
_pubCommand(arguments),
workingDirectory: directory,
mapFunction: filter,
environment: _createPubEnvironment(context),
);
if (code != 69) // UNAVAILABLE in https://github.com/dart-lang/pub/blob/master/lib/src/exit_codes.dart
if (code != 69) { // UNAVAILABLE in https://github.com/dart-lang/pub/blob/master/lib/src/exit_codes.dart
break;
}
printStatus('$failureMessage ($code) -- attempting retry $attempts in $duration second${ duration == 1 ? "" : "s"}...');
await Future<void>.delayed(Duration(seconds: duration));
if (duration < 64)
if (duration < 64) {
duration *= 2;
}
}
assert(code != null);
if (code != 0)
if (code != 0) {
throwToolExit('$failureMessage ($code)', exitCode: code);
}
}
/// Runs pub in 'interactive' mode, directly piping the stdin stream of this
......@@ -182,13 +186,26 @@ Future<void> pubInteractively(
String directory,
}) async {
Cache.releaseLockEarly();
final int code = await runInteractively(
final io.Process process = await processUtils.start(
_pubCommand(arguments),
workingDirectory: directory,
environment: _createPubEnvironment(PubContext.interactive),
);
if (code != 0)
// Pipe the Flutter tool stdin to the pub stdin.
unawaited(process.stdin.addStream(io.stdin));
// Pipe the put stdout and stderr to the tool stdout and stderr.
await Future.wait<dynamic>(<Future<dynamic>>[
io.stdout.addStream(process.stdout),
io.stderr.addStream(process.stderr),
]);
// Wait for pub to exit.
final int code = await process.exitCode;
if (code != 0) {
throwToolExit('pub finished with exit code $code', exitCode: code);
}
}
/// The command used for running pub.
......
......@@ -14,7 +14,7 @@ import 'base/file_system.dart';
import 'base/logger.dart';
import 'base/os.dart';
import 'base/platform.dart';
import 'base/process_manager.dart';
import 'base/process.dart';
import 'base/terminal.dart';
import 'base/user_messages.dart';
import 'base/utils.dart';
......@@ -607,7 +607,7 @@ class FlutterValidator extends DoctorValidator {
bool _genSnapshotRuns(String genSnapshotPath) {
const int kExpectedExitCode = 255;
try {
return processManager.runSync(<String>[genSnapshotPath]).exitCode == kExpectedExitCode;
return processUtils.runSync(<String>[genSnapshotPath]).exitCode == kExpectedExitCode;
} catch (error) {
return false;
}
......
......@@ -8,8 +8,7 @@ import 'dart:math' as math;
import 'android/android_emulator.dart';
import 'android/android_sdk.dart';
import 'base/context.dart';
import 'base/io.dart' show ProcessResult;
import 'base/process_manager.dart';
import 'base/process.dart';
import 'device.dart';
import 'globals.dart';
import 'ios/ios_emulators.dart';
......@@ -118,7 +117,7 @@ class EmulatorManager {
'-k', sdkId,
'-d', device,
];
final ProcessResult runResult = processManager.runSync(args,
final RunResult runResult = processUtils.runSync(args,
environment: androidSdk?.sdkManagerEnv);
return CreateEmulatorResult(
name,
......@@ -139,10 +138,11 @@ class EmulatorManager {
'device',
'-c',
];
final ProcessResult runResult = processManager.runSync(args,
final RunResult runResult = processUtils.runSync(args,
environment: androidSdk?.sdkManagerEnv);
if (runResult.exitCode != 0)
if (runResult.exitCode != 0) {
return null;
}
final List<String> availableDevices = runResult.stdout
.split('\n')
......@@ -165,7 +165,7 @@ class EmulatorManager {
'avd',
'-n', 'temp',
];
final ProcessResult runResult = processManager.runSync(args,
final RunResult runResult = processUtils.runSync(args,
environment: androidSdk?.sdkManagerEnv);
// Get the list of IDs that match our criteria
......
......@@ -32,7 +32,7 @@ class FuchsiaDevFinder {
'list',
'-full'
];
final RunResult result = await runAsync(command);
final RunResult result = await processUtils.run(command);
if (result.exitCode != 0) {
printError('dev_finder failed: ${result.stderr}');
return null;
......@@ -57,7 +57,7 @@ class FuchsiaDevFinder {
'-device-limit', '1',
deviceName
];
final RunResult result = await runAsync(command);
final RunResult result = await processUtils.run(command);
if (result.exitCode != 0) {
printError('dev_finder failed: ${result.stderr}');
return null;
......
......@@ -454,7 +454,7 @@ class FuchsiaDevice extends Device {
throwToolExit('Cannot interact with device. No ssh config.\n'
'Try setting FUCHSIA_SSH_CONFIG or FUCHSIA_BUILD_DIR.');
}
return await runAsync(<String>[
return await processUtils.run(<String>[
'ssh',
'-F',
fuchsiaArtifacts.sshConfig.absolute.path,
......
......@@ -85,7 +85,7 @@ class FuchsiaKernelCompiler {
fuchsiaArtifacts.kernelCompiler.path,
...flags,
];
final Process process = await runCommand(command);
final Process process = await processUtils.start(command);
final Status status = logger.startProgress(
'Building Fuchsia application...',
timeout: null,
......
......@@ -118,7 +118,7 @@ class FuchsiaPM {
'-l',
'$host:$port',
];
final Process process = await runCommand(command);
final Process process = await processUtils.start(command);
process.stdout
.transform(utf8.decoder)
.transform(const LineSplitter())
......@@ -152,7 +152,7 @@ class FuchsiaPM {
throwToolExit('Fuchsia pm tool not found');
}
final List<String> command = <String>[fuchsiaArtifacts.pm.path] + args;
final RunResult result = await runAsync(command);
final RunResult result = await processUtils.run(command);
return result.exitCode == 0;
}
}
......
......@@ -96,8 +96,9 @@ Future<Map<String, String>> getCodeSigningIdentityDevelopmentTeam({
BuildableIOSApp iosApp,
}) async {
final Map<String, String> buildSettings = iosApp.project.buildSettings;
if (buildSettings == null)
if (buildSettings == null) {
return null;
}
// If the user already has it set in the project build settings itself,
// continue with that.
......@@ -114,16 +115,21 @@ Future<Map<String, String>> getCodeSigningIdentityDevelopmentTeam({
// If the user's environment is missing the tools needed to find and read
// certificates, abandon. Tools should be pre-equipped on macOS.
if (!exitsHappy(const <String>['which', 'security']) || !exitsHappy(const <String>['which', 'openssl']))
if (!await processUtils.exitsHappy(const <String>['which', 'security']) ||
!await processUtils.exitsHappy(const <String>['which', 'openssl'])) {
return null;
}
const List<String> findIdentityCommand =
<String>['security', 'find-identity', '-p', 'codesigning', '-v'];
String findIdentityStdout;
try {
findIdentityStdout = runCheckedSync(findIdentityCommand);
} catch (error) {
findIdentityStdout = (await processUtils.run(
findIdentityCommand,
throwOnError: true,
)).stdout.trim();
} on ProcessException catch (error) {
printTrace('Unexpected failure from find-identity: $error.');
return null;
}
......@@ -142,8 +148,9 @@ Future<Map<String, String>> getCodeSigningIdentityDevelopmentTeam({
final String signingIdentity = await _chooseSigningIdentity(validCodeSigningIdentities);
// If none are chosen, return null.
if (signingIdentity == null)
if (signingIdentity == null) {
return null;
}
printStatus('Signing iOS app for device deployment using developer identity: "$signingIdentity"');
......@@ -153,20 +160,23 @@ Future<Map<String, String>> getCodeSigningIdentityDevelopmentTeam({
?.group(1);
// If `security`'s output format changes, we'd have to update the above regex.
if (signingCertificateId == null)
if (signingCertificateId == null) {
return null;
}
String signingCertificateStdout;
try {
signingCertificateStdout = runCheckedSync(
<String>['security', 'find-certificate', '-c', signingCertificateId, '-p']
);
} catch (error) {
signingCertificateStdout = (await processUtils.run(
<String>['security', 'find-certificate', '-c', signingCertificateId, '-p'],
throwOnError: true,
)).stdout.trim();
} on ProcessException catch (error) {
printTrace('Couldn\'t find the certificate: $error.');
return null;
}
final Process opensslProcess = await runCommand(const <String>['openssl', 'x509', '-subject']);
final Process opensslProcess = await processUtils.start(
const <String>['openssl', 'x509', '-subject']);
await (opensslProcess.stdin..write(signingCertificateStdout)).close();
final String opensslOutput = await utf8.decodeStream(opensslProcess.stdout);
......
......@@ -64,7 +64,7 @@ class IOSDeploy {
iosDeployEnv['PATH'] = '/usr/bin:${iosDeployEnv['PATH']}';
iosDeployEnv.addEntries(<MapEntry<String, String>>[cache.dyLdLibEntry]);
return await runCommandAndStreamOutput(
return await processUtils.stream(
launchCommand,
mapFunction: _monitorInstallationFailure,
trace: true,
......@@ -195,8 +195,9 @@ class IOSDevice extends Device {
Future<bool> isAppInstalled(ApplicationPackage app) async {
RunResult apps;
try {
apps = await runCheckedAsync(
apps = await processUtils.run(
<String>[_installerPath, '--list-apps'],
throwOnError: true,
environment: Map<String, String>.fromEntries(
<MapEntry<String, String>>[cache.dyLdLibEntry],
),
......@@ -220,8 +221,9 @@ class IOSDevice extends Device {
}
try {
await runCheckedAsync(
await processUtils.run(
<String>[_installerPath, '-i', iosApp.deviceBundlePath],
throwOnError: true,
environment: Map<String, String>.fromEntries(
<MapEntry<String, String>>[cache.dyLdLibEntry],
),
......@@ -236,8 +238,9 @@ class IOSDevice extends Device {
@override
Future<bool> uninstallApp(ApplicationPackage app) async {
try {
await runCheckedAsync(
await processUtils.run(
<String>[_installerPath, '-U', app.id],
throwOnError: true,
environment: Map<String, String>.fromEntries(
<MapEntry<String, String>>[cache.dyLdLibEntry],
),
......@@ -610,7 +613,7 @@ class _IOSDevicePortForwarder extends DevicePortForwarder {
while (!connected) {
printTrace('attempting to forward device port $devicePort to host port $hostPort');
// Usage: iproxy LOCAL_TCP_PORT DEVICE_TCP_PORT UDID
process = await runCommand(
process = await processUtils.start(
<String>[
device._iproxyPath,
hostPort.toString(),
......
......@@ -47,7 +47,7 @@ class IOSEmulator extends Emulator {
.followedBy(<String>['-a', xcode.getSimulatorPath()])
.toList();
final RunResult launchResult = await runAsync(args);
final RunResult launchResult = await processUtils.run(args);
if (launchResult.exitCode != 0) {
printError('$launchResult');
return false;
......
......@@ -107,7 +107,7 @@ class IMobileDevice {
final String _idevicescreenshotPath;
bool get isInstalled {
_isInstalled ??= exitsHappy(
_isInstalled ??= processUtils.exitsHappySync(
<String>[
_ideviceIdPath,
'-h'
......@@ -136,7 +136,7 @@ class IMobileDevice {
final Map<String, String> executionEnv = Map<String, String>.fromEntries(
<MapEntry<String, String>>[cache.dyLdLibEntry]
);
final ProcessResult ideviceResult = (await runAsync(
final ProcessResult ideviceResult = (await processUtils.run(
<String>[
_ideviceinfoPath,
'-u',
......@@ -150,7 +150,7 @@ class IMobileDevice {
}
// If no device is attached, we're unable to detect any problems. Assume all is well.
final ProcessResult result = (await runAsync(
final ProcessResult result = (await processUtils.run(
<String>[
_ideviceIdPath,
'-l',
......@@ -161,7 +161,7 @@ class IMobileDevice {
_isWorking = true;
} else {
// Check that we can look up the names of any attached devices.
_isWorking = await exitsHappyAsync(
_isWorking = await processUtils.exitsHappy(
<String>[_idevicenamePath],
environment: executionEnv,
);
......@@ -229,7 +229,7 @@ class IMobileDevice {
/// Starts `idevicesyslog` and returns the running process.
Future<Process> startLogger(String deviceID) {
return runCommand(
return processUtils.start(
<String>[
_idevicesyslogPath,
'-u',
......@@ -243,11 +243,12 @@ class IMobileDevice {
/// Captures a screenshot to the specified outputFile.
Future<void> takeScreenshot(File outputFile) {
return runCheckedAsync(
return processUtils.run(
<String>[
_idevicescreenshotPath,
outputFile.path
],
throwOnError: true,
environment: Map<String, String>.fromEntries(
<MapEntry<String, String>>[cache.dyLdLibEntry]
),
......@@ -318,8 +319,9 @@ Future<XcodeBuildResult> buildXcodeProject({
}
Map<String, String> autoSigningConfigs;
if (codesign && buildForDevice)
if (codesign && buildForDevice) {
autoSigningConfigs = await getCodeSigningIdentityDevelopmentTeam(iosApp: app);
}
// Before the build, all service definitions must be updated and the dylibs
// copied over to a location that is suitable for Xcodebuild to find them.
......@@ -440,7 +442,7 @@ Future<XcodeBuildResult> buildXcodeProject({
final Stopwatch sw = Stopwatch()..start();
initialBuildStatus = logger.startProgress('Running Xcode build...', timeout: timeoutConfiguration.fastOperation);
final RunResult buildResult = await runAsync(
final RunResult buildResult = await processUtils.run(
buildCommands,
workingDirectory: app.project.hostAppRoot.path,
allowReentrantFlutter: true,
......@@ -476,8 +478,9 @@ Future<XcodeBuildResult> buildXcodeProject({
const Duration showBuildSettingsTimeout = Duration(minutes: 1);
Map<String, String> buildSettings;
try {
final RunResult showBuildSettingsResult = await runCheckedAsync(
final RunResult showBuildSettingsResult = await processUtils.run(
showBuildSettingsCommand,
throwOnError: true,
workingDirectory: app.project.hostAppRoot.path,
timeout: showBuildSettingsTimeout,
timeoutRetries: 1,
......@@ -677,7 +680,10 @@ Future<void> _copyServiceFrameworks(List<Map<String, String>> services, Director
continue;
}
// Shell out so permissions on the dylib are preserved.
await runCheckedAsync(<String>['/bin/cp', dylib.path, frameworksDirectory.path]);
await processUtils.run(
<String>['/bin/cp', dylib.path, frameworksDirectory.path],
throwOnError: true,
);
}
}
......
......@@ -4,6 +4,7 @@
import '../base/context.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/process.dart';
import '../convert.dart';
import '../globals.dart';
......@@ -38,9 +39,12 @@ class PlistParser {
final List<String> args = <String>[
executable, '-convert', 'json', '-o', '-', normalizedPlistPath,
];
final String jsonContent = runCheckedSync(args);
final String jsonContent = processUtils.runSync(
args,
throwOnError: true,
).stdout.trim();
return json.decode(jsonContent);
} catch (error) {
} on ProcessException catch (error) {
printTrace('$error');
return const <String, dynamic>{};
}
......
......@@ -130,7 +130,7 @@ class SimControl {
}
Future<bool> isInstalled(String deviceId, String appId) {
return exitsHappyAsync(<String>[
return processUtils.exitsHappy(<String>[
_xcrunPath,
'simctl',
'get_app_container',
......@@ -142,7 +142,10 @@ class SimControl {
Future<RunResult> install(String deviceId, String appPath) {
Future<RunResult> result;
try {
result = runCheckedAsync(<String>[_xcrunPath, 'simctl', 'install', deviceId, appPath]);
result = processUtils.run(
<String>[_xcrunPath, 'simctl', 'install', deviceId, appPath],
throwOnError: true,
);
} on ProcessException catch (exception) {
throwToolExit('Unable to install $appPath on $deviceId:\n$exception');
}
......@@ -152,7 +155,10 @@ class SimControl {
Future<RunResult> uninstall(String deviceId, String appId) {
Future<RunResult> result;
try {
result = runCheckedAsync(<String>[_xcrunPath, 'simctl', 'uninstall', deviceId, appId]);
result = processUtils.run(
<String>[_xcrunPath, 'simctl', 'uninstall', deviceId, appId],
throwOnError: true,
);
} on ProcessException catch (exception) {
throwToolExit('Unable to uninstall $appId from $deviceId:\n$exception');
}
......@@ -162,14 +168,17 @@ class SimControl {
Future<RunResult> launch(String deviceId, String appIdentifier, [ List<String> launchArgs ]) {
Future<RunResult> result;
try {
result = runCheckedAsync(<String>[
_xcrunPath,
'simctl',
'launch',
deviceId,
appIdentifier,
...?launchArgs,
]);
result = processUtils.run(
<String>[
_xcrunPath,
'simctl',
'launch',
deviceId,
appIdentifier,
...?launchArgs,
],
throwOnError: true,
);
} on ProcessException catch (exception) {
throwToolExit('Unable to launch $appIdentifier on $deviceId:\n$exception');
}
......@@ -178,7 +187,10 @@ class SimControl {
Future<void> takeScreenshot(String deviceId, String outputPath) async {
try {
await runCheckedAsync(<String>[_xcrunPath, 'simctl', 'io', deviceId, 'screenshot', outputPath]);
await processUtils.run(
<String>[_xcrunPath, 'simctl', 'io', deviceId, 'screenshot', outputPath],
throwOnError: true,
);
} on ProcessException catch (exception) {
throwToolExit('Unable to take screenshot of $deviceId:\n$exception');
}
......@@ -518,20 +530,22 @@ class IOSSimulator extends Device {
/// Launches the device log reader process on the host.
Future<Process> launchDeviceLogTool(IOSSimulator device) async {
// Versions of iOS prior to iOS 11 log to the simulator syslog file.
if (await device.sdkMajorVersion < 11)
return runCommand(<String>['tail', '-n', '0', '-F', device.logFilePath]);
if (await device.sdkMajorVersion < 11) {
return processUtils.start(<String>['tail', '-n', '0', '-F', device.logFilePath]);
}
// For iOS 11 and above, use /usr/bin/log to tail process logs.
// Run in interactive mode (via script), otherwise /usr/bin/log buffers in 4k chunks. (radar: 34420207)
return runCommand(<String>[
return processUtils.start(<String>[
'script', '/dev/null', '/usr/bin/log', 'stream', '--style', 'syslog', '--predicate', 'processImagePath CONTAINS "${device.id}"',
]);
}
Future<Process> launchSystemLogTool(IOSSimulator device) async {
// Versions of iOS prior to 11 tail the simulator syslog file.
if (await device.sdkMajorVersion < 11)
return runCommand(<String>['tail', '-n', '0', '-F', '/private/var/log/system.log']);
if (await device.sdkMajorVersion < 11) {
return processUtils.start(<String>['tail', '-n', '0', '-F', '/private/var/log/system.log']);
}
// For iOS 11 and later, all relevant detail is in the device log.
return null;
......
......@@ -14,7 +14,6 @@ import '../base/logger.dart';
import '../base/os.dart';
import '../base/platform.dart';
import '../base/process.dart';
import '../base/process_manager.dart';
import '../base/utils.dart';
import '../build_info.dart';
import '../cache.dart';
......@@ -211,7 +210,9 @@ class XcodeProjectInterpreter {
return;
}
try {
final ProcessResult result = processManager.runSync(<String>[_executable, '-version']);
final RunResult result = processUtils.runSync(
<String>[_executable, '-version'],
);
if (result.exitCode != 0) {
return;
}
......@@ -255,16 +256,20 @@ class XcodeProjectInterpreter {
/// version below.
Map<String, String> getBuildSettings(String projectPath, String target) {
try {
final String out = runCheckedSync(<String>[
_executable,
'-project',
fs.path.absolute(projectPath),
'-target',
target,
'-showBuildSettings',
], workingDirectory: projectPath);
final String out = processUtils.runSync(
<String>[
_executable,
'-project',
fs.path.absolute(projectPath),
'-target',
target,
'-showBuildSettings',
],
throwOnError: true,
workingDirectory: projectPath,
).stdout.trim();
return parseXcodeBuildSettings(out);
} catch(error) {
} on ProcessException catch (error) {
printTrace('Unexpected failure to get the build settings: $error.');
return const <String, String>{};
}
......@@ -291,8 +296,9 @@ class XcodeProjectInterpreter {
// showBuildSettings is reported to ocassionally timeout. Here, we give it
// a lot of wiggle room (locally on Flutter Gallery, this takes ~1s).
// When there is a timeout, we retry once.
final RunResult result = await runCheckedAsync(
final RunResult result = await processUtils.run(
showBuildSettingsCommand,
throwOnError: true,
workingDirectory: projectPath,
timeout: timeout,
timeoutRetries: 1,
......@@ -313,7 +319,7 @@ class XcodeProjectInterpreter {
}
void cleanWorkspace(String workspacePath, String scheme) {
runSync(<String>[
processUtils.runSync(<String>[
_executable,
'-workspace',
workspacePath,
......@@ -325,11 +331,15 @@ class XcodeProjectInterpreter {
}
Future<XcodeProjectInfo> getInfo(String projectPath, {String projectFilename}) async {
final RunResult result = await runCheckedAsync(<String>[
_executable,
'-list',
if (projectFilename != null) ...<String>['-project', projectFilename],
], workingDirectory: projectPath);
final RunResult result = await processUtils.run(
<String>[
_executable,
'-list',
if (projectFilename != null) ...<String>['-project', projectFilename],
],
throwOnError: true,
workingDirectory: projectPath,
);
return XcodeProjectInfo.fromXcodeBuildOutput(result.toString());
}
}
......
......@@ -67,10 +67,11 @@ class CocoaPods {
String get cocoaPodsMinimumVersion => '1.6.0';
String get cocoaPodsRecommendedVersion => '1.6.0';
Future<bool> get isInstalled => exitsHappyAsync(<String>['which', 'pod']);
Future<bool> get isInstalled =>
processUtils.exitsHappy(<String>['which', 'pod']);
Future<String> get cocoaPodsVersionText {
_versionText ??= runAsync(<String>['pod', '--version']).then<String>((RunResult result) {
_versionText ??= processUtils.run(<String>['pod', '--version']).then<String>((RunResult result) {
return result.exitCode == 0 ? result.stdout.trim() : null;
}, onError: (dynamic _) => null);
return _versionText;
......
......@@ -10,7 +10,6 @@ import '../base/file_system.dart';
import '../base/io.dart';
import '../base/platform.dart';
import '../base/process.dart';
import '../base/process_manager.dart';
import '../ios/xcodeproj.dart';
const int kXcodeRequiredVersionMajor = 9;
......@@ -25,7 +24,9 @@ class Xcode {
String get xcodeSelectPath {
if (_xcodeSelectPath == null) {
try {
_xcodeSelectPath = processManager.runSync(<String>['/usr/bin/xcode-select', '--print-path']).stdout.trim();
_xcodeSelectPath = processUtils.runSync(
<String>['/usr/bin/xcode-select', '--print-path'],
).stdout.trim();
} on ProcessException {
// Ignored, return null below.
} on ArgumentError {
......@@ -52,13 +53,16 @@ class Xcode {
bool get eulaSigned {
if (_eulaSigned == null) {
try {
final ProcessResult result = processManager.runSync(<String>['/usr/bin/xcrun', 'clang']);
if (result.stdout != null && result.stdout.contains('license'))
final RunResult result = processUtils.runSync(
<String>['/usr/bin/xcrun', 'clang'],
);
if (result.stdout != null && result.stdout.contains('license')) {
_eulaSigned = false;
else if (result.stderr != null && result.stderr.contains('license'))
} else if (result.stderr != null && result.stderr.contains('license')) {
_eulaSigned = false;
else
} else {
_eulaSigned = true;
}
} on ProcessException {
_eulaSigned = false;
}
......@@ -74,7 +78,9 @@ class Xcode {
try {
// This command will error if additional components need to be installed in
// xcode 9.2 and above.
final ProcessResult result = processManager.runSync(<String>['/usr/bin/xcrun', 'simctl', 'list']);
final RunResult result = processUtils.runSync(
<String>['/usr/bin/xcrun', 'simctl', 'list'],
);
_isSimctlInstalled = result.stderr == null || result.stderr == '';
} on ProcessException {
_isSimctlInstalled = false;
......@@ -94,16 +100,23 @@ class Xcode {
}
Future<RunResult> cc(List<String> args) {
return runCheckedAsync(<String>['xcrun', 'cc', ...args]);
return processUtils.run(
<String>['xcrun', 'cc', ...args],
throwOnError: true,
);
}
Future<RunResult> clang(List<String> args) {
return runCheckedAsync(<String>['xcrun', 'clang', ...args]);
return processUtils.run(
<String>['xcrun', 'clang', ...args],
throwOnError: true,
);
}
Future<String> iPhoneSdkLocation() async {
final RunResult runResult = await runCheckedAsync(
final RunResult runResult = await processUtils.run(
<String>['xcrun', '--sdk', 'iphoneos', '--show-sdk-path'],
throwOnError: true,
);
if (runResult.exitCode != 0) {
throwToolExit('Could not find iPhone SDK location: ${runResult.stderr}');
......
......@@ -11,7 +11,7 @@ import '../base/io.dart';
import '../base/logger.dart';
import '../base/os.dart';
import '../base/platform.dart';
import '../base/process_manager.dart';
import '../base/process.dart';
import '../dart/package_map.dart';
import '../globals.dart';
import '../vmservice.dart';
......@@ -150,7 +150,7 @@ class CoverageCollector extends TestWatcher {
final Directory tempDir = fs.systemTempDirectory.createTempSync('flutter_tools_test_coverage.');
try {
final File sourceFile = coverageFile.copySync(fs.path.join(tempDir.path, 'lcov.source.info'));
final ProcessResult result = processManager.runSync(<String>[
final RunResult result = processUtils.runSync(<String>[
'lcov',
'--add-tracefile', baseCoverageData,
'--add-tracefile', sourceFile.path,
......
......@@ -538,7 +538,10 @@ String _runSync(List<String> command, { bool lenient = true }) {
}
String _runGit(String command) {
return runSync(command.split(' '), workingDirectory: Cache.flutterRoot);
return processUtils.runSync(
command.split(' '),
workingDirectory: Cache.flutterRoot,
).stdout.trim();
}
/// Runs [command] in the root of the Flutter installation and returns the
......
......@@ -6,7 +6,7 @@ import '../base/context.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/platform.dart';
import '../base/process_manager.dart';
import '../base/process.dart';
import '../convert.dart';
VisualStudio get visualStudio => context.get<VisualStudio>();
......@@ -167,7 +167,7 @@ class VisualStudio {
'-utf8',
'-latest',
];
final ProcessResult whereResult = processManager.runSync(<String>[
final RunResult whereResult = processUtils.runSync(<String>[
_vswherePath,
...defaultArguments,
...?additionalArguments,
......
......@@ -8,7 +8,7 @@ import '../application_package.dart';
import '../base/io.dart';
import '../base/os.dart';
import '../base/platform.dart';
import '../base/process_manager.dart';
import '../base/process.dart';
import '../build_info.dart';
import '../desktop.dart';
import '../device.dart';
......@@ -88,7 +88,7 @@ class WindowsDevice extends Device {
);
}
await stopApp(package);
final Process process = await processManager.start(<String>[
final Process process = await processUtils.start(<String>[
package.executable(debuggingOptions?.buildInfo?.mode)
]);
if (debuggingOptions?.buildInfo?.isRelease == true) {
......@@ -114,7 +114,9 @@ class WindowsDevice extends Device {
if (process == null) {
return false;
}
final ProcessResult result = await processManager.run(<String>['Taskkill', '/PID', process.first, '/F']);
final RunResult result = await processUtils.run(
<String>['Taskkill', '/PID', process.first, '/F'],
);
return result.exitCode == 0;
}
......@@ -163,7 +165,9 @@ final RegExp _whitespace = RegExp(r'\s+');
@visibleForTesting
List<String> runningProcess(String processName) {
// TODO(jonahwilliams): find a way to do this without powershell.
final ProcessResult result = processManager.runSync(<String>['powershell', '-script="Get-CimInstance Win32_Process"']);
final RunResult result = processUtils.runSync(
<String>['powershell', '-script="Get-CimInstance Win32_Process"'],
);
if (result.exitCode != 0) {
return null;
}
......
......@@ -87,7 +87,7 @@ void main() {
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment'),
),
).thenReturn(ProcessResult(0, 0, _aaptDataWithDefaultEnabledAndMainLauncherActivity, null));
).thenReturn(ProcessResult(0, 0, _aaptDataWithDefaultEnabledAndMainLauncherActivity, ''));
final ApplicationPackage applicationPackage = await ApplicationPackageFactory.instance.getPackageForPlatform(
TargetPlatform.android_arm,
......
......@@ -142,10 +142,13 @@ void main() {
final MockDirectory directory = MockDirectory();
when(mockFileSystem.directory(bundlePath)).thenReturn(directory);
when(directory.existsSync()).thenReturn(true);
when(mockProcessManager.run(installArgs, environment: env))
.thenAnswer(
(_) => Future<ProcessResult>.value(ProcessResult(1, 0, '', ''))
);
when(mockProcessManager.run(
installArgs,
workingDirectory: anyNamed('workingDirectory'),
environment: env
)).thenAnswer(
(_) => Future<ProcessResult>.value(ProcessResult(1, 0, '', ''))
);
when(mockIMobileDevice.getInfoForDevice(any, 'CPUArchitecture'))
.thenAnswer((_) => Future<String>.value('arm64'));
......@@ -259,6 +262,21 @@ void main() {
return Future<ProcessResult>.value(ProcessResult(0, 0, '', ''));
});
when(mockProcessManager.run(
argThat(contains('find-identity')),
environment: anyNamed('environment'),
workingDirectory: anyNamed('workingDirectory'),
)).thenAnswer((_) => Future<ProcessResult>.value(ProcessResult(
1, // pid
0, // exitCode
'''
1) 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 "iPhone Developer: Profile 1 (1111AAAA11)"
2) da4b9237bacccdf19c0760cab7aec4a8359010b0 "iPhone Developer: Profile 2 (2222BBBB22)"
3) 5bf1fd927dfb8679496a2e6cf00cbe50c1c87145 "iPhone Developer: Profile 3 (3333CCCC33)"
3 valid identities found''',
'',
)));
// Deploy works.
when(mockIosDeploy.runApp(
deviceId: anyNamed('deviceId'),
......
......@@ -146,7 +146,10 @@ void main() {
});
testUsingOsxContext('build settings is empty when xcodebuild failed to get the build settings', () {
when(mockProcessManager.runSync(argThat(contains(xcodebuild))))
when(mockProcessManager.runSync(
argThat(contains(xcodebuild)),
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment')))
.thenReturn(ProcessResult(0, 1, '', ''));
expect(xcodeProjectInterpreter.getBuildSettings('', ''), const <String, String>{});
});
......
......@@ -69,18 +69,23 @@ void main() {
final String finalResponse =
json.encode(<Map<String, dynamic>>[response]);
when<String>(result.stdout).thenReturn(finalResponse);
when<String>(result.stderr).thenReturn('');
final List<String> requirementArguments = requiredComponents == null
? <String>[]
: <String>['-requires', ...requiredComponents];
when(mockProcessManager.runSync(<String>[
vswherePath,
'-format',
'json',
'-utf8',
'-latest',
...?additionalArguments,
...?requirementArguments,
])).thenAnswer((Invocation invocation) {
when(mockProcessManager.runSync(
<String>[
vswherePath,
'-format',
'json',
'-utf8',
'-latest',
...?additionalArguments,
...?requirementArguments,
],
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment'),
)).thenAnswer((Invocation invocation) {
return result;
});
}
......@@ -111,8 +116,11 @@ void main() {
});
testUsingContext('isInstalled returns false when vswhere is missing', () {
when(mockProcessManager.runSync(any))
.thenThrow(const ProcessException('vswhere', <String>[]));
when(mockProcessManager.runSync(
any,
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment'),
)).thenThrow(const ProcessException('vswhere', <String>[]));
visualStudio = VisualStudio();
expect(visualStudio.isInstalled, false);
......@@ -123,8 +131,11 @@ void main() {
});
testUsingContext('vcvarsPath returns null when vswhere is missing', () {
when(mockProcessManager.runSync(any))
.thenThrow(const ProcessException('vswhere', <String>[]));
when(mockProcessManager.runSync(
any,
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment'),
)).thenThrow(const ProcessException('vswhere', <String>[]));
visualStudio = VisualStudio();
expect(visualStudio.vcvarsPath, isNull);
......@@ -135,13 +146,24 @@ void main() {
});
testUsingContext('isInstalled returns false when vswhere returns non-zero', () {
when(mockProcessManager.runSync(any))
.thenThrow(const ProcessException('vswhere', <String>[]));
when(mockProcessManager.runSync(
any,
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment'),
)).thenThrow(const ProcessException('vswhere', <String>[]));
final MockProcessResult result = MockProcessResult();
when(result.exitCode).thenReturn(1);
when(mockProcessManager.runSync(any)).thenAnswer((Invocation invocation) {
when(mockProcessManager.runSync(
any,
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment'),
)).thenAnswer((Invocation invocation) {
return result;
});
when<String>(result.stdout).thenReturn('');
when<String>(result.stderr).thenReturn('');
visualStudio = VisualStudio();
expect(visualStudio.isInstalled, false);
......
......@@ -26,18 +26,23 @@ void main() {
when(notWindows.isWindows).thenReturn(false);
when(notWindows.environment).thenReturn(const <String, String>{});
when(mockProcessManager.runSync(<String>[
'powershell', '-script="Get-CimInstance Win32_Process"'
])).thenAnswer((Invocation invocation) {
when(mockProcessManager.runSync(
<String>['powershell', '-script="Get-CimInstance Win32_Process"'],
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment'),
)).thenAnswer((Invocation invocation) {
// The flutter tool process is returned as output to the powershell script
final MockProcessResult result = MockProcessResult();
when(result.exitCode).thenReturn(0);
when<String>(result.stdout).thenReturn('$pid $flutterToolBinary');
when<String>(result.stderr).thenReturn('');
return result;
});
when(mockProcessManager.run(<String>[
'Taskkill', '/PID', '$pid', '/F'
])).thenThrow(Exception('Flutter tool process has been killed'));
when(mockProcessManager.run(
<String>['Taskkill', '/PID', '$pid', '/F'],
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment'),
)).thenThrow(Exception('Flutter tool process has been killed'));
testUsingContext('defaults', () async {
final PrebuiltWindowsApp windowsApp = PrebuiltWindowsApp(executable: 'foo');
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment