Commit 34e466f1 authored by Dan Rubel's avatar Dan Rubel Committed by GitHub

Refactor flutter command exit code - part 3 of 3 (#6838)

* Remove the workaround that pinned args to v0.13.6
This reverts most of the changes in commit 6331b6c8
* throw exception if exit code is not an integer
* rework command infrastructure to throw ToolExit when non-zero exitCode
* convert commands to return Future<Null>
* cleanup remaining commands to use throwToolExit for non-zero exit code
* remove isUnusual exception message
* add type annotations for updated args package
parent ece851d5
No related merge requests found
name: flutter_automated_tests
dependencies:
# version 0.13.6+1 does not return the value from the command
# causing flutter tools to always have exit code 0
# see https://github.com/flutter/flutter/issues/6766
args: 0.13.6
flutter:
sdk: flutter
flutter_test:
......
......@@ -2,12 +2,6 @@ name: complex_layout
description: A new flutter project.
dependencies:
# version 0.13.6+1 does not return the value from the command
# causing flutter tools to always have exit code 0
# see https://github.com/flutter/flutter/issues/6766
args: 0.13.6
flutter:
sdk: flutter
flutter_driver:
......
name: microbenchmarks
description: A new flutter project.
dependencies:
# version 0.13.6+1 does not return the value from the command
# causing flutter tools to always have exit code 0
# see https://github.com/flutter/flutter/issues/6766
args: 0.13.6
flutter:
sdk: flutter
flutter_test:
......
......@@ -8,12 +8,7 @@ environment:
sdk: '>=1.12.0 <2.0.0'
dependencies:
# version 0.13.6+1 does not return the value from the command
# causing flutter tools to always have exit code 0
# see https://github.com/flutter/flutter/issues/6766
args: 0.13.6
args: ^0.13.4
meta: ^1.0.3
path: ^1.3.0
stack_trace: ^1.4.0
......
name: flutter_manual_tests
dependencies:
# version 0.13.6+1 does not return the value from the command
# causing flutter tools to always have exit code 0
# see https://github.com/flutter/flutter/issues/6766
args: 0.13.6
flutter:
sdk: flutter
......
......@@ -2,10 +2,5 @@ name: dev_tools
description: Various repository development tools for flutter.
dependencies:
# version 0.13.6+1 does not return the value from the command
# causing flutter tools to always have exit code 0
# see https://github.com/flutter/flutter/issues/6766
args: 0.13.6
args: ^0.13.4
path: ^1.3.0
name: flutter_gallery
dependencies:
# version 0.13.6+1 does not return the value from the command
# causing flutter tools to always have exit code 0
# see https://github.com/flutter/flutter/issues/6766
args: 0.13.6
collection: '>=1.9.1 <2.0.0'
intl: '>=0.14.0 <0.15.0'
string_scanner: ^1.0.0
......
name: hello_services
dependencies:
# version 0.13.6+1 does not return the value from the command
# causing flutter tools to always have exit code 0
# see https://github.com/flutter/flutter/issues/6766
args: 0.13.6
flutter:
sdk: flutter
......
name: hello_world
dependencies:
# version 0.13.6+1 does not return the value from the command
# causing flutter tools to always have exit code 0
# see https://github.com/flutter/flutter/issues/6766
args: 0.13.6
flutter:
sdk: flutter
......
name: flutter_examples_layers
dependencies:
# version 0.13.6+1 does not return the value from the command
# causing flutter tools to always have exit code 0
# see https://github.com/flutter/flutter/issues/6766
args: 0.13.6
flutter:
sdk: flutter
......
name: stocks
dependencies:
# version 0.13.6+1 does not return the value from the command
# causing flutter tools to always have exit code 0
# see https://github.com/flutter/flutter/issues/6766
args: 0.13.6
flutter:
sdk: flutter
intl: '>=0.14.0 <0.15.0'
......
......@@ -5,12 +5,6 @@ description: A framework for writing Flutter applications
homepage: http://flutter.io
dependencies:
# version 0.13.6+1 does not return the value from the command
# causing flutter tools to always have exit code 0
# see https://github.com/flutter/flutter/issues/6766
args: 0.13.6
collection: '>=1.9.1 <2.0.0'
intl: '>=0.14.0 <0.15.0'
meta: ^1.0.3
......
......@@ -8,12 +8,6 @@ environment:
sdk: '>=1.19.0 <2.0.0'
dependencies:
# version 0.13.6+1 does not return the value from the command
# causing flutter tools to always have exit code 0
# see https://github.com/flutter/flutter/issues/6766
args: 0.13.6
file: '^0.1.0'
json_rpc_2: '^2.0.0'
matcher: '>=0.12.0 <1.0.0'
......
......@@ -5,12 +5,6 @@ author: Flutter Authors <flutter-dev@googlegroups.com>
homepage: http://flutter.io
dependencies:
# version 0.13.6+1 does not return the value from the command
# causing flutter tools to always have exit code 0
# see https://github.com/flutter/flutter/issues/6766
args: 0.13.6
flutter:
sdk: flutter
markdown: '^0.9.0'
......
name: flutter_test
dependencies:
# version 0.13.6+1 does not return the value from the command
# causing flutter tools to always have exit code 0
# see https://github.com/flutter/flutter/issues/6766
args: 0.13.6
quiver: ^0.21.4
# The flutter tools depend on very specific internal implementation
......
......@@ -94,8 +94,8 @@ Future<Null> main(List<String> args) async {
if (context[HotRunnerConfig] == null)
context[HotRunnerConfig] = new HotRunnerConfig();
dynamic result = await runner.run(args);
_exit(result is int ? result : 1);
await runner.run(args);
_exit(0);
}, onError: (dynamic error, Chain chain) {
if (error is UsageException) {
stderr.writeln(error.message);
......@@ -114,10 +114,6 @@ Future<Null> main(List<String> args) async {
stderr.writeln(chain.terse.toString());
stderr.writeln();
}
if (error.isUnusual) {
stderr.writeln('If this problem persists, please report the problem at');
stderr.writeln('https://github.com/flutter/flutter/issues/new');
}
_exit(error.exitCode ?? 1);
} else if (error is ProcessExit) {
// We've caught an exit code.
......
......@@ -27,8 +27,8 @@ String _homeDirPath;
/// where the tool should exit with a clear message to the user
/// and no stack trace unless the --verbose option is specified.
/// For example: network errors
void throwToolExit(String message, { int exitCode, bool isUnusual: false }) {
throw new ToolExit(message, exitCode: exitCode, isUnusual: isUnusual);
void throwToolExit(String message, { int exitCode }) {
throw new ToolExit(message, exitCode: exitCode );
}
/// Specialized exception for expected situations
......@@ -37,11 +37,10 @@ void throwToolExit(String message, { int exitCode, bool isUnusual: false }) {
/// For example: network errors
class ToolExit implements Exception {
ToolExit(this.message, { this.exitCode, this.isUnusual: false });
ToolExit(this.message, { this.exitCode });
final String message;
final int exitCode;
final bool isUnusual;
@override
String toString() => "Exception: $message";
......
......@@ -24,7 +24,6 @@ Future<List<int>> fetchUrl(Uri url) async {
'Download failed: $url\n'
' because (${response.statusCode}) ${response.reasonPhrase}',
exitCode: kNetworkProblemExitCode,
isUnusual: true,
);
}
......@@ -38,7 +37,6 @@ Future<List<int>> fetchUrl(Uri url) async {
throw new ToolExit(
'Download failed: $url\n $e',
exitCode: kNetworkProblemExitCode,
isUnusual: true,
);
}
}
......@@ -53,7 +53,7 @@ class AnalyzeCommand extends FlutterCommand {
}
@override
Future<int> runCommand() {
Future<Null> runCommand() {
if (argResults['watch']) {
return new AnalyzeContinuously(argResults, runner.getRepoAnalysisEntryPoints()).analyze();
} else {
......
......@@ -20,7 +20,7 @@ abstract class AnalyzeBase {
AnalyzeBase(this.argResults);
/// Called by [AnalyzeCommand] to start the analysis process.
Future<int> analyze();
Future<Null> analyze();
void dumpErrors(Iterable<String> errors) {
if (argResults['write'] != null) {
......
......@@ -31,7 +31,7 @@ class AnalyzeContinuously extends AnalyzeBase {
Status analysisStatus;
@override
Future<int> analyze() async {
Future<Null> analyze() async {
List<String> directories;
if (argResults['flutter-repo']) {
......@@ -58,7 +58,6 @@ class AnalyzeContinuously extends AnalyzeBase {
if (exitCode != 0)
throwToolExit(message, exitCode: exitCode);
printStatus(message);
return 0;
}
void _handleAnalysisStatus(AnalysisServer server, bool isAnalyzing) {
......
......@@ -28,7 +28,7 @@ class AnalyzeOnce extends AnalyzeBase {
AnalyzeOnce(ArgResults argResults, this.repoPackages) : super(argResults);
@override
Future<int> analyze() async {
Future<Null> analyze() async {
Stopwatch stopwatch = new Stopwatch()..start();
Set<Directory> pubSpecDirectories = new HashSet<Directory>();
List<File> dartFiles = <File>[];
......@@ -205,7 +205,6 @@ class AnalyzeOnce extends AnalyzeBase {
printStatus('No analyzer warnings! (ran in ${elapsed}s)');
}
}
return 0;
}
List<String> flutterRootComponents;
......
......@@ -33,26 +33,26 @@ class BuildCommand extends FlutterCommand {
final String description = 'Flutter build commands.';
@override
Future<int> verifyThenRunCommand() async {
Future<Null> verifyThenRunCommand() async {
commandValidator();
return super.verifyThenRunCommand();
}
@override
Future<int> runCommand() => new Future<int>.value(0);
Future<Null> runCommand() async { }
}
abstract class BuildSubCommand extends FlutterCommand {
@override
@mustCallSuper
Future<int> verifyThenRunCommand() async {
Future<Null> verifyThenRunCommand() async {
commandValidator();
return super.verifyThenRunCommand();
}
@override
@mustCallSuper
Future<int> runCommand() async {
Future<Null> runCommand() async {
if (isRunningOnBot) {
File dotPackages = new File('.packages');
printStatus('Contents of .packages:');
......@@ -68,7 +68,6 @@ abstract class BuildSubCommand extends FlutterCommand {
else
printError('File not found: ${pubspecLock.absolute.path}');
}
return 0;
}
}
......@@ -80,24 +79,23 @@ class BuildCleanCommand extends FlutterCommand {
final String description = 'Delete the build/ directory.';
@override
Future<int> verifyThenRunCommand() async {
Future<Null> verifyThenRunCommand() async {
commandValidator();
return super.verifyThenRunCommand();
}
@override
Future<int> runCommand() async {
Future<Null> runCommand() async {
Directory buildDir = new Directory(getBuildDirectory());
printStatus("Deleting '${buildDir.path}${Platform.pathSeparator}'.");
if (!buildDir.existsSync())
return 0;
return;
try {
buildDir.deleteSync(recursive: true);
} catch (error) {
throwToolExit(error.toString());
}
return 0;
}
}
......@@ -43,7 +43,7 @@ class BuildAotCommand extends BuildSubCommand {
final String description = "Build an ahead-of-time compiled snapshot of your app's Dart code.";
@override
Future<int> runCommand() async {
Future<Null> runCommand() async {
await super.runCommand();
String targetPlatform = argResults['target-platform'];
TargetPlatform platform = getTargetPlatformForName(targetPlatform);
......@@ -65,7 +65,6 @@ class BuildAotCommand extends BuildSubCommand {
throwToolExit(null);
printStatus('Built to $outputPath${Platform.pathSeparator}.');
return 0;
}
}
......
......@@ -224,7 +224,7 @@ class BuildApkCommand extends BuildSubCommand {
}
@override
Future<int> runCommand() async {
Future<Null> runCommand() async {
await super.runCommand();
TargetPlatform targetPlatform = _getTargetPlatform(argResults['target-arch']);
......@@ -258,7 +258,6 @@ class BuildApkCommand extends BuildSubCommand {
)
);
}
return 0;
}
}
......
......@@ -37,7 +37,7 @@ class BuildFlxCommand extends BuildSubCommand {
'they are used by some Flutter Android and iOS runtimes.';
@override
Future<int> runCommand() async {
Future<Null> runCommand() async {
await super.runCommand();
String outputPath = argResults['output-file'];
......@@ -53,6 +53,5 @@ class BuildFlxCommand extends BuildSubCommand {
includeRobotoFonts: argResults['include-roboto-fonts'],
reportLicensedPackages: argResults['report-licensed-packages']
);
return 0;
}
}
......@@ -39,7 +39,7 @@ class BuildIOSCommand extends BuildSubCommand {
final String description = 'Build an iOS application bundle (Mac OS X host only).';
@override
Future<int> runCommand() async {
Future<Null> runCommand() async {
bool forSimulator = argResults['simulator'];
defaultBuildMode = forSimulator ? BuildMode.debug : BuildMode.release;
......@@ -83,7 +83,5 @@ class BuildIOSCommand extends BuildSubCommand {
if (result.output != null)
printStatus('Built ${result.output}.');
return 0;
}
}
......@@ -21,7 +21,7 @@ class ChannelCommand extends FlutterCommand {
String get invocation => '${runner.executableName} $name [<channel-name>]';
@override
Future<int> runCommand() {
Future<Null> runCommand() {
switch (argResults.rest.length) {
case 0:
return _listChannels();
......@@ -32,7 +32,7 @@ class ChannelCommand extends FlutterCommand {
}
}
Future<int> _listChannels() async {
Future<Null> _listChannels() async {
String currentBranch = runSync(
<String>['git', 'rev-parse', '--abbrev-ref', 'HEAD'],
workingDirectory: Cache.flutterRoot);
......@@ -52,10 +52,9 @@ class ChannelCommand extends FlutterCommand {
);
if (result != 0)
throwToolExit('List channels failed: $result', exitCode: result);
return 0;
}
Future<int> _switchChannel(String branchName) async {
Future<Null> _switchChannel(String branchName) async {
printStatus('Switching to flutter channel named $branchName');
int result = await runCommandAndStreamOutput(
<String>['git', 'checkout', branchName],
......@@ -63,6 +62,5 @@ class ChannelCommand extends FlutterCommand {
);
if (result != 0)
throwToolExit('Switch channel failed: $result', exitCode: result);
return 0;
}
}
......@@ -46,7 +46,7 @@ class ConfigCommand extends FlutterCommand {
String get usagePath => null;
@override
Future<int> runCommand() async {
Future<Null> runCommand() async {
if (argResults.wasParsed('analytics')) {
bool value = argResults['analytics'];
flutterUsage.enabled = value;
......@@ -61,8 +61,6 @@ class ConfigCommand extends FlutterCommand {
if (argResults.arguments.isEmpty)
printStatus(usage);
return 0;
}
void _updateConfig(String keyName, String keyValue) {
......
......@@ -46,7 +46,7 @@ class CreateCommand extends FlutterCommand {
String get invocation => "${runner.executableName} $name <output directory>";
@override
Future<int> runCommand() async {
Future<Null> runCommand() async {
if (argResults.rest.isEmpty)
throwToolExit('No option specified for the output directory.\n$usage', exitCode: 2);
......@@ -134,7 +134,6 @@ Your main program file is lib/main.dart in the $relativePath directory.
"directory in order to launch your app.");
printStatus("Your main program file is: $relativePath/lib/main.dart");
}
return 0;
}
int _renderTemplates(String projectName, String projectDescription, String dirPath,
......
......@@ -43,7 +43,7 @@ class DaemonCommand extends FlutterCommand {
final bool hidden;
@override
Future<int> runCommand() {
Future<Null> runCommand() {
printStatus('Starting device daemon...');
AppContext appContext = new AppContext();
......@@ -60,7 +60,6 @@ class DaemonCommand extends FlutterCommand {
int code = await daemon.onExit;
if (code != null)
throwToolExit(null, exitCode: code);
return 0;
}, onError: _handleError);
}
......
......@@ -18,7 +18,7 @@ class DevicesCommand extends FlutterCommand {
final String description = 'List all connected devices.';
@override
Future<int> runCommand() async {
Future<Null> runCommand() async {
if (!doctor.canListAnything) {
throwToolExit(
"Unable to locate a development device; please run 'flutter doctor' for "
......@@ -37,6 +37,5 @@ class DevicesCommand extends FlutterCommand {
printStatus('${devices.length} connected ${pluralize('device', devices.length)}:\n');
Device.printDevices(devices);
}
return 0;
}
}
......@@ -15,8 +15,7 @@ class DoctorCommand extends FlutterCommand {
final String description = 'Show information about the installed tooling.';
@override
Future<int> runCommand() async {
Future<Null> runCommand() async {
await doctor.diagnose();
return 0;
}
}
......@@ -90,13 +90,13 @@ class DriveCommand extends RunCommandBase {
int get debugPort => int.parse(argResults['debug-port']);
@override
Future<int> verifyThenRunCommand() async {
Future<Null> verifyThenRunCommand() async {
commandValidator();
return super.verifyThenRunCommand();
}
@override
Future<int> runCommand() async {
Future<Null> runCommand() async {
String testFile = _getTestFile();
if (testFile == null)
throwToolExit(null);
......@@ -149,7 +149,6 @@ class DriveCommand extends RunCommandBase {
printStatus('Leaving the application running.');
}
}
return 0;
}
String _getTestFile() {
......
......@@ -25,7 +25,7 @@ class FormatCommand extends FlutterCommand {
String get invocation => "${runner.executableName} $name <one or more paths>";
@override
Future<int> runCommand() async {
Future<Null> runCommand() async {
if (argResults.rest.isEmpty) {
throwToolExit(
'No files specified to be formatted.\n'
......@@ -43,6 +43,5 @@ class FormatCommand extends FlutterCommand {
int result = await runCommandAndStreamOutput(cmd);
if (result != 0)
throwToolExit('Formatting failed: $result', exitCode: result);
return 0;
}
}
......@@ -21,7 +21,7 @@ class InstallCommand extends FlutterCommand {
Device device;
@override
Future<int> verifyThenRunCommand() async {
Future<Null> verifyThenRunCommand() async {
commandValidator();
device = await findTargetDevice();
if (device == null)
......@@ -30,7 +30,7 @@ class InstallCommand extends FlutterCommand {
}
@override
Future<int> runCommand() async {
Future<Null> runCommand() async {
ApplicationPackage package = applicationPackages.getPackageForPlatform(device.platform);
Cache.releaseLockEarly();
......@@ -39,7 +39,6 @@ class InstallCommand extends FlutterCommand {
if (!installApp(device, package))
throwToolExit('Install failed');
return 0;
}
}
......
......@@ -29,7 +29,7 @@ class LogsCommand extends FlutterCommand {
Device device;
@override
Future<int> verifyThenRunCommand() async {
Future<Null> verifyThenRunCommand() async {
device = await findTargetDevice();
if (device == null)
throwToolExit(null);
......@@ -37,7 +37,7 @@ class LogsCommand extends FlutterCommand {
}
@override
Future<int> runCommand() async {
Future<Null> runCommand() async {
if (argResults['clear'])
device.clearLogs();
......@@ -76,6 +76,5 @@ class LogsCommand extends FlutterCommand {
subscription.cancel();
if (result != 0)
throwToolExit('Error listening to $logReader logs.');
return 0;
}
}
......@@ -25,13 +25,13 @@ class PackagesCommand extends FlutterCommand {
final String description = 'Commands for managing Flutter packages.';
@override
Future<int> verifyThenRunCommand() async {
Future<Null> verifyThenRunCommand() async {
commandValidator();
return super.verifyThenRunCommand();
}
@override
Future<int> runCommand() => new Future<int>.value(0);
Future<Null> runCommand() async { }
}
class PackagesGetCommand extends FlutterCommand {
......@@ -52,7 +52,7 @@ class PackagesGetCommand extends FlutterCommand {
"${runner.executableName} packages $name [<target directory>]";
@override
Future<int> runCommand() async {
Future<Null> runCommand() async {
if (argResults.rest.length > 1)
throwToolExit('Too many arguments.\n$usage');
......@@ -69,6 +69,5 @@ class PackagesGetCommand extends FlutterCommand {
// TODO: If the user is using a local build, we should use the packages from their build instead of the cache.
await pubGet(directory: target, upgrade: upgrade, checkLastModified: false);
return 0;
}
}
......@@ -20,7 +20,7 @@ class PrecacheCommand extends FlutterCommand {
final String description = 'Populates the Flutter tool\'s cache of binary artifacts.';
@override
Future<int> runCommand() async {
Future<Null> runCommand() async {
if (argResults['all-platforms'])
cache.includeAllPlatforms = true;
......@@ -28,7 +28,5 @@ class PrecacheCommand extends FlutterCommand {
printStatus('Already up-to-date.');
else
await cache.updateAll();
return 0;
}
}
......@@ -148,7 +148,7 @@ class RunCommand extends RunCommandBase {
argResults['use-application-binary'] != null;
@override
Future<int> verifyThenRunCommand() async {
Future<Null> verifyThenRunCommand() async {
commandValidator();
device = await findTargetDevice();
if (device == null)
......@@ -157,7 +157,7 @@ class RunCommand extends RunCommandBase {
}
@override
Future<int> runCommand() async {
Future<Null> runCommand() async {
Cache.releaseLockEarly();
......@@ -238,6 +238,5 @@ class RunCommand extends RunCommandBase {
);
if (result != 0)
throwToolExit(null, exitCode: result);
return 0;
}
}
......@@ -52,7 +52,7 @@ class ScreenshotCommand extends FlutterCommand {
Device device;
@override
Future<int> verifyThenRunCommand() async {
Future<Null> verifyThenRunCommand() async {
if (argResults[_kSkia] != null) {
if (argResults[_kOut] != null && argResults[_kSkiaServe] != null)
throwToolExit('Cannot specify both --$_kOut and --$_kSkiaServe');
......@@ -69,7 +69,7 @@ class ScreenshotCommand extends FlutterCommand {
}
@override
Future<int> runCommand() async {
Future<Null> runCommand() async {
File outputFile;
if (argResults.wasParsed(_kOut))
outputFile = new File(argResults[_kOut]);
......@@ -81,7 +81,7 @@ class ScreenshotCommand extends FlutterCommand {
}
}
Future<int> runScreenshot(File outputFile) async {
Future<Null> runScreenshot(File outputFile) async {
outputFile ??= getUniqueFile(Directory.current, 'flutter', 'png');
try {
if (!await device.takeScreenshot(outputFile))
......@@ -90,10 +90,9 @@ class ScreenshotCommand extends FlutterCommand {
throwToolExit('Error taking screenshot: $error');
}
await showOutputFileInfo(outputFile);
return 0;
}
Future<int> runSkia(File outputFile) async {
Future<Null> runSkia(File outputFile) async {
Uri skpUri = new Uri(scheme: 'http', host: '127.0.0.1',
port: int.parse(argResults[_kSkia]),
path: '/skp');
......@@ -136,7 +135,6 @@ class ScreenshotCommand extends FlutterCommand {
throwToolExit('\nIt appears the output file contains an error message, not valid skia output.\n\n$errorHelpText');
}
}
return 0;
}
Future<Null> showOutputFileInfo(File outputFile) async {
......
......@@ -4,6 +4,7 @@
import 'dart:async';
import '../base/common.dart';
import '../base/os.dart';
import '../base/process.dart';
import '../globals.dart';
......@@ -26,7 +27,7 @@ class SetupCommand extends FlutterCommand {
final bool hidden;
@override
Future<int> runCommand() async {
Future<Null> runCommand() async {
printStatus('Running Flutter setup...');
// setup brew on mac
......@@ -57,9 +58,9 @@ class SetupCommand extends FlutterCommand {
printStatus('\nThe flutter command is available on the path.');
}
if (goodInstall)
printStatus('\nFlutter setup complete!');
if (!goodInstall)
throwToolExit(null);
return goodInstall ? 0 : 1;
printStatus('\nFlutter setup complete!');
}
}
......@@ -5,6 +5,7 @@
import 'dart:async';
import '../application_package.dart';
import '../base/common.dart';
import '../build_info.dart';
import '../device.dart';
import '../globals.dart';
......@@ -20,24 +21,23 @@ class StopCommand extends FlutterCommand {
Device device;
@override
Future<int> verifyThenRunCommand() async {
if (!commandValidator())
return 1;
Future<Null> verifyThenRunCommand() async {
commandValidator();
device = await findTargetDevice();
if (device == null)
return 1;
throwToolExit(null);
return super.verifyThenRunCommand();
}
@override
Future<int> runCommand() async {
Future<Null> runCommand() async {
ApplicationPackage app = applicationPackages.getPackageForPlatform(device.platform);
if (app == null) {
String platformName = getNameForTargetPlatform(device.platform);
printError('No Flutter application for $platformName found in the current directory.');
return 1;
throwToolExit('No Flutter application for $platformName found in the current directory.');
}
printStatus('Stopping apps on ${device.name}.');
return await device.stopApp(app) ? 0 : 1;
if (!await device.stopApp(app))
throwToolExit(null);
}
}
......@@ -8,6 +8,7 @@ import 'dart:io';
import 'package:path/path.dart' as path;
import 'package:test/src/executable.dart' as executable; // ignore: implementation_imports
import '../base/common.dart';
import '../base/logger.dart';
import '../base/os.dart';
import '../cache.dart';
......@@ -38,14 +39,12 @@ class TestCommand extends FlutterCommand {
);
commandValidator = () {
if (!FileSystemEntity.isFileSync('pubspec.yaml')) {
printError(
throwToolExit(
'Error: No pubspec.yaml file found in the current working directory.\n'
'Run this command from the root of your project. Test files must be\n'
'called *_test.dart and must reside in the package\'s \'test\'\n'
'directory (or one of its subdirectories).');
return false;
}
return true;
};
}
......@@ -142,20 +141,17 @@ class TestCommand extends FlutterCommand {
}
@override
Future<int> runCommand() async {
Future<Null> runCommand() async {
List<String> testArgs = argResults.rest.map((String testPath) => path.absolute(testPath)).toList();
if (!commandValidator())
return 1;
commandValidator();
Directory testDir;
if (testArgs.isEmpty) {
testDir = _currentPackageTestDir;
if (!testDir.existsSync()) {
printError("Test directory '${testDir.path}' not found.");
return 1;
}
if (!testDir.existsSync())
throwToolExit("Test directory '${testDir.path}' not found.");
testArgs.addAll(_findTests(testDir));
}
......@@ -169,10 +165,8 @@ class TestCommand extends FlutterCommand {
loader.installHook();
loader.shellPath = tools.getHostToolPath(HostTool.SkyShell);
if (!FileSystemEntity.isFileSync(loader.shellPath)) {
printError('Cannot find Flutter shell at ${loader.shellPath}');
return 1;
}
if (!FileSystemEntity.isFileSync(loader.shellPath))
throwToolExit('Cannot find Flutter shell at ${loader.shellPath}');
Cache.releaseLockEarly();
......@@ -183,9 +177,10 @@ class TestCommand extends FlutterCommand {
if (collector.enabled) {
if (!await _collectCoverageData(collector, mergeCoverageData: argResults['merge-coverage']))
return 1;
throwToolExit(null);
}
return result;
if (result != 0)
throwToolExit(null);
}
}
......@@ -46,14 +46,13 @@ class TraceCommand extends FlutterCommand {
'with --start and later with --stop.';
@override
Future<int> verifyThenRunCommand() async {
if (!commandValidator())
return 1;
Future<Null> verifyThenRunCommand() async {
commandValidator();
return super.verifyThenRunCommand();
}
@override
Future<int> runCommand() async {
Future<Null> runCommand() async {
int observatoryPort = int.parse(argResults['debug-port']);
Tracing tracing;
......@@ -61,8 +60,7 @@ class TraceCommand extends FlutterCommand {
try {
tracing = await Tracing.connect(observatoryPort);
} catch (error) {
printError('Error connecting to observatory: $error');
return 1;
throwToolExit('Error connecting to observatory: $error');
}
Cache.releaseLockEarly();
......@@ -81,8 +79,6 @@ class TraceCommand extends FlutterCommand {
} else {
await tracing.startTracing();
}
return 0;
}
Future<Null> _stopTracing(Tracing tracing) async {
......
......@@ -46,24 +46,19 @@ class UpdatePackagesCommand extends FlutterCommand {
}
@override
Future<int> runCommand() async {
try {
final Stopwatch timer = new Stopwatch()..start();
int count = 0;
final bool upgrade = argResults['upgrade'];
Future<Null> runCommand() async {
final Stopwatch timer = new Stopwatch()..start();
int count = 0;
final bool upgrade = argResults['upgrade'];
for (Directory dir in runner.getRepoPackages()) {
await pubGet(directory: dir.path, upgrade: upgrade, checkLastModified: false);
count++;
}
for (Directory dir in runner.getRepoPackages()) {
await pubGet(directory: dir.path, upgrade: upgrade, checkLastModified: false);
count++;
}
await _downloadCoverageData();
await _downloadCoverageData();
final double seconds = timer.elapsedMilliseconds / 1000.0;
printStatus('\nRan \'pub\' $count time${count == 1 ? "" : "s"} and fetched coverage data in ${seconds.toStringAsFixed(1)}s.');
return 0;
} on int catch (code) {
return code;
}
final double seconds = timer.elapsedMilliseconds / 1000.0;
printStatus('\nRan \'pub\' $count time${count == 1 ? "" : "s"} and fetched coverage data in ${seconds.toStringAsFixed(1)}s.');
}
}
......@@ -4,6 +4,7 @@
import 'dart:async';
import '../base/common.dart';
import '../base/os.dart';
import '../base/process.dart';
import '../dart/pub.dart';
......@@ -21,14 +22,13 @@ class UpgradeCommand extends FlutterCommand {
final String description = 'Upgrade your copy of Flutter.';
@override
Future<int> runCommand() async {
Future<Null> runCommand() async {
try {
runCheckedSync(<String>[
'git', 'rev-parse', '@{u}'
], workingDirectory: Cache.flutterRoot);
} catch (e) {
printError('Unable to upgrade Flutter: no upstream repository configured.');
return 1;
throwToolExit('Unable to upgrade Flutter: no upstream repository configured.');
}
FlutterVersion version = new FlutterVersion(Cache.flutterRoot);
......@@ -48,7 +48,7 @@ class UpgradeCommand extends FlutterCommand {
);
if (code != 0)
return code;
throwToolExit(null, exitCode: code);
await buildUnlinkedForPackages(Cache.flutterRoot);
......@@ -79,8 +79,6 @@ class UpgradeCommand extends FlutterCommand {
printStatus('');
printStatus('Running flutter doctor...');
await doctor.diagnose();
return 0;
}
// dev/benchmarks/complex_layout/lib/main.dart | 24 +-
......
......@@ -9,6 +9,7 @@ import 'package:args/command_runner.dart';
import 'package:meta/meta.dart';
import '../application_package.dart';
import '../base/common.dart';
import '../build_info.dart';
import '../dart/package_map.dart';
import '../dart/pub.dart';
......@@ -18,9 +19,9 @@ import '../globals.dart';
import '../usage.dart';
import 'flutter_command_runner.dart';
typedef bool Validator();
typedef void Validator();
abstract class FlutterCommand extends Command {
abstract class FlutterCommand extends Command<Null> {
FlutterCommand() {
commandValidator = commonCommandValidator;
}
......@@ -107,18 +108,17 @@ abstract class FlutterCommand extends Command {
/// and [runCommand] to execute the command
/// so that this method can record and report the overall time to analytics.
@override
Future<int> run() {
Future<Null> run() {
Stopwatch stopwatch = new Stopwatch()..start();
UsageTimer analyticsTimer = usagePath == null ? null : flutterUsage.startTimer(name);
if (flutterUsage.isFirstRun)
flutterUsage.printUsage();
return verifyThenRunCommand().then((int exitCode) {
return verifyThenRunCommand().whenComplete(() {
int ms = stopwatch.elapsedMilliseconds;
printTrace("'flutter $name' took ${ms}ms; exiting with code $exitCode.");
printTrace("'flutter $name' took ${ms}ms.");
analyticsTimer?.finish();
return exitCode;
});
}
......@@ -130,7 +130,7 @@ abstract class FlutterCommand extends Command {
/// then call this method to execute the command
/// rather than calling [runCommand] directly.
@mustCallSuper
Future<int> verifyThenRunCommand() async {
Future<Null> verifyThenRunCommand() async {
// Populate the cache. We call this before pub get below so that the sky_engine
// package is available in the flutter cache for pub to find.
await cache.updateAll();
......@@ -144,11 +144,11 @@ abstract class FlutterCommand extends Command {
if (commandPath != null)
flutterUsage.sendCommand(usagePath);
return await runCommand();
await runCommand();
}
/// Subclasses must implement this to execute the command.
Future<int> runCommand();
Future<Null> runCommand();
/// Find and return the target [Device] based upon currently connected
/// devices and criteria entered by the user on the command line.
......@@ -203,35 +203,28 @@ abstract class FlutterCommand extends Command {
// This is a field so that you can modify the value for testing.
Validator commandValidator;
bool commonCommandValidator() {
void commonCommandValidator() {
if (!PackageMap.isUsingCustomPackagesPath) {
// Don't expect a pubspec.yaml file if the user passed in an explicit .packages file path.
if (!FileSystemEntity.isFileSync('pubspec.yaml')) {
printError('Error: No pubspec.yaml file found.\n'
throw new ToolExit('Error: No pubspec.yaml file found.\n'
'This command should be run from the root of your Flutter project.\n'
'Do not run this command from the root of your git clone of Flutter.');
return false;
}
}
if (_usesTargetOption) {
String targetPath = targetFile;
if (!FileSystemEntity.isFileSync(targetPath)) {
printError('Target file "$targetPath" not found.');
return false;
}
if (!FileSystemEntity.isFileSync(targetPath))
throw new ToolExit('Target file "$targetPath" not found.');
}
// Validate the current package map only if we will not be running "pub get" later.
if (!(_usesPubOption && argResults['pub'])) {
String error = new PackageMap(PackageMap.globalPackagesPath).checkValid();
if (error != null) {
printError(error);
return false;
}
if (error != null)
throw new ToolExit(error);
}
return true;
}
ApplicationPackageStore applicationPackages;
......
......@@ -25,7 +25,7 @@ const String kSnapshotFileName = 'flutter_tools.snapshot'; // in //flutter/bin/c
const String kFlutterToolsScriptFileName = 'flutter_tools.dart'; // in //flutter/packages/flutter_tools/bin/
const String kFlutterEnginePackageName = 'sky_engine';
class FlutterCommandRunner extends CommandRunner {
class FlutterCommandRunner extends CommandRunner<Null> {
FlutterCommandRunner({ bool verboseHelp: false }) : super(
'flutter',
'Manage your Flutter app development.\n'
......@@ -124,7 +124,7 @@ class FlutterCommandRunner extends CommandRunner {
}
@override
Future<dynamic> run(Iterable<String> args) {
Future<Null> run(Iterable<String> args) {
// Have an invocation of 'build' print out it's sub-commands.
if (args.length == 1 && args.first == 'build')
args = <String>['build', '-h'];
......@@ -133,7 +133,7 @@ class FlutterCommandRunner extends CommandRunner {
}
@override
Future<int> runCommand(ArgResults globalResults) async {
Future<Null> runCommand(ArgResults globalResults) async {
// Check for verbose.
if (globalResults['verbose'])
context[Logger] = new VerboseLogger();
......@@ -153,8 +153,7 @@ class FlutterCommandRunner extends CommandRunner {
if (globalResults['suppress-analytics'])
flutterUsage.suppressAnalytics = true;
if (!_checkFlutterCopy())
return 1;
_checkFlutterCopy();
if (globalResults.wasParsed('packages'))
PackageMap.globalPackagesPath = path.normalize(path.absolute(globalResults['packages']));
......@@ -176,10 +175,10 @@ class FlutterCommandRunner extends CommandRunner {
if (globalResults['version']) {
flutterUsage.sendCommand('version');
printStatus(FlutterVersion.getVersion(Cache.flutterRoot).toString());
return 0;
return;
}
return await super.runCommand(globalResults);
await super.runCommand(globalResults);
}
String _tryEnginePath(String enginePath) {
......@@ -285,7 +284,7 @@ class FlutterCommandRunner extends CommandRunner {
return result;
}
bool _checkFlutterCopy() {
void _checkFlutterCopy() {
// If the current directory is contained by a flutter repo, check that it's
// the same flutter that is currently running.
String directory = path.normalize(path.absolute(Directory.current.path));
......@@ -334,8 +333,6 @@ class FlutterCommandRunner extends CommandRunner {
}
}
}
return true;
}
// Check if `bin/flutter` and `bin/cache/engine.stamp` exist.
......
......@@ -9,12 +9,7 @@ environment:
dependencies:
archive: ^1.0.20
# version 0.13.6+1 does not return the value from the command
# causing flutter tools to always have exit code 0
# see https://github.com/flutter/flutter/issues/6766
args: 0.13.6
args: ^0.13.4
coverage: ^0.8.0
crypto: '>=1.1.1 <3.0.0'
file: ^0.1.0
......
......@@ -39,22 +39,19 @@ void main() {
flutterUsage.enabled = false;
CreateCommand command = new CreateCommand();
CommandRunner runner = createTestCommandRunner(command);
int code = await runner.run(<String>['create', '--no-pub', temp.path]);
expect(code, 0);
CommandRunner<Null> runner = createTestCommandRunner(command);
await runner.run(<String>['create', '--no-pub', temp.path]);
expect(count, 0);
flutterUsage.enabled = true;
code = await runner.run(<String>['create', '--no-pub', temp.path]);
expect(code, 0);
await runner.run(<String>['create', '--no-pub', temp.path]);
expect(count, flutterUsage.isFirstRun ? 0 : 2);
count = 0;
flutterUsage.enabled = false;
DoctorCommand doctorCommand = new DoctorCommand();
runner = createTestCommandRunner(doctorCommand);
code = await runner.run(<String>['doctor']);
expect(code, 0);
await runner.run(<String>['doctor']);
expect(count, 0);
}, overrides: <Type, dynamic>{
Usage: new Usage()
......@@ -67,7 +64,7 @@ void main() {
flutterUsage.enabled = false;
ConfigCommand command = new ConfigCommand();
CommandRunner runner = createTestCommandRunner(command);
CommandRunner<Null> runner = createTestCommandRunner(command);
await runner.run(<String>['config']);
expect(count, 0);
......
......@@ -37,8 +37,7 @@ void main() {
applyMocksToCommand(command);
return createTestCommandRunner(command).run(
<String>['analyze', '--no-current-package', '--no-current-directory', dartFileA.path, dartFileB.path]
).then((int code) {
expect(code, 0);
).then((_) {
expect(testLogger.statusText, startsWith('Analyzing 2 files...\nNo analyzer warnings!'));
});
......
......@@ -3,8 +3,6 @@
// found in the LICENSE file.
import 'package:args/command_runner.dart';
import 'package:flutter_tools/src/base/context.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/commands/channel.dart';
import 'package:test/test.dart';
......@@ -15,14 +13,13 @@ void main() {
group('channel', () {
testUsingContext('list', () async {
ChannelCommand command = new ChannelCommand();
CommandRunner runner = createTestCommandRunner(command);
expect(await runner.run(<String>['channel']), 0);
BufferLogger logger = context[Logger];
expect(logger.errorText, hasLength(0));
CommandRunner<Null> runner = createTestCommandRunner(command);
await runner.run(<String>['channel']);
expect(testLogger.errorText, hasLength(0));
// The bots may return an empty list of channels (network hiccup?)
// and when run locally the list of branches might be different
// so we check for the header text rather than any specific channel name.
expect(logger.statusText, contains('Flutter channels:'));
expect(testLogger.statusText, contains('Flutter channels:'));
});
});
}
......@@ -43,10 +43,9 @@ void main() {
Cache.flutterRoot = '../..';
CreateCommand command = new CreateCommand();
CommandRunner runner = createTestCommandRunner(command);
CommandRunner<Null> runner = createTestCommandRunner(command);
int code = await runner.run(<String>['create', '--no-pub', temp.path]);
expect(code, 0);
await runner.run(<String>['create', '--no-pub', temp.path]);
void expectExists(String relPath) {
expect(FileSystemEntity.isFileSync('${temp.path}/$relPath'), true);
......@@ -74,13 +73,11 @@ void main() {
Cache.flutterRoot = '../..';
CreateCommand command = new CreateCommand();
CommandRunner runner = createTestCommandRunner(command);
CommandRunner<Null> runner = createTestCommandRunner(command);
int code = await runner.run(<String>['create', '--no-pub', temp.path]);
expect(code, 0);
await runner.run(<String>['create', '--no-pub', temp.path]);
code = await runner.run(<String>['create', '--no-pub', temp.path]);
expect(code, 0);
await runner.run(<String>['create', '--no-pub', temp.path]);
});
// Verify that we help the user correct an option ordering issue
......@@ -88,7 +85,7 @@ void main() {
Cache.flutterRoot = '../..';
CreateCommand command = new CreateCommand();
CommandRunner runner = createTestCommandRunner(command);
CommandRunner<Null> runner = createTestCommandRunner(command);
try {
await runner.run(<String>['create', temp.path, '--pub']);
......@@ -103,7 +100,7 @@ void main() {
testUsingContext('fails when file exists', () async {
Cache.flutterRoot = '../..';
CreateCommand command = new CreateCommand();
CommandRunner runner = createTestCommandRunner(command);
CommandRunner<Null> runner = createTestCommandRunner(command);
File existingFile = new File("${temp.path.toString()}/bad");
if (!existingFile.existsSync()) existingFile.createSync();
try {
......@@ -119,12 +116,11 @@ void main() {
Future<Null> _createAndAnalyzeProject(Directory dir, List<String> createArgs) async {
Cache.flutterRoot = '../..';
CreateCommand command = new CreateCommand();
CommandRunner runner = createTestCommandRunner(command);
CommandRunner<Null> runner = createTestCommandRunner(command);
List<String> args = <String>['create'];
args.addAll(createArgs);
args.add(dir.path);
int code = await runner.run(args);
expect(code, 0);
await runner.run(args);
String mainPath = path.join(dir.path, 'lib', 'main.dart');
expect(new File(mainPath).existsSync(), true);
......
......@@ -12,19 +12,15 @@ import 'src/context.dart';
void main() {
group('devices', () {
testUsingContext('returns 0 when called', () {
testUsingContext('returns 0 when called', () async {
DevicesCommand command = new DevicesCommand();
return createTestCommandRunner(command).run(<String>['devices']).then((int code) {
expect(code, 0);
});
await createTestCommandRunner(command).run(<String>['devices']);
});
testUsingContext('no error when no connected devices', () {
testUsingContext('no error when no connected devices', () async {
DevicesCommand command = new DevicesCommand();
return createTestCommandRunner(command).run(<String>['devices']).then((int code) {
expect(code, 0);
expect(testLogger.statusText, contains('No devices detected'));
});
await createTestCommandRunner(command).run(<String>['devices']);
expect(testLogger.statusText, contains('No devices detected'));
}, overrides: <Type, dynamic>{
AndroidSdk: null,
DeviceManager: new DeviceManager()
......
......@@ -8,11 +8,9 @@ import 'package:file/file.dart';
import 'package:flutter_tools/src/android/android_device.dart';
import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/os.dart';
import 'package:flutter_tools/src/commands/drive.dart';
import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/globals.dart';
import 'package:flutter_tools/src/ios/simulators.dart';
import 'package:mockito/mockito.dart';
import 'package:test/test.dart';
......@@ -164,11 +162,8 @@ void main() {
'drive',
'--target=$testApp',
];
return createTestCommandRunner(command).run(args).then((int code) {
expect(code, 0);
BufferLogger buffer = logger;
expect(buffer.errorText, isEmpty);
});
await createTestCommandRunner(command).run(args);
expect(testLogger.errorText, isEmpty);
});
testUsingContext('returns exitCode set by test runner', () async {
......
......@@ -30,10 +30,9 @@ void main() {
Future<Null> createProject() async {
CreateCommand command = new CreateCommand();
CommandRunner runner = createTestCommandRunner(command);
CommandRunner<Null> runner = createTestCommandRunner(command);
int code = await runner.run(<String>['create', '--no-pub', temp.path]);
expect(code, 0);
await runner.run(<String>['create', '--no-pub', temp.path]);
}
testUsingContext('a file', () async {
......@@ -44,9 +43,8 @@ void main() {
srcFile.writeAsStringSync(original.replaceFirst('main()', 'main( )'));
FormatCommand command = new FormatCommand();
CommandRunner runner = createTestCommandRunner(command);
int code = await runner.run(<String>['format', srcFile.path]);
expect(code, 0);
CommandRunner<Null> runner = createTestCommandRunner(command);
await runner.run(<String>['format', srcFile.path]);
String formatted = srcFile.readAsStringSync();
expect(formatted, original);
......
......@@ -12,7 +12,7 @@ import 'src/mocks.dart';
void main() {
group('install', () {
testUsingContext('returns 0 when Android is connected and ready for an install', () {
testUsingContext('returns 0 when Android is connected and ready for an install', () async {
InstallCommand command = new InstallCommand();
applyMocksToCommand(command);
......@@ -21,12 +21,10 @@ void main() {
when(device.installApp(any)).thenReturn(true);
testDeviceManager.addDevice(device);
return createTestCommandRunner(command).run(<String>['install']).then((int code) {
expect(code, 0);
});
await createTestCommandRunner(command).run(<String>['install']);
});
testUsingContext('returns 0 when iOS is connected and ready for an install', () {
testUsingContext('returns 0 when iOS is connected and ready for an install', () async {
InstallCommand command = new InstallCommand();
applyMocksToCommand(command);
......@@ -35,9 +33,7 @@ void main() {
when(device.installApp(any)).thenReturn(true);
testDeviceManager.addDevice(device);
return createTestCommandRunner(command).run(<String>['install']).then((int code) {
expect(code, 0);
});
await createTestCommandRunner(command).run(<String>['install']);
});
});
}
......@@ -27,20 +27,18 @@ void main() {
Future<Null> createProject() async {
CreateCommand command = new CreateCommand();
CommandRunner runner = createTestCommandRunner(command);
CommandRunner<Null> runner = createTestCommandRunner(command);
int code = await runner.run(<String>['create', '--no-pub', temp.path]);
expect(code, 0);
await runner.run(<String>['create', '--no-pub', temp.path]);
}
Future<Null> runCommand(String verb) async {
await createProject();
PackagesCommand command = new PackagesCommand();
CommandRunner runner = createTestCommandRunner(command);
CommandRunner<Null> runner = createTestCommandRunner(command);
int code = await runner.run(<String>['packages', verb, temp.path]);
expect(code, 0);
await runner.run(<String>['packages', verb, temp.path]);
}
void expectExists(String relPath) {
......
......@@ -6,7 +6,7 @@ import 'package:args/command_runner.dart';
import 'package:flutter_tools/src/runner/flutter_command.dart';
import 'package:flutter_tools/src/runner/flutter_command_runner.dart';
CommandRunner createTestCommandRunner([FlutterCommand command]) {
CommandRunner<Null> createTestCommandRunner([FlutterCommand command]) {
FlutterCommandRunner runner = new FlutterCommandRunner();
if (command != null)
runner.addCommand(command);
......
......@@ -14,27 +14,23 @@ import 'src/mocks.dart';
void main() {
group('stop', () {
testUsingContext('returns 0 when Android is connected and ready to be stopped', () {
testUsingContext('returns 0 when Android is connected and ready to be stopped', () async {
StopCommand command = new StopCommand();
applyMocksToCommand(command);
MockAndroidDevice device = new MockAndroidDevice();
when(device.stopApp(any)).thenReturn(new Future<bool>.value(true));
testDeviceManager.addDevice(device);
return createTestCommandRunner(command).run(<String>['stop']).then((int code) {
expect(code, 0);
});
await createTestCommandRunner(command).run(<String>['stop']);
});
testUsingContext('returns 0 when iOS is connected and ready to be stopped', () {
testUsingContext('returns 0 when iOS is connected and ready to be stopped', () async {
StopCommand command = new StopCommand();
applyMocksToCommand(command);
MockIOSDevice device = new MockIOSDevice();
when(device.stopApp(any)).thenReturn(new Future<bool>.value(true));
testDeviceManager.addDevice(device);
return createTestCommandRunner(command).run(<String>['stop']).then((int code) {
expect(code, 0);
});
await createTestCommandRunner(command).run(<String>['stop']);
});
});
}
......@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/commands/trace.dart';
import 'package:test/test.dart';
......@@ -11,12 +12,15 @@ import 'src/mocks.dart';
void main() {
group('trace', () {
testUsingContext('returns 1 when no Android device is connected', () {
testUsingContext('returns 1 when no Android device is connected', () async {
TraceCommand command = new TraceCommand();
applyMocksToCommand(command);
return createTestCommandRunner(command).run(<String>['trace']).then((int code) {
expect(code, 1);
});
try {
await createTestCommandRunner(command).run(<String>['trace']);
fail('Exception expected');
} on ToolExit catch (e) {
expect(e.exitCode ?? 1, 1);
}
});
});
}
......@@ -49,9 +49,8 @@ void main() {
Future<Null> createProject() async {
CreateCommand command = new CreateCommand();
CommandRunner runner = createTestCommandRunner(command);
int code = await runner.run(<String>['create', '--no-pub', temp.path]);
expect(code, 0);
CommandRunner<Null> runner = createTestCommandRunner(command);
await runner.run(<String>['create', '--no-pub', temp.path]);
}
testUsingContext('in project', () async {
......
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