Add listen command and basic test, and don’t do unnecessary repeated work when listening or poking the android server.
This commit is contained in:
parent
2bc289dec9
commit
00bed774ce
@ -13,6 +13,7 @@ import 'package:sky_tools/src/build.dart';
|
||||
import 'package:sky_tools/src/cache.dart';
|
||||
import 'package:sky_tools/src/init.dart';
|
||||
import 'package:sky_tools/src/install.dart';
|
||||
import 'package:sky_tools/src/listen.dart';
|
||||
import 'package:sky_tools/src/logs.dart';
|
||||
import 'package:sky_tools/src/run_mojo.dart';
|
||||
import 'package:sky_tools/src/start.dart';
|
||||
@ -149,6 +150,7 @@ void main(List<String> args) {
|
||||
..addCommand(new CacheCommand())
|
||||
..addCommand(new InitCommand())
|
||||
..addCommand(new InstallCommand())
|
||||
..addCommand(new ListenCommand())
|
||||
..addCommand(new LogsCommand())
|
||||
..addCommand(new RunMojoCommand())
|
||||
..addCommand(new StartCommand())
|
||||
|
@ -256,19 +256,21 @@ class AndroidDevice extends _Device {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set up port forwarding for observatory.
|
||||
String observatoryPortString = 'tcp:$_observatoryPort';
|
||||
runCheckedSync(
|
||||
[adbPath, 'forward', observatoryPortString, observatoryPortString]);
|
||||
if (!poke) {
|
||||
// Set up port forwarding for observatory.
|
||||
String observatoryPortString = 'tcp:$_observatoryPort';
|
||||
runCheckedSync(
|
||||
[adbPath, 'forward', observatoryPortString, observatoryPortString]);
|
||||
|
||||
// Actually start the server.
|
||||
await Process.start('pub', ['run', 'sky_tools:sky_server', _serverPort],
|
||||
workingDirectory: serverRoot, mode: ProcessStartMode.DETACHED);
|
||||
// Actually start the server.
|
||||
await Process.start('pub', ['run', 'sky_tools:sky_server', _serverPort],
|
||||
workingDirectory: serverRoot, mode: ProcessStartMode.DETACHED);
|
||||
|
||||
// Set up reverse port-forwarding so that the Android app can reach the
|
||||
// server running on localhost.
|
||||
String serverPortString = 'tcp:$_serverPort';
|
||||
runCheckedSync([adbPath, 'reverse', serverPortString, serverPortString]);
|
||||
// Set up reverse port-forwarding so that the Android app can reach the
|
||||
// server running on localhost.
|
||||
String serverPortString = 'tcp:$_serverPort';
|
||||
runCheckedSync([adbPath, 'reverse', serverPortString, serverPortString]);
|
||||
}
|
||||
|
||||
String relativeDartMain = path.relative(mainDart, from: serverRoot);
|
||||
String url = 'http://localhost:$_serverPort/$relativeDartMain';
|
||||
|
@ -15,7 +15,11 @@ class InstallCommand extends Command {
|
||||
final name = 'install';
|
||||
final description = 'Install your Flutter app on attached devices.';
|
||||
AndroidDevice android = null;
|
||||
InstallCommand([this.android]);
|
||||
InstallCommand([this.android]) {
|
||||
if (android == null) {
|
||||
android = new AndroidDevice();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> run() async {
|
||||
@ -31,9 +35,6 @@ class InstallCommand extends Command {
|
||||
|
||||
Map<BuildPlatform, ApplicationPackage> packages =
|
||||
ApplicationPackageFactory.getAvailableApplicationPackages();
|
||||
if (android == null) {
|
||||
android = new AndroidDevice();
|
||||
}
|
||||
ApplicationPackage androidApp = packages[BuildPlatform.android];
|
||||
if (androidApp != null && android.isConnected()) {
|
||||
installedSomewhere = android.installApp(androidApp) || installedSomewhere;
|
||||
|
118
packages/flutter_tools/lib/src/listen.dart
Normal file
118
packages/flutter_tools/lib/src/listen.dart
Normal file
@ -0,0 +1,118 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
library sky_tools.listen;
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:args/command_runner.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:sky_tools/src/application_package.dart';
|
||||
import 'package:sky_tools/src/device.dart';
|
||||
import 'package:sky_tools/src/process.dart';
|
||||
|
||||
final Logger _logging = new Logger('sky_tools.listen');
|
||||
|
||||
class ListenCommand extends Command {
|
||||
final name = 'listen';
|
||||
final description = 'Listen for changes to files and reload the running app '
|
||||
'on all connected devices.';
|
||||
AndroidDevice android = null;
|
||||
List<String> watchCommand;
|
||||
|
||||
/// Only run once. Used for testing.
|
||||
bool singleRun;
|
||||
|
||||
ListenCommand({this.android, this.singleRun: false}) {
|
||||
argParser.addFlag('checked',
|
||||
negatable: true,
|
||||
defaultsTo: true,
|
||||
help: 'Toggle Dart\'s checked mode.');
|
||||
argParser.addOption('target',
|
||||
defaultsTo: '.',
|
||||
abbr: 't',
|
||||
help: 'Target app path or filename to start.');
|
||||
|
||||
if (android == null) {
|
||||
android = new AndroidDevice();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> run() async {
|
||||
if (argResults.rest.length > 0) {
|
||||
watchCommand = _initWatchCommand(argResults.rest);
|
||||
} else {
|
||||
watchCommand = _initWatchCommand(['.']);
|
||||
}
|
||||
|
||||
Map<BuildPlatform, ApplicationPackage> packages =
|
||||
ApplicationPackageFactory.getAvailableApplicationPackages();
|
||||
ApplicationPackage androidApp = packages[BuildPlatform.android];
|
||||
|
||||
while (true) {
|
||||
_logging.info('Updating running Sky apps...');
|
||||
|
||||
if (android.isConnected()) {
|
||||
await android.startServer(
|
||||
argResults['target'], true, argResults['checked'], androidApp);
|
||||
}
|
||||
|
||||
if (singleRun || !watchDirectory()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
List<String> _initWatchCommand(List<String> directories) {
|
||||
if (Platform.isMacOS) {
|
||||
try {
|
||||
runCheckedSync(['which', 'fswatch']);
|
||||
} catch (e) {
|
||||
_logging.severe('"listen" command is only useful if you have installed '
|
||||
'fswatch on Mac. Run "brew install fswatch" to install it with '
|
||||
'homebrew.');
|
||||
return null;
|
||||
}
|
||||
return ['fswatch', '-r', '-v', '-1']..addAll(directories);
|
||||
} else if (Platform.isLinux) {
|
||||
try {
|
||||
runCheckedSync(['which', 'inotifywait']);
|
||||
} catch (e) {
|
||||
_logging.severe('"listen" command is only useful if you have installed '
|
||||
'inotifywait on Linux. Run "apt-get install inotify-tools" or '
|
||||
'equivalent to install it.');
|
||||
return null;
|
||||
}
|
||||
return [
|
||||
'inotifywait',
|
||||
'-r',
|
||||
'-e',
|
||||
// Only listen for events that matter, to avoid triggering constantly
|
||||
// from the editor watching files
|
||||
'modify,close_write,move,create,delete',
|
||||
]..addAll(directories);
|
||||
} else {
|
||||
_logging.severe('"listen" command is only available on Mac and Linux.');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
bool watchDirectory() {
|
||||
if (watchCommand == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
runCheckedSync(watchCommand);
|
||||
} catch (e) {
|
||||
_logging.warning('Watching directories failed.', e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
34
packages/flutter_tools/test/listen_test.dart
Normal file
34
packages/flutter_tools/test/listen_test.dart
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
library stop_test;
|
||||
|
||||
import 'package:args/command_runner.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:sky_tools/src/application_package.dart';
|
||||
import 'package:sky_tools/src/listen.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import 'src/common.dart';
|
||||
|
||||
main() => defineTests();
|
||||
|
||||
defineTests() {
|
||||
group('listen', () {
|
||||
test('returns 0 when no device is connected', () {
|
||||
ApplicationPackageFactory.srcPath = './';
|
||||
ApplicationPackageFactory.setBuildPath(
|
||||
BuildType.prebuilt, BuildPlatform.android, './');
|
||||
|
||||
MockAndroidDevice android = new MockAndroidDevice();
|
||||
when(android.isConnected()).thenReturn(false);
|
||||
ListenCommand command =
|
||||
new ListenCommand(android: android, singleRun: true);
|
||||
|
||||
CommandRunner runner = new CommandRunner('test_flutter', '')
|
||||
..addCommand(command);
|
||||
runner.run(['listen']).then((int code) => expect(code, equals(0)));
|
||||
});
|
||||
});
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user