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