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/cache.dart';
|
||||||
import 'package:sky_tools/src/init.dart';
|
import 'package:sky_tools/src/init.dart';
|
||||||
import 'package:sky_tools/src/install.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/logs.dart';
|
||||||
import 'package:sky_tools/src/run_mojo.dart';
|
import 'package:sky_tools/src/run_mojo.dart';
|
||||||
import 'package:sky_tools/src/start.dart';
|
import 'package:sky_tools/src/start.dart';
|
||||||
@ -149,6 +150,7 @@ void main(List<String> args) {
|
|||||||
..addCommand(new CacheCommand())
|
..addCommand(new CacheCommand())
|
||||||
..addCommand(new InitCommand())
|
..addCommand(new InitCommand())
|
||||||
..addCommand(new InstallCommand())
|
..addCommand(new InstallCommand())
|
||||||
|
..addCommand(new ListenCommand())
|
||||||
..addCommand(new LogsCommand())
|
..addCommand(new LogsCommand())
|
||||||
..addCommand(new RunMojoCommand())
|
..addCommand(new RunMojoCommand())
|
||||||
..addCommand(new StartCommand())
|
..addCommand(new StartCommand())
|
||||||
|
@ -256,6 +256,7 @@ class AndroidDevice extends _Device {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!poke) {
|
||||||
// Set up port forwarding for observatory.
|
// Set up port forwarding for observatory.
|
||||||
String observatoryPortString = 'tcp:$_observatoryPort';
|
String observatoryPortString = 'tcp:$_observatoryPort';
|
||||||
runCheckedSync(
|
runCheckedSync(
|
||||||
@ -269,6 +270,7 @@ class AndroidDevice extends _Device {
|
|||||||
// server running on localhost.
|
// server running on localhost.
|
||||||
String serverPortString = 'tcp:$_serverPort';
|
String serverPortString = 'tcp:$_serverPort';
|
||||||
runCheckedSync([adbPath, 'reverse', serverPortString, serverPortString]);
|
runCheckedSync([adbPath, 'reverse', serverPortString, serverPortString]);
|
||||||
|
}
|
||||||
|
|
||||||
String relativeDartMain = path.relative(mainDart, from: serverRoot);
|
String relativeDartMain = path.relative(mainDart, from: serverRoot);
|
||||||
String url = 'http://localhost:$_serverPort/$relativeDartMain';
|
String url = 'http://localhost:$_serverPort/$relativeDartMain';
|
||||||
|
@ -15,7 +15,11 @@ class InstallCommand extends Command {
|
|||||||
final name = 'install';
|
final name = 'install';
|
||||||
final description = 'Install your Flutter app on attached devices.';
|
final description = 'Install your Flutter app on attached devices.';
|
||||||
AndroidDevice android = null;
|
AndroidDevice android = null;
|
||||||
InstallCommand([this.android]);
|
InstallCommand([this.android]) {
|
||||||
|
if (android == null) {
|
||||||
|
android = new AndroidDevice();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<int> run() async {
|
Future<int> run() async {
|
||||||
@ -31,9 +35,6 @@ class InstallCommand extends Command {
|
|||||||
|
|
||||||
Map<BuildPlatform, ApplicationPackage> packages =
|
Map<BuildPlatform, ApplicationPackage> packages =
|
||||||
ApplicationPackageFactory.getAvailableApplicationPackages();
|
ApplicationPackageFactory.getAvailableApplicationPackages();
|
||||||
if (android == null) {
|
|
||||||
android = new AndroidDevice();
|
|
||||||
}
|
|
||||||
ApplicationPackage androidApp = packages[BuildPlatform.android];
|
ApplicationPackage androidApp = packages[BuildPlatform.android];
|
||||||
if (androidApp != null && android.isConnected()) {
|
if (androidApp != null && android.isConnected()) {
|
||||||
installedSomewhere = android.installApp(androidApp) || installedSomewhere;
|
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