introduce globals scoped to the app's context
diff --git a/packages/flutter_tools/lib/executable.dart b/packages/flutter_tools/lib/executable.dart
index e92e058..b6ff950 100644
--- a/packages/flutter_tools/lib/executable.dart
+++ b/packages/flutter_tools/lib/executable.dart
@@ -8,6 +8,8 @@
import 'package:args/command_runner.dart';
import 'package:stack_trace/stack_trace.dart';
+import 'src/base/context.dart';
+import 'src/base/logger.dart';
import 'src/base/process.dart';
import 'src/commands/analyze.dart';
import 'src/commands/apk.dart';
@@ -27,6 +29,7 @@
import 'src/commands/test.dart';
import 'src/commands/trace.dart';
import 'src/commands/upgrade.dart';
+import 'src/device.dart';
import 'src/runner/flutter_command_runner.dart';
/// Main entry point for commands.
@@ -62,7 +65,12 @@
if (args.isNotEmpty && args[0] == 'init')
args[0] = 'create';
+ // Initialize globals.
+ context[Logger] = new StdoutLogger();
+ context[DeviceManager] = new DeviceManager();
+
dynamic result = await runner.run(args);
+
if (result is int)
exit(result);
}, onError: (error, Chain chain) {
diff --git a/packages/flutter_tools/lib/src/android/adb.dart b/packages/flutter_tools/lib/src/android/adb.dart
index aad03e3..e8b0f94 100644
--- a/packages/flutter_tools/lib/src/android/adb.dart
+++ b/packages/flutter_tools/lib/src/android/adb.dart
@@ -5,7 +5,7 @@
import 'dart:async';
import 'dart:io';
-import '../base/context.dart';
+import '../base/globals.dart';
import '../base/process.dart';
// https://android.googlesource.com/platform/system/core/+/android-4.4_r1/adb/OVERVIEW.TXT
diff --git a/packages/flutter_tools/lib/src/android/device_android.dart b/packages/flutter_tools/lib/src/android/device_android.dart
index e0eadf9..c55e0d4 100644
--- a/packages/flutter_tools/lib/src/android/device_android.dart
+++ b/packages/flutter_tools/lib/src/android/device_android.dart
@@ -10,7 +10,7 @@
import '../application_package.dart';
import '../base/common.dart';
-import '../base/context.dart';
+import '../base/globals.dart';
import '../base/os.dart';
import '../base/process.dart';
import '../build_configuration.dart';
diff --git a/packages/flutter_tools/lib/src/artifacts.dart b/packages/flutter_tools/lib/src/artifacts.dart
index 123b752..4d304ed 100644
--- a/packages/flutter_tools/lib/src/artifacts.dart
+++ b/packages/flutter_tools/lib/src/artifacts.dart
@@ -8,7 +8,7 @@
import 'package:archive/archive.dart';
import 'package:path/path.dart' as path;
-import 'base/context.dart';
+import 'base/globals.dart';
import 'base/os.dart';
import 'base/process.dart';
import 'build_configuration.dart';
diff --git a/packages/flutter_tools/lib/src/base/context.dart b/packages/flutter_tools/lib/src/base/context.dart
index 21054a4..8c1f54d 100644
--- a/packages/flutter_tools/lib/src/base/context.dart
+++ b/packages/flutter_tools/lib/src/base/context.dart
@@ -3,9 +3,8 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:io';
-final AppContext _defaultContext = new _DefaultAppContext();
+final AppContext _defaultContext = new AppContext();
/// A singleton for application functionality. This singleton can be different
/// on a per-Zone basis.
@@ -14,57 +13,42 @@
return currentContext == null ? _defaultContext : currentContext;
}
-/// Display an error level message to the user. Commands should use this if they
-/// fail in some way.
-void printError(String message, [StackTrace stackTrace]) => context.printError(message, stackTrace);
+class AppContext {
+ Map<Type, dynamic> _instances = <Type, dynamic>{};
-/// Display normal output of the command. This should be used for things like
-/// progress messages, success messages, or just normal command output.
-void printStatus(String message) => context.printStatus(message);
+ dynamic getVariable(Type type) {
+ if (_instances.containsKey(type))
+ return _instances[type];
-/// Use this for verbose tracing output. Users can turn this output on in order
-/// to help diagnose issues with the toolchain or with their setup.
-void printTrace(String message) => context.printTrace(message);
-
-abstract class AppContext {
- bool get verbose;
- set verbose(bool value);
-
- void printError(String message, [StackTrace stackTrace]);
- void printStatus(String message);
- void printTrace(String message);
-}
-
-class _DefaultAppContext implements AppContext {
- DateTime _startTime = new DateTime.now();
-
- bool _verbose = false;
-
- bool get verbose => _verbose;
-
- set verbose(bool value) {
- _verbose = value;
+ AppContext parent = _calcParent(Zone.current);
+ return parent?.getVariable(type);
}
- void printError(String message, [StackTrace stackTrace]) {
- stderr.writeln(_prefix + message);
- if (stackTrace != null)
- stderr.writeln(stackTrace);
+ void setVariable(Type type, dynamic instance) {
+ _instances[type] = instance;
}
- void printStatus(String message) {
- print(_prefix + message);
+ dynamic operator[](Type type) => getVariable(type);
+
+ void operator[]=(Type type, dynamic instance) => setVariable(type, instance);
+
+ AppContext _calcParent(Zone zone) {
+ if (this == _defaultContext)
+ return null;
+
+ Zone parentZone = zone.parent;
+ if (parentZone == null)
+ return _defaultContext;
+
+ AppContext deps = parentZone['context'];
+ if (deps == this) {
+ return _calcParent(parentZone);
+ } else {
+ return deps != null ? deps : _defaultContext;
+ }
}
- void printTrace(String message) {
- if (_verbose)
- print('$_prefix- $message');
- }
-
- String get _prefix {
- if (!_verbose)
- return '';
- Duration elapsed = new DateTime.now().difference(_startTime);
- return '[${elapsed.inMilliseconds.toString().padLeft(4)} ms] ';
+ dynamic runInZone(dynamic method()) {
+ return runZoned(method, zoneValues: {'context': this});
}
}
diff --git a/packages/flutter_tools/lib/src/base/globals.dart b/packages/flutter_tools/lib/src/base/globals.dart
new file mode 100644
index 0000000..5c86fb2
--- /dev/null
+++ b/packages/flutter_tools/lib/src/base/globals.dart
@@ -0,0 +1,22 @@
+// Copyright 2016 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.
+
+import '../device.dart';
+import 'context.dart';
+import 'logger.dart';
+
+DeviceManager get deviceManager => context[DeviceManager];
+Logger get logger => context[Logger];
+
+/// Display an error level message to the user. Commands should use this if they
+/// fail in some way.
+void printError(String message, [StackTrace stackTrace]) => logger.printError(message, stackTrace);
+
+/// Display normal output of the command. This should be used for things like
+/// progress messages, success messages, or just normal command output.
+void printStatus(String message) => logger.printStatus(message);
+
+/// Use this for verbose tracing output. Users can turn this output on in order
+/// to help diagnose issues with the toolchain or with their setup.
+void printTrace(String message) => logger.printTrace(message);
diff --git a/packages/flutter_tools/lib/src/base/logger.dart b/packages/flutter_tools/lib/src/base/logger.dart
new file mode 100644
index 0000000..0489279
--- /dev/null
+++ b/packages/flutter_tools/lib/src/base/logger.dart
@@ -0,0 +1,65 @@
+// Copyright 2016 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.
+
+import 'dart:io';
+
+abstract class Logger {
+ bool verbose = false;
+
+ /// Display an error level message to the user. Commands should use this if they
+ /// fail in some way.
+ void printError(String message, [StackTrace stackTrace]);
+
+ /// Display normal output of the command. This should be used for things like
+ /// progress messages, success messages, or just normal command output.
+ void printStatus(String message);
+
+ /// Use this for verbose tracing output. Users can turn this output on in order
+ /// to help diagnose issues with the toolchain or with their setup.
+ void printTrace(String message);
+}
+
+class StdoutLogger implements Logger {
+ DateTime _startTime = new DateTime.now();
+
+ bool verbose = false;
+
+ void printError(String message, [StackTrace stackTrace]) {
+ stderr.writeln(_prefix + message);
+ if (stackTrace != null)
+ stderr.writeln(stackTrace);
+ }
+
+ void printStatus(String message) {
+ print(_prefix + message);
+ }
+
+ void printTrace(String message) {
+ if (verbose)
+ print('$_prefix- $message');
+ }
+
+ String get _prefix {
+ if (!verbose)
+ return '';
+ Duration elapsed = new DateTime.now().difference(_startTime);
+ return '[${elapsed.inMilliseconds.toString().padLeft(4)} ms] ';
+ }
+}
+
+class BufferLogger implements Logger {
+ StringBuffer _error = new StringBuffer();
+ StringBuffer _status = new StringBuffer();
+ StringBuffer _trace = new StringBuffer();
+
+ bool verbose = false;
+
+ String get errorText => _error.toString();
+ String get statusText => _status.toString();
+ String get traceText => _trace.toString();
+
+ void printError(String message, [StackTrace stackTrace]) => _error.writeln(message);
+ void printStatus(String message) => _status.writeln(message);
+ void printTrace(String message) => _trace.writeln(message);
+}
diff --git a/packages/flutter_tools/lib/src/base/process.dart b/packages/flutter_tools/lib/src/base/process.dart
index 7da7699..cac6702 100644
--- a/packages/flutter_tools/lib/src/base/process.dart
+++ b/packages/flutter_tools/lib/src/base/process.dart
@@ -6,7 +6,7 @@
import 'dart:convert';
import 'dart:io';
-import 'context.dart';
+import 'globals.dart';
typedef String StringConverter(String string);
diff --git a/packages/flutter_tools/lib/src/build_configuration.dart b/packages/flutter_tools/lib/src/build_configuration.dart
index 82a5bbb..160334b 100644
--- a/packages/flutter_tools/lib/src/build_configuration.dart
+++ b/packages/flutter_tools/lib/src/build_configuration.dart
@@ -6,7 +6,7 @@
import 'package:path/path.dart' as path;
-import 'base/context.dart';
+import 'base/globals.dart';
enum BuildType {
prebuilt,
diff --git a/packages/flutter_tools/lib/src/commands/analyze.dart b/packages/flutter_tools/lib/src/commands/analyze.dart
index 7d6742f..b50b90e 100644
--- a/packages/flutter_tools/lib/src/commands/analyze.dart
+++ b/packages/flutter_tools/lib/src/commands/analyze.dart
@@ -11,7 +11,7 @@
import 'package:path/path.dart' as path;
import '../artifacts.dart';
-import '../base/context.dart';
+import '../base/globals.dart';
import '../base/process.dart';
import '../build_configuration.dart';
import '../runner/flutter_command.dart';
diff --git a/packages/flutter_tools/lib/src/commands/apk.dart b/packages/flutter_tools/lib/src/commands/apk.dart
index 14070c9..f0f728f 100644
--- a/packages/flutter_tools/lib/src/commands/apk.dart
+++ b/packages/flutter_tools/lib/src/commands/apk.dart
@@ -12,8 +12,8 @@
import '../android/device_android.dart';
import '../application_package.dart';
import '../artifacts.dart';
-import '../base/context.dart';
import '../base/file_system.dart';
+import '../base/globals.dart';
import '../base/process.dart';
import '../build_configuration.dart';
import '../device.dart';
diff --git a/packages/flutter_tools/lib/src/commands/build.dart b/packages/flutter_tools/lib/src/commands/build.dart
index 1cfa1b0..5e1f763 100644
--- a/packages/flutter_tools/lib/src/commands/build.dart
+++ b/packages/flutter_tools/lib/src/commands/build.dart
@@ -4,7 +4,7 @@
import 'dart:async';
-import '../base/context.dart';
+import '../base/globals.dart';
import '../flx.dart';
import '../runner/flutter_command.dart';
import '../toolchain.dart';
diff --git a/packages/flutter_tools/lib/src/commands/create.dart b/packages/flutter_tools/lib/src/commands/create.dart
index 60da5e5..f58bc77 100644
--- a/packages/flutter_tools/lib/src/commands/create.dart
+++ b/packages/flutter_tools/lib/src/commands/create.dart
@@ -11,7 +11,7 @@
import '../android/android.dart' as android;
import '../artifacts.dart';
-import '../base/context.dart';
+import '../base/globals.dart';
import '../base/process.dart';
class CreateCommand extends Command {
diff --git a/packages/flutter_tools/lib/src/commands/daemon.dart b/packages/flutter_tools/lib/src/commands/daemon.dart
index 1656d8e..0dee7cc 100644
--- a/packages/flutter_tools/lib/src/commands/daemon.dart
+++ b/packages/flutter_tools/lib/src/commands/daemon.dart
@@ -9,6 +9,8 @@
import '../android/adb.dart';
import '../android/device_android.dart';
import '../base/context.dart';
+import '../base/globals.dart';
+import '../base/logger.dart';
import '../device.dart';
import '../ios/device_ios.dart';
import '../ios/simulator.dart';
@@ -33,9 +35,11 @@
Future<int> runInProject() {
printStatus('Starting device daemon...');
- NotifyingAppContext appContext = new NotifyingAppContext();
+ AppContext appContext = new AppContext();
+ NotifyingLogger notifyingLogger = new NotifyingLogger();
+ appContext[Logger] = notifyingLogger;
- return runZoned(() {
+ return appContext.runInZone(() {
Stream<Map<String, dynamic>> commandStream = stdin
.transform(UTF8.decoder)
.transform(const LineSplitter())
@@ -47,10 +51,10 @@
Daemon daemon = new Daemon(commandStream, (Map command) {
stdout.writeln('[${JSON.encode(command, toEncodable: _jsonEncodeObject)}]');
- }, daemonCommand: this, appContext: appContext);
+ }, daemonCommand: this, notifyingLogger: notifyingLogger);
return daemon.onExit;
- }, zoneValues: {'context': appContext});
+ });
}
dynamic _jsonEncodeObject(dynamic object) {
@@ -67,7 +71,7 @@
class Daemon {
Daemon(Stream<Map> commandStream, this.sendCommand, {
this.daemonCommand,
- this.appContext
+ this.notifyingLogger
}) {
// Set up domains.
_registerDomain(new DaemonDomain(this));
@@ -83,7 +87,7 @@
final DispatchComand sendCommand;
final DaemonCommand daemonCommand;
- final NotifyingAppContext appContext;
+ final NotifyingLogger notifyingLogger;
final Completer<int> _onExitCompleter = new Completer<int>();
final Map<String, Domain> _domainMap = <String, Domain>{};
@@ -185,7 +189,7 @@
registerHandler('version', version);
registerHandler('shutdown', shutdown);
- _subscription = daemon.appContext.onMessage.listen((LogMessage message) {
+ _subscription = daemon.notifyingLogger.onMessage.listen((LogMessage message) {
if (message.stackTrace != null) {
sendEvent('daemon.logMessage', {
'level': message.level,
@@ -467,13 +471,11 @@
return '$obj';
}
-class NotifyingAppContext implements AppContext {
+class NotifyingLogger extends Logger {
StreamController<LogMessage> _messageController = new StreamController<LogMessage>.broadcast();
Stream<LogMessage> get onMessage => _messageController.stream;
- bool verbose = false;
-
void printError(String message, [StackTrace stackTrace]) {
_messageController.add(new LogMessage('error', message, stackTrace));
}
diff --git a/packages/flutter_tools/lib/src/commands/ios.dart b/packages/flutter_tools/lib/src/commands/ios.dart
index b424981..96f110a 100644
--- a/packages/flutter_tools/lib/src/commands/ios.dart
+++ b/packages/flutter_tools/lib/src/commands/ios.dart
@@ -8,7 +8,7 @@
import "package:path/path.dart" as path;
import "../artifacts.dart";
-import "../base/context.dart";
+import "../base/globals.dart";
import "../base/process.dart";
import "../runner/flutter_command.dart";
import "../runner/flutter_command_runner.dart";
diff --git a/packages/flutter_tools/lib/src/commands/list.dart b/packages/flutter_tools/lib/src/commands/list.dart
index 885ba15..2eb0437 100644
--- a/packages/flutter_tools/lib/src/commands/list.dart
+++ b/packages/flutter_tools/lib/src/commands/list.dart
@@ -4,7 +4,7 @@
import 'dart:async';
-import '../base/context.dart';
+import '../base/globals.dart';
import '../device.dart';
import '../runner/flutter_command.dart';
@@ -15,9 +15,7 @@
bool get requiresProjectRoot => false;
Future<int> runInProject() async {
- DeviceManager deviceManager = new DeviceManager();
-
- List<Device> devices = await deviceManager.getDevices();
+ List<Device> devices = await deviceManager.getAllConnectedDevices();
if (devices.isEmpty) {
printStatus('No connected devices.');
diff --git a/packages/flutter_tools/lib/src/commands/listen.dart b/packages/flutter_tools/lib/src/commands/listen.dart
index b139355..4fd76de 100644
--- a/packages/flutter_tools/lib/src/commands/listen.dart
+++ b/packages/flutter_tools/lib/src/commands/listen.dart
@@ -5,7 +5,7 @@
import 'dart:async';
import 'dart:io';
-import '../base/context.dart';
+import '../base/globals.dart';
import '../base/process.dart';
import 'start.dart';
diff --git a/packages/flutter_tools/lib/src/commands/logs.dart b/packages/flutter_tools/lib/src/commands/logs.dart
index 0b274d3..3766de2 100644
--- a/packages/flutter_tools/lib/src/commands/logs.dart
+++ b/packages/flutter_tools/lib/src/commands/logs.dart
@@ -4,7 +4,7 @@
import 'dart:async';
-import '../base/context.dart';
+import '../base/globals.dart';
import '../device.dart';
import '../runner/flutter_command.dart';
@@ -24,21 +24,14 @@
Future<int> runInProject() async {
DeviceManager deviceManager = new DeviceManager();
- List<Device> devices;
+ deviceManager.specifiedDeviceId = globalResults['device-id'];
- String deviceId = globalResults['device-id'];
- if (deviceId != null) {
- Device device = await deviceManager.getDeviceById(deviceId);
- if (device == null) {
- printError("No device found with id '$deviceId'.");
- return 1;
- }
- devices = <Device>[device];
- } else {
- devices = await deviceManager.getDevices();
- }
+ List<Device> devices = await deviceManager.getDevices();
- if (devices.isEmpty) {
+ if (devices.isEmpty && deviceManager.hasSpecifiedDeviceId) {
+ printError("No device found with id '${deviceManager.specifiedDeviceId}'.");
+ return 1;
+ } else if (devices.isEmpty) {
printStatus('No connected devices.');
return 0;
}
diff --git a/packages/flutter_tools/lib/src/commands/refresh.dart b/packages/flutter_tools/lib/src/commands/refresh.dart
index 02bb4d5..35ff972 100644
--- a/packages/flutter_tools/lib/src/commands/refresh.dart
+++ b/packages/flutter_tools/lib/src/commands/refresh.dart
@@ -7,7 +7,7 @@
import 'package:path/path.dart' as path;
-import '../base/context.dart';
+import '../base/globals.dart';
import '../flx.dart';
import '../runner/flutter_command.dart';
diff --git a/packages/flutter_tools/lib/src/commands/run_mojo.dart b/packages/flutter_tools/lib/src/commands/run_mojo.dart
index 9acffbc..77dc2a1 100644
--- a/packages/flutter_tools/lib/src/commands/run_mojo.dart
+++ b/packages/flutter_tools/lib/src/commands/run_mojo.dart
@@ -8,7 +8,7 @@
import 'package:path/path.dart' as path;
import '../artifacts.dart';
-import '../base/context.dart';
+import '../base/globals.dart';
import '../base/process.dart';
import '../build_configuration.dart';
import '../flx.dart' as flx;
@@ -118,7 +118,7 @@
if (useDevtools) {
final String buildFlag = argResults['mojo-debug'] ? '--debug' : '--release';
args.add(buildFlag);
- if (context.verbose)
+ if (logger.verbose)
args.add('--verbose');
}
diff --git a/packages/flutter_tools/lib/src/commands/start.dart b/packages/flutter_tools/lib/src/commands/start.dart
index ba653b0..9b9259e 100644
--- a/packages/flutter_tools/lib/src/commands/start.dart
+++ b/packages/flutter_tools/lib/src/commands/start.dart
@@ -9,7 +9,7 @@
import '../application_package.dart';
import '../base/common.dart';
-import '../base/context.dart';
+import '../base/globals.dart';
import '../build_configuration.dart';
import '../device.dart';
import '../flx.dart';
diff --git a/packages/flutter_tools/lib/src/commands/test.dart b/packages/flutter_tools/lib/src/commands/test.dart
index 127391b..e7ebac2 100644
--- a/packages/flutter_tools/lib/src/commands/test.dart
+++ b/packages/flutter_tools/lib/src/commands/test.dart
@@ -9,7 +9,7 @@
import 'package:test/src/executable.dart' as executable;
import '../artifacts.dart';
-import '../base/context.dart';
+import '../base/globals.dart';
import '../build_configuration.dart';
import '../runner/flutter_command.dart';
import '../test/loader.dart' as loader;
diff --git a/packages/flutter_tools/lib/src/commands/trace.dart b/packages/flutter_tools/lib/src/commands/trace.dart
index d66b741..a40af6d 100644
--- a/packages/flutter_tools/lib/src/commands/trace.dart
+++ b/packages/flutter_tools/lib/src/commands/trace.dart
@@ -6,7 +6,7 @@
import '../android/device_android.dart';
import '../application_package.dart';
-import '../base/context.dart';
+import '../base/globals.dart';
import '../runner/flutter_command.dart';
class TraceCommand extends FlutterCommand {
diff --git a/packages/flutter_tools/lib/src/commands/upgrade.dart b/packages/flutter_tools/lib/src/commands/upgrade.dart
index b9d249c..5e2a124 100644
--- a/packages/flutter_tools/lib/src/commands/upgrade.dart
+++ b/packages/flutter_tools/lib/src/commands/upgrade.dart
@@ -5,7 +5,7 @@
import 'dart:async';
import '../artifacts.dart';
-import '../base/context.dart';
+import '../base/globals.dart';
import '../base/process.dart';
import '../runner/flutter_command.dart';
import '../runner/version.dart';
diff --git a/packages/flutter_tools/lib/src/device.dart b/packages/flutter_tools/lib/src/device.dart
index 460ade4..7c865b3 100644
--- a/packages/flutter_tools/lib/src/device.dart
+++ b/packages/flutter_tools/lib/src/device.dart
@@ -7,33 +7,48 @@
import 'android/device_android.dart';
import 'application_package.dart';
import 'base/common.dart';
-import 'base/context.dart';
+import 'base/globals.dart';
import 'build_configuration.dart';
import 'ios/device_ios.dart';
import 'toolchain.dart';
/// A class to get all available devices.
class DeviceManager {
+ /// Constructing DeviceManagers is cheap; they only do expensive work if some
+ /// of their methods are invoked.
DeviceManager() {
- // Init the known discoverers.
+ // Register the known discoverers.
_deviceDiscoverers.add(new AndroidDeviceDiscovery());
_deviceDiscoverers.add(new IOSDeviceDiscovery());
_deviceDiscoverers.add(new IOSSimulatorDiscovery());
+ }
- Future.forEach(_deviceDiscoverers, (DeviceDiscovery discoverer) {
- if (!discoverer.supportsPlatform)
- return null;
- return discoverer.init();
- }).then((_) {
- _initedCompleter.complete();
- }).catchError((error, stackTrace) {
- _initedCompleter.completeError(error, stackTrace);
- });
+ Future _init() {
+ if (_initedCompleter == null) {
+ _initedCompleter = new Completer();
+
+ Future.forEach(_deviceDiscoverers, (DeviceDiscovery discoverer) {
+ if (!discoverer.supportsPlatform)
+ return null;
+ return discoverer.init();
+ }).then((_) {
+ _initedCompleter.complete();
+ }).catchError((error, stackTrace) {
+ _initedCompleter.completeError(error, stackTrace);
+ });
+ }
+
+ return _initedCompleter.future;
}
List<DeviceDiscovery> _deviceDiscoverers = <DeviceDiscovery>[];
- Completer _initedCompleter = new Completer();
+ /// A user-specified device ID.
+ String specifiedDeviceId;
+
+ Completer _initedCompleter;
+
+ bool get hasSpecifiedDeviceId => specifiedDeviceId != null;
/// Return the device with the matching ID; else, complete the Future with
/// `null`.
@@ -41,15 +56,26 @@
/// This does a case insentitive compare with `deviceId`.
Future<Device> getDeviceById(String deviceId) async {
deviceId = deviceId.toLowerCase();
- List<Device> devices = await getDevices();
+ List<Device> devices = await getAllConnectedDevices();
return devices.firstWhere(
(Device device) => device.id.toLowerCase() == deviceId,
orElse: () => null
);
}
+ /// Return the list of connected devices, filtered by any user-specified device id.
Future<List<Device>> getDevices() async {
- await _initedCompleter.future;
+ if (specifiedDeviceId == null) {
+ return getAllConnectedDevices();
+ } else {
+ Device device = await getDeviceById(specifiedDeviceId);
+ return device == null ? <Device>[] : <Device>[device];
+ }
+ }
+
+ /// Return the list of all connected devices.
+ Future<List<Device>> getAllConnectedDevices() async {
+ await _init();
return _deviceDiscoverers
.where((DeviceDiscovery discoverer) => discoverer.supportsPlatform)
diff --git a/packages/flutter_tools/lib/src/flx.dart b/packages/flutter_tools/lib/src/flx.dart
index 2fb6efc..00973bc 100644
--- a/packages/flutter_tools/lib/src/flx.dart
+++ b/packages/flutter_tools/lib/src/flx.dart
@@ -13,7 +13,7 @@
import 'package:path/path.dart' as path;
import 'package:yaml/yaml.dart';
-import 'base/context.dart';
+import 'base/globals.dart';
import 'base/file_system.dart';
import 'toolchain.dart';
diff --git a/packages/flutter_tools/lib/src/ios/device_ios.dart b/packages/flutter_tools/lib/src/ios/device_ios.dart
index 321ef61..6ce1789 100644
--- a/packages/flutter_tools/lib/src/ios/device_ios.dart
+++ b/packages/flutter_tools/lib/src/ios/device_ios.dart
@@ -9,7 +9,7 @@
import '../application_package.dart';
import '../base/common.dart';
-import '../base/context.dart';
+import '../base/globals.dart';
import '../base/process.dart';
import '../build_configuration.dart';
import '../device.dart';
diff --git a/packages/flutter_tools/lib/src/ios/simulator.dart b/packages/flutter_tools/lib/src/ios/simulator.dart
index eecd1af..f776382 100644
--- a/packages/flutter_tools/lib/src/ios/simulator.dart
+++ b/packages/flutter_tools/lib/src/ios/simulator.dart
@@ -6,7 +6,7 @@
import 'dart:convert' show JSON;
import 'dart:io';
-import '../base/context.dart';
+import '../base/globals.dart';
import '../base/process.dart';
const String _xcrunPath = '/usr/bin/xcrun';
diff --git a/packages/flutter_tools/lib/src/runner/flutter_command.dart b/packages/flutter_tools/lib/src/runner/flutter_command.dart
index 4df0131..2e94cbc 100644
--- a/packages/flutter_tools/lib/src/runner/flutter_command.dart
+++ b/packages/flutter_tools/lib/src/runner/flutter_command.dart
@@ -8,9 +8,9 @@
import 'package:args/command_runner.dart';
import '../application_package.dart';
-import '../base/context.dart';
-import '../build_configuration.dart';
import '../artifacts.dart';
+import '../base/globals.dart';
+import '../build_configuration.dart';
import '../device.dart';
import '../toolchain.dart';
import 'flutter_command_runner.dart';
diff --git a/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart b/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart
index 65da945..a01c21f 100644
--- a/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart
+++ b/packages/flutter_tools/lib/src/runner/flutter_command_runner.dart
@@ -10,7 +10,7 @@
import 'package:path/path.dart' as path;
import '../artifacts.dart';
-import '../base/context.dart';
+import '../base/globals.dart';
import '../base/process.dart';
import '../build_configuration.dart';
import 'version.dart';
@@ -158,10 +158,15 @@
}
Future<int> runCommand(ArgResults globalResults) {
- if (globalResults['verbose'])
- context.verbose = true;
-
_globalResults = globalResults;
+
+ // Check for verbose.
+ if (globalResults['verbose'])
+ logger.verbose = true;
+
+ // See if the user specified a specific device.
+ deviceManager.specifiedDeviceId = globalResults['device-id'];
+
ArtifactStore.flutterRoot = path.normalize(path.absolute(globalResults['flutter-root']));
if (globalResults.wasParsed('package-root'))
ArtifactStore.packageRoot = path.normalize(path.absolute(globalResults['package-root']));
diff --git a/packages/flutter_tools/test/android_device_test.dart b/packages/flutter_tools/test/android_device_test.dart
index 13122c3..1d34f1e 100644
--- a/packages/flutter_tools/test/android_device_test.dart
+++ b/packages/flutter_tools/test/android_device_test.dart
@@ -5,11 +5,13 @@
import 'package:flutter_tools/src/android/device_android.dart';
import 'package:test/test.dart';
+import 'src/test_context.dart';
+
main() => defineTests();
defineTests() {
group('android_device', () {
- test('stores the requested id', () {
+ testUsingContext('stores the requested id', () {
String deviceId = '1234';
AndroidDevice device = new AndroidDevice(deviceId);
expect(device.id, equals(deviceId));
diff --git a/packages/flutter_tools/test/context_test.dart b/packages/flutter_tools/test/context_test.dart
index c7d81e2..74ecb0c 100644
--- a/packages/flutter_tools/test/context_test.dart
+++ b/packages/flutter_tools/test/context_test.dart
@@ -2,9 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-import 'dart:async';
-
-import 'package:flutter_tools/src/base/context.dart';
+import 'package:flutter_tools/src/base/context.dart' hide context;
+import 'package:flutter_tools/src/base/globals.dart';
+import 'package:flutter_tools/src/base/logger.dart';
import 'package:test/test.dart';
main() => defineTests();
@@ -12,55 +12,45 @@
defineTests() {
group('DeviceManager', () {
test('error', () async {
- MockContext mockContext = new MockContext();
+ AppContext context = new AppContext();
+ BufferLogger mockLogger = new BufferLogger();
+ context[Logger] = mockLogger;
- runZoned(() {
+ context.runInZone(() {
printError('foo bar');
- }, zoneValues: {'context': mockContext});
+ });
- expect(mockContext.errorText, 'foo bar\n');
- expect(mockContext.statusText, '');
- expect(mockContext.traceText, '');
+ expect(mockLogger.errorText, 'foo bar\n');
+ expect(mockLogger.statusText, '');
+ expect(mockLogger.traceText, '');
});
test('status', () async {
- MockContext mockContext = new MockContext();
+ AppContext context = new AppContext();
+ BufferLogger mockLogger = new BufferLogger();
+ context[Logger] = mockLogger;
- runZoned(() {
+ context.runInZone(() {
printStatus('foo bar');
- }, zoneValues: {'context': mockContext});
+ });
- expect(mockContext.errorText, '');
- expect(mockContext.statusText, 'foo bar\n');
- expect(mockContext.traceText, '');
+ expect(mockLogger.errorText, '');
+ expect(mockLogger.statusText, 'foo bar\n');
+ expect(mockLogger.traceText, '');
});
test('trace', () async {
- MockContext mockContext = new MockContext();
+ AppContext context = new AppContext();
+ BufferLogger mockLogger = new BufferLogger();
+ context[Logger] = mockLogger;
- runZoned(() {
+ context.runInZone(() {
printTrace('foo bar');
- }, zoneValues: {'context': mockContext});
+ });
- expect(mockContext.errorText, '');
- expect(mockContext.statusText, '');
- expect(mockContext.traceText, 'foo bar\n');
+ expect(mockLogger.errorText, '');
+ expect(mockLogger.statusText, '');
+ expect(mockLogger.traceText, 'foo bar\n');
});
});
}
-
-class MockContext implements AppContext {
- bool verbose = false;
-
- StringBuffer _error = new StringBuffer();
- StringBuffer _status = new StringBuffer();
- StringBuffer _trace = new StringBuffer();
-
- String get errorText => _error.toString();
- String get statusText => _status.toString();
- String get traceText => _trace.toString();
-
- void printError(String message, [StackTrace stackTrace]) => _error.writeln(message);
- void printStatus(String message) => _status.writeln(message);
- void printTrace(String message) => _trace.writeln(message);
-}
diff --git a/packages/flutter_tools/test/create_test.dart b/packages/flutter_tools/test/create_test.dart
index 69939aa..4e736d9 100644
--- a/packages/flutter_tools/test/create_test.dart
+++ b/packages/flutter_tools/test/create_test.dart
@@ -11,6 +11,8 @@
import 'package:path/path.dart' as path;
import 'package:test/test.dart';
+import 'src/test_context.dart';
+
main() => defineTests();
defineTests() {
@@ -31,7 +33,7 @@
// TODO(devoncarew): https://github.com/flutter/flutter/issues/1709
if (Platform.isLinux) {
// Verify that we create a project that is well-formed.
- test('flutter-simple', () async {
+ testUsingContext('flutter-simple', () async {
ArtifactStore.flutterRoot = '../..';
CreateCommand command = new CreateCommand();
CommandRunner runner = new CommandRunner('test_flutter', '')
diff --git a/packages/flutter_tools/test/daemon_test.dart b/packages/flutter_tools/test/daemon_test.dart
index d7a771f..7ad73a1 100644
--- a/packages/flutter_tools/test/daemon_test.dart
+++ b/packages/flutter_tools/test/daemon_test.dart
@@ -5,6 +5,8 @@
import 'dart:async';
import 'package:flutter_tools/src/base/context.dart';
+import 'package:flutter_tools/src/base/globals.dart';
+import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/commands/daemon.dart';
import 'package:mockito/mockito.dart';
import 'package:test/test.dart';
@@ -16,10 +18,13 @@
defineTests() {
group('daemon', () {
Daemon daemon;
- NotifyingAppContext appContext;
+ AppContext appContext;
+ NotifyingLogger notifyingLogger;
setUp(() {
- appContext = new NotifyingAppContext();
+ appContext = new AppContext();
+ notifyingLogger = new NotifyingLogger();
+ appContext[Logger] = notifyingLogger;
});
tearDown(() {
@@ -33,7 +38,7 @@
daemon = new Daemon(
commands.stream,
(Map<String, dynamic> result) => responses.add(result),
- appContext: appContext
+ notifyingLogger: notifyingLogger
);
commands.add({'id': 0, 'method': 'daemon.version'});
Map response = await responses.stream.where(_notEvent).first;
@@ -43,13 +48,13 @@
});
test('daemon.logMessage', () {
- return runZoned(() async {
+ return appContext.runInZone(() async {
StreamController<Map<String, dynamic>> commands = new StreamController();
StreamController<Map<String, dynamic>> responses = new StreamController();
daemon = new Daemon(
commands.stream,
(Map<String, dynamic> result) => responses.add(result),
- appContext: appContext
+ notifyingLogger: notifyingLogger
);
printError('daemon.logMessage test');
Map<String, dynamic> response = await responses.stream.where((Map<String, dynamic> map) {
@@ -60,7 +65,7 @@
Map<String, String> logMessage = response['params'];
expect(logMessage['level'], 'error');
expect(logMessage['message'], 'daemon.logMessage test');
- }, zoneValues: {'context': appContext});
+ });
});
test('daemon.shutdown', () async {
@@ -69,7 +74,7 @@
daemon = new Daemon(
commands.stream,
(Map<String, dynamic> result) => responses.add(result),
- appContext: appContext
+ notifyingLogger: notifyingLogger
);
commands.add({'id': 0, 'method': 'daemon.shutdown'});
return daemon.onExit.then((int code) {
@@ -87,7 +92,7 @@
commands.stream,
(Map<String, dynamic> result) => responses.add(result),
daemonCommand: command,
- appContext: appContext
+ notifyingLogger: notifyingLogger
);
MockDeviceStore mockDevices = command.devices;
@@ -113,7 +118,7 @@
daemon = new Daemon(
commands.stream,
(Map<String, dynamic> result) => responses.add(result),
- appContext: appContext
+ notifyingLogger: notifyingLogger
);
commands.add({'id': 0, 'method': 'device.getDevices'});
Map response = await responses.stream.where(_notEvent).first;
diff --git a/packages/flutter_tools/test/device_test.dart b/packages/flutter_tools/test/device_test.dart
index 62903bd..dd9b5c6 100644
--- a/packages/flutter_tools/test/device_test.dart
+++ b/packages/flutter_tools/test/device_test.dart
@@ -5,11 +5,13 @@
import 'package:flutter_tools/src/device.dart';
import 'package:test/test.dart';
+import 'src/test_context.dart';
+
main() => defineTests();
defineTests() {
group('DeviceManager', () {
- test('getDevices', () async {
+ testUsingContext('getDevices', () async {
// Test that DeviceManager.getDevices() doesn't throw.
DeviceManager deviceManager = new DeviceManager();
List<Device> devices = await deviceManager.getDevices();
diff --git a/packages/flutter_tools/test/install_test.dart b/packages/flutter_tools/test/install_test.dart
index c5c8776..f876456 100644
--- a/packages/flutter_tools/test/install_test.dart
+++ b/packages/flutter_tools/test/install_test.dart
@@ -33,7 +33,7 @@
CommandRunner runner = new CommandRunner('test_flutter', '')
..addCommand(command);
- runner.run(['install']).then((int code) => expect(code, equals(0)));
+ return runner.run(['install']).then((int code) => expect(code, equals(0)));
});
test('returns 0 when iOS is connected and ready for an install', () {
@@ -55,7 +55,7 @@
CommandRunner runner = new CommandRunner('test_flutter', '')
..addCommand(command);
- runner.run(['install']).then((int code) => expect(code, equals(0)));
+ return runner.run(['install']).then((int code) => expect(code, equals(0)));
});
});
}
diff --git a/packages/flutter_tools/test/list_test.dart b/packages/flutter_tools/test/list_test.dart
index 91c05b7..f01949c 100644
--- a/packages/flutter_tools/test/list_test.dart
+++ b/packages/flutter_tools/test/list_test.dart
@@ -10,12 +10,13 @@
import 'package:test/test.dart';
import 'src/mocks.dart';
+import 'src/test_context.dart';
main() => defineTests();
defineTests() {
group('list', () {
- test('returns 0 when called', () {
+ testUsingContext('returns 0 when called', () {
final String mockCommand = Platform.isWindows ? 'cmd /c echo' : 'echo';
ListCommand command = new ListCommand();
@@ -36,9 +37,8 @@
// Instead, cause the test to run the echo command.
when(mockDevices.iOSSimulator.xcrunPath).thenReturn(mockCommand);
- CommandRunner runner = new CommandRunner('test_flutter', '')
- ..addCommand(command);
- runner.run(['list']).then((int code) => expect(code, equals(0)));
+ CommandRunner runner = new CommandRunner('test_flutter', '')..addCommand(command);
+ return runner.run(['list']).then((int code) => expect(code, equals(0)));
});
});
}
diff --git a/packages/flutter_tools/test/listen_test.dart b/packages/flutter_tools/test/listen_test.dart
index 18170bb..dcbf122 100644
--- a/packages/flutter_tools/test/listen_test.dart
+++ b/packages/flutter_tools/test/listen_test.dart
@@ -9,12 +9,13 @@
import 'package:test/test.dart';
import 'src/mocks.dart';
+import 'src/test_context.dart';
main() => defineTests();
defineTests() {
group('listen', () {
- test('returns 0 when no device is connected', () {
+ testUsingContext('returns 0 when no device is connected', () {
ListenCommand command = new ListenCommand(singleRun: true);
applyMocksToCommand(command);
MockDeviceStore mockDevices = command.devices;
@@ -24,7 +25,7 @@
when(mockDevices.iOSSimulator.isConnected()).thenReturn(false);
CommandRunner runner = new FlutterCommandRunner()..addCommand(command);
- runner.run(['listen']).then((int code) => expect(code, equals(0)));
+ return runner.run(['listen']).then((int code) => expect(code, equals(0)));
});
});
}
diff --git a/packages/flutter_tools/test/logs_test.dart b/packages/flutter_tools/test/logs_test.dart
index 1e5590b..2dd67d5 100644
--- a/packages/flutter_tools/test/logs_test.dart
+++ b/packages/flutter_tools/test/logs_test.dart
@@ -8,16 +8,17 @@
import 'package:test/test.dart';
import 'src/mocks.dart';
+import 'src/test_context.dart';
main() => defineTests();
defineTests() {
group('logs', () {
- test('fail with a bad device id', () {
+ testUsingContext('fail with a bad device id', () {
LogsCommand command = new LogsCommand();
applyMocksToCommand(command);
CommandRunner runner = new FlutterCommandRunner()..addCommand(command);
- runner.run(<String>['-d', 'abc123', 'logs']).then((int code) {
+ return runner.run(<String>['-d', 'abc123', 'logs']).then((int code) {
expect(code, equals(1));
});
});
diff --git a/packages/flutter_tools/test/src/test_context.dart b/packages/flutter_tools/test/src/test_context.dart
new file mode 100644
index 0000000..c5a5d9d
--- /dev/null
+++ b/packages/flutter_tools/test/src/test_context.dart
@@ -0,0 +1,30 @@
+// Copyright 2016 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.
+
+import 'dart:async';
+
+import 'package:flutter_tools/src/base/context.dart';
+import 'package:flutter_tools/src/base/logger.dart';
+import 'package:flutter_tools/src/device.dart';
+import 'package:test/test.dart';
+
+void testUsingContext(String description, dynamic testMethod(), { Timeout timeout }) {
+ test(description, () {
+ AppContext testContext = new AppContext();
+
+ testContext[Logger] = new BufferLogger();
+ testContext[DeviceManager] = new MockDeviceManager();
+
+ return testContext.runInZone(testMethod);
+ }, timeout: timeout);
+}
+
+class MockDeviceManager implements DeviceManager {
+ String specifiedDeviceId;
+ bool get hasSpecifiedDeviceId => specifiedDeviceId != null;
+
+ Future<List<Device>> getAllConnectedDevices() => new Future.value(<Device>[]);
+ Future<Device> getDeviceById(String deviceId) => new Future.value(null);
+ Future<List<Device>> getDevices() => getAllConnectedDevices();
+}
diff --git a/packages/flutter_tools/test/stop_test.dart b/packages/flutter_tools/test/stop_test.dart
index 40583cd..f700e3b 100644
--- a/packages/flutter_tools/test/stop_test.dart
+++ b/packages/flutter_tools/test/stop_test.dart
@@ -29,7 +29,7 @@
CommandRunner runner = new CommandRunner('test_flutter', '')
..addCommand(command);
- runner.run(['stop']).then((int code) => expect(code, equals(0)));
+ return runner.run(['stop']).then((int code) => expect(code, equals(0)));
});
test('returns 0 when iOS is connected and ready to be stopped', () {
@@ -48,7 +48,7 @@
CommandRunner runner = new CommandRunner('test_flutter', '')
..addCommand(command);
- runner.run(['stop']).then((int code) => expect(code, equals(0)));
+ return runner.run(['stop']).then((int code) => expect(code, equals(0)));
});
});
}
diff --git a/packages/flutter_tools/test/trace_test.dart b/packages/flutter_tools/test/trace_test.dart
index e55648c..279e7a8 100644
--- a/packages/flutter_tools/test/trace_test.dart
+++ b/packages/flutter_tools/test/trace_test.dart
@@ -8,12 +8,13 @@
import 'package:test/test.dart';
import 'src/mocks.dart';
+import 'src/test_context.dart';
main() => defineTests();
defineTests() {
group('trace', () {
- test('returns 1 when no Android device is connected', () {
+ testUsingContext('returns 1 when no Android device is connected', () {
TraceCommand command = new TraceCommand();
applyMocksToCommand(command);
MockDeviceStore mockDevices = command.devices;
@@ -22,7 +23,7 @@
CommandRunner runner = new CommandRunner('test_flutter', '')
..addCommand(command);
- runner.run(['trace']).then((int code) => expect(code, equals(1)));
+ return runner.run(['trace']).then((int code) => expect(code, equals(1)));
});
});
}