Skip to content

Commit 445b5a1

Browse files
Precache platform filter change (flutter#53701)
Makes the following changes to the behavior of precache: - The --all-platforms flags now fetches all artifacts, rather than just turning off platform filtering of selected artifacts. - Explicitly requested artifacts are no longer subject to platform filtering. E.g., 'precache --ios' will download iOS artifacts on Windows and Linux (but 'precache' without an 'ios' flag will still only download iOS artifacts on macOS). - Desktop platform artifacts now respect the bypassing of platform filtering. Fixes flutter#53272
1 parent 67f70b4 commit 445b5a1

File tree

5 files changed

+199
-31
lines changed

5 files changed

+199
-31
lines changed

packages/flutter_tools/lib/src/cache.dart

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,10 @@ class Cache {
156156
// artifacts for the current platform.
157157
bool includeAllPlatforms = false;
158158

159+
// Names of artifacts which should be cached even if they would normally
160+
// be filtered out for the current platform.
161+
Set<String> platformOverrideArtifacts;
162+
159163
// Whether to cache the unsigned mac binaries. Defaults to caching the signed binaries.
160164
bool useUnsignedMacBinaries = false;
161165

@@ -523,6 +527,12 @@ abstract class CachedArtifact extends ArtifactSet {
523527
@visibleForTesting
524528
final List<File> downloadedFiles = <File>[];
525529

530+
// Whether or not to bypass normal platform filtering for this artifact.
531+
bool get ignorePlatformFiltering {
532+
return cache.includeAllPlatforms ||
533+
(cache.platformOverrideArtifacts != null && cache.platformOverrideArtifacts.contains(developmentArtifact.name));
534+
}
535+
526536
@override
527537
bool isUpToDate() {
528538
if (!location.existsSync()) {
@@ -859,7 +869,7 @@ class MacOSEngineArtifacts extends EngineCachedArtifact {
859869

860870
@override
861871
List<List<String>> getBinaryDirs() {
862-
if (globals.platform.isMacOS) {
872+
if (globals.platform.isMacOS || ignorePlatformFiltering) {
863873
return _macOSDesktopBinaryDirs;
864874
}
865875
return const <List<String>>[];
@@ -881,7 +891,7 @@ class WindowsEngineArtifacts extends EngineCachedArtifact {
881891

882892
@override
883893
List<List<String>> getBinaryDirs() {
884-
if (globals.platform.isWindows) {
894+
if (globals.platform.isWindows || ignorePlatformFiltering) {
885895
return _windowsDesktopBinaryDirs;
886896
}
887897
return const <List<String>>[];
@@ -903,7 +913,7 @@ class LinuxEngineArtifacts extends EngineCachedArtifact {
903913

904914
@override
905915
List<List<String>> getBinaryDirs() {
906-
if (globals.platform.isLinux) {
916+
if (globals.platform.isLinux || ignorePlatformFiltering) {
907917
return _linuxDesktopBinaryDirs;
908918
}
909919
return const <List<String>>[];
@@ -1020,14 +1030,14 @@ class IOSEngineArtifacts extends EngineCachedArtifact {
10201030
@override
10211031
List<List<String>> getBinaryDirs() {
10221032
return <List<String>>[
1023-
if (globals.platform.isMacOS || cache.includeAllPlatforms)
1033+
if (globals.platform.isMacOS || ignorePlatformFiltering)
10241034
..._iosBinaryDirs,
10251035
];
10261036
}
10271037

10281038
@override
10291039
List<String> getLicenseDirs() {
1030-
if (cache.includeAllPlatforms || globals.platform.isMacOS) {
1040+
if (globals.platform.isMacOS || ignorePlatformFiltering) {
10311041
return const <String>['ios', 'ios-profile', 'ios-release'];
10321042
}
10331043
return const <String>[];
@@ -1302,7 +1312,7 @@ class IosUsbArtifacts extends CachedArtifact {
13021312

13031313
@override
13041314
Future<void> updateInner() {
1305-
if (!globals.platform.isMacOS && !cache.includeAllPlatforms) {
1315+
if (!globals.platform.isMacOS && !ignorePlatformFiltering) {
13061316
return Future<void>.value();
13071317
}
13081318
if (location.existsSync()) {

packages/flutter_tools/lib/src/commands/precache.dart

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,33 @@ class PrecacheCommand extends FlutterCommand {
6666
]
6767
};
6868

69+
/// Returns a reverse mapping of _expandedArtifacts, from child artifact name
70+
/// to umbrella name.
71+
Map<String, String> _umbrellaForArtifactMap() {
72+
return <String, String>{
73+
for (final MapEntry<String, List<String>> entry in _expandedArtifacts.entries)
74+
for (final String childArtifactName in entry.value)
75+
childArtifactName: entry.key
76+
};
77+
}
78+
79+
/// Returns the name of all artifacts that were explicitly chosen via flags.
80+
///
81+
/// If an umbrella is chosen, its children will be included as well.
82+
Set<String> _explicitArtifactSelections() {
83+
final Map<String, String> umbrellaForArtifact = _umbrellaForArtifactMap();
84+
final Set<String> selections = <String>{};
85+
bool explicitlySelected(String name) => boolArg(name) && argResults.wasParsed(name);
86+
for (final DevelopmentArtifact artifact in DevelopmentArtifact.values) {
87+
final String umbrellaName = umbrellaForArtifact[artifact.name];
88+
if (explicitlySelected(artifact.name) ||
89+
(umbrellaName != null && explicitlySelected(umbrellaName))) {
90+
selections.add(artifact.name);
91+
}
92+
}
93+
return selections;
94+
}
95+
6996
@override
7097
Future<void> validateCommand() {
7198
_expandedArtifacts.forEach((String umbrellaName, List<String> childArtifactNames) {
@@ -84,12 +111,15 @@ class PrecacheCommand extends FlutterCommand {
84111

85112
@override
86113
Future<FlutterCommandResult> runCommand() async {
87-
if (boolArg('all-platforms')) {
114+
final bool includeAllPlatforms = boolArg('all-platforms');
115+
if (includeAllPlatforms) {
88116
globals.cache.includeAllPlatforms = true;
89117
}
90118
if (boolArg('use-unsigned-mac-binaries')) {
91119
globals.cache.useUnsignedMacBinaries = true;
92120
}
121+
globals.cache.platformOverrideArtifacts = _explicitArtifactSelections();
122+
final Map<String, String> umbrellaForArtifact = _umbrellaForArtifactMap();
93123
final Set<DevelopmentArtifact> requiredArtifacts = <DevelopmentArtifact>{};
94124
for (final DevelopmentArtifact artifact in DevelopmentArtifact.values) {
95125
// Don't include unstable artifacts on stable branches.
@@ -100,25 +130,8 @@ class PrecacheCommand extends FlutterCommand {
100130
continue;
101131
}
102132

103-
bool expandedArtifactProcessed = false;
104-
_expandedArtifacts.forEach((String umbrellaName, List<String> childArtifactNames) {
105-
if (!childArtifactNames.contains(artifact.name)) {
106-
return;
107-
}
108-
expandedArtifactProcessed = true;
109-
110-
// Expanded artifacts options are true by default.
111-
// Explicitly ignore them if umbrella name is excluded.
112-
// Example: --no-android [--android_gen_snapshot]
113-
if (!boolArg(umbrellaName)) {
114-
return;
115-
}
116-
117-
// Example: --android [--android_gen_snapshot]
118-
requiredArtifacts.add(artifact);
119-
});
120-
121-
if (!expandedArtifactProcessed && boolArg(artifact.name)) {
133+
final String argumentName = umbrellaForArtifact[artifact.name] ?? artifact.name;
134+
if (includeAllPlatforms || boolArg(argumentName)) {
122135
requiredArtifacts.add(artifact);
123136
}
124137
}

packages/flutter_tools/test/commands.shard/hermetic/precache_test.dart

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import 'package:flutter_tools/src/features.dart';
88
import 'package:flutter_tools/src/runner/flutter_command.dart';
99
import 'package:flutter_tools/src/version.dart';
1010
import 'package:mockito/mockito.dart';
11+
import 'package:platform/platform.dart';
1112

1213
import '../../src/common.dart';
1314
import '../../src/context.dart';
@@ -270,6 +271,111 @@ void main() {
270271
FeatureFlags: () => TestFeatureFlags(isWebEnabled: false),
271272
});
272273

274+
testUsingContext('precache downloads iOS and Android artifacts by default', () async {
275+
final PrecacheCommand command = PrecacheCommand();
276+
applyMocksToCommand(command);
277+
278+
await createTestCommandRunner(command).run(
279+
const <String>[
280+
'precache',
281+
],
282+
);
283+
284+
expect(artifacts, unorderedEquals(<DevelopmentArtifact>{
285+
DevelopmentArtifact.universal,
286+
DevelopmentArtifact.iOS,
287+
DevelopmentArtifact.androidGenSnapshot,
288+
DevelopmentArtifact.androidMaven,
289+
DevelopmentArtifact.androidInternalBuild,
290+
}));
291+
}, overrides: <Type, Generator>{
292+
Cache: () => cache,
293+
});
294+
295+
testUsingContext('precache --all-platforms gets all artifacts', () async {
296+
final PrecacheCommand command = PrecacheCommand();
297+
applyMocksToCommand(command);
298+
299+
await createTestCommandRunner(command).run(
300+
const <String>[
301+
'precache',
302+
'--all-platforms',
303+
],
304+
);
305+
306+
expect(artifacts, unorderedEquals(<DevelopmentArtifact>{
307+
DevelopmentArtifact.universal,
308+
DevelopmentArtifact.iOS,
309+
DevelopmentArtifact.androidGenSnapshot,
310+
DevelopmentArtifact.androidMaven,
311+
DevelopmentArtifact.androidInternalBuild,
312+
DevelopmentArtifact.web,
313+
DevelopmentArtifact.macOS,
314+
DevelopmentArtifact.linux,
315+
DevelopmentArtifact.windows,
316+
DevelopmentArtifact.fuchsia,
317+
DevelopmentArtifact.flutterRunner,
318+
}));
319+
}, overrides: <Type, Generator>{
320+
Cache: () => cache,
321+
FeatureFlags: () => TestFeatureFlags(
322+
isWebEnabled: true,
323+
isLinuxEnabled: true,
324+
isMacOSEnabled: true,
325+
isWindowsEnabled: true,
326+
),
327+
FlutterVersion: () => masterFlutterVersion,
328+
});
329+
330+
testUsingContext('precache with default artifacts does not override platform filtering', () async {
331+
final PrecacheCommand command = PrecacheCommand();
332+
applyMocksToCommand(command);
333+
334+
await createTestCommandRunner(command).run(
335+
const <String>[
336+
'precache',
337+
],
338+
);
339+
340+
verify(cache.platformOverrideArtifacts = <String>{});
341+
}, overrides: <Type, Generator>{
342+
Cache: () => cache,
343+
FlutterVersion: () => masterFlutterVersion,
344+
});
345+
346+
testUsingContext('precache with explicit artifact options overrides platform filtering', () async {
347+
final PrecacheCommand command = PrecacheCommand();
348+
applyMocksToCommand(command);
349+
350+
await createTestCommandRunner(command).run(
351+
const <String>[
352+
'precache',
353+
'--no-ios',
354+
'--no-android',
355+
'--macos',
356+
],
357+
);
358+
359+
expect(artifacts, unorderedEquals(<DevelopmentArtifact>{
360+
DevelopmentArtifact.universal,
361+
DevelopmentArtifact.macOS,
362+
}));
363+
verify(cache.platformOverrideArtifacts = <String>{'macos'});
364+
}, overrides: <Type, Generator>{
365+
Cache: () => cache,
366+
FlutterVersion: () => masterFlutterVersion,
367+
FeatureFlags: () => TestFeatureFlags(
368+
isMacOSEnabled: true,
369+
),
370+
Platform: () => FakePlatform(
371+
operatingSystem: 'windows',
372+
environment: <String, String>{
373+
'FLUTTER_ROOT': 'flutter',
374+
'FLUTTER_ALREADY_LOCKED': 'true',
375+
},
376+
),
377+
});
378+
273379
testUsingContext('precache downloads artifacts when --force is provided', () async {
274380
when(cache.isUpToDate()).thenReturn(true);
275381
final PrecacheCommand command = PrecacheCommand();
@@ -285,6 +391,9 @@ void main() {
285391
}, overrides: <Type, Generator>{
286392
Cache: () => cache,
287393
FlutterVersion: () => flutterVersion,
394+
FeatureFlags: () => TestFeatureFlags(
395+
isMacOSEnabled: true,
396+
),
288397
});
289398
}
290399

packages/flutter_tools/test/general.shard/cache_test.dart

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,7 @@ void main() {
520520
when(mockCache.includeAllPlatforms).thenReturn(false);
521521
expect(artifacts.getBinaryDirs(), <List<String>>[<String>['linux-x64', 'linux-x64/font-subset.zip']]);
522522
}, overrides: <Type, Generator> {
523-
Platform: () => FakePlatform()..operatingSystem = 'linux',
523+
Platform: () => FakePlatform(operatingSystem: 'linux'),
524524
});
525525

526526
testUsingContext('FontSubset artifacts on windows', () {
@@ -529,7 +529,7 @@ void main() {
529529
when(mockCache.includeAllPlatforms).thenReturn(false);
530530
expect(artifacts.getBinaryDirs(), <List<String>>[<String>['windows-x64', 'windows-x64/font-subset.zip']]);
531531
}, overrides: <Type, Generator> {
532-
Platform: () => FakePlatform()..operatingSystem = 'windows',
532+
Platform: () => FakePlatform(operatingSystem: 'windows'),
533533
});
534534

535535
testUsingContext('FontSubset artifacts on macos', () {
@@ -538,7 +538,7 @@ void main() {
538538
when(mockCache.includeAllPlatforms).thenReturn(false);
539539
expect(artifacts.getBinaryDirs(), <List<String>>[<String>['darwin-x64', 'darwin-x64/font-subset.zip']]);
540540
}, overrides: <Type, Generator> {
541-
Platform: () => FakePlatform()..operatingSystem = 'macos',
541+
Platform: () => FakePlatform(operatingSystem: 'macos'),
542542
});
543543

544544
testUsingContext('FontSubset artifacts on fuchsia', () {
@@ -547,7 +547,7 @@ void main() {
547547
when(mockCache.includeAllPlatforms).thenReturn(false);
548548
expect(() => artifacts.getBinaryDirs(), throwsToolExit(message: 'Unsupported operating system: ${globals.platform.operatingSystem}'));
549549
}, overrides: <Type, Generator> {
550-
Platform: () => FakePlatform()..operatingSystem = 'fuchsia',
550+
Platform: () => FakePlatform(operatingSystem: 'fuchsia'),
551551
});
552552

553553
testUsingContext('FontSubset artifacts for all platforms', () {
@@ -560,7 +560,40 @@ void main() {
560560
<String>['windows-x64', 'windows-x64/font-subset.zip'],
561561
]);
562562
}, overrides: <Type, Generator> {
563-
Platform: () => FakePlatform()..operatingSystem = 'fuchsia',
563+
Platform: () => FakePlatform(operatingSystem: 'fuchsia'),
564+
});
565+
566+
testUsingContext('macOS desktop artifacts ignore filtering when requested', () {
567+
final MockCache mockCache = MockCache();
568+
final MacOSEngineArtifacts artifacts = MacOSEngineArtifacts(mockCache);
569+
when(mockCache.includeAllPlatforms).thenReturn(false);
570+
when(mockCache.platformOverrideArtifacts).thenReturn(<String>{'macos'});
571+
572+
expect(artifacts.getBinaryDirs(), isNotEmpty);
573+
}, overrides: <Type, Generator> {
574+
Platform: () => FakePlatform(operatingSystem: 'linux'),
575+
});
576+
577+
testUsingContext('Windows desktop artifacts ignore filtering when requested', () {
578+
final MockCache mockCache = MockCache();
579+
final WindowsEngineArtifacts artifacts = WindowsEngineArtifacts(mockCache);
580+
when(mockCache.includeAllPlatforms).thenReturn(false);
581+
when(mockCache.platformOverrideArtifacts).thenReturn(<String>{'windows'});
582+
583+
expect(artifacts.getBinaryDirs(), isNotEmpty);
584+
}, overrides: <Type, Generator> {
585+
Platform: () => FakePlatform(operatingSystem: 'linux'),
586+
});
587+
588+
testUsingContext('Linux desktop artifacts ignore filtering when requested', () {
589+
final MockCache mockCache = MockCache();
590+
final LinuxEngineArtifacts artifacts = LinuxEngineArtifacts(mockCache);
591+
when(mockCache.includeAllPlatforms).thenReturn(false);
592+
when(mockCache.platformOverrideArtifacts).thenReturn(<String>{'linux'});
593+
594+
expect(artifacts.getBinaryDirs(), isNotEmpty);
595+
}, overrides: <Type, Generator> {
596+
Platform: () => FakePlatform(operatingSystem: 'macos'),
564597
});
565598
}
566599

packages/flutter_tools/test/src/testbed.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,9 @@ class FakeCache implements Cache {
829829
@override
830830
bool includeAllPlatforms;
831831

832+
@override
833+
Set<String> platformOverrideArtifacts;
834+
832835
@override
833836
bool useUnsignedMacBinaries;
834837

0 commit comments

Comments
 (0)