Unverified Commit dd8820bc authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tool] initialize flutter root in executable (#69549)

initialize the flutter root as early as possible. This allows all interfaces to be normally injected into commands, even if those objects might read from the flutter root.
parent bc2a4a64
......@@ -6,10 +6,14 @@ import 'package:meta/meta.dart';
import 'runner.dart' as runner;
import 'src/base/context.dart';
import 'src/base/file_system.dart';
import 'src/base/io.dart';
import 'src/base/logger.dart';
import 'src/base/platform.dart';
import 'src/base/template.dart';
import 'src/base/terminal.dart';
import 'src/base/user_messages.dart';
import 'src/cache.dart';
import 'src/commands/analyze.dart';
import 'src/commands/assemble.dart';
import 'src/commands/attach.dart';
......@@ -74,6 +78,15 @@ Future<void> main(List<String> args) async {
final bool runMachine = (args.contains('--machine') && args.contains('run')) ||
(args.contains('--machine') && args.contains('attach'));
// Cache.flutterRoot must be set early because other features use it (e.g.
// enginePath's initializer uses it). This can only work with the real
// instances of the platform or filesystem, so just use those.
Cache.flutterRoot = Cache.defaultFlutterRoot(
platform: const LocalPlatform(),
fileSystem: LocalFileSystem.instance,
userMessages: UserMessages(),
);
await runner.run(args, () => <FlutterCommand>[
AnalyzeCommand(
verboseHelp: verboseHelp,
......
......@@ -217,7 +217,6 @@ class Cache {
// Initialized by FlutterCommandRunner on startup.
static String flutterRoot;
/// Determine the absolute and normalized path for the root of the current
/// Flutter checkout.
///
......
......@@ -6,7 +6,6 @@ import 'package:args/args.dart';
import 'package:args/command_runner.dart';
import 'package:completion/completion.dart';
import 'package:file/file.dart';
import 'package:meta/meta.dart';
import '../artifacts.dart';
import '../base/common.dart';
......@@ -96,13 +95,6 @@ class FlutterCommandRunner extends CommandRunner<void> {
argParser.addOption('packages',
hide: !showPackagesCommand,
help: 'Path to your ".packages" file.\n$packagesHelp');
argParser.addOption('flutter-root',
hide: !verboseHelp,
help: 'The root directory of the Flutter repository.\n'
'Defaults to \$$kFlutterRootEnvironmentVariableName if set, otherwise uses the parent '
'of the directory that the "flutter" script itself is in.');
if (verboseHelp) {
argParser.addSeparator('Local build selection options (not normally required):');
}
......@@ -112,8 +104,7 @@ class FlutterCommandRunner extends CommandRunner<void> {
help: 'Path to your engine src directory, if you are building Flutter locally.\n'
'Defaults to \$$kFlutterEngineEnvironmentVariableName if set, otherwise defaults to '
'the path given in your pubspec.yaml dependency_overrides for $kFlutterEnginePackageName, '
'if any, or, failing that, tries to guess at the location based on the value of the '
'--flutter-root option.');
'if any.');
argParser.addOption('local-engine',
hide: !verboseHelp,
......@@ -225,15 +216,6 @@ class FlutterCommandRunner extends CommandRunner<void> {
FlutterTesterDevices.showFlutterTesterDevice = true;
}
// We must set Cache.flutterRoot early because other features use it (e.g.
// enginePath's initializer uses it).
final String flutterRoot = topLevelResults['flutter-root'] as String ?? Cache.defaultFlutterRoot(
platform: globals.platform,
fileSystem: globals.fs,
userMessages: globals.userMessages,
);
Cache.flutterRoot = globals.fs.path.normalize(globals.fs.path.absolute(flutterRoot));
// Set up the tooling configuration.
final EngineBuildPaths engineBuildPaths = await globals.localEngineLocator.findEnginePath(
topLevelResults['local-engine-src-path'] as String,
......@@ -304,15 +286,6 @@ class FlutterCommandRunner extends CommandRunner<void> {
);
}
@visibleForTesting
static void initFlutterRoot() {
Cache.flutterRoot ??= Cache.defaultFlutterRoot(
platform: globals.platform,
fileSystem: globals.fs,
userMessages: globals.userMessages,
);
}
/// Get the root directories of the repo - the directories containing Dart packages.
List<String> getRepoRoots() {
final String root = globals.fs.path.absolute(Cache.flutterRoot);
......
......@@ -11,7 +11,6 @@ import 'package:flutter_tools/src/build_system/build_system.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/assemble.dart';
import 'package:flutter_tools/src/convert.dart';
import 'package:flutter_tools/src/runner/flutter_command_runner.dart';
import 'package:mockito/mockito.dart';
import 'package:flutter_tools/src/globals.dart' as globals;
......@@ -20,8 +19,9 @@ import '../../src/context.dart';
import '../../src/testbed.dart';
void main() {
FlutterCommandRunner.initFlutterRoot();
Cache.disableLocking();
Cache.flutterRoot = '';
final Testbed testbed = Testbed(overrides: <Type, Generator>{
BuildSystem: () => MockBuildSystem(),
Cache: () => FakeCache(),
......
......@@ -20,6 +20,7 @@ void main() {
setUpAll(() {
Cache.disableLocking();
Cache.flutterRoot = 'flutter';
});
setUp(() {
......@@ -56,16 +57,16 @@ void main() {
final CreateCommand command = CreateCommand();
final CommandRunner<void> runner = createTestCommandRunner(command);
await runner.run(<String>['create', '--flutter-root=flutter', '--no-pub', '--template=module', 'testy']);
await runner.run(<String>['create', '--no-pub', '--template=module', 'testy']);
expect(await command.usageValues, containsPair(CustomDimensions.commandCreateProjectType, 'module'));
await runner.run(<String>['create', '--flutter-root=flutter', '--no-pub', '--template=app', 'testy']);
await runner.run(<String>['create', '--no-pub', '--template=app', 'testy']);
expect(await command.usageValues, containsPair(CustomDimensions.commandCreateProjectType, 'app'));
await runner.run(<String>['create', '--flutter-root=flutter', '--no-pub', '--template=package', 'testy']);
await runner.run(<String>['create', '--no-pub', '--template=package', 'testy']);
expect(await command.usageValues, containsPair(CustomDimensions.commandCreateProjectType, 'package'));
await runner.run(<String>['create', '--flutter-root=flutter', '--no-pub', '--template=plugin', 'testy']);
await runner.run(<String>['create', '--no-pub', '--template=plugin', 'testy']);
expect(await command.usageValues, containsPair(CustomDimensions.commandCreateProjectType, 'plugin'));
}));
......@@ -74,13 +75,12 @@ void main() {
final CommandRunner<void> runner = createTestCommandRunner(command);
await runner.run(<String>[
'create', '--flutter-root=flutter', '--no-pub', '--template=app', 'testy']);
'create', '--no-pub', '--template=app', 'testy']);
expect(await command.usageValues,
containsPair(CustomDimensions.commandCreateIosLanguage, 'swift'));
await runner.run(<String>[
'create',
'--flutter-root=flutter',
'--no-pub',
'--template=app',
'--ios-language=objc',
......@@ -95,13 +95,12 @@ void main() {
final CreateCommand command = CreateCommand();
final CommandRunner<void> runner = createTestCommandRunner(command);
await runner.run(<String>['create', '--flutter-root=flutter', '--no-pub', '--template=app', 'testy']);
await runner.run(<String>['create', '--no-pub', '--template=app', 'testy']);
expect(await command.usageValues,
containsPair(CustomDimensions.commandCreateAndroidLanguage, 'kotlin'));
await runner.run(<String>[
'create',
'--flutter-root=flutter',
'--no-pub',
'--template=app',
'--android-language=java',
......
......@@ -81,10 +81,10 @@ void main() {
List<String> unexpectedPaths = const <String>[],
}) async {
dir ??= tempDir;
Cache.flutterRoot = tempDir.absolute.path;
final IdeConfigCommand command = IdeConfigCommand();
final CommandRunner<void> runner = createTestCommandRunner(command);
await runner.run(<String>[
'--flutter-root=${tempDir.absolute.path}',
'ide-config',
...args,
]);
......
......@@ -389,74 +389,6 @@ void main() {
});
});
group('dart-flags option', () {
RunCommand command;
List<String> args;
MockDeviceManager mockDeviceManager;
setUp(() {
command = TestRunCommand();
args = <String> [
'run',
'--dart-flags', '"--observe"',
'--no-hot',
'--no-pub',
];
mockDeviceManager = MockDeviceManager();
final FakeDevice fakeDevice = FakeDevice();
when(mockDeviceManager.getDevices()).thenAnswer((Invocation invocation) {
return Future<List<Device>>.value(<Device>[fakeDevice]);
});
when(mockDeviceManager.findTargetDevices(any, timeout: anyNamed('timeout'))).thenAnswer(
(Invocation invocation) => Future<List<Device>>.value(<Device>[fakeDevice])
);
});
testUsingContext('is populated in debug mode', () async {
// FakeDevice.startApp checks that --dart-flags doesn't get dropped and
// throws ToolExit with FakeDevice.kSuccess if the flag is populated.
try {
await createTestCommandRunner(command).run(args);
fail('Expect exception');
} on ToolExit catch (e) {
expect(e.exitCode, FakeDevice.kSuccess);
}
}, overrides: <Type, Generator>{
DeviceManager: () => mockDeviceManager,
});
testUsingContext('is populated in profile mode', () async {
args.add('--profile');
// FakeDevice.startApp checks that --dart-flags doesn't get dropped and
// throws ToolExit with FakeDevice.kSuccess if the flag is populated.
try {
await createTestCommandRunner(command).run(args);
fail('Expect exception');
} on ToolExit catch (e) {
expect(e.exitCode, FakeDevice.kSuccess);
}
}, overrides: <Type, Generator>{
DeviceManager: () => mockDeviceManager,
});
testUsingContext('is not populated in release mode', () async {
args.add('--release');
// FakeDevice.startApp checks that --dart-flags *does* get dropped and
// throws ToolExit with FakeDevice.kSuccess if the flag is set to the
// empty string.
try {
await createTestCommandRunner(command).run(args);
fail('Expect exception');
} on ToolExit catch (e) {
expect(e.exitCode, FakeDevice.kSuccess);
}
}, overrides: <Type, Generator>{
DeviceManager: () => mockDeviceManager,
});
});
testUsingContext('should only request artifacts corresponding to connected devices', () async {
when(mockDeviceManager.getDevices()).thenAnswer((Invocation invocation) {
return Future<List<Device>>.value(<Device>[
......
......@@ -20,8 +20,7 @@ import 'package:process/process.dart';
import '../../src/common.dart';
import '../../src/context.dart';
final Platform _kNoColorTerminalPlatform = FakePlatform(
stdoutSupportsAnsi: false);
final Platform _kNoColorTerminalPlatform = FakePlatform(stdoutSupportsAnsi: false);
void main() {
String analyzerSeparator;
......@@ -45,7 +44,6 @@ void main() {
int exitCode = 0,
}) async {
try {
arguments.insert(0, '--flutter-root=${Cache.flutterRoot}');
await createTestCommandRunner(command).run(arguments);
expect(toolExit, isFalse, reason: 'Expected ToolExit exception');
} on ToolExit catch (e) {
......@@ -112,10 +110,7 @@ void main() {
platform = const LocalPlatform();
terminal = AnsiTerminal(platform: platform, stdio: Stdio());
fileSystem = LocalFileSystem.instance;
logger = BufferLogger(
outputPreferences: OutputPreferences.test(),
terminal: terminal,
);
logger = BufferLogger.test();
analyzerSeparator = platform.isWindows ? '-' : '•';
artifacts = CachedArtifacts(
cache: globals.cache,
......
......@@ -2283,7 +2283,7 @@ Future<void> _createProject(
List<String> expectedPaths, {
List<String> unexpectedPaths = const <String>[],
}) async {
Cache.flutterRoot = '../../..';
Cache.flutterRoot = '../..';
final CreateCommand command = CreateCommand();
final CommandRunner<void> runner = createTestCommandRunner(command);
await runner.run(<String>[
......
......@@ -8,6 +8,8 @@ import 'package:args/args.dart';
import 'package:args/command_runner.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/base/user_messages.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/convert.dart';
import 'package:flutter_tools/src/doctor.dart';
import 'package:vm_service/vm_service.dart' as vm_service;
......@@ -401,7 +403,16 @@ class TestFlutterCommandRunner extends FlutterCommandRunner {
overrides: contextOverrides.map<Type, Generator>((Type type, dynamic value) {
return MapEntry<Type, Generator>(type, () => value);
}),
body: () => super.runCommand(topLevelResults),
body: () {
Cache.flutterRoot ??= Cache.defaultFlutterRoot(
platform: globals.platform,
fileSystem: globals.fs,
userMessages: UserMessages(),
);
// For compatibility with tests that set this to a relative path.
Cache.flutterRoot = globals.fs.path.normalize(globals.fs.path.absolute(Cache.flutterRoot));
return super.runCommand(topLevelResults);
}
);
}
}
......
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