Commit 0b737ac5 authored by John McCutchan's avatar John McCutchan Committed by GitHub

Remove default AppContext and cleanup globals (#6999)

parent 1d2f7e3c
...@@ -40,6 +40,7 @@ import 'src/device.dart'; ...@@ -40,6 +40,7 @@ import 'src/device.dart';
import 'src/doctor.dart'; import 'src/doctor.dart';
import 'src/globals.dart'; import 'src/globals.dart';
import 'src/hot.dart'; import 'src/hot.dart';
import 'src/usage.dart';
import 'src/runner/flutter_command_runner.dart'; import 'src/runner/flutter_command_runner.dart';
/// Main entry point for commands. /// Main entry point for commands.
...@@ -81,8 +82,12 @@ Future<Null> main(List<String> args) async { ...@@ -81,8 +82,12 @@ Future<Null> main(List<String> args) async {
..addCommand(new UpdatePackagesCommand(hidden: !verboseHelp)) ..addCommand(new UpdatePackagesCommand(hidden: !verboseHelp))
..addCommand(new UpgradeCommand()); ..addCommand(new UpgradeCommand());
return Chain.capture/*<Future<Null>>*/(() async { // Construct a context.
// Initialize globals. AppContext _executableContext = new AppContext();
// Make the context current.
_executableContext.runInZone(() {
// Initialize the context with some defaults.
if (context[Logger] == null) if (context[Logger] == null)
context[Logger] = new StdoutLogger(); context[Logger] = new StdoutLogger();
if (context[DeviceManager] == null) if (context[DeviceManager] == null)
...@@ -94,56 +99,58 @@ Future<Null> main(List<String> args) async { ...@@ -94,56 +99,58 @@ Future<Null> main(List<String> args) async {
if (context[HotRunnerConfig] == null) if (context[HotRunnerConfig] == null)
context[HotRunnerConfig] = new HotRunnerConfig(); context[HotRunnerConfig] = new HotRunnerConfig();
await runner.run(args); return Chain.capture/*<Future<Null>>*/(() async {
_exit(0); await runner.run(args);
}, onError: (dynamic error, Chain chain) { _exit(0);
if (error is UsageException) { }, onError: (dynamic error, Chain chain) {
stderr.writeln(error.message); if (error is UsageException) {
stderr.writeln();
stderr.writeln(
"Run 'flutter -h' (or 'flutter <command> -h') for available "
"flutter commands and options."
);
// Argument error exit code.
_exit(64);
} else if (error is ToolExit) {
if (error.message != null)
stderr.writeln(error.message); stderr.writeln(error.message);
if (verbose) {
stderr.writeln();
stderr.writeln(chain.terse.toString());
stderr.writeln(); stderr.writeln();
} stderr.writeln(
_exit(error.exitCode ?? 1); "Run 'flutter -h' (or 'flutter <command> -h') for available "
} else if (error is ProcessExit) { "flutter commands and options."
// We've caught an exit code. );
_exit(error.exitCode); // Argument error exit code.
} else { _exit(64);
// We've crashed; emit a log report. } else if (error is ToolExit) {
stderr.writeln(); if (error.message != null)
stderr.writeln(error.message);
flutterUsage.sendException(error, chain); if (verbose) {
stderr.writeln();
if (isRunningOnBot) { stderr.writeln(chain.terse.toString());
// Print the stack trace on the bots - don't write a crash report. stderr.writeln();
stderr.writeln('$error'); }
stderr.writeln(chain.terse.toString()); _exit(error.exitCode ?? 1);
_exit(1); } else if (error is ProcessExit) {
// We've caught an exit code.
_exit(error.exitCode);
} else { } else {
if (error is String) // We've crashed; emit a log report.
stderr.writeln('Oops; flutter has exited unexpectedly: "$error".'); stderr.writeln();
else
stderr.writeln('Oops; flutter has exited unexpectedly.'); flutterUsage.sendException(error, chain);
_createCrashReport(args, error, chain).then((File file) { if (isRunningOnBot) {
stderr.writeln( // Print the stack trace on the bots - don't write a crash report.
'Crash report written to ${file.path};\n' stderr.writeln('$error');
'please let us know at https://github.com/flutter/flutter/issues.' stderr.writeln(chain.terse.toString());
);
_exit(1); _exit(1);
}); } else {
if (error is String)
stderr.writeln('Oops; flutter has exited unexpectedly: "$error".');
else
stderr.writeln('Oops; flutter has exited unexpectedly.');
_createCrashReport(args, error, chain).then((File file) {
stderr.writeln(
'Crash report written to ${file.path};\n'
'please let us know at https://github.com/flutter/flutter/issues.'
);
_exit(1);
});
}
} }
} });
}); });
} }
......
...@@ -8,9 +8,12 @@ import 'package:path/path.dart' as path; ...@@ -8,9 +8,12 @@ import 'package:path/path.dart' as path;
import 'package:pub_semver/pub_semver.dart'; import 'package:pub_semver/pub_semver.dart';
import '../base/common.dart'; import '../base/common.dart';
import '../base/context.dart';
import '../base/os.dart'; import '../base/os.dart';
import '../globals.dart'; import '../globals.dart';
AndroidSdk get androidSdk => context[AndroidSdk];
const String kAndroidHome = 'ANDROID_HOME'; const String kAndroidHome = 'ANDROID_HOME';
// Android SDK layout: // Android SDK layout:
......
...@@ -7,6 +7,7 @@ import 'dart:io'; ...@@ -7,6 +7,7 @@ import 'dart:io';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
import 'package:xml/xml.dart' as xml; import 'package:xml/xml.dart' as xml;
import 'android/android_sdk.dart';
import 'android/gradle.dart'; import 'android/gradle.dart';
import 'base/os.dart' show os; import 'base/os.dart' show os;
import 'base/process.dart'; import 'base/process.dart';
......
...@@ -4,16 +4,11 @@ ...@@ -4,16 +4,11 @@
import 'dart:async'; import 'dart:async';
final AppContext _defaultContext = new AppContext();
typedef void ErrorHandler(dynamic error, StackTrace stackTrace); typedef void ErrorHandler(dynamic error, StackTrace stackTrace);
/// A singleton for application functionality. This singleton can be different /// A singleton for application functionality. This singleton can be different
/// on a per-Zone basis. /// on a per-Zone basis.
AppContext get context { AppContext get context => Zone.current['context'];
AppContext currentContext = Zone.current['context'];
return currentContext == null ? _defaultContext : currentContext;
}
class AppContext { class AppContext {
Map<Type, dynamic> _instances = <Type, dynamic>{}; Map<Type, dynamic> _instances = <Type, dynamic>{};
...@@ -44,18 +39,15 @@ class AppContext { ...@@ -44,18 +39,15 @@ class AppContext {
void operator[]=(Type type, dynamic instance) => setVariable(type, instance); void operator[]=(Type type, dynamic instance) => setVariable(type, instance);
AppContext _calcParent(Zone zone) { AppContext _calcParent(Zone zone) {
if (this == _defaultContext)
return null;
Zone parentZone = zone.parent; Zone parentZone = zone.parent;
if (parentZone == null) if (parentZone == null)
return _defaultContext; return null;
AppContext deps = parentZone['context']; AppContext deps = parentZone['context'];
if (deps == this) { if (deps == this) {
return _calcParent(parentZone); return _calcParent(parentZone);
} else { } else {
return deps != null ? deps : _defaultContext; return deps;
} }
} }
......
...@@ -13,11 +13,11 @@ import 'process.dart'; ...@@ -13,11 +13,11 @@ import 'process.dart';
/// Returns [OperatingSystemUtils] active in the current app context (i.e. zone). /// Returns [OperatingSystemUtils] active in the current app context (i.e. zone).
OperatingSystemUtils get os { OperatingSystemUtils get os {
return context[OperatingSystemUtils] ?? (context[OperatingSystemUtils] = new OperatingSystemUtils._()); return context[OperatingSystemUtils] ?? (context[OperatingSystemUtils] = new OperatingSystemUtils());
} }
abstract class OperatingSystemUtils { abstract class OperatingSystemUtils {
factory OperatingSystemUtils._() { factory OperatingSystemUtils() {
if (Platform.isWindows) { if (Platform.isWindows) {
return new _WindowsUtils(); return new _WindowsUtils();
} else { } else {
......
...@@ -6,6 +6,7 @@ import 'dart:io'; ...@@ -6,6 +6,7 @@ import 'dart:io';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
import 'base/context.dart';
import 'base/utils.dart'; import 'base/utils.dart';
import 'globals.dart'; import 'globals.dart';
...@@ -118,6 +119,11 @@ HostPlatform getCurrentHostPlatform() { ...@@ -118,6 +119,11 @@ HostPlatform getCurrentHostPlatform() {
/// Returns the top-level build output directory. /// Returns the top-level build output directory.
String getBuildDirectory() { String getBuildDirectory() {
// TODO(johnmccutchan): Stop calling this function as part of setting
// up command line argument processing.
if (context == null)
return 'build';
String buildDir = config.getValue('build-dir') ?? 'build'; String buildDir = config.getValue('build-dir') ?? 'build';
if (path.isAbsolute(buildDir)) { if (path.isAbsolute(buildDir)) {
throw new Exception( throw new Exception(
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import 'dart:async'; import 'dart:async';
import '../globals.dart'; import '../globals.dart';
import '../usage.dart';
import '../runner/flutter_command.dart'; import '../runner/flutter_command.dart';
class ConfigCommand extends FlutterCommand { class ConfigCommand extends FlutterCommand {
......
...@@ -12,6 +12,7 @@ import '../base/common.dart'; ...@@ -12,6 +12,7 @@ import '../base/common.dart';
import '../base/utils.dart'; import '../base/utils.dart';
import '../cache.dart'; import '../cache.dart';
import '../dart/pub.dart'; import '../dart/pub.dart';
import '../doctor.dart';
import '../globals.dart'; import '../globals.dart';
import '../runner/flutter_command.dart'; import '../runner/flutter_command.dart';
import '../template.dart'; import '../template.dart';
......
...@@ -7,6 +7,7 @@ import 'dart:async'; ...@@ -7,6 +7,7 @@ import 'dart:async';
import '../base/common.dart'; import '../base/common.dart';
import '../base/utils.dart'; import '../base/utils.dart';
import '../device.dart'; import '../device.dart';
import '../doctor.dart';
import '../globals.dart'; import '../globals.dart';
import '../runner/flutter_command.dart'; import '../runner/flutter_command.dart';
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
import 'dart:async'; import 'dart:async';
import '../globals.dart'; import '../doctor.dart';
import '../runner/flutter_command.dart'; import '../runner/flutter_command.dart';
class DoctorCommand extends FlutterCommand { class DoctorCommand extends FlutterCommand {
......
...@@ -7,6 +7,7 @@ import 'dart:async'; ...@@ -7,6 +7,7 @@ import 'dart:async';
import '../base/common.dart'; import '../base/common.dart';
import '../base/os.dart'; import '../base/os.dart';
import '../base/process.dart'; import '../base/process.dart';
import '../doctor.dart';
import '../globals.dart'; import '../globals.dart';
import '../runner/flutter_command.dart'; import '../runner/flutter_command.dart';
......
...@@ -7,9 +7,10 @@ import 'dart:async'; ...@@ -7,9 +7,10 @@ import 'dart:async';
import '../base/common.dart'; import '../base/common.dart';
import '../base/os.dart'; import '../base/os.dart';
import '../base/process.dart'; import '../base/process.dart';
import '../cache.dart';
import '../dart/pub.dart'; import '../dart/pub.dart';
import '../dart/summary.dart'; import '../dart/summary.dart';
import '../cache.dart'; import '../doctor.dart';
import '../globals.dart'; import '../globals.dart';
import '../runner/flutter_command.dart'; import '../runner/flutter_command.dart';
import '../version.dart'; import '../version.dart';
......
...@@ -9,6 +9,7 @@ import 'dart:math' as math; ...@@ -9,6 +9,7 @@ import 'dart:math' as math;
import 'android/android_device.dart'; import 'android/android_device.dart';
import 'application_package.dart'; import 'application_package.dart';
import 'base/common.dart'; import 'base/common.dart';
import 'base/context.dart';
import 'base/os.dart'; import 'base/os.dart';
import 'base/utils.dart'; import 'base/utils.dart';
import 'build_info.dart'; import 'build_info.dart';
...@@ -16,6 +17,8 @@ import 'globals.dart'; ...@@ -16,6 +17,8 @@ import 'globals.dart';
import 'ios/devices.dart'; import 'ios/devices.dart';
import 'ios/simulators.dart'; import 'ios/simulators.dart';
DeviceManager get deviceManager => context[DeviceManager];
/// A class to get all available devices. /// A class to get all available devices.
class DeviceManager { class DeviceManager {
/// Constructing DeviceManagers is cheap; they only do expensive work if some /// Constructing DeviceManagers is cheap; they only do expensive work if some
......
...@@ -9,11 +9,14 @@ import 'package:path/path.dart' as path; ...@@ -9,11 +9,14 @@ import 'package:path/path.dart' as path;
import 'android/android_workflow.dart'; import 'android/android_workflow.dart';
import 'base/common.dart'; import 'base/common.dart';
import 'base/context.dart';
import 'device.dart'; import 'device.dart';
import 'globals.dart'; import 'globals.dart';
import 'ios/ios_workflow.dart'; import 'ios/ios_workflow.dart';
import 'version.dart'; import 'version.dart';
Doctor get doctor => context[Doctor];
const Map<String, String> _osNames = const <String, String>{ const Map<String, String> _osNames = const <String, String>{
'macos': 'Mac OS', 'macos': 'Mac OS',
'linux': 'Linux', 'linux': 'Linux',
......
...@@ -2,24 +2,16 @@ ...@@ -2,24 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'android/android_sdk.dart';
import 'base/config.dart'; import 'base/config.dart';
import 'base/context.dart'; import 'base/context.dart';
import 'base/logger.dart'; import 'base/logger.dart';
import 'cache.dart'; import 'cache.dart';
import 'device.dart';
import 'doctor.dart';
import 'toolchain.dart'; import 'toolchain.dart';
import 'usage.dart';
DeviceManager get deviceManager => context[DeviceManager];
Logger get logger => context[Logger]; Logger get logger => context[Logger];
AndroidSdk get androidSdk => context[AndroidSdk];
Cache get cache => Cache.instance; Cache get cache => Cache.instance;
Config get config => Config.instance; Config get config => Config.instance;
Doctor get doctor => context[Doctor];
ToolConfiguration get tools => ToolConfiguration.instance; ToolConfiguration get tools => ToolConfiguration.instance;
Usage get flutterUsage => Usage.instance;
/// Display an error level message to the user. Commands should use this if they /// Display an error level message to the user. Commands should use this if they
/// fail in some way. /// fail in some way.
......
...@@ -24,6 +24,7 @@ import 'globals.dart'; ...@@ -24,6 +24,7 @@ import 'globals.dart';
import 'resident_runner.dart'; import 'resident_runner.dart';
import 'toolchain.dart'; import 'toolchain.dart';
import 'vmservice.dart'; import 'vmservice.dart';
import 'usage.dart';
class HotRunnerConfig { class HotRunnerConfig {
/// Should the hot runner compute the minimal Dart dependencies? /// Should the hot runner compute the minimal Dart dependencies?
......
...@@ -11,6 +11,7 @@ import '../base/os.dart'; ...@@ -11,6 +11,7 @@ import '../base/os.dart';
import '../base/process.dart'; import '../base/process.dart';
import '../build_info.dart'; import '../build_info.dart';
import '../device.dart'; import '../device.dart';
import '../doctor.dart';
import '../globals.dart'; import '../globals.dart';
import '../protocol_discovery.dart'; import '../protocol_discovery.dart';
import 'mac.dart'; import 'mac.dart';
......
...@@ -14,6 +14,7 @@ import '../build_info.dart'; ...@@ -14,6 +14,7 @@ import '../build_info.dart';
import '../dart/package_map.dart'; import '../dart/package_map.dart';
import '../dart/pub.dart'; import '../dart/pub.dart';
import '../device.dart'; import '../device.dart';
import '../doctor.dart';
import '../flx.dart' as flx; import '../flx.dart' as flx;
import '../globals.dart'; import '../globals.dart';
import '../usage.dart'; import '../usage.dart';
......
...@@ -15,8 +15,10 @@ import '../base/logger.dart'; ...@@ -15,8 +15,10 @@ import '../base/logger.dart';
import '../base/process.dart'; import '../base/process.dart';
import '../cache.dart'; import '../cache.dart';
import '../dart/package_map.dart'; import '../dart/package_map.dart';
import '../device.dart';
import '../globals.dart'; import '../globals.dart';
import '../toolchain.dart'; import '../toolchain.dart';
import '../usage.dart';
import '../version.dart'; import '../version.dart';
const String kFlutterRootEnvironmentVariableName = 'FLUTTER_ROOT'; // should point to //flutter/ (root of flutter/flutter repo) const String kFlutterRootEnvironmentVariableName = 'FLUTTER_ROOT'; // should point to //flutter/ (root of flutter/flutter repo)
......
...@@ -10,6 +10,7 @@ import 'package:path/path.dart' as path; ...@@ -10,6 +10,7 @@ import 'package:path/path.dart' as path;
import 'package:yaml/yaml.dart'; import 'package:yaml/yaml.dart';
import 'dart/package_map.dart'; import 'dart/package_map.dart';
import 'android/android_sdk.dart';
import 'globals.dart'; import 'globals.dart';
const String _kFlutterManifestPath = 'flutter.yaml'; const String _kFlutterManifestPath = 'flutter.yaml';
......
...@@ -16,6 +16,8 @@ import 'version.dart'; ...@@ -16,6 +16,8 @@ import 'version.dart';
const String _kFlutterUA = 'UA-67589403-6'; const String _kFlutterUA = 'UA-67589403-6';
Usage get flutterUsage => Usage.instance;
class Usage { class Usage {
/// Create a new Usage instance; [versionOverride] is used for testing. /// Create a new Usage instance; [versionOverride] is used for testing.
Usage({ String settingsName: 'flutter', String versionOverride }) { Usage({ String settingsName: 'flutter', String versionOverride }) {
......
...@@ -9,7 +9,6 @@ import 'package:flutter_tools/src/cache.dart'; ...@@ -9,7 +9,6 @@ import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/create.dart'; import 'package:flutter_tools/src/commands/create.dart';
import 'package:flutter_tools/src/commands/config.dart'; import 'package:flutter_tools/src/commands/config.dart';
import 'package:flutter_tools/src/commands/doctor.dart'; import 'package:flutter_tools/src/commands/doctor.dart';
import 'package:flutter_tools/src/globals.dart';
import 'package:flutter_tools/src/usage.dart'; import 'package:flutter_tools/src/usage.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
...@@ -19,16 +18,13 @@ import 'src/context.dart'; ...@@ -19,16 +18,13 @@ import 'src/context.dart';
void main() { void main() {
group('analytics', () { group('analytics', () {
Directory temp; Directory temp;
bool wasEnabled;
setUp(() { setUp(() {
Cache.flutterRoot = '../..'; Cache.flutterRoot = '../..';
wasEnabled = flutterUsage.enabled;
temp = Directory.systemTemp.createTempSync('flutter_tools'); temp = Directory.systemTemp.createTempSync('flutter_tools');
}); });
tearDown(() { tearDown(() {
flutterUsage.enabled = wasEnabled;
temp.deleteSync(recursive: true); temp.deleteSync(recursive: true);
}); });
......
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
import 'dart:io'; import 'dart:io';
import 'package:flutter_tools/src/base/os.dart';
import 'package:flutter_tools/src/commands/analyze.dart'; import 'package:flutter_tools/src/commands/analyze.dart';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
import 'package:test/test.dart'; import 'package:test/test.dart';
...@@ -26,7 +25,6 @@ void main() { ...@@ -26,7 +25,6 @@ void main() {
group('analyze', () { group('analyze', () {
testUsingContext('flutter analyze with two files with the same name', () async { testUsingContext('flutter analyze with two files with the same name', () async {
File dartFileA = new File(path.join(tempDir.path, 'a.dart')); File dartFileA = new File(path.join(tempDir.path, 'a.dart'));
dartFileA.parent.createSync(); dartFileA.parent.createSync();
dartFileA.writeAsStringSync('library test;'); dartFileA.writeAsStringSync('library test;');
...@@ -41,8 +39,6 @@ void main() { ...@@ -41,8 +39,6 @@ void main() {
expect(testLogger.statusText, startsWith('Analyzing 2 files...\nNo analyzer warnings!')); expect(testLogger.statusText, startsWith('Analyzing 2 files...\nNo analyzer warnings!'));
}); });
}, overrides: <Type, dynamic>{
OperatingSystemUtils: os
}); });
}); });
} }
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
import 'dart:io'; import 'dart:io';
import 'src/context.dart';
import 'package:flutter_tools/src/base/os.dart'; import 'package:flutter_tools/src/base/os.dart';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
import 'package:test/test.dart'; import 'package:test/test.dart';
...@@ -20,7 +22,7 @@ void main() { ...@@ -20,7 +22,7 @@ void main() {
temp.deleteSync(recursive: true); temp.deleteSync(recursive: true);
}); });
test('makeExecutable', () { testUsingContext('makeExecutable', () async {
File file = new File(path.join(temp.path, 'foo.script')); File file = new File(path.join(temp.path, 'foo.script'));
file.writeAsStringSync('hello world'); file.writeAsStringSync('hello world');
os.makeExecutable(file); os.makeExecutable(file);
...@@ -31,6 +33,8 @@ void main() { ...@@ -31,6 +33,8 @@ void main() {
// rwxr--r-- // rwxr--r--
expect(mode.substring(0, 3), endsWith('x')); expect(mode.substring(0, 3), endsWith('x'));
} }
}, overrides: <Type, dynamic> {
OperatingSystemUtils: new OperatingSystemUtils(),
}); });
}); });
} }
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