Fix flutter run cache (#45267)
diff --git a/packages/flutter_tools/lib/src/cache.dart b/packages/flutter_tools/lib/src/cache.dart
index 5e1950b..ed63c6a 100644
--- a/packages/flutter_tools/lib/src/cache.dart
+++ b/packages/flutter_tools/lib/src/cache.dart
@@ -63,6 +63,9 @@
static const DevelopmentArtifact flutterRunner = DevelopmentArtifact._('flutter_runner', unstable: true);
/// 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');
/// The values of DevelopmentArtifacts.
diff --git a/packages/flutter_tools/lib/src/commands/analyze.dart b/packages/flutter_tools/lib/src/commands/analyze.dart
index 7ebe931..7c9561e 100644
--- a/packages/flutter_tools/lib/src/commands/analyze.dart
+++ b/packages/flutter_tools/lib/src/commands/analyze.dart
@@ -65,11 +65,6 @@
String get description => "Analyze the project's Dart code.";
@override
- Future<Set<DevelopmentArtifact>> get requiredArtifacts async => const <DevelopmentArtifact>{
- DevelopmentArtifact.universal,
- };
-
- @override
bool get shouldRunPub {
// If they're not analyzing the current project.
if (!boolArg('current-package')) {
diff --git a/packages/flutter_tools/lib/src/commands/build_aar.dart b/packages/flutter_tools/lib/src/commands/build_aar.dart
index bd6e398..44ad277 100644
--- a/packages/flutter_tools/lib/src/commands/build_aar.dart
+++ b/packages/flutter_tools/lib/src/commands/build_aar.dart
@@ -55,7 +55,6 @@
@override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => <DevelopmentArtifact>{
DevelopmentArtifact.androidGenSnapshot,
- DevelopmentArtifact.universal,
};
@override
diff --git a/packages/flutter_tools/lib/src/commands/build_apk.dart b/packages/flutter_tools/lib/src/commands/build_apk.dart
index 28abedc..455c458 100644
--- a/packages/flutter_tools/lib/src/commands/build_apk.dart
+++ b/packages/flutter_tools/lib/src/commands/build_apk.dart
@@ -45,7 +45,6 @@
@override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => <DevelopmentArtifact>{
DevelopmentArtifact.androidGenSnapshot,
- DevelopmentArtifact.universal,
};
@override
diff --git a/packages/flutter_tools/lib/src/commands/build_appbundle.dart b/packages/flutter_tools/lib/src/commands/build_appbundle.dart
index b7f9a8d..f637809 100644
--- a/packages/flutter_tools/lib/src/commands/build_appbundle.dart
+++ b/packages/flutter_tools/lib/src/commands/build_appbundle.dart
@@ -38,7 +38,6 @@
@override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => <DevelopmentArtifact>{
DevelopmentArtifact.androidGenSnapshot,
- DevelopmentArtifact.universal,
};
@override
diff --git a/packages/flutter_tools/lib/src/commands/build_fuchsia.dart b/packages/flutter_tools/lib/src/commands/build_fuchsia.dart
index 5e992f4..2f14627 100644
--- a/packages/flutter_tools/lib/src/commands/build_fuchsia.dart
+++ b/packages/flutter_tools/lib/src/commands/build_fuchsia.dart
@@ -47,7 +47,6 @@
@override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => <DevelopmentArtifact>{
DevelopmentArtifact.fuchsia,
- DevelopmentArtifact.universal,
};
@override
diff --git a/packages/flutter_tools/lib/src/commands/build_ios.dart b/packages/flutter_tools/lib/src/commands/build_ios.dart
index 7794f5f..d929d6c 100644
--- a/packages/flutter_tools/lib/src/commands/build_ios.dart
+++ b/packages/flutter_tools/lib/src/commands/build_ios.dart
@@ -43,7 +43,6 @@
@override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => const <DevelopmentArtifact>{
- DevelopmentArtifact.universal,
DevelopmentArtifact.iOS,
};
diff --git a/packages/flutter_tools/lib/src/commands/build_ios_framework.dart b/packages/flutter_tools/lib/src/commands/build_ios_framework.dart
index aeaa0a5..dcb5c1a 100644
--- a/packages/flutter_tools/lib/src/commands/build_ios_framework.dart
+++ b/packages/flutter_tools/lib/src/commands/build_ios_framework.dart
@@ -85,7 +85,6 @@
@override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => const <DevelopmentArtifact>{
- DevelopmentArtifact.universal,
DevelopmentArtifact.iOS,
};
diff --git a/packages/flutter_tools/lib/src/commands/build_linux.dart b/packages/flutter_tools/lib/src/commands/build_linux.dart
index 1f07d4c..1abf8b6 100644
--- a/packages/flutter_tools/lib/src/commands/build_linux.dart
+++ b/packages/flutter_tools/lib/src/commands/build_linux.dart
@@ -30,7 +30,6 @@
@override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => <DevelopmentArtifact>{
DevelopmentArtifact.linux,
- DevelopmentArtifact.universal,
};
@override
diff --git a/packages/flutter_tools/lib/src/commands/build_macos.dart b/packages/flutter_tools/lib/src/commands/build_macos.dart
index fe3cf29..950555b 100644
--- a/packages/flutter_tools/lib/src/commands/build_macos.dart
+++ b/packages/flutter_tools/lib/src/commands/build_macos.dart
@@ -30,7 +30,6 @@
@override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => <DevelopmentArtifact>{
DevelopmentArtifact.macOS,
- DevelopmentArtifact.universal,
};
@override
diff --git a/packages/flutter_tools/lib/src/commands/build_web.dart b/packages/flutter_tools/lib/src/commands/build_web.dart
index 4ea8189..7b3284a 100644
--- a/packages/flutter_tools/lib/src/commands/build_web.dart
+++ b/packages/flutter_tools/lib/src/commands/build_web.dart
@@ -30,7 +30,6 @@
@override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async =>
const <DevelopmentArtifact>{
- DevelopmentArtifact.universal,
DevelopmentArtifact.web,
};
diff --git a/packages/flutter_tools/lib/src/commands/build_windows.dart b/packages/flutter_tools/lib/src/commands/build_windows.dart
index a9103ac..75b989f 100644
--- a/packages/flutter_tools/lib/src/commands/build_windows.dart
+++ b/packages/flutter_tools/lib/src/commands/build_windows.dart
@@ -30,7 +30,6 @@
@override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async => <DevelopmentArtifact>{
DevelopmentArtifact.windows,
- DevelopmentArtifact.universal,
};
@override
diff --git a/packages/flutter_tools/lib/src/commands/create.dart b/packages/flutter_tools/lib/src/commands/create.dart
index aefbaf3..4fd4377 100644
--- a/packages/flutter_tools/lib/src/commands/create.dart
+++ b/packages/flutter_tools/lib/src/commands/create.dart
@@ -337,8 +337,6 @@
'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 flutterPackagesDirectory = fs.path.join(flutterRoot, 'packages');
diff --git a/packages/flutter_tools/lib/src/commands/doctor.dart b/packages/flutter_tools/lib/src/commands/doctor.dart
index 20670e9..4cf78eb 100644
--- a/packages/flutter_tools/lib/src/commands/doctor.dart
+++ b/packages/flutter_tools/lib/src/commands/doctor.dart
@@ -33,7 +33,6 @@
@override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async {
return <DevelopmentArtifact>{
- DevelopmentArtifact.universal,
// This is required because we use gen_snapshot to check if the host
// machine can execute the provided artifacts. See `_genSnapshotRuns`
// in `doctor.dart`.
diff --git a/packages/flutter_tools/lib/src/commands/format.dart b/packages/flutter_tools/lib/src/commands/format.dart
index 66fd400..c4d65d0 100644
--- a/packages/flutter_tools/lib/src/commands/format.dart
+++ b/packages/flutter_tools/lib/src/commands/format.dart
@@ -45,11 +45,6 @@
final String description = 'Format one or more dart files.';
@override
- Future<Set<DevelopmentArtifact>> get requiredArtifacts async => const <DevelopmentArtifact>{
- DevelopmentArtifact.universal,
- };
-
- @override
String get invocation => '${runner.executableName} $name <one or more paths>';
@override
diff --git a/packages/flutter_tools/lib/src/commands/generate.dart b/packages/flutter_tools/lib/src/commands/generate.dart
index 6dba59f..6fd8ef6 100644
--- a/packages/flutter_tools/lib/src/commands/generate.dart
+++ b/packages/flutter_tools/lib/src/commands/generate.dart
@@ -21,11 +21,6 @@
String get name => 'generate';
@override
- Future<Set<DevelopmentArtifact>> get requiredArtifacts async => const <DevelopmentArtifact>{
- DevelopmentArtifact.universal,
- };
-
- @override
Future<FlutterCommandResult> runCommand() async {
Cache.releaseLockEarly();
final FlutterProject flutterProject = FlutterProject.current();
diff --git a/packages/flutter_tools/lib/src/commands/ide_config.dart b/packages/flutter_tools/lib/src/commands/ide_config.dart
index 9b05dba..050d654 100644
--- a/packages/flutter_tools/lib/src/commands/ide_config.dart
+++ b/packages/flutter_tools/lib/src/commands/ide_config.dart
@@ -217,8 +217,6 @@
throwToolExit('Currently, the only supported IDE is IntelliJ\n$usage', exitCode: 2);
}
- await Cache.instance.updateAll(<DevelopmentArtifact>{ DevelopmentArtifact.universal });
-
if (boolArg('update-templates')) {
_handleTemplateUpdate();
return null;
diff --git a/packages/flutter_tools/lib/src/commands/packages.dart b/packages/flutter_tools/lib/src/commands/packages.dart
index 868a120..45b25a7 100644
--- a/packages/flutter_tools/lib/src/commands/packages.dart
+++ b/packages/flutter_tools/lib/src/commands/packages.dart
@@ -38,11 +38,6 @@
final String description = 'Commands for managing Flutter packages.';
@override
- Future<Set<DevelopmentArtifact>> get requiredArtifacts async => const <DevelopmentArtifact>{
- DevelopmentArtifact.universal,
- };
-
- @override
Future<FlutterCommandResult> runCommand() async => null;
}
diff --git a/packages/flutter_tools/lib/src/commands/run.dart b/packages/flutter_tools/lib/src/commands/run.dart
index 60e1eac..d47d121 100644
--- a/packages/flutter_tools/lib/src/commands/run.dart
+++ b/packages/flutter_tools/lib/src/commands/run.dart
@@ -284,10 +284,6 @@
if (!runningWithPrebuiltApplication) {
await super.validateCommand();
}
- devices = await findAllTargetDevices();
- if (devices == null) {
- throwToolExit(null);
- }
if (deviceManager.hasSpecifiedAllDevices && runningWithPrebuiltApplication) {
throwToolExit('Using -d all with --use-application-binary is not supported');
}
@@ -336,6 +332,11 @@
writePidFile(stringArg('pid-file'));
+ devices = await findAllTargetDevices();
+ if (devices == null) {
+ throwToolExit(null);
+ }
+
if (boolArg('machine')) {
if (devices.length > 1) {
throwToolExit('--machine does not support -d all.');
diff --git a/packages/flutter_tools/lib/src/commands/test.dart b/packages/flutter_tools/lib/src/commands/test.dart
index 71f89bf..43c2247 100644
--- a/packages/flutter_tools/lib/src/commands/test.dart
+++ b/packages/flutter_tools/lib/src/commands/test.dart
@@ -106,9 +106,7 @@
@override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async {
- final Set<DevelopmentArtifact> results = <DevelopmentArtifact>{
- DevelopmentArtifact.universal,
- };
+ final Set<DevelopmentArtifact> results = <DevelopmentArtifact>{};
if (stringArg('platform') == 'chrome') {
results.add(DevelopmentArtifact.web);
}
diff --git a/packages/flutter_tools/lib/src/commands/unpack.dart b/packages/flutter_tools/lib/src/commands/unpack.dart
index 2d9263c..566383d 100644
--- a/packages/flutter_tools/lib/src/commands/unpack.dart
+++ b/packages/flutter_tools/lib/src/commands/unpack.dart
@@ -55,9 +55,7 @@
@override
Future<Set<DevelopmentArtifact>> get requiredArtifacts async {
- final Set<DevelopmentArtifact> result = <DevelopmentArtifact>{
- DevelopmentArtifact.universal,
- };
+ final Set<DevelopmentArtifact> result = <DevelopmentArtifact>{};
final TargetPlatform targetPlatform = getTargetPlatformForName(stringArg('target-platform'));
switch (targetPlatform) {
case TargetPlatform.windows_x64:
diff --git a/packages/flutter_tools/lib/src/commands/update_packages.dart b/packages/flutter_tools/lib/src/commands/update_packages.dart
index 3e8aee9..57cb4f2 100644
--- a/packages/flutter_tools/lib/src/commands/update_packages.dart
+++ b/packages/flutter_tools/lib/src/commands/update_packages.dart
@@ -88,11 +88,6 @@
@override
final bool hidden;
- @override
- Future<Set<DevelopmentArtifact>> get requiredArtifacts async => <DevelopmentArtifact>{
- DevelopmentArtifact.universal,
- };
-
Future<void> _downloadCoverageData() async {
final Status status = logger.startProgress(
'Downloading lcov data for package:flutter...',
diff --git a/packages/flutter_tools/lib/src/commands/upgrade.dart b/packages/flutter_tools/lib/src/commands/upgrade.dart
index ace639e..cd1ace5 100644
--- a/packages/flutter_tools/lib/src/commands/upgrade.dart
+++ b/packages/flutter_tools/lib/src/commands/upgrade.dart
@@ -52,11 +52,6 @@
bool get shouldUpdateCache => false;
@override
- Future<Set<DevelopmentArtifact>> get requiredArtifacts async => <DevelopmentArtifact>{
- DevelopmentArtifact.universal,
- };
-
- @override
Future<FlutterCommandResult> runCommand() async {
await _commandRunner.runCommand(
boolArg('force'),
diff --git a/packages/flutter_tools/lib/src/runner/flutter_command.dart b/packages/flutter_tools/lib/src/runner/flutter_command.dart
index e08eb72..250de74 100644
--- a/packages/flutter_tools/lib/src/runner/flutter_command.dart
+++ b/packages/flutter_tools/lib/src/runner/flutter_command.dart
@@ -589,9 +589,13 @@
Future<FlutterCommandResult> verifyThenRunCommand(String commandPath) async {
await validateCommand();
- // Populate the cache. We call this before pub get below so that the sky_engine
- // package is available in the flutter cache for pub to find.
+ // Populate the cache. We call this before pub get below so that the
+ // sky_engine package is available in the flutter cache for pub to find.
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);
}
@@ -617,10 +621,9 @@
/// The set of development artifacts required for this command.
///
- /// Defaults to [DevelopmentArtifact.universal].
- Future<Set<DevelopmentArtifact>> get requiredArtifacts async => const <DevelopmentArtifact>{
- DevelopmentArtifact.universal,
- };
+ /// Defaults to an empty set. Including [DevelopmentArtifact.universal] is
+ /// not required as it is always updated.
+ Future<Set<DevelopmentArtifact>> get requiredArtifacts async => const <DevelopmentArtifact>{};
/// Subclasses must implement this to execute the command.
/// Optionally provide a [FlutterCommandResult] to send more details about the
@@ -758,9 +761,7 @@
return super.requiredArtifacts;
}
- final Set<DevelopmentArtifact> artifacts = <DevelopmentArtifact>{
- DevelopmentArtifact.universal,
- };
+ final Set<DevelopmentArtifact> artifacts = <DevelopmentArtifact>{};
final DevelopmentArtifact developmentArtifact = _artifactFromTargetPlatform(targetPlatform);
if (developmentArtifact != null) {
artifacts.add(developmentArtifact);
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/run_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/run_test.dart
index fb92f5c..bf59cd5 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/run_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/run_test.dart
@@ -53,13 +53,83 @@
}
});
+ 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', () {
setUpAll(() {
+ final FakeDevice fakeDevice = FakeDevice();
when(mockDeviceManager.getDevices()).thenAnswer((Invocation invocation) {
return Stream<Device>.fromIterable(<Device>[
- FakeDevice(),
+ fakeDevice,
]);
});
+ when(mockDeviceManager.findTargetDevices(any)).thenAnswer(
+ (Invocation invocation) => Future<List<Device>>.value(<Device>[fakeDevice])
+ );
});
RunCommand command;
@@ -195,11 +265,13 @@
MockWebRunnerFactory mockWebRunnerFactory;
setUpAll(() {
- when(mockDeviceManager.getDevices()).thenAnswer((Invocation invocation) {
- return Stream<Device>.fromIterable(<Device>[
- FakeDevice().._targetPlatform = TargetPlatform.web_javascript,
- ]);
- });
+ final FakeDevice fakeDevice = FakeDevice().._targetPlatform = TargetPlatform.web_javascript;
+ when(mockDeviceManager.getDevices()).thenAnswer(
+ (Invocation invocation) => Stream<Device>.fromIterable(<Device>[fakeDevice])
+ );
+ when(mockDeviceManager.findTargetDevices(any)).thenAnswer(
+ (Invocation invocation) => Future<List<Device>>.value(<Device>[fakeDevice])
+ );
});
RunCommand command;
@@ -279,6 +351,8 @@
});
}
+class MockCache extends Mock implements Cache {}
+
class MockDeviceManager extends Mock implements DeviceManager {}
class MockDevice extends Mock implements Device {
MockDevice(this._targetPlatform);
diff --git a/packages/flutter_tools/test/general.shard/runner/flutter_command_test.dart b/packages/flutter_tools/test/general.shard/runner/flutter_command_test.dart
index 744b3b6..a981490 100644
--- a/packages/flutter_tools/test/general.shard/runner/flutter_command_test.dart
+++ b/packages/flutter_tools/test/general.shard/runner/flutter_command_test.dart
@@ -52,7 +52,14 @@
testUsingContext('honors shouldUpdateCache true', () async {
final DummyFlutterCommand flutterCommand = DummyFlutterCommand(shouldUpdateCache: true);
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>{
Cache: () => cache,