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'; ...@@ -6,10 +6,14 @@ import 'package:meta/meta.dart';
import 'runner.dart' as runner; import 'runner.dart' as runner;
import 'src/base/context.dart'; import 'src/base/context.dart';
import 'src/base/file_system.dart';
import 'src/base/io.dart'; import 'src/base/io.dart';
import 'src/base/logger.dart'; import 'src/base/logger.dart';
import 'src/base/platform.dart';
import 'src/base/template.dart'; import 'src/base/template.dart';
import 'src/base/terminal.dart'; import 'src/base/terminal.dart';
import 'src/base/user_messages.dart';
import 'src/cache.dart';
import 'src/commands/analyze.dart'; import 'src/commands/analyze.dart';
import 'src/commands/assemble.dart'; import 'src/commands/assemble.dart';
import 'src/commands/attach.dart'; import 'src/commands/attach.dart';
...@@ -74,6 +78,15 @@ Future<void> main(List<String> args) async { ...@@ -74,6 +78,15 @@ Future<void> main(List<String> args) async {
final bool runMachine = (args.contains('--machine') && args.contains('run')) || final bool runMachine = (args.contains('--machine') && args.contains('run')) ||
(args.contains('--machine') && args.contains('attach')); (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>[ await runner.run(args, () => <FlutterCommand>[
AnalyzeCommand( AnalyzeCommand(
verboseHelp: verboseHelp, verboseHelp: verboseHelp,
......
...@@ -217,7 +217,6 @@ class Cache { ...@@ -217,7 +217,6 @@ class Cache {
// Initialized by FlutterCommandRunner on startup. // Initialized by FlutterCommandRunner on startup.
static String flutterRoot; static String flutterRoot;
/// Determine the absolute and normalized path for the root of the current /// Determine the absolute and normalized path for the root of the current
/// Flutter checkout. /// Flutter checkout.
/// ///
......
...@@ -6,7 +6,6 @@ import 'package:args/args.dart'; ...@@ -6,7 +6,6 @@ import 'package:args/args.dart';
import 'package:args/command_runner.dart'; import 'package:args/command_runner.dart';
import 'package:completion/completion.dart'; import 'package:completion/completion.dart';
import 'package:file/file.dart'; import 'package:file/file.dart';
import 'package:meta/meta.dart';
import '../artifacts.dart'; import '../artifacts.dart';
import '../base/common.dart'; import '../base/common.dart';
...@@ -96,13 +95,6 @@ class FlutterCommandRunner extends CommandRunner<void> { ...@@ -96,13 +95,6 @@ class FlutterCommandRunner extends CommandRunner<void> {
argParser.addOption('packages', argParser.addOption('packages',
hide: !showPackagesCommand, hide: !showPackagesCommand,
help: 'Path to your ".packages" file.\n$packagesHelp'); 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) { if (verboseHelp) {
argParser.addSeparator('Local build selection options (not normally required):'); argParser.addSeparator('Local build selection options (not normally required):');
} }
...@@ -112,8 +104,7 @@ class FlutterCommandRunner extends CommandRunner<void> { ...@@ -112,8 +104,7 @@ class FlutterCommandRunner extends CommandRunner<void> {
help: 'Path to your engine src directory, if you are building Flutter locally.\n' help: 'Path to your engine src directory, if you are building Flutter locally.\n'
'Defaults to \$$kFlutterEngineEnvironmentVariableName if set, otherwise defaults to ' 'Defaults to \$$kFlutterEngineEnvironmentVariableName if set, otherwise defaults to '
'the path given in your pubspec.yaml dependency_overrides for $kFlutterEnginePackageName, ' '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 ' 'if any.');
'--flutter-root option.');
argParser.addOption('local-engine', argParser.addOption('local-engine',
hide: !verboseHelp, hide: !verboseHelp,
...@@ -225,15 +216,6 @@ class FlutterCommandRunner extends CommandRunner<void> { ...@@ -225,15 +216,6 @@ class FlutterCommandRunner extends CommandRunner<void> {
FlutterTesterDevices.showFlutterTesterDevice = true; 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. // Set up the tooling configuration.
final EngineBuildPaths engineBuildPaths = await globals.localEngineLocator.findEnginePath( final EngineBuildPaths engineBuildPaths = await globals.localEngineLocator.findEnginePath(
topLevelResults['local-engine-src-path'] as String, topLevelResults['local-engine-src-path'] as String,
...@@ -304,15 +286,6 @@ class FlutterCommandRunner extends CommandRunner<void> { ...@@ -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. /// Get the root directories of the repo - the directories containing Dart packages.
List<String> getRepoRoots() { List<String> getRepoRoots() {
final String root = globals.fs.path.absolute(Cache.flutterRoot); final String root = globals.fs.path.absolute(Cache.flutterRoot);
......
...@@ -11,7 +11,6 @@ import 'package:flutter_tools/src/build_system/build_system.dart'; ...@@ -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/cache.dart';
import 'package:flutter_tools/src/commands/assemble.dart'; import 'package:flutter_tools/src/commands/assemble.dart';
import 'package:flutter_tools/src/convert.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:mockito/mockito.dart';
import 'package:flutter_tools/src/globals.dart' as globals; import 'package:flutter_tools/src/globals.dart' as globals;
...@@ -20,8 +19,9 @@ import '../../src/context.dart'; ...@@ -20,8 +19,9 @@ import '../../src/context.dart';
import '../../src/testbed.dart'; import '../../src/testbed.dart';
void main() { void main() {
FlutterCommandRunner.initFlutterRoot();
Cache.disableLocking(); Cache.disableLocking();
Cache.flutterRoot = '';
final Testbed testbed = Testbed(overrides: <Type, Generator>{ final Testbed testbed = Testbed(overrides: <Type, Generator>{
BuildSystem: () => MockBuildSystem(), BuildSystem: () => MockBuildSystem(),
Cache: () => FakeCache(), Cache: () => FakeCache(),
......
...@@ -20,6 +20,7 @@ void main() { ...@@ -20,6 +20,7 @@ void main() {
setUpAll(() { setUpAll(() {
Cache.disableLocking(); Cache.disableLocking();
Cache.flutterRoot = 'flutter';
}); });
setUp(() { setUp(() {
...@@ -56,16 +57,16 @@ void main() { ...@@ -56,16 +57,16 @@ void main() {
final CreateCommand command = CreateCommand(); final CreateCommand command = CreateCommand();
final CommandRunner<void> runner = createTestCommandRunner(command); 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')); 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')); 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')); 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')); expect(await command.usageValues, containsPair(CustomDimensions.commandCreateProjectType, 'plugin'));
})); }));
...@@ -74,13 +75,12 @@ void main() { ...@@ -74,13 +75,12 @@ void main() {
final CommandRunner<void> runner = createTestCommandRunner(command); final CommandRunner<void> runner = createTestCommandRunner(command);
await runner.run(<String>[ await runner.run(<String>[
'create', '--flutter-root=flutter', '--no-pub', '--template=app', 'testy']); 'create', '--no-pub', '--template=app', 'testy']);
expect(await command.usageValues, expect(await command.usageValues,
containsPair(CustomDimensions.commandCreateIosLanguage, 'swift')); containsPair(CustomDimensions.commandCreateIosLanguage, 'swift'));
await runner.run(<String>[ await runner.run(<String>[
'create', 'create',
'--flutter-root=flutter',
'--no-pub', '--no-pub',
'--template=app', '--template=app',
'--ios-language=objc', '--ios-language=objc',
...@@ -95,13 +95,12 @@ void main() { ...@@ -95,13 +95,12 @@ void main() {
final CreateCommand command = CreateCommand(); final CreateCommand command = CreateCommand();
final CommandRunner<void> runner = createTestCommandRunner(command); 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, expect(await command.usageValues,
containsPair(CustomDimensions.commandCreateAndroidLanguage, 'kotlin')); containsPair(CustomDimensions.commandCreateAndroidLanguage, 'kotlin'));
await runner.run(<String>[ await runner.run(<String>[
'create', 'create',
'--flutter-root=flutter',
'--no-pub', '--no-pub',
'--template=app', '--template=app',
'--android-language=java', '--android-language=java',
......
...@@ -81,10 +81,10 @@ void main() { ...@@ -81,10 +81,10 @@ void main() {
List<String> unexpectedPaths = const <String>[], List<String> unexpectedPaths = const <String>[],
}) async { }) async {
dir ??= tempDir; dir ??= tempDir;
Cache.flutterRoot = tempDir.absolute.path;
final IdeConfigCommand command = IdeConfigCommand(); final IdeConfigCommand command = IdeConfigCommand();
final CommandRunner<void> runner = createTestCommandRunner(command); final CommandRunner<void> runner = createTestCommandRunner(command);
await runner.run(<String>[ await runner.run(<String>[
'--flutter-root=${tempDir.absolute.path}',
'ide-config', 'ide-config',
...args, ...args,
]); ]);
......
...@@ -389,74 +389,6 @@ void main() { ...@@ -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 { testUsingContext('should only request artifacts corresponding to connected devices', () async {
when(mockDeviceManager.getDevices()).thenAnswer((Invocation invocation) { when(mockDeviceManager.getDevices()).thenAnswer((Invocation invocation) {
return Future<List<Device>>.value(<Device>[ return Future<List<Device>>.value(<Device>[
......
...@@ -20,8 +20,7 @@ import 'package:process/process.dart'; ...@@ -20,8 +20,7 @@ import 'package:process/process.dart';
import '../../src/common.dart'; import '../../src/common.dart';
import '../../src/context.dart'; import '../../src/context.dart';
final Platform _kNoColorTerminalPlatform = FakePlatform( final Platform _kNoColorTerminalPlatform = FakePlatform(stdoutSupportsAnsi: false);
stdoutSupportsAnsi: false);
void main() { void main() {
String analyzerSeparator; String analyzerSeparator;
...@@ -45,7 +44,6 @@ void main() { ...@@ -45,7 +44,6 @@ void main() {
int exitCode = 0, int exitCode = 0,
}) async { }) async {
try { try {
arguments.insert(0, '--flutter-root=${Cache.flutterRoot}');
await createTestCommandRunner(command).run(arguments); await createTestCommandRunner(command).run(arguments);
expect(toolExit, isFalse, reason: 'Expected ToolExit exception'); expect(toolExit, isFalse, reason: 'Expected ToolExit exception');
} on ToolExit catch (e) { } on ToolExit catch (e) {
...@@ -112,10 +110,7 @@ void main() { ...@@ -112,10 +110,7 @@ void main() {
platform = const LocalPlatform(); platform = const LocalPlatform();
terminal = AnsiTerminal(platform: platform, stdio: Stdio()); terminal = AnsiTerminal(platform: platform, stdio: Stdio());
fileSystem = LocalFileSystem.instance; fileSystem = LocalFileSystem.instance;
logger = BufferLogger( logger = BufferLogger.test();
outputPreferences: OutputPreferences.test(),
terminal: terminal,
);
analyzerSeparator = platform.isWindows ? '-' : '•'; analyzerSeparator = platform.isWindows ? '-' : '•';
artifacts = CachedArtifacts( artifacts = CachedArtifacts(
cache: globals.cache, cache: globals.cache,
......
...@@ -2283,7 +2283,7 @@ Future<void> _createProject( ...@@ -2283,7 +2283,7 @@ Future<void> _createProject(
List<String> expectedPaths, { List<String> expectedPaths, {
List<String> unexpectedPaths = const <String>[], List<String> unexpectedPaths = const <String>[],
}) async { }) async {
Cache.flutterRoot = '../../..'; Cache.flutterRoot = '../..';
final CreateCommand command = CreateCommand(); final CreateCommand command = CreateCommand();
final CommandRunner<void> runner = createTestCommandRunner(command); final CommandRunner<void> runner = createTestCommandRunner(command);
await runner.run(<String>[ await runner.run(<String>[
......
...@@ -8,6 +8,8 @@ import 'package:args/args.dart'; ...@@ -8,6 +8,8 @@ import 'package:args/args.dart';
import 'package:args/command_runner.dart'; import 'package:args/command_runner.dart';
import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/platform.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/convert.dart';
import 'package:flutter_tools/src/doctor.dart'; import 'package:flutter_tools/src/doctor.dart';
import 'package:vm_service/vm_service.dart' as vm_service; import 'package:vm_service/vm_service.dart' as vm_service;
...@@ -401,7 +403,16 @@ class TestFlutterCommandRunner extends FlutterCommandRunner { ...@@ -401,7 +403,16 @@ class TestFlutterCommandRunner extends FlutterCommandRunner {
overrides: contextOverrides.map<Type, Generator>((Type type, dynamic value) { overrides: contextOverrides.map<Type, Generator>((Type type, dynamic value) {
return MapEntry<Type, Generator>(type, () => 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