Invalidate pod install
output if .flutter-plugins-dependencies
content changes. (#163275)
Closes https://github.com/flutter/flutter/issues/162399. Closes https://github.com/flutter/flutter/issues/163272. `refreshPluginsList` is commonly called in iOS/macOS apps, more times than you expect (and load bearing); https://github.com/flutter/flutter/issues/157391. With `--explicit-package-dependencies`, we no longer write (or compare) the output of `.flutter-plugins`. The iOS/macOS workflows required `pod install` output to be invalidated when plugins when change, but the logic that was being used to see if plugins changed _only_ worked for the `.flutter-plugins` file format. In the original code: ```txt # oldPluginsFileStringContent {"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"integration_test","path":"/Users/matanl/Developer/flutter/packages/integration_test/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"ios_objc_cocoapods_plugin","path":"/var/folders/qw/qw_3qd1x4kz5w975jhdq4k58007b7h/T/swift_package_manager_enabled.XrEWXS/ios_objc_cocoapods_plugin/","native_build":true,"dependencies":[],"dev_dependency":false}],"android":[{"name":"integration_test","path":"/Users/matanl/Developer/flutter/packages/integration_test/","native_build":true,"dependencies":[],"dev_dependency":false}],"macos":[],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"integration_test","dependencies":[]},{"name":"ios_objc_cocoapods_plugin","dependencies":[]}],"date_created":"2025-02-13 17:01:11.023097","version":"3.30.0-1.0.pre.163","swift_package_manager_enabled":{"ios":true,"macos":false}} # pluginsMap {ios: [{name: integration_test, path: /Users/matanl/Developer/flutter/packages/integration_test/, native_build: true, dependencies: [], dev_dependency: false}, {name: ios_objc_cocoapods_plugin, path: /var/folders/qw/qw_3qd1x4kz5w975jhdq4k58007b7h/T/swift_package_manager_enabled.XrEWXS/ios_objc_cocoapods_plugin/, native_build: true, dependencies: [], dev_dependency: false}], android: [{name: integration_test, path: /Users/matanl/Developer/flutter/packages/integration_test/, native_build: true, dependencies: [], dev_dependency: false}], macos: [], linux: [], windows: [], web: []} ``` As you can see, `pluginsChanged = oldPluginsFileStringContent.contains(pluginsMap.toString());` was _always_ `false`, but we never knew because we'd always just fall back to using the `.flutter-plugins` content comparison (which always worked). I added a test as well. This also appears to fix https://github.com/flutter/flutter/issues/162399. /cc @jmagman @jonahwilliams
This commit is contained in:
parent
5365993ff5
commit
29d1e10a02
@ -244,7 +244,15 @@ bool _writeFlutterPluginsList(
|
||||
final String? oldPluginsFileStringContent = _readFileContent(pluginsFile);
|
||||
bool pluginsChanged = true;
|
||||
if (oldPluginsFileStringContent != null) {
|
||||
pluginsChanged = oldPluginsFileStringContent.contains(pluginsMap.toString());
|
||||
Object? decodedJson;
|
||||
try {
|
||||
decodedJson = jsonDecode(oldPluginsFileStringContent);
|
||||
if (decodedJson is Map<String, Object?>) {
|
||||
final String jsonOfNewPluginsMap = jsonEncode(pluginsMap);
|
||||
final String jsonOfOldPluginsMap = jsonEncode(decodedJson[_kFlutterPluginsPluginListKey]);
|
||||
pluginsChanged = jsonOfNewPluginsMap != jsonOfOldPluginsMap;
|
||||
}
|
||||
} on FormatException catch (_) {}
|
||||
}
|
||||
final String pluginFileContent = json.encode(result);
|
||||
pluginsFile.writeAsStringSync(pluginFileContent, flush: true);
|
||||
|
@ -20,6 +20,7 @@ import 'package:flutter_tools/src/flutter_manifest.dart';
|
||||
import 'package:flutter_tools/src/flutter_plugins.dart';
|
||||
import 'package:flutter_tools/src/globals.dart' as globals;
|
||||
import 'package:flutter_tools/src/ios/xcodeproj.dart';
|
||||
import 'package:flutter_tools/src/macos/cocoapods.dart';
|
||||
import 'package:flutter_tools/src/macos/darwin_dependency_management.dart';
|
||||
import 'package:flutter_tools/src/platform_plugins.dart';
|
||||
import 'package:flutter_tools/src/plugins.dart';
|
||||
@ -102,6 +103,8 @@ void main() {
|
||||
late FakeLinuxProject linuxProject;
|
||||
late FakeSystemClock systemClock;
|
||||
late FlutterVersion flutterVersion;
|
||||
late FakeCocoaPodsCapturesInvalidate cocoaPods;
|
||||
|
||||
// A Windows-style filesystem. This is not populated by default, so tests
|
||||
// using it instead of fs must re-run any necessary setup (e.g.,
|
||||
// setUpProject).
|
||||
@ -190,6 +193,7 @@ void main() {
|
||||
fsWindows = MemoryFileSystem(style: FileSystemStyle.windows);
|
||||
systemClock = FakeSystemClock()..currentTime = DateTime(1970);
|
||||
flutterVersion = FakeFlutterVersion(frameworkVersion: '1.0.0');
|
||||
cocoaPods = FakeCocoaPodsCapturesInvalidate();
|
||||
|
||||
// Add basic properties to the Flutter project and subprojects
|
||||
setUpProject(fs);
|
||||
@ -628,6 +632,78 @@ dependencies:
|
||||
},
|
||||
);
|
||||
|
||||
testUsingContext(
|
||||
'Refreshing the plugin list for iOS/macOS projects invokes invalidatePodInstallOutput if the plugins changed',
|
||||
() async {
|
||||
// Refresh the plugin list (we have no plugins).
|
||||
await refreshPluginsList(flutterProject, iosPlatform: true, macOSPlatform: true);
|
||||
expect(
|
||||
cocoaPods.capturedInvocations,
|
||||
isEmpty,
|
||||
reason: 'No plugins exist, so no invalidatePodInstallOutput calls expected.',
|
||||
);
|
||||
|
||||
// Create an initial plugin (we previously had none).
|
||||
createPlugin(
|
||||
name: 'plugin-a',
|
||||
platforms: const <String, _PluginPlatformInfo>{
|
||||
'ios': _PluginPlatformInfo(
|
||||
pluginClass: 'Foo',
|
||||
dartPluginClass: 'Bar',
|
||||
sharedDarwinSource: true,
|
||||
),
|
||||
},
|
||||
);
|
||||
await refreshPluginsList(flutterProject, iosPlatform: true, macOSPlatform: true);
|
||||
expect(
|
||||
cocoaPods.capturedInvocations,
|
||||
containsAll(<Matcher>[isA<IosProject>(), isA<MacOSProject>()]),
|
||||
reason: 'A new plugin was added, so it should cause invalidatePodInstallOutput calls.',
|
||||
);
|
||||
cocoaPods.capturedInvocations.clear();
|
||||
|
||||
// Add a new plugin.
|
||||
createPlugin(
|
||||
name: 'plugin-b',
|
||||
platforms: const <String, _PluginPlatformInfo>{
|
||||
'ios': _PluginPlatformInfo(
|
||||
pluginClass: 'Foo',
|
||||
dartPluginClass: 'Bar',
|
||||
sharedDarwinSource: true,
|
||||
),
|
||||
},
|
||||
);
|
||||
await refreshPluginsList(flutterProject, iosPlatform: true, macOSPlatform: true);
|
||||
expect(
|
||||
cocoaPods.capturedInvocations,
|
||||
containsAll(<Matcher>[isA<IosProject>(), isA<MacOSProject>()]),
|
||||
reason: 'A new plugin was added, so it should cause invalidatePodInstallOutput calls.',
|
||||
);
|
||||
cocoaPods.capturedInvocations.clear();
|
||||
|
||||
// Do not add new plugins.
|
||||
await refreshPluginsList(flutterProject, iosPlatform: true, macOSPlatform: true);
|
||||
expect(
|
||||
cocoaPods.capturedInvocations,
|
||||
isEmpty,
|
||||
reason: 'No plugins changed, so no updates expected',
|
||||
);
|
||||
},
|
||||
overrides: <Type, Generator>{
|
||||
CocoaPods: () => cocoaPods,
|
||||
FileSystem: () => fs,
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
SystemClock: () => systemClock,
|
||||
FlutterVersion: () => flutterVersion,
|
||||
Pub: FakePubWithPrimedDeps.new,
|
||||
// TODO(matanlurey): Remove as part of https://github.com/flutter/flutter/issues/160257.
|
||||
// Not necessary, you can observe this bug by calling `generateLegacyPlugins: false`,
|
||||
// but since this flag is about to be enabled, and enabling it implicitly sets that
|
||||
// argument to false, this is a more "honest" test.
|
||||
FeatureFlags: enableExplicitPackageDependencies,
|
||||
},
|
||||
);
|
||||
|
||||
testUsingContext(
|
||||
'.flutter-plugins-dependencies contains plugin platform info',
|
||||
() async {
|
||||
@ -3004,3 +3080,13 @@ class FakeDarwinDependencyManagement extends Fake implements DarwinDependencyMan
|
||||
setupPlatforms.add(platform);
|
||||
}
|
||||
}
|
||||
|
||||
/// A fake of [CocoaPods] that writes calls to [invalidatePodInstallOutput] to [capturedInvocations].
|
||||
final class FakeCocoaPodsCapturesInvalidate extends Fake implements CocoaPods {
|
||||
final List<XcodeBasedProject> capturedInvocations = <XcodeBasedProject>[];
|
||||
|
||||
@override
|
||||
void invalidatePodInstallOutput(XcodeBasedProject xcodeProject) {
|
||||
capturedInvocations.add(xcodeProject);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user