refactor commands to move out re-usable functionality
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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<dynamic> start(dynamic args) {
|
||||
Future<dynamic> 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<bool> stopAll(dynamic args) {
|
||||
StopCommand stopCommand = new StopCommand();
|
||||
stopCommand.inheritFromParent(daemon.daemonCommand);
|
||||
return stopCommand.stop();
|
||||
return stop.stopAll(command.devices, command.applicationPackages);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<int> 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;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ class ListCommand extends FlutterCommand {
|
||||
help: 'Log additional details about attached devices.');
|
||||
}
|
||||
|
||||
bool get requiresProjectRoot => false;
|
||||
|
||||
@override
|
||||
Future<int> runInProject() async {
|
||||
connectToDevices();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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<int> 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<int> 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;
|
||||
}
|
||||
|
||||
@@ -18,17 +18,19 @@ class StopCommand extends FlutterCommand {
|
||||
return await stop() ? 0 : 2;
|
||||
}
|
||||
|
||||
Future<bool> 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<bool> stop() => stopAll(devices, applicationPackages);
|
||||
}
|
||||
|
||||
Future<bool> 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;
|
||||
}
|
||||
|
||||
@@ -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<Match> matches = new RegExp(
|
||||
r'[\W]*(.*) \(([^\)]+)\) \(Booted\)',
|
||||
multiLine: true
|
||||
|
||||
@@ -47,12 +47,6 @@ abstract class FlutterCommand extends Command {
|
||||
connectToDevices();
|
||||
}
|
||||
|
||||
void inheritFromParent(FlutterCommand other) {
|
||||
applicationPackages = other.applicationPackages;
|
||||
toolchain = other.toolchain;
|
||||
devices = other.devices;
|
||||
}
|
||||
|
||||
Future<int> run() async {
|
||||
if (requiresProjectRoot && !validateProjectRoot())
|
||||
return 1;
|
||||
|
||||
Reference in New Issue
Block a user