Commit d7fbf530 authored by Devon Carew's avatar Devon Carew

use status(), error(), and trace() for logging

rename to printTrace(), printStatus(), and printError()
parent 91c0af60
......@@ -6,9 +6,9 @@ import 'dart:async';
import 'dart:io';
import 'package:args/command_runner.dart';
import 'package:logging/logging.dart';
import 'package:stack_trace/stack_trace.dart';
import 'src/base/context.dart';
import 'src/base/process.dart';
import 'src/commands/analyze.dart';
import 'src/commands/apk.dart';
......@@ -33,28 +33,6 @@ import 'src/runner/flutter_command_runner.dart';
///
/// This function is intended to be used from the [flutter] command line tool.
Future main(List<String> args) async {
DateTime startTime = new DateTime.now();
// This level can be adjusted by users through the `--verbose` option.
Logger.root.level = Level.WARNING;
Logger.root.onRecord.listen((LogRecord record) {
String prefix = '';
if (Logger.root.level <= Level.FINE) {
Duration elapsed = record.time.difference(startTime);
prefix = '[${elapsed.inMilliseconds.toString().padLeft(4)} ms] ';
}
String level = record.level.name.toLowerCase();
if (record.level >= Level.WARNING) {
stderr.writeln('$prefix$level: ${record.message}');
} else {
print('$prefix$level: ${record.message}');
}
if (record.error != null)
stderr.writeln(record.error);
if (record.stackTrace != null)
stderr.writeln(record.stackTrace);
});
FlutterCommandRunner runner = new FlutterCommandRunner()
..addCommand(new AnalyzeCommand())
..addCommand(new ApkCommand())
......@@ -92,8 +70,7 @@ Future main(List<String> args) async {
// We've caught an exit code.
exit(error.exitCode);
} else {
stderr.writeln(error);
Logger.root.log(Level.SEVERE, '\nException:', null, chain.terse.toTrace());
printError(error, chain.terse.toTrace());
exit(1);
}
});
......
......@@ -5,7 +5,7 @@
import 'dart:async';
import 'dart:io';
import '../base/logging.dart';
import '../base/context.dart';
import '../base/process.dart';
// https://android.googlesource.com/platform/system/core/+/android-4.4_r1/adb/OVERVIEW.TXT
......@@ -83,11 +83,11 @@ class Adb {
controller = new StreamController(
onListen: () async {
socket = await Socket.connect(InternetAddress.LOOPBACK_IP_V4, adbServerPort);
logging.fine('--> host:track-devices');
printTrace('--> host:track-devices');
socket.add(_createAdbRequest('host:track-devices'));
socket.listen((List<int> data) {
String stringResult = new String.fromCharCodes(data);
logging.fine('<-- ${stringResult.trim()}');
printTrace('<-- ${stringResult.trim()}');
_AdbServerResponse response = new _AdbServerResponse(
stringResult,
noStatus: !isFirstNotification
......@@ -116,14 +116,14 @@ class Adb {
Socket socket = await Socket.connect(InternetAddress.LOOPBACK_IP_V4, adbServerPort);
try {
logging.fine('--> $command');
printTrace('--> $command');
socket.add(_createAdbRequest(command));
List<List<int>> result = await socket.toList();
List<int> data = result.fold(<int>[], (List<int> previous, List<int> element) {
return previous..addAll(element);
});
String stringResult = new String.fromCharCodes(data);
logging.fine('<-- ${stringResult.trim()}');
printTrace('<-- ${stringResult.trim()}');
return stringResult;
} finally {
socket.destroy();
......
......@@ -9,7 +9,7 @@ import 'package:crypto/crypto.dart';
import 'package:path/path.dart' as path;
import '../application_package.dart';
import '../base/logging.dart';
import '../base/context.dart';
import '../base/process.dart';
import '../build_configuration.dart';
import '../device.dart';
......@@ -74,7 +74,7 @@ class AndroidDevice extends Device {
_hasValidAndroid = _checkForSupportedAndroidVersion();
if (!_hasAdb || !_hasValidAndroid) {
logging.warning('Unable to run on Android.');
printError('Unable to run on Android.');
}
}
......@@ -88,11 +88,11 @@ class AndroidDevice extends Device {
path.join(androidHomeDir, 'sdk', 'platform-tools'))) {
return path.join(androidHomeDir, 'sdk');
} else {
logging.warning('Android SDK not found at $androidHomeDir');
printError('Android SDK not found at $androidHomeDir');
return null;
}
} else {
logging.warning('Android SDK not found. The ANDROID_HOME variable must be set.');
printError('Android SDK not found. The ANDROID_HOME variable must be set.');
return null;
}
}
......@@ -125,7 +125,7 @@ class AndroidDevice extends Device {
}
return false;
}
logging.warning(
printError(
'Unrecognized adb version string $adbVersion. Skipping version check.');
return true;
}
......@@ -138,16 +138,15 @@ class AndroidDevice extends Device {
}
String locatedAdbPath = runCheckedSync(['which', 'adb']);
logging.severe('"$locatedAdbPath" is too old. '
printError('"$locatedAdbPath" is too old. '
'Please install version 1.0.32 or later.\n'
'Try setting ANDROID_HOME to the path to your Android SDK install. '
'Android builds are unavailable.');
} catch (e, stack) {
logging.severe('"adb" not found in \$PATH. '
} catch (e) {
printError('"adb" not found in \$PATH. '
'Please install the Android SDK or set ANDROID_HOME '
'to the path of your Android SDK install.');
logging.info(e);
logging.info(stack);
printTrace('$e');
}
return false;
}
......@@ -162,7 +161,7 @@ class AndroidDevice extends Device {
String ready = runSync(adbCommandForDevice(['shell', 'echo', 'ready']));
if (ready.trim() != 'ready') {
logging.info('Android device not found.');
printTrace('Android device not found.');
return false;
}
......@@ -174,18 +173,18 @@ class AndroidDevice extends Device {
int sdkVersionParsed =
int.parse(sdkVersion, onError: (String source) => null);
if (sdkVersionParsed == null) {
logging.severe('Unexpected response from getprop: "$sdkVersion"');
printError('Unexpected response from getprop: "$sdkVersion"');
return false;
}
if (sdkVersionParsed < minApiLevel) {
logging.severe(
printError(
'The Android version ($sdkVersion) on the target device is too old. Please '
'use a $minVersionName (version $minApiLevel / $minVersionText) device or later.');
return false;
}
return true;
} catch (e) {
logging.severe('Unexpected failure from adb: ', e);
printError('Unexpected failure from adb: $e');
}
return false;
}
......@@ -213,12 +212,11 @@ class AndroidDevice extends Device {
return false;
}
if (runCheckedSync(adbCommandForDevice(['shell', 'pm', 'path', app.id])) == '') {
logging.info(
'TODO(iansf): move this log to the caller. ${app.name} is not on the device. Installing now...');
printTrace('TODO(iansf): move this log to the caller. ${app.name} is not on the device. Installing now...');
return false;
}
if (_getDeviceApkSha1(app) != _getSourceSha1(app)) {
logging.info(
printTrace(
'TODO(iansf): move this log to the caller. ${app.name} is out of date. Installing now...');
return false;
}
......@@ -228,17 +226,17 @@ class AndroidDevice extends Device {
@override
bool installApp(ApplicationPackage app) {
if (!isConnected()) {
logging.info('Android device not connected. Not installing.');
printTrace('Android device not connected. Not installing.');
return false;
}
if (!FileSystemEntity.isFileSync(app.localPath)) {
logging.severe('"${app.localPath}" does not exist.');
printError('"${app.localPath}" does not exist.');
return false;
}
print('Installing ${app.name} on device.');
runCheckedSync(adbCommandForDevice(['install', '-r', app.localPath]));
runCheckedSync(adbCommandForDevice(['shell', 'echo', '-n', _getSourceSha1(app), '>', _getDeviceSha1Path(app)]));
printStatus('Installing ${app.name} on device.');
runCheckedSync(adbCommandForDevice(<String>['install', '-r', app.localPath]));
runCheckedSync(adbCommandForDevice(<String>['shell', 'echo', '-n', _getSourceSha1(app), '>', _getDeviceSha1Path(app)]));
return true;
}
......@@ -246,9 +244,9 @@ class AndroidDevice extends Device {
// Set up port forwarding for observatory.
String portString = 'tcp:$_observatoryPort';
try {
runCheckedSync(adbCommandForDevice(['forward', portString, portString]));
runCheckedSync(adbCommandForDevice(<String>['forward', portString, portString]));
} catch (e) {
logging.warning('Unable to forward observatory port ($_observatoryPort):\n$e');
printError('Unable to forward observatory port ($_observatoryPort):\n$e');
}
}
......@@ -259,10 +257,10 @@ class AndroidDevice extends Device {
String route,
bool clearLogs: false
}) {
logging.fine('$this startBundle');
printTrace('$this startBundle');
if (!FileSystemEntity.isFileSync(bundlePath)) {
logging.severe('Cannot find $bundlePath');
printError('Cannot find $bundlePath');
return false;
}
......@@ -303,7 +301,7 @@ class AndroidDevice extends Device {
toolchain,
mainPath: mainPath
).then((flx.DirectoryResult buildResult) {
logging.fine('Starting bundle for $this.');
printTrace('Starting bundle for $this.');
try {
if (startBundle(
......@@ -426,7 +424,7 @@ class AndroidDevice extends Device {
));
return localPath;
}
logging.warning('No trace file detected. '
printError('No trace file detected. '
'Did you remember to start the trace before stopping it?');
return null;
}
......@@ -447,7 +445,7 @@ List<AndroidDevice> getAdbDevices([AndroidDevice mockAndroid]) {
try {
runCheckedSync([adbPath, 'version']);
} catch (e) {
logging.severe('Unable to find adb. Is "adb" in your path?');
printError('Unable to find adb. Is "adb" in your path?');
return devices;
}
......@@ -497,16 +495,16 @@ List<AndroidDevice> getAdbDevices([AndroidDevice mockAndroid]) {
} else if (unauthorizedRegex.hasMatch(line)) {
Match match = unauthorizedRegex.firstMatch(line);
String deviceID = match[1];
logging.warning(
printError(
'Device $deviceID is not authorized.\n'
'You might need to check your device for an authorization dialog.'
);
} else if (offlineRegex.hasMatch(line)) {
Match match = offlineRegex.firstMatch(line);
String deviceID = match[1];
logging.warning('Device $deviceID is offline.');
printError('Device $deviceID is offline.');
} else {
logging.warning(
printError(
'Unexpected failure parsing device information from adb output:\n'
'$line\n'
'Please report a bug at https://github.com/flutter/flutter/issues/new');
......@@ -525,7 +523,7 @@ String getAdbPath() {
} else if (FileSystemEntity.isFileSync(adbPath2)) {
return adbPath2;
} else {
logging.info('"adb" not found at\n "$adbPath1" or\n "$adbPath2"\n' +
printTrace('"adb" not found at\n "$adbPath1" or\n "$adbPath2"\n' +
'using default path "$_defaultAdbPath"');
return _defaultAdbPath;
}
......
......@@ -8,7 +8,7 @@ import 'dart:io';
import 'package:archive/archive.dart';
import 'package:path/path.dart' as path;
import 'base/logging.dart';
import 'base/context.dart';
import 'base/os.dart';
import 'base/process.dart';
import 'build_configuration.dart';
......@@ -187,7 +187,7 @@ class ArtifactStore {
else
message += '\nDid you run this command from the same directory as your pubspec.yaml file?';
}
stderr.writeln(message);
printError(message);
throw new ProcessExit(2);
}
}
......@@ -195,7 +195,7 @@ class ArtifactStore {
static void ensureHasSkyEnginePackage() {
Directory skyEnginePackage = new Directory(path.join(packageRoot, 'sky_engine'));
if (!skyEnginePackage.existsSync()) {
stderr.writeln("Cannot locate the sky_engine package; did you include 'flutter' in your pubspec.yaml file?");
printError("Cannot locate the sky_engine package; did you include 'flutter' in your pubspec.yaml file?");
throw new ProcessExit(2);
}
}
......@@ -221,12 +221,12 @@ class ArtifactStore {
/// Download a file from the given URL and return the bytes.
static Future<List<int>> _downloadFile(Uri url) async {
logging.info('Downloading $url.');
printStatus('Downloading $url.');
HttpClient httpClient = new HttpClient();
HttpClientRequest request = await httpClient.getUrl(url);
HttpClientResponse response = await request.close();
logging.fine('Received response statusCode=${response.statusCode}');
printTrace('Received response statusCode=${response.statusCode}');
if (response.statusCode != 200)
throw new Exception(response.reasonPhrase);
......@@ -276,7 +276,7 @@ class ArtifactStore {
if (_pendingZipDownloads.containsKey(platform)) {
return _pendingZipDownloads[platform];
}
print('Downloading $platform artifacts from the cloud, one moment please...');
printStatus('Downloading $platform artifacts from the cloud, one moment please...');
Future future = _doDownloadArtifactsFromZip(platform);
_pendingZipDownloads[platform] = future;
return future.then((_) => _pendingZipDownloads.remove(platform));
......@@ -286,7 +286,7 @@ class ArtifactStore {
static Directory _getBaseCacheDir() {
if (flutterRoot == null) {
logging.severe('FLUTTER_ROOT not specified. Cannot find artifact cache.');
printError('FLUTTER_ROOT not specified. Cannot find artifact cache.');
throw new ProcessExit(2);
}
Directory cacheDir = new Directory(path.join(flutterRoot, 'bin', 'cache', 'artifacts'));
......@@ -313,7 +313,7 @@ class ArtifactStore {
if (!cachedFile.existsSync()) {
await _downloadArtifactsFromZip(artifact.platform);
if (!cachedFile.existsSync()) {
logging.severe('File not found in the platform artifacts: ${cachedFile.path}');
printError('File not found in the platform artifacts: ${cachedFile.path}');
throw new ProcessExit(2);
}
}
......@@ -331,7 +331,7 @@ class ArtifactStore {
try {
await _downloadFileToCache(url, cachedFile);
} catch (e) {
logging.severe('Failed to fetch third-party artifact: $url: $e');
printError('Failed to fetch third-party artifact: $url: $e');
throw new ProcessExit(2);
}
}
......@@ -340,7 +340,7 @@ class ArtifactStore {
static void clear() {
Directory cacheDir = _getBaseCacheDir();
logging.fine('Clearing cache directory ${cacheDir.path}');
printTrace('Clearing cache directory ${cacheDir.path}');
cacheDir.deleteSync(recursive: true);
}
......
// 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 'dart:io';
final AppContext _defaultContext = new _DefaultAppContext();
/// A singleton for application functionality. This singleton can be different
/// on a per-Zone basis.
AppContext get context {
AppContext currentContext = Zone.current['context'];
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);
/// 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);
/// 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;
}
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] ';
}
}
// 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.
import 'package:logging/logging.dart';
final Logger logging = new Logger('flutter_tools');
......@@ -6,7 +6,7 @@ import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'logging.dart';
import 'context.dart';
/// This runs the command and streams stdout/stderr from the child process to
/// this process' stdout/stderr.
......@@ -15,7 +15,7 @@ Future<int> runCommandAndStreamOutput(List<String> cmd, {
RegExp filter,
String workingDirectory
}) async {
logging.info(cmd.join(' '));
printTrace(cmd.join(' '));
Process process = await Process.start(
cmd[0],
cmd.sublist(1),
......@@ -28,7 +28,7 @@ Future<int> runCommandAndStreamOutput(List<String> cmd, {
dataLines = dataLines.where((String s) => filter.hasMatch(s)).toList();
}
if (dataLines.length > 0) {
stdout.write('$prefix${dataLines.join('\n$prefix')}\n');
printStatus('$prefix${dataLines.join('\n$prefix')}');
}
});
process.stderr.transform(UTF8.decoder).listen((String data) {
......@@ -38,7 +38,7 @@ Future<int> runCommandAndStreamOutput(List<String> cmd, {
dataLines = dataLines.where((String s) => filter.hasMatch(s));
}
if (dataLines.length > 0) {
stderr.write('$prefix${dataLines.join('\n$prefix')}\n');
printError('$prefix${dataLines.join('\n$prefix')}');
}
});
return await process.exitCode;
......@@ -47,13 +47,13 @@ Future<int> runCommandAndStreamOutput(List<String> cmd, {
Future runAndKill(List<String> cmd, Duration timeout) {
Future<Process> proc = runDetached(cmd);
return new Future.delayed(timeout, () async {
logging.info('Intentionally killing ${cmd[0]}');
printTrace('Intentionally killing ${cmd[0]}');
Process.killPid((await proc).pid);
});
}
Future<Process> runDetached(List<String> cmd) {
logging.info(cmd.join(' '));
printTrace(cmd.join(' '));
Future<Process> proc = Process.start(
cmd[0], cmd.getRange(1, cmd.length).toList(),
mode: ProcessStartMode.DETACHED);
......@@ -81,20 +81,20 @@ String _runWithLoggingSync(List<String> cmd, {
bool checked: false,
String workingDirectory
}) {
logging.info(cmd.join(' '));
printTrace(cmd.join(' '));
ProcessResult results =
Process.runSync(cmd[0], cmd.getRange(1, cmd.length).toList(), workingDirectory: workingDirectory);
if (results.exitCode != 0) {
String errorDescription = 'Error code ${results.exitCode} '
'returned when attempting to run command: ${cmd.join(' ')}';
logging.info(errorDescription);
printTrace(errorDescription);
if (results.stderr.length > 0)
logging.info('Errors logged: ${results.stderr.trim()}');
printTrace('Errors logged: ${results.stderr.trim()}');
if (checked)
throw errorDescription;
}
if (results.stdout.trim().isNotEmpty)
logging.fine(results.stdout.trim());
printTrace(results.stdout.trim());
return results.stdout;
}
......
......@@ -6,7 +6,7 @@ import 'dart:io';
import 'package:path/path.dart' as path;
import 'base/logging.dart';
import 'base/context.dart';
enum BuildType {
prebuilt,
......@@ -32,7 +32,7 @@ HostPlatform getCurrentHostPlatform() {
return HostPlatform.mac;
if (Platform.isLinux)
return HostPlatform.linux;
logging.warning('Unsupported host platform, defaulting to Linux');
printError('Unsupported host platform, defaulting to Linux');
return HostPlatform.linux;
}
......@@ -41,7 +41,7 @@ TargetPlatform getCurrentHostPlatformAsTarget() {
return TargetPlatform.mac;
if (Platform.isLinux)
return TargetPlatform.linux;
logging.warning('Unsupported host platform, defaulting to Linux');
printError('Unsupported host platform, defaulting to Linux');
return TargetPlatform.linux;
}
......
......@@ -11,7 +11,7 @@ import 'package:den_api/den_api.dart';
import 'package:path/path.dart' as path;
import '../artifacts.dart';
import '../base/logging.dart';
import '../base/context.dart';
import '../base/process.dart';
import '../build_configuration.dart';
import '../runner/flutter_command.dart';
......@@ -188,7 +188,7 @@ class AnalyzeCommand extends FlutterCommand {
String packageName = pubSpecYaml.name;
String packagePath = path.normalize(path.absolute(path.join(directory.path, 'lib')));
if (packages.containsKey(packageName) && packages[packageName] != packagePath) {
logging.warning('Inconsistent requirements for $packageName; using $packagePath (and not ${packages[packageName]}).');
printError('Inconsistent requirements for $packageName; using $packagePath (and not ${packages[packageName]}).');
hadInconsistentRequirements = true;
}
packages[packageName] = packagePath;
......@@ -208,7 +208,7 @@ class AnalyzeCommand extends FlutterCommand {
for (String package in dependencies.keys) {
if (packages.containsKey(package)) {
if (packages[package] != dependencies[package]) {
logging.warning('Inconsistent requirements for $package; using ${packages[package]} (and not ${dependencies[package]}).');
printError('Inconsistent requirements for $package; using ${packages[package]} (and not ${dependencies[package]}).');
hadInconsistentRequirements = true;
}
} else {
......@@ -219,9 +219,9 @@ class AnalyzeCommand extends FlutterCommand {
}
if (hadInconsistentRequirements) {
if (foundAnyInFlutterRepo)
logging.warning('You may need to run "dart ${path.normalize(path.relative(path.join(ArtifactStore.flutterRoot, 'dev/update_packages.dart')))} --upgrade".');
printError('You may need to run "dart ${path.normalize(path.relative(path.join(ArtifactStore.flutterRoot, 'dev/update_packages.dart')))} --upgrade".');
if (foundAnyInCurrentDirectory)
logging.warning('You may need to run "pub upgrade".');
printError('You may need to run "pub upgrade".');
}
String buildDir = buildConfigurations.firstWhere((BuildConfiguration config) => config.testable, orElse: () => null)?.buildDir;
......@@ -256,7 +256,7 @@ class AnalyzeCommand extends FlutterCommand {
mainFile.path
];
logging.info(cmd.join(' '));
printStatus(cmd.join(' '));
Process process = await Process.start(
cmd[0],
cmd.sublist(1),
......@@ -270,7 +270,7 @@ class AnalyzeCommand extends FlutterCommand {
process.stderr.transform(UTF8.decoder).listen((String data) {
// dartanalyzer doesn't seem to ever output anything on stderr
errorCount += 1;
print(data);
printError(data);
});
int exitCode = await process.exitCode;
......@@ -336,7 +336,7 @@ class AnalyzeCommand extends FlutterCommand {
if (shouldIgnore)
continue;
}
print(errorLine);
printError(errorLine);
errorCount += 1;
}
}
......@@ -349,7 +349,7 @@ class AnalyzeCommand extends FlutterCommand {
if (errorCount > 0)
return 1; // Doesn't this mean 'hints' per the above comment?
if (argResults['congratulate'])
print('No analyzer warnings! (ran in ${elapsed}s)');
printStatus('No analyzer warnings! (ran in ${elapsed}s)');
return 0;
}
}
......@@ -11,8 +11,8 @@ import 'package:yaml/yaml.dart';
import '../android/device_android.dart';
import '../artifacts.dart';
import '../base/context.dart';
import '../base/file_system.dart';
import '../base/logging.dart';
import '../base/process.dart';
import '../build_configuration.dart';
import '../flx.dart' as flx;
......@@ -251,25 +251,25 @@ class ApkCommand extends FlutterCommand {
if (!components.resources.existsSync()) {
// TODO(eseidel): This level should be higher when path is manually set.
logging.info('Can not locate Resources: ${components.resources}, ignoring.');
printStatus('Can not locate Resources: ${components.resources}, ignoring.');
components.resources = null;
}
if (!components.androidSdk.existsSync()) {
logging.severe('Can not locate Android SDK: $androidSdkPath');
printError('Can not locate Android SDK: $androidSdkPath');
return null;
}
if (!(new _ApkBuilder(components.androidSdk.path).checkSdkPath())) {
logging.severe('Can not locate expected Android SDK tools at $androidSdkPath');
logging.severe('You must install version $_kAndroidPlatformVersion of the SDK platform');
logging.severe('and version $_kBuildToolsVersion of the build tools.');
printError('Can not locate expected Android SDK tools at $androidSdkPath');
printError('You must install version $_kAndroidPlatformVersion of the SDK platform');
printError('and version $_kBuildToolsVersion of the build tools.');
return null;
}
for (File f in [components.manifest, components.icuData,
components.libSkyShell, components.debugKeystore]
..addAll(components.jars)) {
if (!f.existsSync()) {
logging.severe('Can not locate file: ${f.path}');
printError('Can not locate file: ${f.path}');
return null;
}
}
......@@ -327,7 +327,7 @@ class ApkCommand extends FlutterCommand {
ensureDirectoryExists(finalApk.path);
builder.align(unalignedApk, finalApk);
print('APK generated: ${finalApk.path}');
printStatus('APK generated: ${finalApk.path}');
return 0;
} finally {
......@@ -342,7 +342,7 @@ class ApkCommand extends FlutterCommand {
String keyPassword;
if (argResults['keystore'].isEmpty) {
logging.warning('Signing the APK using the debug keystore');
printError('Signing the APK using the debug keystore');
keystore = components.debugKeystore;
keystorePassword = _kDebugKeystorePassword;
keyAlias = _kDebugKeystoreKeyAlias;
......@@ -352,7 +352,7 @@ class ApkCommand extends FlutterCommand {
keystorePassword = argResults['keystore-password'];
keyAlias = argResults['keystore-key-alias'];
if (keystorePassword.isEmpty || keyAlias.isEmpty) {
logging.severe('Must provide a keystore password and a key alias');
printError('Must provide a keystore password and a key alias');
return 1;
}
keyPassword = argResults['keystore-key-password'];
......@@ -373,7 +373,7 @@ class ApkCommand extends FlutterCommand {
_ApkComponents components = await _findApkComponents(config);
if (components == null) {
logging.severe('Unable to build APK.');
printError('Unable to build APK.');
return 1;
}
......@@ -381,8 +381,8 @@ class ApkCommand extends FlutterCommand {
if (!flxPath.isEmpty) {
if (!FileSystemEntity.isFileSync(flxPath)) {
logging.severe('FLX does not exist: $flxPath');
logging.severe('(Omit the --flx option to build the FLX automatically)');
printError('FLX does not exist: $flxPath');
printError('(Omit the --flx option to build the FLX automatically)');
return 1;
}
return _buildApk(components, flxPath);
......
......@@ -4,7 +4,7 @@
import 'dart:async';
import '../base/logging.dart';
import '../base/context.dart';
import '../flx.dart';
import '../runner/flutter_command.dart';
import '../toolchain.dart';
......@@ -45,9 +45,9 @@ class BuildCommand extends FlutterCommand {
precompiledSnapshot: argResults['precompiled']
).then((int result) {
if (result == 0)
print('Built $outputPath.');
printStatus('Built $outputPath.');
else
logging.severe('Error building $outputPath: $result.');
printError('Error building $outputPath: $result.');
return result;
});
}
......
......@@ -11,7 +11,7 @@ import 'package:path/path.dart' as path;
import '../android/android.dart' as android;
import '../artifacts.dart';
import '../base/logging.dart';
import '../base/context.dart';
import '../base/process.dart';
class CreateCommand extends Command {
......@@ -28,21 +28,21 @@ class CreateCommand extends Command {
@override
Future<int> run() async {
if (!argResults.wasParsed('out')) {
print('No option specified for the output directory.');
print(argParser.usage);
printStatus('No option specified for the output directory.');
printStatus(argParser.usage);
return 2;
}
if (ArtifactStore.flutterRoot == null) {
stderr.writeln('Neither the --flutter-root command line flag nor the FLUTTER_ROOT environment');
stderr.writeln('variable was specified. Unable to find package:flutter.');
printError('Neither the --flutter-root command line flag nor the FLUTTER_ROOT environment');
printError('variable was specified. Unable to find package:flutter.');
return 2;
}
String flutterRoot = path.absolute(ArtifactStore.flutterRoot);
String flutterPackagePath = path.join(flutterRoot, 'packages', 'flutter');
if (!FileSystemEntity.isFileSync(path.join(flutterPackagePath, 'pubspec.yaml'))) {
print('Unable to find package:flutter in $flutterPackagePath');
printError('Unable to find package:flutter in $flutterPackagePath');
return 2;
}
......@@ -50,7 +50,7 @@ class CreateCommand extends Command {
new FlutterSimpleTemplate().generateInto(out, flutterPackagePath);
print('');
printStatus('');
String message = '''All done! To run your application:
......@@ -64,7 +64,7 @@ class CreateCommand extends Command {
return code;
}
print(message);
printStatus(message);
return 0;
}
......@@ -80,13 +80,13 @@ class CreateCommand extends Command {
if (!pubSpecYaml.existsSync()) {
if (skipIfAbsent)
return 0;
logging.severe('$directory: no pubspec.yaml found');
printError('$directory: no pubspec.yaml found');
return 1;
}
if (!pubSpecLock.existsSync() || pubSpecYaml.lastModifiedSync().isAfter(pubSpecLock.lastModifiedSync())) {
if (verbose)
print("Running pub get in $directory...");
printStatus("Running pub get in $directory...");
int code = await runCommandAndStreamOutput(
[sdkBinaryName('pub'), 'get'],
workingDirectory: directory
......@@ -99,7 +99,7 @@ class CreateCommand extends Command {
(dotPackages.existsSync() && dotPackages.lastModifiedSync().isAfter(pubSpecYaml.lastModifiedSync())))
return 0;
logging.severe('$directory: pubspec.yaml, pubspec.lock, and .packages are in an inconsistent state');
printError('$directory: pubspec.yaml, pubspec.lock, and .packages are in an inconsistent state');
return 1;
}
}
......@@ -115,7 +115,7 @@ abstract class Template {
void generateInto(Directory dir, String flutterPackagePath) {
String dirPath = path.normalize(dir.absolute.path);
String projectName = _normalizeProjectName(path.basename(dirPath));
print('Creating ${path.basename(projectName)}...');
printStatus('Creating ${path.basename(projectName)}...');
dir.createSync(recursive: true);
String relativeFlutterPackagePath = path.relative(flutterPackagePath, from: dirPath);
......@@ -131,7 +131,7 @@ abstract class Template {
File file = new File(path.join(dir.path, filePath));
file.parent.createSync();
file.writeAsStringSync(contents);
print(file.path);
printStatus(file.path);
});
}
......
......@@ -6,11 +6,9 @@ import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:logging/logging.dart';
import '../android/adb.dart';
import '../android/device_android.dart';
import '../base/logging.dart';
import '../base/context.dart';
import '../device.dart';
import '../runner/flutter_command.dart';
import 'start.dart';
......@@ -30,29 +28,32 @@ class DaemonCommand extends FlutterCommand {
bool get requiresProjectRoot => false;
Future<int> runInProject() async {
print('Starting device daemon...');
Future<int> runInProject() {
printStatus('Starting device daemon...');
NotifyingAppContext appContext = new NotifyingAppContext();
Stream<Map> commandStream = stdin
.transform(UTF8.decoder)
.transform(const LineSplitter())
.where((String line) => line.startsWith('[{') && line.endsWith('}]'))
.map((String line) {
line = line.substring(1, line.length - 1);
return JSON.decode(line);
});
return runZoned(() {
Stream<Map<String, dynamic>> commandStream = stdin
.transform(UTF8.decoder)
.transform(const LineSplitter())
.where((String line) => line.startsWith('[{') && line.endsWith('}]'))
.map((String line) {
line = line.substring(1, line.length - 1);
return JSON.decode(line);
});
Daemon daemon = new Daemon(commandStream, (Map command) {
stdout.writeln('[${JSON.encode(command, toEncodable: _jsonEncodeObject)}]');
}, daemonCommand: this);
Daemon daemon = new Daemon(commandStream, (Map command) {
stdout.writeln('[${JSON.encode(command, toEncodable: _jsonEncodeObject)}]');
}, daemonCommand: this, appContext: appContext);
return await daemon.onExit;
return daemon.onExit;
}, zoneValues: {'context': appContext});
}
dynamic _jsonEncodeObject(dynamic object) {
if (object is Device)
return _deviceToMap(object);
return object;
}
}
......@@ -62,7 +63,10 @@ typedef void DispatchComand(Map<String, dynamic> command);
typedef Future<dynamic> CommandHandler(dynamic args);
class Daemon {
Daemon(Stream<Map> commandStream, this.sendCommand, {this.daemonCommand}) {
Daemon(Stream<Map> commandStream, this.sendCommand, {
this.daemonCommand,
this.appContext
}) {
// Set up domains.
_registerDomain(new DaemonDomain(this));
_registerDomain(new AppDomain(this));
......@@ -77,6 +81,7 @@ class Daemon {
final DispatchComand sendCommand;
final DaemonCommand daemonCommand;
final NotifyingAppContext appContext;
final Completer<int> _onExitCompleter = new Completer<int>();
final Map<String, Domain> _domainMap = <String, Domain>{};
......@@ -94,7 +99,7 @@ class Daemon {
dynamic id = request['id'];
if (id == null) {
logging.severe('no id for request: $request');
stderr.writeln('no id for request: $request');
return;
}
......@@ -111,7 +116,8 @@ class Daemon {
_domainMap[prefix].handleCommand(name, id, request['params']);
} catch (error, trace) {
_send({'id': id, 'error': _toJsonable(error)});
logging.warning('error handling $request', error, trace);
stderr.writeln('error handling $request: $error');
stderr.writeln(trace);
}
}
......@@ -152,7 +158,8 @@ abstract class Domain {
}
}).catchError((error, trace) {
_send({'id': id, 'error': _toJsonable(error)});
logging.warning("error handling '$name.$command'", error, trace);
stderr.writeln("error handling '$name.$command': $error");
stderr.writeln(trace);
});
}
......@@ -176,25 +183,23 @@ class DaemonDomain extends Domain {
registerHandler('version', version);
registerHandler('shutdown', shutdown);
_subscription = Logger.root.onRecord.listen((LogRecord record) {
String message = record.error == null ? record.message : '${record.message}: ${record.error}';
if (record.stackTrace != null) {
_subscription = daemon.appContext.onMessage.listen((LogMessage message) {
if (message.stackTrace != null) {
sendEvent('daemon.logMessage', {
'level': record.level.name.toLowerCase(),
'message': message,
'stackTrace': record.stackTrace.toString()
'level': message.level,
'message': message.message,
'stackTrace': message.stackTrace.toString()
});
} else {
sendEvent('daemon.logMessage', {
'level': record.level.name.toLowerCase(),
'message': message
'level': message.level,
'message': message.message
});
}
});
}
StreamSubscription<LogRecord> _subscription;
StreamSubscription<LogMessage> _subscription;
Future<String> version(dynamic args) {
return new Future.value(protocolVersion);
......@@ -403,3 +408,31 @@ dynamic _toJsonable(dynamic obj) {
return obj;
return '$obj';
}
class NotifyingAppContext implements AppContext {
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));
}
void printStatus(String message) {
_messageController.add(new LogMessage('status', message));
}
void printTrace(String message) {
_messageController.add(new LogMessage('trace', message));
}
}
class LogMessage {
final String level;
final String message;
final StackTrace stackTrace;
LogMessage(this.level, this.message, [this.stackTrace]);
}
......@@ -8,7 +8,7 @@ import "dart:io";
import "package:path/path.dart" as path;
import "../artifacts.dart";
import "../base/logging.dart";
import "../base/context.dart";
import "../base/process.dart";
import "../runner/flutter_command.dart";
import "../runner/flutter_command_runner.dart";
......@@ -29,12 +29,12 @@ class IOSCommand extends FlutterCommand {
}
Future<List<int>> _fetchXcodeArchive() async {
print("Fetching the Xcode project archive from the cloud...");
printStatus("Fetching the Xcode project archive from the cloud...");
HttpClient client = new HttpClient();
Uri xcodeProjectUri = _xcodeProjectUri(ArtifactStore.engineRevision);
logging.info("Downloading $xcodeProjectUri...");
printStatus("Downloading $xcodeProjectUri...");
HttpClientRequest request = await client.getUrl(xcodeProjectUri);
HttpClientResponse response = await request.close();
......@@ -49,7 +49,7 @@ class IOSCommand extends FlutterCommand {
}
Future<bool> _inflateXcodeArchive(String directory, List<int> archiveBytes) async {
print("Unzipping Xcode project to local directory...");
printStatus("Unzipping Xcode project to local directory...");
// We cannot use ArchiveFile because this archive contains files that are exectuable
// and there is currently no provision to modify file permissions during
......@@ -117,16 +117,16 @@ class IOSCommand extends FlutterCommand {
List<int> archiveBytes = await _fetchXcodeArchive();
if (archiveBytes.isEmpty) {
print("Error: No archive bytes received.");
printError("Error: No archive bytes received.");
return 1;
}
// Step 2: Inflate the archive into the user project directory
bool result = await _inflateXcodeArchive(xcodeprojPath, archiveBytes);
if (!result) {
print("Error: Could not init the Xcode project: the 'ios' directory already exists.");
print("To proceed, remove the 'ios' directory and try again.");
print("Warning: You may have made manual changes to files in the 'ios' directory.");
printError("Error: Could not init the Xcode project: the 'ios' directory already exists.");
printError("To proceed, remove the 'ios' directory and try again.");
printError("Warning: You may have made manual changes to files in the 'ios' directory.");
return 1;
}
......@@ -134,22 +134,22 @@ class IOSCommand extends FlutterCommand {
_setupXcodeProjXcconfig(path.join(xcodeprojPath, "Local.xcconfig"));
// Step 4: Tell the user the location of the generated project.
print("An Xcode project has been placed in 'ios/'.");
print("You may edit it to modify iOS specific configuration.");
printStatus("An Xcode project has been placed in 'ios/'.");
printStatus("You may edit it to modify iOS specific configuration.");
return 0;
}
@override
Future<int> runInProject() async {
if (!Platform.isMacOS) {
print("iOS specific commands may only be run on a Mac.");
printStatus("iOS specific commands may only be run on a Mac.");
return 1;
}
if (argResults['init'])
return await _runInitCommand();
print("No flags specified.");
printError("No flags specified.");
return 1;
}
}
......@@ -4,6 +4,7 @@
import 'dart:async';
import '../base/context.dart';
import '../device.dart';
import '../runner/flutter_command.dart';
......@@ -19,12 +20,13 @@ class ListCommand extends FlutterCommand {
List<Device> devices = await deviceManager.getDevices();
if (devices.isEmpty) {
print('No connected devices.');
printStatus('No connected devices.');
} else {
print('${devices.length} connected ${pluralize('device', devices.length)}:');
print('');
printStatus('${devices.length} connected ${pluralize('device', devices.length)}:');
printStatus('');
for (Device device in devices) {
print('${device.name} (${device.id})');
printStatus('${device.name} (${device.id})');
}
}
......
......@@ -5,7 +5,7 @@
import 'dart:async';
import 'dart:io';
import '../base/logging.dart';
import '../base/context.dart';
import '../base/process.dart';
import 'start.dart';
......@@ -36,7 +36,7 @@ class ListenCommand extends StartCommandBase {
int result = 0;
bool firstTime = true;
do {
logging.info('Updating running Flutter apps...');
printStatus('Updating running Flutter apps...');
result = await startApp(
devices,
applicationPackages,
......@@ -58,7 +58,7 @@ class ListenCommand extends StartCommandBase {
try {
runCheckedSync(<String>['which', 'fswatch']);
} catch (e) {
logging.severe('"listen" command is only useful if you have installed '
printError('"listen" command is only useful if you have installed '
'fswatch on Mac. Run "brew install fswatch" to install it with '
'homebrew.');
return null;
......@@ -68,7 +68,7 @@ class ListenCommand extends StartCommandBase {
try {
runCheckedSync(<String>['which', 'inotifywait']);
} catch (e) {
logging.severe('"listen" command is only useful if you have installed '
printError('"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;
......@@ -82,18 +82,18 @@ class ListenCommand extends StartCommandBase {
'modify,close_write,move,create,delete',
]..addAll(directories);
} else {
logging.severe('"listen" command is only available on Mac and Linux.');
printError('"listen" command is only available on Mac and Linux.');
}
return null;
}
bool _watchDirectory(List<String> watchCommand) {
logging.info('Attempting to listen to these directories: ${watchCommand.join(", ")}');
printStatus('Attempting to listen to these directories: ${watchCommand.join(", ")}');
assert(watchCommand != null);
try {
runCheckedSync(watchCommand);
} catch (e) {
logging.warning('Watching directories failed.', e);
printError('Watching directories failed.', e);
return false;
}
return true;
......
......@@ -5,11 +5,10 @@
import 'dart:async';
import 'dart:io';
import 'package:logging/logging.dart';
import 'package:path/path.dart' as path;
import '../artifacts.dart';
import '../base/logging.dart';
import '../base/context.dart';
import '../base/process.dart';
import '../build_configuration.dart';
import '../flx.dart' as flx;
......@@ -119,12 +118,8 @@ class RunMojoCommand extends FlutterCommand {
if (useDevtools) {
final String buildFlag = argResults['mojo-debug'] ? '--debug' : '--release';
args.add(buildFlag);
if (logging.level <= Level.INFO) {
if (context.verbose)
args.add('--verbose');
if (logging.level <= Level.FINE) {
args.add('--verbose');
}
}
}
if (argResults['checked']) {
......@@ -132,19 +127,19 @@ class RunMojoCommand extends FlutterCommand {
}
args.addAll(argResults.rest);
print(args);
printStatus('$args');
return args;
}
@override
Future<int> runInProject() async {
if ((argResults['mojo-path'] == null && argResults['devtools-path'] == null) || (argResults['mojo-path'] != null && argResults['devtools-path'] != null)) {
logging.severe('Must specify either --mojo-path or --devtools-path.');
printError('Must specify either --mojo-path or --devtools-path.');
return 1;
}
if (argResults['mojo-debug'] && argResults['mojo-release']) {
logging.severe('Cannot specify both --mojo-debug and --mojo-release');
printError('Cannot specify both --mojo-debug and --mojo-release');
return 1;
}
......
......@@ -8,7 +8,7 @@ import 'dart:io';
import 'package:path/path.dart' as path;
import '../application_package.dart';
import '../base/logging.dart';
import '../base/context.dart';
import '../device.dart';
import '../runner/flutter_command.dart';
import '../toolchain.dart';
......@@ -64,7 +64,7 @@ class StartCommand extends StartCommandBase {
@override
Future<int> runInProject() async {
logging.fine('Downloading toolchain.');
printTrace('Downloading toolchain.');
await Future.wait([
downloadToolchain(),
......@@ -89,7 +89,7 @@ class StartCommand extends StartCommandBase {
clearLogs: clearLogs
);
logging.fine('Finished start command.');
printTrace('Finished start command.');
return result;
}
}
......@@ -113,17 +113,17 @@ Future<int> startApp(
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);
printError(message);
return 1;
}
if (stop) {
logging.fine('Running stop command.');
printTrace('Running stop command.');
stopAll(devices, applicationPackages);
}
if (install) {
logging.fine('Running install command.');
printTrace('Running install command.');
installApp(devices, applicationPackages);
}
......@@ -134,7 +134,7 @@ Future<int> startApp(
if (package == null || !device.isConnected())
continue;
logging.fine('Running build command for $device.');
printTrace('Running build command for $device.');
Map<String, dynamic> platformArgs = <String, dynamic>{};
......@@ -155,7 +155,7 @@ Future<int> startApp(
);
if (!result) {
logging.severe('Could not start \'${package.name}\' on \'${device.id}\'');
printError('Could not start \'${package.name}\' on \'${device.id}\'');
} else {
startedSomething = true;
}
......@@ -163,9 +163,9 @@ Future<int> startApp(
if (!startedSomething) {
if (!devices.all.any((device) => device.isConnected())) {
logging.severe('Unable to run application - no connected devices.');
printError('Unable to run application - no connected devices.');
} else {
logging.severe('Unable to run application.');
printError('Unable to run application.');
}
}
......
......@@ -9,7 +9,7 @@ import 'package:path/path.dart' as path;
import 'package:test/src/executable.dart' as executable;
import '../artifacts.dart';
import '../base/logging.dart';
import '../base/context.dart';
import '../build_configuration.dart';
import '../runner/flutter_command.dart';
import '../test/loader.dart' as loader;
......@@ -105,7 +105,7 @@ class TestCommand extends FlutterCommand {
foundOne = true;
loader.shellPath = path.absolute(await _getShellPath(config));
if (!FileSystemEntity.isFileSync(loader.shellPath)) {
logging.severe('Cannot find Flutter shell at ${loader.shellPath}');
printError('Cannot find Flutter shell at ${loader.shellPath}');
return 1;
}
await _runTests(testArgs, testDir);
......@@ -113,7 +113,7 @@ class TestCommand extends FlutterCommand {
return exitCode;
}
if (!foundOne) {
stderr.writeln('At least one of --debug or --release must be set, to specify the local build products to test.');
printError('At least one of --debug or --release must be set, to specify the local build products to test.');
return 1;
}
......
......@@ -6,7 +6,7 @@ import 'dart:async';
import '../android/device_android.dart';
import '../application_package.dart';
import '../base/logging.dart';
import '../base/context.dart';
import '../runner/flutter_command.dart';
class TraceCommand extends FlutterCommand {
......@@ -30,7 +30,7 @@ class TraceCommand extends FlutterCommand {
await downloadApplicationPackagesAndConnectToDevices();
if (!devices.android.isConnected()) {
logging.warning('No device connected, so no trace was completed.');
printError('No device connected, so no trace was completed.');
return 1;
}
......@@ -56,9 +56,9 @@ class TraceCommand extends FlutterCommand {
Future _stopTracing(AndroidDevice android, AndroidApk androidApp) async {
String tracePath = await android.stopTracing(androidApp, outPath: argResults['out']);
if (tracePath == null) {
logging.warning('No trace file saved.');
printError('No trace file saved.');
} else {
print('Trace file saved to $tracePath');
printStatus('Trace file saved to $tracePath');
}
}
}
......@@ -5,6 +5,7 @@
import 'dart:async';
import '../artifacts.dart';
import '../base/context.dart';
import '../base/process.dart';
import '../runner/flutter_command.dart';
......@@ -19,7 +20,7 @@ class UpgradeCommand extends FlutterCommand {
'git', 'rev-parse', '@{u}'
], workingDirectory: ArtifactStore.flutterRoot);
} catch (e) {
print('Unable to upgrade Flutter. No upstream repository configured for Flutter.');
printError('Unable to upgrade Flutter. No upstream repository configured for Flutter.');
return 1;
}
......
......@@ -6,7 +6,7 @@ import 'dart:async';
import 'android/device_android.dart';
import 'application_package.dart';
import 'base/logging.dart';
import 'base/context.dart';
import 'build_configuration.dart';
import 'ios/device_ios.dart';
import 'toolchain.dart';
......@@ -132,7 +132,7 @@ class DeviceStore {
(Device dev) => (dev.id == config.deviceId),
orElse: () => null);
if (device == null) {
logging.severe('Warning: Device ID ${config.deviceId} not found');
printError('Warning: Device ID ${config.deviceId} not found');
}
} else if (devices.length == 1) {
// Step 2: If no identifier is specified and there is only one connected
......@@ -140,8 +140,8 @@ class DeviceStore {
device = devices[0];
} else if (devices.length > 1) {
// Step 3: D:
logging.fine('Multiple devices are connected, but no device ID was specified.');
logging.fine('Attempting to launch on all connected devices.');
printTrace('Multiple devices are connected, but no device ID was specified.');
printTrace('Attempting to launch on all connected devices.');
}
return device;
......
......@@ -12,8 +12,8 @@ import 'package:flx/signing.dart';
import 'package:path/path.dart' as path;
import 'package:yaml/yaml.dart';
import 'base/context.dart';
import 'base/file_system.dart';
import 'base/logging.dart';
import 'toolchain.dart';
const String defaultMainPath = 'lib/main.dart';
......@@ -158,7 +158,7 @@ Future<int> build(
String privateKeyPath: defaultPrivateKeyPath,
bool precompiledSnapshot: false
}) async {
logging.fine('Building $outputPath');
printTrace('Building $outputPath');
Map manifestDescriptor = _loadManifest(manifestPath);
......@@ -174,7 +174,7 @@ Future<int> build(
// content equivalents
int result = await toolchain.compiler.compile(mainPath: mainPath, snapshotPath: snapshotPath);
if (result != 0) {
logging.severe('Failed to run the Flutter compiler. Exit code: $result');
printError('Failed to run the Flutter compiler. Exit code: $result');
return result;
}
......@@ -184,7 +184,7 @@ Future<int> build(
for (_Asset asset in assets) {
ArchiveFile file = _createFile(asset.key, asset.base);
if (file == null) {
stderr.writeln('Cannot find asset "${asset.key}" in directory "${path.absolute(asset.base)}".');
printError('Cannot find asset "${asset.key}" in directory "${path.absolute(asset.base)}".');
return 1;
}
archive.addFile(file);
......
......@@ -8,7 +8,7 @@ import 'dart:io';
import 'package:path/path.dart' as path;
import '../application_package.dart';
import '../base/logging.dart';
import '../base/context.dart';
import '../base/process.dart';
import '../build_configuration.dart';
import '../device.dart';
......@@ -129,9 +129,9 @@ class IOSDevice extends Device {
command = runCheckedSync(['which', command]).trim();
} catch (e) {
if (Platform.isMacOS) {
logging.severe('$command not found. $macInstructions');
printError('$command not found. $macInstructions');
} else {
logging.severe('Cannot control iOS devices or simulators. $command is not available on your platform.');
printError('Cannot control iOS devices or simulators. $command is not available on your platform.');
}
}
return command;
......@@ -187,13 +187,13 @@ class IOSDevice extends Device {
Map<String, dynamic> platformArgs
}) async {
// TODO: Use checked, mainPath, route
logging.fine('Building ${app.name} for $id');
printTrace('Building ${app.name} for $id');
// Step 1: Install the precompiled application if necessary
bool buildResult = await _buildIOSXcodeProject(app, true);
if (!buildResult) {
logging.severe('Could not build the precompiled application for the device');
printError('Could not build the precompiled application for the device');
return false;
}
......@@ -202,7 +202,7 @@ class IOSDevice extends Device {
bool bundleExists = bundle.existsSync();
if (!bundleExists) {
logging.severe('Could not find the built application bundle at ${bundle.path}');
printError('Could not find the built application bundle at ${bundle.path}');
return false;
}
......@@ -217,11 +217,11 @@ class IOSDevice extends Device {
]);
if (installationResult != 0) {
logging.severe('Could not install ${bundle.path} on $id');
printError('Could not install ${bundle.path} on $id');
return false;
}
logging.fine('Installation successful');
printTrace('Installation successful');
return true;
}
......@@ -311,13 +311,13 @@ class IOSSimulator extends Device {
// More than one simulator is listed as booted, which is not allowed but
// sometimes happens erroneously. Kill them all because we don't know
// which one is actually running.
logging.warning('Multiple running simulators were detected, '
printError('Multiple running simulators were detected, '
'which is not supposed to happen.');
for (Match match in matches) {
if (match.groupCount > 0) {
// TODO: We're killing simulator devices inside an accessor method;
// we probably shouldn't be changing state here.
logging.warning('Killing simulator ${match.group(1)}');
printError('Killing simulator ${match.group(1)}');
runSync([xcrunPath, 'simctl', 'shutdown', match.group(2)]);
}
}
......@@ -328,7 +328,7 @@ class IOSSimulator extends Device {
if (match != null && match.groupCount > 0) {
return new _IOSSimulatorInfo(match.group(2), match.group(1));
} else {
logging.info('No running simulators found');
printTrace('No running simulators found');
return null;
}
}
......@@ -368,11 +368,11 @@ class IOSSimulator extends Device {
runDetached([iOSSimPath]);
Future<bool> checkConnection([int attempts = 20]) async {
if (attempts == 0) {
logging.info('Timed out waiting for iOS Simulator $id to boot.');
printStatus('Timed out waiting for iOS Simulator $id to boot.');
return false;
}
if (!isConnected()) {
logging.info('Waiting for iOS Simulator $id to boot...');
printStatus('Waiting for iOS Simulator $id to boot...');
return await new Future.delayed(new Duration(milliseconds: 500),
() => checkConnection(attempts - 1));
}
......@@ -383,7 +383,7 @@ class IOSSimulator extends Device {
try {
runCheckedSync([xcrunPath, 'simctl', 'boot', id]);
} catch (e) {
logging.warning('Unable to boot iOS Simulator $id: ', e);
printError('Unable to boot iOS Simulator $id: ', e);
return false;
}
}
......@@ -441,12 +441,12 @@ class IOSSimulator extends Device {
Map<String, dynamic> platformArgs
}) async {
// TODO: Use checked, mainPath, route
logging.fine('Building ${app.name} for $id');
printTrace('Building ${app.name} for $id');
// Step 1: Build the Xcode project
bool buildResult = await _buildIOSXcodeProject(app, false);
if (!buildResult) {
logging.severe('Could not build the application for the simulator');
printError('Could not build the application for the simulator');
return false;
}
......@@ -454,7 +454,7 @@ class IOSSimulator extends Device {
Directory bundle = new Directory(path.join(app.localPath, 'build', 'Release-iphonesimulator', 'Runner.app'));
bool bundleExists = await bundle.exists();
if (!bundleExists) {
logging.severe('Could not find the built application bundle at ${bundle.path}');
printError('Could not find the built application bundle at ${bundle.path}');
return false;
}
......@@ -468,7 +468,7 @@ class IOSSimulator extends Device {
]);
if (installResult != 0) {
logging.severe('Could not install the application bundle on the simulator');
printError('Could not install the application bundle on the simulator');
return false;
}
......@@ -482,11 +482,11 @@ class IOSSimulator extends Device {
]);
if (launchResult != 0) {
logging.severe('Could not launch the freshly installed application on the simulator');
printError('Could not launch the freshly installed application on the simulator');
return false;
}
logging.fine('Successfully started ${app.name} on $id');
printTrace('Successfully started ${app.name} on $id');
return true;
}
......@@ -545,11 +545,11 @@ bool _checkXcodeVersion() {
String version = runCheckedSync(['xcodebuild', '-version']);
Match match = _xcodeVersionRegExp.firstMatch(version);
if (int.parse(match[1]) < 7) {
logging.severe('Found "${match[0]}". $_xcodeRequirement');
printError('Found "${match[0]}". $_xcodeRequirement');
return false;
}
} catch (e) {
logging.severe('Cannot find "xcodebuid". $_xcodeRequirement');
printError('Cannot find "xcodebuid". $_xcodeRequirement');
return false;
}
return true;
......@@ -557,7 +557,7 @@ bool _checkXcodeVersion() {
Future<bool> _buildIOSXcodeProject(ApplicationPackage app, bool isDevice) async {
if (!FileSystemEntity.isDirectorySync(app.localPath)) {
logging.severe('Path "${path.absolute(app.localPath)}" does not exist.\nDid you run `flutter ios --init`?');
printError('Path "${path.absolute(app.localPath)}" does not exist.\nDid you run `flutter ios --init`?');
return false;
}
......
......@@ -8,6 +8,7 @@ import 'dart:io';
import 'package:args/command_runner.dart';
import '../application_package.dart';
import '../base/context.dart';
import '../build_configuration.dart';
import '../device.dart';
import '../toolchain.dart';
......@@ -55,7 +56,7 @@ abstract class FlutterCommand extends Command {
bool validateProjectRoot() {
if (!FileSystemEntity.isFileSync('pubspec.yaml')) {
stderr.writeln(projectRootValidationErrorMessage);
printError(projectRootValidationErrorMessage);
return false;
}
return true;
......
......@@ -7,11 +7,10 @@ import 'dart:io';
import 'package:args/args.dart';
import 'package:args/command_runner.dart';
import 'package:logging/logging.dart';
import 'package:path/path.dart' as path;
import '../artifacts.dart';
import '../base/logging.dart';
import '../base/context.dart';
import '../base/process.dart';
import '../build_configuration.dart';
import 'version.dart';
......@@ -29,10 +28,6 @@ class FlutterCommandRunner extends CommandRunner {
abbr: 'v',
negatable: false,
help: 'Noisy logging, including all shell commands executed.');
argParser.addFlag('very-verbose',
negatable: false,
help: 'Very noisy logging, including the output of all '
'shell commands executed.');
argParser.addFlag('version',
negatable: false,
help: 'Reports the version of this tool.');
......@@ -141,10 +136,7 @@ class FlutterCommandRunner extends CommandRunner {
Future<int> runCommand(ArgResults globalResults) {
if (globalResults['verbose'])
Logger.root.level = Level.INFO;
if (globalResults['very-verbose'])
Logger.root.level = Level.FINE;
context.verbose = true;
_globalResults = globalResults;
ArtifactStore.flutterRoot = path.normalize(path.absolute(globalResults['flutter-root']));
......@@ -152,7 +144,7 @@ class FlutterCommandRunner extends CommandRunner {
ArtifactStore.packageRoot = path.normalize(path.absolute(globalResults['package-root']));
if (globalResults['version']) {
print(getVersion(ArtifactStore.flutterRoot));
printStatus(getVersion(ArtifactStore.flutterRoot));
return new Future<int>.value(0);
}
......@@ -186,7 +178,7 @@ class FlutterCommandRunner extends CommandRunner {
engineSourcePath = _tryEnginePath(path.join(ArtifactStore.flutterRoot, '../engine/src'));
if (engineSourcePath == null) {
stderr.writeln('Unable to detect local Flutter engine build directory.\n'
printError('Unable to detect local Flutter engine build directory.\n'
'Either specify a dependency_override for the $kFlutterEnginePackageName package in your pubspec.yaml and\n'
'ensure --package-root is set if necessary, or set the \$$kFlutterEngineEnvironmentVariableName environment variable, or\n'
'use --engine-src-path to specify the path to the root of your flutter/engine repository.');
......@@ -195,7 +187,7 @@ class FlutterCommandRunner extends CommandRunner {
}
if (engineSourcePath != null && _tryEnginePath(engineSourcePath) == null) {
stderr.writeln('Unable to detect a Flutter engine build directory in $engineSourcePath.\n'
printError('Unable to detect a Flutter engine build directory in $engineSourcePath.\n'
'Please ensure that $engineSourcePath is a Flutter engine \'src\' directory and that\n'
'you have compiled the engine in that directory, which should produce an \'out\' directory');
throw new ProcessExit(2);
......@@ -240,7 +232,7 @@ class FlutterCommandRunner extends CommandRunner {
}
} else {
if (!FileSystemEntity.isDirectorySync(enginePath))
logging.warning('$enginePath is not a valid directory');
printError('$enginePath is not a valid directory');
if (!isDebug && !isRelease)
isDebug = true;
......
......@@ -7,8 +7,6 @@ import 'dart:convert';
import 'dart:io';
import 'package:path/path.dart' as path;
import 'package:flutter_tools/src/test/json_socket.dart';
import 'package:flutter_tools/src/test/remote_test.dart';
import 'package:stack_trace/stack_trace.dart';
import 'package:test/src/backend/group.dart';
import 'package:test/src/backend/metadata.dart';
......@@ -21,6 +19,9 @@ import 'package:test/src/runner/vm/environment.dart';
import 'package:test/src/util/io.dart';
import 'package:test/src/util/remote_exception.dart';
import 'json_socket.dart';
import 'remote_test.dart';
void installHook() {
hack.loadVMFileHook = _loadVMFile;
}
......
......@@ -14,8 +14,8 @@ import 'package:test/src/backend/live_test.dart';
import 'package:test/src/backend/metadata.dart';
import 'package:test/src/backend/operating_system.dart';
import 'package:test/src/backend/suite.dart';
import 'package:test/src/backend/test_platform.dart';
import 'package:test/src/backend/test.dart';
import 'package:test/src/backend/test_platform.dart';
import 'package:test/src/util/remote_exception.dart';
final OperatingSystem currentOS = (() {
......
......@@ -5,18 +5,18 @@
import 'dart:async';
import 'package:stack_trace/stack_trace.dart';
import 'package:test/src/backend/group.dart';
import 'package:test/src/backend/live_test.dart';
import 'package:test/src/backend/live_test_controller.dart';
import 'package:test/src/backend/metadata.dart';
import 'package:test/src/backend/operating_system.dart';
import 'package:test/src/backend/group.dart';
import 'package:test/src/backend/state.dart';
import 'package:test/src/backend/suite.dart';
import 'package:test/src/backend/test.dart';
import 'package:test/src/backend/test_platform.dart';
import 'package:test/src/util/remote_exception.dart';
import 'package:flutter_tools/src/test/json_socket.dart';
import 'json_socket.dart';
class RemoteTest extends Test {
RemoteTest(this.name, this.metadata, this._socket, this._index);
......
// 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:test/test.dart';
main() => defineTests();
defineTests() {
group('DeviceManager', () {
test('error', () async {
MockContext mockContext = new MockContext();
runZoned(() {
printError('foo bar');
}, zoneValues: {'context': mockContext});
expect(mockContext.errorText, 'foo bar\n');
expect(mockContext.statusText, '');
expect(mockContext.traceText, '');
});
test('status', () async {
MockContext mockContext = new MockContext();
runZoned(() {
printStatus('foo bar');
}, zoneValues: {'context': mockContext});
expect(mockContext.errorText, '');
expect(mockContext.statusText, 'foo bar\n');
expect(mockContext.traceText, '');
});
test('trace', () async {
MockContext mockContext = new MockContext();
runZoned(() {
printTrace('foo bar');
}, zoneValues: {'context': mockContext});
expect(mockContext.errorText, '');
expect(mockContext.statusText, '');
expect(mockContext.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);
}
......@@ -5,10 +5,10 @@
import 'dart:io';
import 'package:args/command_runner.dart';
import 'package:path/path.dart' as path;
import 'package:flutter_tools/src/artifacts.dart';
import 'package:flutter_tools/src/commands/create.dart';
import 'package:flutter_tools/src/base/process.dart';
import 'package:flutter_tools/src/commands/create.dart';
import 'package:path/path.dart' as path;
import 'package:test/test.dart';
main() => defineTests();
......
......@@ -4,7 +4,7 @@
import 'dart:async';
import 'package:flutter_tools/src/base/logging.dart';
import 'package:flutter_tools/src/base/context.dart';
import 'package:flutter_tools/src/commands/daemon.dart';
import 'package:mockito/mockito.dart';
import 'package:test/test.dart';
......@@ -16,6 +16,11 @@ main() => defineTests();
defineTests() {
group('daemon', () {
Daemon daemon;
NotifyingAppContext appContext;
setUp(() {
appContext = new NotifyingAppContext();
});
tearDown(() {
if (daemon != null)
......@@ -23,11 +28,12 @@ defineTests() {
});
test('daemon.version', () async {
StreamController<Map> commands = new StreamController();
StreamController<Map> responses = new StreamController();
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)
(Map<String, dynamic> result) => responses.add(result),
appContext: appContext
);
commands.add({'id': 0, 'method': 'daemon.version'});
Map response = await responses.stream.where(_notEvent).first;
......@@ -36,30 +42,34 @@ defineTests() {
expect(response['result'] is String, true);
});
test('daemon.logMessage', () async {
StreamController<Map> commands = new StreamController();
StreamController<Map> responses = new StreamController();
daemon = new Daemon(
commands.stream,
(Map<String, dynamic> result) => responses.add(result)
);
logging.warning('daemon.logMessage test');
Map response = await responses.stream.where((Map<String, dynamic> map) {
return map['event'] == 'daemon.logMessage' && map['params']['level'] == 'warning';
}).first;
expect(response['id'], isNull);
expect(response['event'], 'daemon.logMessage');
Map<String, String> logMessage = response['params'];
expect(logMessage['level'], 'warning');
expect(logMessage['message'], 'daemon.logMessage test');
test('daemon.logMessage', () {
return runZoned(() 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
);
printError('daemon.logMessage test');
Map<String, dynamic> response = await responses.stream.where((Map<String, dynamic> map) {
return map['event'] == 'daemon.logMessage' && map['params']['level'] == 'error';
}).first;
expect(response['id'], isNull);
expect(response['event'], 'daemon.logMessage');
Map<String, String> logMessage = response['params'];
expect(logMessage['level'], 'error');
expect(logMessage['message'], 'daemon.logMessage test');
}, zoneValues: {'context': appContext});
});
test('daemon.shutdown', () async {
StreamController<Map> commands = new StreamController();
StreamController<Map> responses = new StreamController();
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)
(Map<String, dynamic> result) => responses.add(result),
appContext: appContext
);
commands.add({'id': 0, 'method': 'daemon.shutdown'});
return daemon.onExit.then((int code) {
......@@ -71,12 +81,13 @@ defineTests() {
DaemonCommand command = new DaemonCommand();
applyMocksToCommand(command);
StreamController<Map> commands = new StreamController();
StreamController<Map> responses = new StreamController();
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),
daemonCommand: command
daemonCommand: command,
appContext: appContext
);
MockDeviceStore mockDevices = command.devices;
......@@ -97,11 +108,12 @@ defineTests() {
});
test('device.getDevices', () async {
StreamController<Map> commands = new StreamController();
StreamController<Map> responses = new StreamController();
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)
(Map<String, dynamic> result) => responses.add(result),
appContext: appContext
);
commands.add({'id': 0, 'method': 'device.getDevices'});
Map response = await responses.stream.where(_notEvent).first;
......
// Copyright 2015 The Chromium Authors. All rights reserved.
// 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.
......
......@@ -3,8 +3,8 @@
// found in the LICENSE file.
import 'package:args/command_runner.dart';
import 'package:mockito/mockito.dart';
import 'package:flutter_tools/src/commands/install.dart';
import 'package:mockito/mockito.dart';
import 'package:test/test.dart';
import 'src/mocks.dart';
......
......@@ -5,8 +5,8 @@
import 'dart:io';
import 'package:args/command_runner.dart';
import 'package:mockito/mockito.dart';
import 'package:flutter_tools/src/commands/list.dart';
import 'package:mockito/mockito.dart';
import 'package:test/test.dart';
import 'src/mocks.dart';
......
......@@ -3,8 +3,8 @@
// found in the LICENSE file.
import 'package:args/command_runner.dart';
import 'package:mockito/mockito.dart';
import 'package:flutter_tools/src/commands/listen.dart';
import 'package:mockito/mockito.dart';
import 'package:test/test.dart';
import 'src/mocks.dart';
......
......@@ -3,8 +3,8 @@
// found in the LICENSE file.
import 'package:args/command_runner.dart';
import 'package:mockito/mockito.dart';
import 'package:flutter_tools/src/commands/logs.dart';
import 'package:mockito/mockito.dart';
import 'package:test/test.dart';
import 'src/mocks.dart';
......
......@@ -5,8 +5,8 @@
import 'dart:io';
import 'package:flutter_tools/src/base/os.dart';
import 'package:test/test.dart';
import 'package:path/path.dart' as path;
import 'package:test/test.dart';
main() => defineTests();
......
......@@ -3,8 +3,8 @@
// found in the LICENSE file.
import 'package:args/command_runner.dart';
import 'package:mockito/mockito.dart';
import 'package:flutter_tools/src/commands/stop.dart';
import 'package:mockito/mockito.dart';
import 'package:test/test.dart';
import 'src/mocks.dart';
......
......@@ -3,8 +3,8 @@
// found in the LICENSE file.
import 'package:args/command_runner.dart';
import 'package:mockito/mockito.dart';
import 'package:flutter_tools/src/commands/trace.dart';
import 'package:mockito/mockito.dart';
import 'package:test/test.dart';
import 'src/mocks.dart';
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment