From 5daf58ce1eec66bc3ea20ee2ea2db956a42097d3 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Thu, 21 Jan 2016 09:38:46 -0800 Subject: [PATCH] refactor commands to move out re-usable functionality --- .../flutter_tools/lib/src/commands/apk.dart | 2 +- .../lib/src/commands/daemon.dart | 26 ++- .../lib/src/commands/install.dart | 48 +++-- .../flutter_tools/lib/src/commands/list.dart | 2 + .../lib/src/commands/listen.dart | 12 +- .../lib/src/commands/run_mojo.dart | 2 +- .../flutter_tools/lib/src/commands/start.dart | 201 ++++++++++-------- .../flutter_tools/lib/src/commands/stop.dart | 28 +-- packages/flutter_tools/lib/src/device.dart | 2 +- .../lib/src/runner/flutter_command.dart | 6 - 10 files changed, 186 insertions(+), 143 deletions(-) diff --git a/packages/flutter_tools/lib/src/commands/apk.dart b/packages/flutter_tools/lib/src/commands/apk.dart index 43a3037c47..b9bfe124cf 100644 --- a/packages/flutter_tools/lib/src/commands/apk.dart +++ b/packages/flutter_tools/lib/src/commands/apk.dart @@ -302,7 +302,7 @@ class ApkCommand extends FlutterCommand { await downloadToolchain(); // Find the path to the main Dart file. - String mainPath = StartCommandBase.findMainDartFile(argResults['target']); + String mainPath = findMainDartFile(argResults['target']); // Build the FLX. int result; diff --git a/packages/flutter_tools/lib/src/commands/daemon.dart b/packages/flutter_tools/lib/src/commands/daemon.dart index 3fe357a8e2..3609c506e8 100644 --- a/packages/flutter_tools/lib/src/commands/daemon.dart +++ b/packages/flutter_tools/lib/src/commands/daemon.dart @@ -11,10 +11,12 @@ import '../base/logging.dart'; import '../device.dart'; import '../runner/flutter_command.dart'; import 'start.dart'; -import 'stop.dart'; +import 'stop.dart' as stop; const String protocolVersion = '0.0.2'; +// TODO(devoncarew): Pass logging data back to the client. + /// A server process command. This command will start up a long-lived server. /// It reads JSON-RPC based commands from stdin, executes them, and returns /// JSON-RPC based responses and events to stdout. @@ -132,6 +134,8 @@ abstract class Domain { _handlers[name] = handler; } + FlutterCommand get command => daemon.daemonCommand; + String toString() => name; void handleCommand(String name, dynamic id, dynamic args) { @@ -190,17 +194,23 @@ class AppDomain extends Domain { registerHandler('stopAll', stopAll); } - Future start(dynamic args) { + Future start(dynamic args) async { // TODO: Add the ability to pass args: target, http, checked - StartCommand startComand = new StartCommand(); - startComand.inheritFromParent(daemon.daemonCommand); - return startComand.runInProject().then((_) => null); + + await Future.wait([ + command.downloadToolchain(), + command.downloadApplicationPackagesAndConnectToDevices(), + ], eagerError: true); + + return startApp( + command.devices, + command.applicationPackages, + command.toolchain + ).then((int result) => null); } Future stopAll(dynamic args) { - StopCommand stopCommand = new StopCommand(); - stopCommand.inheritFromParent(daemon.daemonCommand); - return stopCommand.stop(); + return stop.stopAll(command.devices, command.applicationPackages); } } diff --git a/packages/flutter_tools/lib/src/commands/install.dart b/packages/flutter_tools/lib/src/commands/install.dart index 40c133a896..5c3147c5c2 100644 --- a/packages/flutter_tools/lib/src/commands/install.dart +++ b/packages/flutter_tools/lib/src/commands/install.dart @@ -13,30 +13,38 @@ class InstallCommand extends FlutterCommand { final String description = 'Install Flutter apps on attached devices.'; InstallCommand() { - argParser.addFlag('boot', - help: 'Boot the iOS Simulator if it isn\'t already running.'); + argParser.addFlag('boot', help: 'Boot the iOS Simulator if it isn\'t already running.'); } @override Future runInProject() async { await downloadApplicationPackagesAndConnectToDevices(); - return install(boot: argResults['boot']) ? 0 : 2; - } - - bool install({ bool boot: false }) { - if (boot) - devices.iOSSimulator?.boot(); - - bool installedSomewhere = false; - - for (Device device in devices.all) { - ApplicationPackage package = applicationPackages.getPackageForPlatform(device.platform); - if (package == null || !device.isConnected() || device.isAppInstalled(package)) - continue; - if (device.installApp(package)) - installedSomewhere = true; - } - - return installedSomewhere; + bool installedAny = installApp( + devices, + applicationPackages, + boot: argResults['boot'] + ); + return installedAny ? 0 : 2; } } + +bool installApp( + DeviceStore devices, + ApplicationPackageStore applicationPackages, { + bool boot: false +}) { + if (boot) + devices.iOSSimulator?.boot(); + + bool installedSomewhere = false; + + for (Device device in devices.all) { + ApplicationPackage package = applicationPackages.getPackageForPlatform(device.platform); + if (package == null || !device.isConnected() || device.isAppInstalled(package)) + continue; + if (device.installApp(package)) + installedSomewhere = true; + } + + return installedSomewhere; +} diff --git a/packages/flutter_tools/lib/src/commands/list.dart b/packages/flutter_tools/lib/src/commands/list.dart index 08deaf12ce..4347b30429 100644 --- a/packages/flutter_tools/lib/src/commands/list.dart +++ b/packages/flutter_tools/lib/src/commands/list.dart @@ -18,6 +18,8 @@ class ListCommand extends FlutterCommand { help: 'Log additional details about attached devices.'); } + bool get requiresProjectRoot => false; + @override Future runInProject() async { connectToDevices(); diff --git a/packages/flutter_tools/lib/src/commands/listen.dart b/packages/flutter_tools/lib/src/commands/listen.dart index f636b3f3b0..7ebe4824b2 100644 --- a/packages/flutter_tools/lib/src/commands/listen.dart +++ b/packages/flutter_tools/lib/src/commands/listen.dart @@ -34,7 +34,17 @@ class ListenCommand extends StartCommandBase { bool firstTime = true; do { logging.info('Updating running Flutter apps...'); - result = await startApp(install: firstTime, stop: true); + result = await startApp( + devices, + applicationPackages, + toolchain, + target: argResults['target'], + install: firstTime, + stop: true, + checked: argResults['checked'], + traceStartup: argResults['trace-startup'], + route: argResults['route'] + ); firstTime = false; } while (!singleRun && result == 0 && _watchDirectory(watchCommand)); return 0; diff --git a/packages/flutter_tools/lib/src/commands/run_mojo.dart b/packages/flutter_tools/lib/src/commands/run_mojo.dart index e3d0ff635b..24d2561674 100644 --- a/packages/flutter_tools/lib/src/commands/run_mojo.dart +++ b/packages/flutter_tools/lib/src/commands/run_mojo.dart @@ -154,7 +154,7 @@ class RunMojoCommand extends FlutterCommand { if (bundlePath == null) { bundlePath = _kDefaultBundlePath; - String mainPath = StartCommandBase.findMainDartFile(argResults['target']); + String mainPath = findMainDartFile(argResults['target']); int result = await flx.build( toolchain, diff --git a/packages/flutter_tools/lib/src/commands/start.dart b/packages/flutter_tools/lib/src/commands/start.dart index dd1a57a81e..862327fc8b 100644 --- a/packages/flutter_tools/lib/src/commands/start.dart +++ b/packages/flutter_tools/lib/src/commands/start.dart @@ -13,9 +13,23 @@ import '../build_configuration.dart'; import '../device.dart'; import '../flx.dart' as flx; import '../runner/flutter_command.dart'; +import '../toolchain.dart'; import 'install.dart'; import 'stop.dart'; +/// Given the value of the --target option, return the path of the Dart file +/// where the app's main function should be. +String findMainDartFile([String target]) { + if (target == null) + target = ''; + String targetPath = path.absolute(target); + if (FileSystemEntity.isDirectorySync(targetPath)) { + return path.join(targetPath, 'lib', 'main.dart'); + } else { + return targetPath; + } +} + // We don't yet support iOS here. https://github.com/flutter/flutter/issues/1036 abstract class StartCommandBase extends FlutterCommand { @@ -29,101 +43,11 @@ abstract class StartCommandBase extends FlutterCommand { defaultsTo: false, help: 'Start tracing during startup.'); argParser.addOption('target', - defaultsTo: '', abbr: 't', help: 'Target app path or filename to start.'); argParser.addOption('route', help: 'Which route to load when starting the app.'); } - - /// Given the value of the --target option, return the path of the Dart file - /// where the app's main function should be. - static String findMainDartFile(String target) { - String targetPath = path.absolute(target); - if (FileSystemEntity.isDirectorySync(targetPath)) { - return path.join(targetPath, 'lib', 'main.dart'); - } else { - return targetPath; - } - } - - Future startApp({ - bool stop: true, - bool install: true, - bool poke: false, - bool clearLogs: false - }) async { - - String mainPath = findMainDartFile(argResults['target']); - if (!FileSystemEntity.isFileSync(mainPath)) { - String message = 'Tried to run $mainPath, but that file does not exist.'; - if (!argResults.wasParsed('target')) - message += '\nConsider using the -t option to specify that Dart file to start.'; - logging.severe(message); - return 1; - } - - if (stop) { - logging.fine('Running stop command.'); - StopCommand stopper = new StopCommand(); - stopper.inheritFromParent(this); - stopper.stop(); - } - - if (install) { - logging.fine('Running install command.'); - InstallCommand installer = new InstallCommand(); - installer.inheritFromParent(this); - installer.install(); - } - - bool startedSomething = false; - - for (Device device in devices.all) { - ApplicationPackage package = applicationPackages.getPackageForPlatform(device.platform); - if (package == null || !device.isConnected()) - continue; - - logging.fine('Running build command for $device.'); - - if (device.platform == TargetPlatform.android) { - await flx.buildInTempDir( - toolchain, - mainPath: mainPath, - onBundleAvailable: (String localBundlePath) { - logging.fine('Starting bundle for $device.'); - final AndroidDevice androidDevice = device; // https://github.com/flutter/flutter/issues/1035 - if (androidDevice.startBundle(package, localBundlePath, - poke: poke, - checked: argResults['checked'], - traceStartup: argResults['trace-startup'], - route: argResults['route'], - clearLogs: clearLogs - )) { - startedSomething = true; - } - } - ); - } else { - bool result = await device.startApp(package); - if (!result) { - logging.severe('Could not start \'${package.name}\' on \'${device.id}\''); - } else { - startedSomething = true; - } - } - } - - if (!startedSomething) { - if (!devices.all.any((device) => device.isConnected())) { - logging.severe('Unable to run application - no connected devices.'); - } else { - logging.severe('Unable to run application.'); - } - } - - return startedSomething ? 0 : 2; - } } class StartCommand extends StartCommandBase { @@ -152,10 +76,103 @@ class StartCommand extends StartCommandBase { bool poke = argResults['poke']; bool clearLogs = argResults['clear-logs']; - // Only stop and reinstall if the user did not specify a poke - int result = await startApp(stop: !poke, install: !poke, poke: poke, clearLogs: clearLogs); + // Only stop and reinstall if the user did not specify a poke. + int result = await startApp( + devices, + applicationPackages, + toolchain, + target: argResults['target'], + install: !poke, + stop: !poke, + checked: argResults['checked'], + traceStartup: argResults['trace-startup'], + route: argResults['route'], + poke: poke, + clearLogs: clearLogs + ); logging.fine('Finished start command.'); return result; } } + +Future startApp( + DeviceStore devices, + ApplicationPackageStore applicationPackages, + Toolchain toolchain, { + String target, + bool stop: true, + bool install: true, + bool checked: true, + bool traceStartup: false, + String route, + bool poke: false, + bool clearLogs: false +}) async { + + String mainPath = findMainDartFile(target); + if (!FileSystemEntity.isFileSync(mainPath)) { + String message = 'Tried to run $mainPath, but that file does not exist.'; + if (target == null) + message += '\nConsider using the -t option to specify the Dart file to start.'; + logging.severe(message); + return 1; + } + + if (stop) { + logging.fine('Running stop command.'); + stopAll(devices, applicationPackages); + } + + if (install) { + logging.fine('Running install command.'); + installApp(devices, applicationPackages); + } + + bool startedSomething = false; + + for (Device device in devices.all) { + ApplicationPackage package = applicationPackages.getPackageForPlatform(device.platform); + if (package == null || !device.isConnected()) + continue; + + logging.fine('Running build command for $device.'); + + if (device.platform == TargetPlatform.android) { + await flx.buildInTempDir( + toolchain, + mainPath: mainPath, + onBundleAvailable: (String localBundlePath) { + logging.fine('Starting bundle for $device.'); + final AndroidDevice androidDevice = device; // https://github.com/flutter/flutter/issues/1035 + if (androidDevice.startBundle(package, localBundlePath, + poke: poke, + checked: checked, + traceStartup: traceStartup, + route: route, + clearLogs: clearLogs + )) { + startedSomething = true; + } + } + ); + } else { + bool result = await device.startApp(package); + if (!result) { + logging.severe('Could not start \'${package.name}\' on \'${device.id}\''); + } else { + startedSomething = true; + } + } + } + + if (!startedSomething) { + if (!devices.all.any((device) => device.isConnected())) { + logging.severe('Unable to run application - no connected devices.'); + } else { + logging.severe('Unable to run application.'); + } + } + + return startedSomething ? 0 : 2; +} diff --git a/packages/flutter_tools/lib/src/commands/stop.dart b/packages/flutter_tools/lib/src/commands/stop.dart index b4c56eece5..8f9447243e 100644 --- a/packages/flutter_tools/lib/src/commands/stop.dart +++ b/packages/flutter_tools/lib/src/commands/stop.dart @@ -18,17 +18,19 @@ class StopCommand extends FlutterCommand { return await stop() ? 0 : 2; } - Future stop() async { - bool stoppedSomething = false; - - for (Device device in devices.all) { - ApplicationPackage package = applicationPackages.getPackageForPlatform(device.platform); - if (package == null || !device.isConnected()) - continue; - if (await device.stopApp(package)) - stoppedSomething = true; - } - - return stoppedSomething; - } + Future stop() => stopAll(devices, applicationPackages); +} + +Future stopAll(DeviceStore devices, ApplicationPackageStore applicationPackages) async { + bool stoppedSomething = false; + + for (Device device in devices.all) { + ApplicationPackage package = applicationPackages.getPackageForPlatform(device.platform); + if (package == null || !device.isConnected()) + continue; + if (await device.stopApp(package)) + stoppedSomething = true; + } + + return stoppedSomething; } diff --git a/packages/flutter_tools/lib/src/device.dart b/packages/flutter_tools/lib/src/device.dart index a9265c952e..b5d56a0c56 100644 --- a/packages/flutter_tools/lib/src/device.dart +++ b/packages/flutter_tools/lib/src/device.dart @@ -310,7 +310,7 @@ class IOSSimulator extends Device { String output = runCheckedSync([xcrunPath, 'simctl', 'list', 'devices']); Match match; - /// iPhone 6s Plus (8AC808E1-6BAE-4153-BBC5-77F83814D414) (Booted) + // iPhone 6s Plus (8AC808E1-6BAE-4153-BBC5-77F83814D414) (Booted) Iterable matches = new RegExp( r'[\W]*(.*) \(([^\)]+)\) \(Booted\)', multiLine: true diff --git a/packages/flutter_tools/lib/src/runner/flutter_command.dart b/packages/flutter_tools/lib/src/runner/flutter_command.dart index 6aa76eb2a4..b6eee333c2 100644 --- a/packages/flutter_tools/lib/src/runner/flutter_command.dart +++ b/packages/flutter_tools/lib/src/runner/flutter_command.dart @@ -47,12 +47,6 @@ abstract class FlutterCommand extends Command { connectToDevices(); } - void inheritFromParent(FlutterCommand other) { - applicationPackages = other.applicationPackages; - toolchain = other.toolchain; - devices = other.devices; - } - Future run() async { if (requiresProjectRoot && !validateProjectRoot()) return 1;