Unverified Commit dc68d570 authored by Christopher Fujino's avatar Christopher Fujino Committed by GitHub

Fix flutter run cache (#45267)

parent 943f98d3
...@@ -63,6 +63,9 @@ class DevelopmentArtifact { ...@@ -63,6 +63,9 @@ class DevelopmentArtifact {
static const DevelopmentArtifact flutterRunner = DevelopmentArtifact._('flutter_runner', unstable: true); static const DevelopmentArtifact flutterRunner = DevelopmentArtifact._('flutter_runner', unstable: true);
/// Artifacts required for any development platform. /// Artifacts required for any development platform.
///
/// This does not need to be explicitly returned from requiredArtifacts as
/// it will always be downloaded.
static const DevelopmentArtifact universal = DevelopmentArtifact._('universal'); static const DevelopmentArtifact universal = DevelopmentArtifact._('universal');
/// The values of DevelopmentArtifacts. /// The values of DevelopmentArtifacts.
......
...@@ -64,11 +64,6 @@ class AnalyzeCommand extends FlutterCommand { ...@@ -64,11 +64,6 @@ class AnalyzeCommand extends FlutterCommand {
@override @override
String get description => "Analyze the project's Dart code."; String get description => "Analyze the project's Dart code.";
@override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => const <DevelopmentArtifact>{
DevelopmentArtifact.universal,
};
@override @override
bool get shouldRunPub { bool get shouldRunPub {
// If they're not analyzing the current project. // If they're not analyzing the current project.
......
...@@ -55,7 +55,6 @@ class BuildAarCommand extends BuildSubCommand { ...@@ -55,7 +55,6 @@ class BuildAarCommand extends BuildSubCommand {
@override @override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => <DevelopmentArtifact>{ Future<Set<DevelopmentArtifact>> get requiredArtifacts async => <DevelopmentArtifact>{
DevelopmentArtifact.androidGenSnapshot, DevelopmentArtifact.androidGenSnapshot,
DevelopmentArtifact.universal,
}; };
@override @override
......
...@@ -45,7 +45,6 @@ class BuildApkCommand extends BuildSubCommand { ...@@ -45,7 +45,6 @@ class BuildApkCommand extends BuildSubCommand {
@override @override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => <DevelopmentArtifact>{ Future<Set<DevelopmentArtifact>> get requiredArtifacts async => <DevelopmentArtifact>{
DevelopmentArtifact.androidGenSnapshot, DevelopmentArtifact.androidGenSnapshot,
DevelopmentArtifact.universal,
}; };
@override @override
......
...@@ -38,7 +38,6 @@ class BuildAppBundleCommand extends BuildSubCommand { ...@@ -38,7 +38,6 @@ class BuildAppBundleCommand extends BuildSubCommand {
@override @override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => <DevelopmentArtifact>{ Future<Set<DevelopmentArtifact>> get requiredArtifacts async => <DevelopmentArtifact>{
DevelopmentArtifact.androidGenSnapshot, DevelopmentArtifact.androidGenSnapshot,
DevelopmentArtifact.universal,
}; };
@override @override
......
...@@ -47,7 +47,6 @@ class BuildFuchsiaCommand extends BuildSubCommand { ...@@ -47,7 +47,6 @@ class BuildFuchsiaCommand extends BuildSubCommand {
@override @override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => <DevelopmentArtifact>{ Future<Set<DevelopmentArtifact>> get requiredArtifacts async => <DevelopmentArtifact>{
DevelopmentArtifact.fuchsia, DevelopmentArtifact.fuchsia,
DevelopmentArtifact.universal,
}; };
@override @override
......
...@@ -43,7 +43,6 @@ class BuildIOSCommand extends BuildSubCommand { ...@@ -43,7 +43,6 @@ class BuildIOSCommand extends BuildSubCommand {
@override @override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => const <DevelopmentArtifact>{ Future<Set<DevelopmentArtifact>> get requiredArtifacts async => const <DevelopmentArtifact>{
DevelopmentArtifact.universal,
DevelopmentArtifact.iOS, DevelopmentArtifact.iOS,
}; };
......
...@@ -85,7 +85,6 @@ class BuildIOSFrameworkCommand extends BuildSubCommand { ...@@ -85,7 +85,6 @@ class BuildIOSFrameworkCommand extends BuildSubCommand {
@override @override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => const <DevelopmentArtifact>{ Future<Set<DevelopmentArtifact>> get requiredArtifacts async => const <DevelopmentArtifact>{
DevelopmentArtifact.universal,
DevelopmentArtifact.iOS, DevelopmentArtifact.iOS,
}; };
......
...@@ -30,7 +30,6 @@ class BuildLinuxCommand extends BuildSubCommand { ...@@ -30,7 +30,6 @@ class BuildLinuxCommand extends BuildSubCommand {
@override @override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => <DevelopmentArtifact>{ Future<Set<DevelopmentArtifact>> get requiredArtifacts async => <DevelopmentArtifact>{
DevelopmentArtifact.linux, DevelopmentArtifact.linux,
DevelopmentArtifact.universal,
}; };
@override @override
......
...@@ -30,7 +30,6 @@ class BuildMacosCommand extends BuildSubCommand { ...@@ -30,7 +30,6 @@ class BuildMacosCommand extends BuildSubCommand {
@override @override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => <DevelopmentArtifact>{ Future<Set<DevelopmentArtifact>> get requiredArtifacts async => <DevelopmentArtifact>{
DevelopmentArtifact.macOS, DevelopmentArtifact.macOS,
DevelopmentArtifact.universal,
}; };
@override @override
......
...@@ -30,7 +30,6 @@ class BuildWebCommand extends BuildSubCommand { ...@@ -30,7 +30,6 @@ class BuildWebCommand extends BuildSubCommand {
@override @override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => Future<Set<DevelopmentArtifact>> get requiredArtifacts async =>
const <DevelopmentArtifact>{ const <DevelopmentArtifact>{
DevelopmentArtifact.universal,
DevelopmentArtifact.web, DevelopmentArtifact.web,
}; };
......
...@@ -30,7 +30,6 @@ class BuildWindowsCommand extends BuildSubCommand { ...@@ -30,7 +30,6 @@ class BuildWindowsCommand extends BuildSubCommand {
@override @override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => <DevelopmentArtifact>{ Future<Set<DevelopmentArtifact>> get requiredArtifacts async => <DevelopmentArtifact>{
DevelopmentArtifact.windows, DevelopmentArtifact.windows,
DevelopmentArtifact.universal,
}; };
@override @override
......
...@@ -337,8 +337,6 @@ class CreateCommand extends FlutterCommand { ...@@ -337,8 +337,6 @@ class CreateCommand extends FlutterCommand {
'variable was specified. Unable to find package:flutter.', exitCode: 2); 'variable was specified. Unable to find package:flutter.', exitCode: 2);
} }
await Cache.instance.updateAll(<DevelopmentArtifact>{ DevelopmentArtifact.universal });
final String flutterRoot = fs.path.absolute(Cache.flutterRoot); final String flutterRoot = fs.path.absolute(Cache.flutterRoot);
final String flutterPackagesDirectory = fs.path.join(flutterRoot, 'packages'); final String flutterPackagesDirectory = fs.path.join(flutterRoot, 'packages');
......
...@@ -33,7 +33,6 @@ class DoctorCommand extends FlutterCommand { ...@@ -33,7 +33,6 @@ class DoctorCommand extends FlutterCommand {
@override @override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async { Future<Set<DevelopmentArtifact>> get requiredArtifacts async {
return <DevelopmentArtifact>{ return <DevelopmentArtifact>{
DevelopmentArtifact.universal,
// This is required because we use gen_snapshot to check if the host // This is required because we use gen_snapshot to check if the host
// machine can execute the provided artifacts. See `_genSnapshotRuns` // machine can execute the provided artifacts. See `_genSnapshotRuns`
// in `doctor.dart`. // in `doctor.dart`.
......
...@@ -44,11 +44,6 @@ class FormatCommand extends FlutterCommand { ...@@ -44,11 +44,6 @@ class FormatCommand extends FlutterCommand {
@override @override
final String description = 'Format one or more dart files.'; final String description = 'Format one or more dart files.';
@override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => const <DevelopmentArtifact>{
DevelopmentArtifact.universal,
};
@override @override
String get invocation => '${runner.executableName} $name <one or more paths>'; String get invocation => '${runner.executableName} $name <one or more paths>';
......
...@@ -20,11 +20,6 @@ class GenerateCommand extends FlutterCommand { ...@@ -20,11 +20,6 @@ class GenerateCommand extends FlutterCommand {
@override @override
String get name => 'generate'; String get name => 'generate';
@override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => const <DevelopmentArtifact>{
DevelopmentArtifact.universal,
};
@override @override
Future<FlutterCommandResult> runCommand() async { Future<FlutterCommandResult> runCommand() async {
Cache.releaseLockEarly(); Cache.releaseLockEarly();
......
...@@ -217,8 +217,6 @@ class IdeConfigCommand extends FlutterCommand { ...@@ -217,8 +217,6 @@ class IdeConfigCommand extends FlutterCommand {
throwToolExit('Currently, the only supported IDE is IntelliJ\n$usage', exitCode: 2); throwToolExit('Currently, the only supported IDE is IntelliJ\n$usage', exitCode: 2);
} }
await Cache.instance.updateAll(<DevelopmentArtifact>{ DevelopmentArtifact.universal });
if (boolArg('update-templates')) { if (boolArg('update-templates')) {
_handleTemplateUpdate(); _handleTemplateUpdate();
return null; return null;
......
...@@ -37,11 +37,6 @@ class PackagesCommand extends FlutterCommand { ...@@ -37,11 +37,6 @@ class PackagesCommand extends FlutterCommand {
@override @override
final String description = 'Commands for managing Flutter packages.'; final String description = 'Commands for managing Flutter packages.';
@override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => const <DevelopmentArtifact>{
DevelopmentArtifact.universal,
};
@override @override
Future<FlutterCommandResult> runCommand() async => null; Future<FlutterCommandResult> runCommand() async => null;
} }
......
...@@ -284,10 +284,6 @@ class RunCommand extends RunCommandBase { ...@@ -284,10 +284,6 @@ class RunCommand extends RunCommandBase {
if (!runningWithPrebuiltApplication) { if (!runningWithPrebuiltApplication) {
await super.validateCommand(); await super.validateCommand();
} }
devices = await findAllTargetDevices();
if (devices == null) {
throwToolExit(null);
}
if (deviceManager.hasSpecifiedAllDevices && runningWithPrebuiltApplication) { if (deviceManager.hasSpecifiedAllDevices && runningWithPrebuiltApplication) {
throwToolExit('Using -d all with --use-application-binary is not supported'); throwToolExit('Using -d all with --use-application-binary is not supported');
} }
...@@ -336,6 +332,11 @@ class RunCommand extends RunCommandBase { ...@@ -336,6 +332,11 @@ class RunCommand extends RunCommandBase {
writePidFile(stringArg('pid-file')); writePidFile(stringArg('pid-file'));
devices = await findAllTargetDevices();
if (devices == null) {
throwToolExit(null);
}
if (boolArg('machine')) { if (boolArg('machine')) {
if (devices.length > 1) { if (devices.length > 1) {
throwToolExit('--machine does not support -d all.'); throwToolExit('--machine does not support -d all.');
......
...@@ -106,9 +106,7 @@ class TestCommand extends FastFlutterCommand { ...@@ -106,9 +106,7 @@ class TestCommand extends FastFlutterCommand {
@override @override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async { Future<Set<DevelopmentArtifact>> get requiredArtifacts async {
final Set<DevelopmentArtifact> results = <DevelopmentArtifact>{ final Set<DevelopmentArtifact> results = <DevelopmentArtifact>{};
DevelopmentArtifact.universal,
};
if (stringArg('platform') == 'chrome') { if (stringArg('platform') == 'chrome') {
results.add(DevelopmentArtifact.web); results.add(DevelopmentArtifact.web);
} }
......
...@@ -55,9 +55,7 @@ class UnpackCommand extends FlutterCommand { ...@@ -55,9 +55,7 @@ class UnpackCommand extends FlutterCommand {
@override @override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async { Future<Set<DevelopmentArtifact>> get requiredArtifacts async {
final Set<DevelopmentArtifact> result = <DevelopmentArtifact>{ final Set<DevelopmentArtifact> result = <DevelopmentArtifact>{};
DevelopmentArtifact.universal,
};
final TargetPlatform targetPlatform = getTargetPlatformForName(stringArg('target-platform')); final TargetPlatform targetPlatform = getTargetPlatformForName(stringArg('target-platform'));
switch (targetPlatform) { switch (targetPlatform) {
case TargetPlatform.windows_x64: case TargetPlatform.windows_x64:
......
...@@ -88,11 +88,6 @@ class UpdatePackagesCommand extends FlutterCommand { ...@@ -88,11 +88,6 @@ class UpdatePackagesCommand extends FlutterCommand {
@override @override
final bool hidden; final bool hidden;
@override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => <DevelopmentArtifact>{
DevelopmentArtifact.universal,
};
Future<void> _downloadCoverageData() async { Future<void> _downloadCoverageData() async {
final Status status = logger.startProgress( final Status status = logger.startProgress(
'Downloading lcov data for package:flutter...', 'Downloading lcov data for package:flutter...',
......
...@@ -51,11 +51,6 @@ class UpgradeCommand extends FlutterCommand { ...@@ -51,11 +51,6 @@ class UpgradeCommand extends FlutterCommand {
@override @override
bool get shouldUpdateCache => false; bool get shouldUpdateCache => false;
@override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => <DevelopmentArtifact>{
DevelopmentArtifact.universal,
};
@override @override
Future<FlutterCommandResult> runCommand() async { Future<FlutterCommandResult> runCommand() async {
await _commandRunner.runCommand( await _commandRunner.runCommand(
......
...@@ -589,9 +589,13 @@ abstract class FlutterCommand extends Command<void> { ...@@ -589,9 +589,13 @@ abstract class FlutterCommand extends Command<void> {
Future<FlutterCommandResult> verifyThenRunCommand(String commandPath) async { Future<FlutterCommandResult> verifyThenRunCommand(String commandPath) async {
await validateCommand(); await validateCommand();
// Populate the cache. We call this before pub get below so that the sky_engine // Populate the cache. We call this before pub get below so that the
// package is available in the flutter cache for pub to find. // sky_engine package is available in the flutter cache for pub to find.
if (shouldUpdateCache) { if (shouldUpdateCache) {
// First always update universal artifacts, as some of these (e.g.
// idevice_id on macOS) are required to determine `requiredArtifacts`.
await cache.updateAll(<DevelopmentArtifact>{DevelopmentArtifact.universal});
await cache.updateAll(await requiredArtifacts); await cache.updateAll(await requiredArtifacts);
} }
...@@ -617,10 +621,9 @@ abstract class FlutterCommand extends Command<void> { ...@@ -617,10 +621,9 @@ abstract class FlutterCommand extends Command<void> {
/// The set of development artifacts required for this command. /// The set of development artifacts required for this command.
/// ///
/// Defaults to [DevelopmentArtifact.universal]. /// Defaults to an empty set. Including [DevelopmentArtifact.universal] is
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => const <DevelopmentArtifact>{ /// not required as it is always updated.
DevelopmentArtifact.universal, Future<Set<DevelopmentArtifact>> get requiredArtifacts async => const <DevelopmentArtifact>{};
};
/// Subclasses must implement this to execute the command. /// Subclasses must implement this to execute the command.
/// Optionally provide a [FlutterCommandResult] to send more details about the /// Optionally provide a [FlutterCommandResult] to send more details about the
...@@ -758,9 +761,7 @@ mixin TargetPlatformBasedDevelopmentArtifacts on FlutterCommand { ...@@ -758,9 +761,7 @@ mixin TargetPlatformBasedDevelopmentArtifacts on FlutterCommand {
return super.requiredArtifacts; return super.requiredArtifacts;
} }
final Set<DevelopmentArtifact> artifacts = <DevelopmentArtifact>{ final Set<DevelopmentArtifact> artifacts = <DevelopmentArtifact>{};
DevelopmentArtifact.universal,
};
final DevelopmentArtifact developmentArtifact = _artifactFromTargetPlatform(targetPlatform); final DevelopmentArtifact developmentArtifact = _artifactFromTargetPlatform(targetPlatform);
if (developmentArtifact != null) { if (developmentArtifact != null) {
artifacts.add(developmentArtifact); artifacts.add(developmentArtifact);
......
...@@ -53,13 +53,83 @@ void main() { ...@@ -53,13 +53,83 @@ void main() {
} }
}); });
group('cache', () {
MemoryFileSystem fs;
MockCache mockCache;
MockProcessManager mockProcessManager;
Directory tempDir;
setUpAll(() {
mockCache = MockCache();
fs = MemoryFileSystem();
mockProcessManager = MockProcessManager();
tempDir = fs.systemTempDirectory.createTempSync('flutter_run_test.');
fs.currentDirectory = tempDir;
tempDir.childFile('pubspec.yaml')
..writeAsStringSync('name: flutter_app');
tempDir.childFile('.packages')
..writeAsStringSync('# Generated by pub on 2019-11-25 12:38:01.801784.');
final Directory libDir = tempDir.childDirectory('lib');
libDir.createSync();
final File mainFile = libDir.childFile('main.dart');
mainFile.writeAsStringSync('void main() {}');
when(mockDeviceManager.hasSpecifiedDeviceId).thenReturn(false);
when(mockDeviceManager.hasSpecifiedAllDevices).thenReturn(false);
});
testUsingContext('updates before checking for devices', () async {
final RunCommand command = RunCommand();
applyMocksToCommand(command);
// No devices are attached, we just want to verify update the cache
// BEFORE checking for devices
when(mockDeviceManager.getDevices()).thenAnswer(
(Invocation invocation) => Stream<Device>.fromIterable(<Device>[])
);
when(mockDeviceManager.findTargetDevices(any)).thenAnswer(
(Invocation invocation) => Future<List<Device>>.value(<Device>[])
);
try {
await createTestCommandRunner(command).run(<String>[
'run',
'--no-pub',
]);
fail('Exception expected');
} on ToolExit catch (e) {
// We expect a ToolExit because no devices are attached
expect(e.message, null);
} catch (e) {
fail('ToolExit expected');
}
verifyInOrder(<void>[
mockCache.updateAll(<DevelopmentArtifact>{DevelopmentArtifact.universal}),
mockDeviceManager.findTargetDevices(any),
]);
}, overrides: <Type, Generator>{
ApplicationPackageFactory: () => mockApplicationPackageFactory,
Cache: () => mockCache,
DeviceManager: () => mockDeviceManager,
FileSystem: () => fs,
ProcessManager: () => mockProcessManager,
});
});
group('dart-flags option', () { group('dart-flags option', () {
setUpAll(() { setUpAll(() {
final FakeDevice fakeDevice = FakeDevice();
when(mockDeviceManager.getDevices()).thenAnswer((Invocation invocation) { when(mockDeviceManager.getDevices()).thenAnswer((Invocation invocation) {
return Stream<Device>.fromIterable(<Device>[ return Stream<Device>.fromIterable(<Device>[
FakeDevice(), fakeDevice,
]); ]);
}); });
when(mockDeviceManager.findTargetDevices(any)).thenAnswer(
(Invocation invocation) => Future<List<Device>>.value(<Device>[fakeDevice])
);
}); });
RunCommand command; RunCommand command;
...@@ -195,11 +265,13 @@ void main() { ...@@ -195,11 +265,13 @@ void main() {
MockWebRunnerFactory mockWebRunnerFactory; MockWebRunnerFactory mockWebRunnerFactory;
setUpAll(() { setUpAll(() {
when(mockDeviceManager.getDevices()).thenAnswer((Invocation invocation) { final FakeDevice fakeDevice = FakeDevice().._targetPlatform = TargetPlatform.web_javascript;
return Stream<Device>.fromIterable(<Device>[ when(mockDeviceManager.getDevices()).thenAnswer(
FakeDevice().._targetPlatform = TargetPlatform.web_javascript, (Invocation invocation) => Stream<Device>.fromIterable(<Device>[fakeDevice])
]); );
}); when(mockDeviceManager.findTargetDevices(any)).thenAnswer(
(Invocation invocation) => Future<List<Device>>.value(<Device>[fakeDevice])
);
}); });
RunCommand command; RunCommand command;
...@@ -279,6 +351,8 @@ void main() { ...@@ -279,6 +351,8 @@ void main() {
}); });
} }
class MockCache extends Mock implements Cache {}
class MockDeviceManager extends Mock implements DeviceManager {} class MockDeviceManager extends Mock implements DeviceManager {}
class MockDevice extends Mock implements Device { class MockDevice extends Mock implements Device {
MockDevice(this._targetPlatform); MockDevice(this._targetPlatform);
......
...@@ -52,7 +52,14 @@ void main() { ...@@ -52,7 +52,14 @@ void main() {
testUsingContext('honors shouldUpdateCache true', () async { testUsingContext('honors shouldUpdateCache true', () async {
final DummyFlutterCommand flutterCommand = DummyFlutterCommand(shouldUpdateCache: true); final DummyFlutterCommand flutterCommand = DummyFlutterCommand(shouldUpdateCache: true);
await flutterCommand.run(); await flutterCommand.run();
verify(cache.updateAll(any)).called(1); // First call for universal, second for the rest
expect(
verify(cache.updateAll(captureAny)).captured,
<Set<DevelopmentArtifact>>[
<DevelopmentArtifact>{DevelopmentArtifact.universal},
<DevelopmentArtifact>{},
],
);
}, },
overrides: <Type, Generator>{ overrides: <Type, Generator>{
Cache: () => cache, Cache: () => cache,
......
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