Remove specific iOS extended attributes to fix code signing (#180710)
## Summary
Fixes #180351 by removing only the specific extended attributes that
cause iOS code signing failures, while preserving Xcode-required
metadata.
## Changes
- Updated `removeExtendedAttributes` to remove only:
- `com.apple.FinderInfo`
- `com.apple.provenance`
- Preserves `com.apple.xcode.CreatedByBuildSystem`, which Xcode relies
on for build directory management
- Updated all related tests to expect two targeted `xattr -r -d`
invocations
## Why
The previous approach in #180355 used `xattr -cr`, which removed **all**
extended attributes.
This unintentionally deleted `com.apple.xcode.CreatedByBuildSystem`,
causing Xcode post-submit failures related to build directory ownership.
This change applies the minimal fix needed to resolve the code signing
issue without breaking Xcode behavior.
## Testing
- [x] Code formatted with `dart format`
- [x] `flutter analyze` passes
- [x] Updated and passing iOS build and signing-related tests
Addresses feedback from @jmagman
---------
Co-authored-by: Navaron Bracke <brackenavaron@gmail.com>
Co-authored-by: Elijah Okoroh <okorohelijah@google.com>
diff --git a/packages/flutter_tools/lib/src/build_system/targets/ios.dart b/packages/flutter_tools/lib/src/build_system/targets/ios.dart
index 8e3d909..f5c7d73 100644
--- a/packages/flutter_tools/lib/src/build_system/targets/ios.dart
+++ b/packages/flutter_tools/lib/src/build_system/targets/ios.dart
@@ -914,7 +914,7 @@
}
Future<void> _signFramework(Environment environment, File binary, BuildMode buildMode) async {
- await removeFinderExtendedAttributes(
+ await removeExtendedAttributes(
binary,
ProcessUtils(processManager: environment.processManager, logger: environment.logger),
environment.logger,
diff --git a/packages/flutter_tools/lib/src/ios/mac.dart b/packages/flutter_tools/lib/src/ios/mac.dart
index c456365..99a10c8 100644
--- a/packages/flutter_tools/lib/src/ios/mac.dart
+++ b/packages/flutter_tools/lib/src/ios/mac.dart
@@ -196,7 +196,7 @@
return XcodeBuildResult(success: false);
}
- await removeFinderExtendedAttributes(
+ await removeExtendedAttributes(
app.project.parent.directory,
globals.processUtils,
globals.logger,
@@ -710,23 +710,36 @@
return headersChanged;
}
-/// Extended attributes applied by Finder can cause code signing errors. Remove them.
-/// https://developer.apple.com/library/archive/qa/qa1940/_index.html
-Future<void> removeFinderExtendedAttributes(
+/// Extended attributes can cause code signing errors. Remove them.
+///
+/// Attributes like `com.apple.FinderInfo` and `com.apple.provenance` are added
+/// by Finder, cloud storage services (OneDrive, iCloud, Dropbox), or when files
+/// are downloaded. These must be removed before code signing.
+///
+/// See: https://developer.apple.com/library/archive/qa/qa1940/_index.html
+/// See: https://github.com/flutter/flutter/issues/180351
+Future<void> removeExtendedAttributes(
FileSystemEntity projectDirectory,
ProcessUtils processUtils,
Logger logger,
) async {
- final bool success = await processUtils.exitsHappy(<String>[
- 'xattr',
- '-r',
- '-d',
- 'com.apple.FinderInfo',
- projectDirectory.path,
- ]);
- // Ignore all errors, for example if directory is missing.
- if (!success) {
- logger.printTrace('Failed to remove xattr com.apple.FinderInfo from ${projectDirectory.path}');
+ // Remove specific extended attributes that cause code signing failures.
+ // We remove com.apple.FinderInfo and com.apple.provenance, but preserve
+ // com.apple.xcode.CreatedByBuildSystem which Xcode uses to manage build directories.
+ const attributesToRemove = <String>{'com.apple.FinderInfo', 'com.apple.provenance'};
+
+ for (final attribute in attributesToRemove) {
+ final bool success = await processUtils.exitsHappy(<String>[
+ 'xattr',
+ '-r',
+ '-d',
+ attribute,
+ projectDirectory.path,
+ ]);
+ // Ignore all errors, for example if directory is missing or attribute doesn't exist.
+ if (!success) {
+ logger.printTrace('Failed to remove $attribute from ${projectDirectory.path}');
+ }
}
}
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/build_ios_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/build_ios_test.dart
index 2b9c33b..4efca7d 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/build_ios_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/build_ios_test.dart
@@ -107,9 +107,12 @@
createCoreMockProjectFiles();
}
- const xattrCommand = FakeCommand(
+ const xattrCommand1 = FakeCommand(
command: <String>['xattr', '-r', '-d', 'com.apple.FinderInfo', '/'],
);
+ const xattrCommand2 = FakeCommand(
+ command: <String>['xattr', '-r', '-d', 'com.apple.provenance', '/'],
+ );
FakeCommand setUpRsyncCommand({void Function(List<String> command)? onRun}) {
return FakeCommand(
@@ -304,7 +307,9 @@
FileSystem: () => fileSystem,
Pub: ThrowingPub.new,
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
onRun: (_) {
fileSystem
@@ -333,7 +338,9 @@
createMinimalMockProjectFiles();
processManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
onRun: (_) {
fileSystem
@@ -377,7 +384,9 @@
overrides: <Type, Generator>{
FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
disablePortPublication: true,
onRun: (_) {
@@ -415,7 +424,9 @@
overrides: <Type, Generator>{
FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
onRun: (_) {
fileSystem
@@ -444,7 +455,9 @@
);
processManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
customNaming: true,
onRun: (_) {
@@ -491,7 +504,9 @@
osUtils: FakeOperatingSystemUtils(),
);
processManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
deviceId: '1234',
onRun: (_) {
@@ -530,7 +545,9 @@
osUtils: FakeOperatingSystemUtils(),
);
processManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
simulator: true,
onRun: (_) {
@@ -569,7 +586,9 @@
);
createMinimalMockProjectFiles();
processManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
verbose: true,
onRun: (_) {
@@ -604,7 +623,9 @@
osUtils: FakeOperatingSystemUtils(),
);
processManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
onRun: (_) {
fileSystem
@@ -694,7 +715,9 @@
overrides: <Type, Generator>{
FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
onRun: (_) {
fileSystem
@@ -747,7 +770,9 @@
overrides: <Type, Generator>{
FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
onRun: (_) {
fileSystem
@@ -796,7 +821,9 @@
osUtils: FakeOperatingSystemUtils(),
);
processManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
exitCode: 1,
onRun: (_) {
@@ -838,7 +865,9 @@
osUtils: FakeOperatingSystemUtils(),
);
processManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
exitCode: 1,
onRun: (_) {
@@ -887,7 +916,9 @@
osUtils: FakeOperatingSystemUtils(),
);
processManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
exitCode: 1,
onRun: (_) {
@@ -941,7 +972,9 @@
osUtils: FakeOperatingSystemUtils(),
);
processManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(exitCode: 1),
setUpLegacyXCResultCommand(stdout: kSampleResultJsonWithIssues),
setUpRsyncCommand(),
@@ -980,7 +1013,9 @@
osUtils: FakeOperatingSystemUtils(),
);
processManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
exitCode: 1,
onRun: (_) {
@@ -1037,7 +1072,9 @@
osUtils: FakeOperatingSystemUtils(),
);
processManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
exitCode: 1,
onRun: (_) {
@@ -1085,7 +1122,9 @@
osUtils: FakeOperatingSystemUtils(),
);
processManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
exitCode: 1,
onRun: (_) {
@@ -1127,7 +1166,9 @@
osUtils: FakeOperatingSystemUtils(),
);
processManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
// Intentionally fail the first xcodebuild command with concurrent run failure message.
setUpFakeXcodeBuildHandler(
exitCode: 1,
@@ -1186,7 +1227,9 @@
osUtils: FakeOperatingSystemUtils(),
);
processManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
exitCode: 1,
stdout: '''
@@ -1231,7 +1274,9 @@
osUtils: FakeOperatingSystemUtils(),
);
processManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
exitCode: 1,
onRun: (_) {
@@ -1286,7 +1331,9 @@
overrides: <Type, Generator>{
FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
exitCode: 1,
stdout: '''
@@ -1318,7 +1365,9 @@
osUtils: FakeOperatingSystemUtils(),
);
processManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
exitCode: 1,
onRun: (_) {
@@ -1360,7 +1409,9 @@
osUtils: FakeOperatingSystemUtils(),
);
processManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
exitCode: 1,
onRun: (_) {
@@ -1404,7 +1455,9 @@
osUtils: FakeOperatingSystemUtils(),
);
processManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
exitCode: 1,
onRun: (_) {
@@ -1457,7 +1510,9 @@
osUtils: FakeOperatingSystemUtils(),
);
processManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
simulator: true,
exitCode: 1,
@@ -1502,7 +1557,9 @@
osUtils: FakeOperatingSystemUtils(),
);
processManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
simulator: true,
exitCode: 1,
@@ -1552,7 +1609,9 @@
);
processManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
simulator: true,
exitCode: 1,
@@ -1609,7 +1668,9 @@
osUtils: FakeOperatingSystemUtils(),
);
processManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(simulator: true, exitCode: 1),
setUpLegacyXCResultCommand(stdout: kSampleResultJsonWithIssues),
setUpRsyncCommand(),
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/build_ipa_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/build_ipa_test.dart
index 1c4294e..c3ccd25 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/build_ipa_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/build_ipa_test.dart
@@ -138,9 +138,12 @@
createCoreMockProjectFiles();
}
- const xattrCommand = FakeCommand(
+ const xattrCommand1 = FakeCommand(
command: <String>['xattr', '-r', '-d', 'com.apple.FinderInfo', '/'],
);
+ const xattrCommand2 = FakeCommand(
+ command: <String>['xattr', '-r', '-d', 'com.apple.provenance', '/'],
+ );
// Sets up xcresulttool command for Xcode versions below 16.
FakeCommand setUpLegacyXCResultCommand({
@@ -418,7 +421,9 @@
osUtils: FakeOperatingSystemUtils(),
);
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(),
exportArchiveCommand(exportOptionsPlist: _exportOptionsPlist),
]);
@@ -453,7 +458,9 @@
osUtils: FakeOperatingSystemUtils(),
);
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(),
exportArchiveCommand(
exportOptionsPlist: _exportOptionsPlist,
@@ -509,7 +516,9 @@
osUtils: FakeOperatingSystemUtils(),
);
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(),
exportArchiveCommand(
exportOptionsPlist: _exportOptionsPlist,
@@ -565,7 +574,9 @@
osUtils: FakeOperatingSystemUtils(),
);
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(),
exportArchiveCommand(
exportOptionsPlist: _exportOptionsPlist,
@@ -620,7 +631,9 @@
osUtils: FakeOperatingSystemUtils(),
);
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(),
exportArchiveCommand(exportOptionsPlist: _exportOptionsPlist),
]);
@@ -654,7 +667,9 @@
osUtils: FakeOperatingSystemUtils(),
);
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(),
exportArchiveCommand(
exportOptionsPlist: _exportOptionsPlist,
@@ -709,7 +724,9 @@
osUtils: FakeOperatingSystemUtils(),
);
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(),
exportArchiveCommand(exportOptionsPlist: _exportOptionsPlist),
]);
@@ -743,7 +760,9 @@
};
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(),
exportArchiveCommand(exportOptionsPlist: exportOptions.path),
]);
@@ -784,7 +803,9 @@
osUtils: FakeOperatingSystemUtils(),
);
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(),
const FakeCommand(
command: <String>[
@@ -844,7 +865,9 @@
osUtils: FakeOperatingSystemUtils(),
);
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(),
exportArchiveCommand(
exportOptionsPlist: _exportOptionsPlist,
@@ -880,7 +903,9 @@
osUtils: FakeOperatingSystemUtils(),
);
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(),
exportArchiveCommand(
exportOptionsPlist: _exportOptionsPlist,
@@ -939,7 +964,9 @@
osUtils: FakeOperatingSystemUtils(),
);
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(),
exportArchiveCommand(
exportOptionsPlist: _exportOptionsPlist,
@@ -1000,7 +1027,9 @@
osUtils: FakeOperatingSystemUtils(),
);
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(),
exportArchiveCommand(
exportOptionsPlist: _exportOptionsPlist,
@@ -1060,7 +1089,9 @@
osUtils: FakeOperatingSystemUtils(),
);
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(verbose: true),
exportArchiveCommand(exportOptionsPlist: _exportOptionsPlist),
]);
@@ -1091,7 +1122,9 @@
osUtils: FakeOperatingSystemUtils(),
);
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(),
exportArchiveCommand(exportOptionsPlist: _exportOptionsPlist),
]);
@@ -1123,7 +1156,9 @@
osUtils: FakeOperatingSystemUtils(),
);
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
const FakeCommand(
command: <String>[
'xcrun',
@@ -1221,7 +1256,9 @@
..createSync(recursive: true)
..writeAsBytesSync(List<int>.generate(10000, (int index) => 0));
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
onRun: (_) {
fileSystem.file('build/flutter_size_01/snapshot.arm64.json')
@@ -1280,7 +1317,9 @@
osUtils: FakeOperatingSystemUtils(),
);
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(),
exportArchiveCommand(),
]);
@@ -1323,7 +1362,9 @@
osUtils: FakeOperatingSystemUtils(),
);
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
exitCode: 1,
onRun: (_) {
@@ -1364,7 +1405,9 @@
osUtils: FakeOperatingSystemUtils(),
);
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
exitCode: 1,
onRun: (_) {
@@ -1409,7 +1452,9 @@
osUtils: FakeOperatingSystemUtils(),
);
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
exitCode: 1,
onRun: (_) {
@@ -1462,7 +1507,9 @@
osUtils: FakeOperatingSystemUtils(),
);
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(exitCode: 1),
]);
createMinimalMockProjectFiles();
@@ -1500,7 +1547,9 @@
osUtils: FakeOperatingSystemUtils(),
);
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
exitCode: 1,
onRun: (_) {
@@ -1551,7 +1600,9 @@
const plistPath =
'build/ios/archive/Runner.xcarchive/Products/Applications/Runner.app/Info.plist';
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
onRun: (_) {
fileSystem.file(plistPath).createSync(recursive: true);
@@ -1610,7 +1661,9 @@
const plistPath =
'build/ios/archive/Runner.xcarchive/Products/Applications/Runner.app/Info.plist';
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
onRun: (_) {
fileSystem.file(plistPath).createSync(recursive: true);
@@ -1674,7 +1727,9 @@
const plistPath =
'build/ios/archive/Runner.xcarchive/Products/Applications/Runner.app/Info.plist';
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
onRun: (_) {
fileSystem.file(plistPath).createSync(recursive: true);
@@ -1737,7 +1792,9 @@
const plistPath =
'build/ios/archive/Runner.xcarchive/Products/Applications/Runner.app/Info.plist';
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
onRun: (_) {
fileSystem.file(plistPath).createSync(recursive: true);
@@ -1786,7 +1843,9 @@
const plistPath =
'build/ios/archive/Runner.xcarchive/Products/Applications/Runner.app/Info.plist';
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
onRun: (_) {
fileSystem.file(plistPath).createSync(recursive: true);
@@ -1844,7 +1903,9 @@
'/flutter_template_images/templates/app/ios.tmpl/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png';
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
onRun: (_) {
fileSystem.file(templateIconContentsJsonPath)
@@ -1937,7 +1998,9 @@
'/flutter_template_images/templates/app/ios.tmpl/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png';
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
onRun: (_) {
fileSystem.file(templateIconContentsJsonPath)
@@ -2026,7 +2089,9 @@
'ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png';
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
onRun: (_) {
fileSystem.file(projectIconContentsJsonPath)
@@ -2101,7 +2166,9 @@
'ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png';
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
onRun: (_) {
fileSystem.file(projectIconContentsJsonPath)
@@ -2176,7 +2243,9 @@
'ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png';
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
onRun: (_) {
fileSystem.file(projectIconContentsJsonPath)
@@ -2251,7 +2320,9 @@
'ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png';
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
onRun: (_) {
// Uses unknown format version 123.
@@ -2334,7 +2405,9 @@
];
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
onRun: (_) {
// The following json contains examples of:
@@ -2453,7 +2526,9 @@
'/flutter_template_images/templates/app/ios.tmpl/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png';
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
onRun: (_) {
fileSystem.file(templateLaunchImageContentsJsonPath)
@@ -2544,7 +2619,9 @@
'/flutter_template_images/templates/app/ios.tmpl/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png';
fakeProcessManager.addCommands(<FakeCommand>[
- xattrCommand,
+ xattrCommand1,
+
+ xattrCommand2,
setUpFakeXcodeBuildHandler(
onRun: (_) {
fileSystem.file(templateLaunchImageContentsJsonPath)
diff --git a/packages/flutter_tools/test/general.shard/build_system/targets/ios_test.dart b/packages/flutter_tools/test/general.shard/build_system/targets/ios_test.dart
index 4bef0c3..fdd54a8 100644
--- a/packages/flutter_tools/test/general.shard/build_system/targets/ios_test.dart
+++ b/packages/flutter_tools/test/general.shard/build_system/targets/ios_test.dart
@@ -137,6 +137,9 @@
command: <String>['xattr', '-r', '-d', 'com.apple.FinderInfo', appFrameworkPath],
),
FakeCommand(
+ command: <String>['xattr', '-r', '-d', 'com.apple.provenance', appFrameworkPath],
+ ),
+ FakeCommand(
command: <String>[
'codesign',
'--force',
@@ -189,6 +192,9 @@
command: <String>['xattr', '-r', '-d', 'com.apple.FinderInfo', appFrameworkPath],
),
FakeCommand(
+ command: <String>['xattr', '-r', '-d', 'com.apple.provenance', appFrameworkPath],
+ ),
+ FakeCommand(
command: <String>[
'codesign',
'--force',
@@ -259,6 +265,9 @@
command: <String>['xattr', '-r', '-d', 'com.apple.FinderInfo', frameworkBinary.path],
),
FakeCommand(
+ command: <String>['xattr', '-r', '-d', 'com.apple.provenance', frameworkBinary.path],
+ ),
+ FakeCommand(
command: <String>[
'codesign',
'--force',
@@ -333,6 +342,15 @@
),
FakeCommand(
command: <String>[
+ 'xattr',
+ '-r',
+ '-d',
+ 'com.apple.provenance',
+ frameworkDirectoryBinary.path,
+ ],
+ ),
+ FakeCommand(
+ command: <String>[
'codesign',
'--force',
'--sign',
@@ -425,6 +443,15 @@
),
FakeCommand(
command: <String>[
+ 'xattr',
+ '-r',
+ '-d',
+ 'com.apple.provenance',
+ frameworkDirectoryBinary.path,
+ ],
+ ),
+ FakeCommand(
+ command: <String>[
'codesign',
'--force',
'--sign',
@@ -527,6 +554,15 @@
),
FakeCommand(
command: <String>[
+ 'xattr',
+ '-r',
+ '-d',
+ 'com.apple.provenance',
+ frameworkDirectoryBinary.path,
+ ],
+ ),
+ FakeCommand(
+ command: <String>[
'codesign',
'--force',
'--sign',
@@ -603,6 +639,15 @@
),
FakeCommand(
command: <String>[
+ 'xattr',
+ '-r',
+ '-d',
+ 'com.apple.provenance',
+ frameworkDirectoryBinary.path,
+ ],
+ ),
+ FakeCommand(
+ command: <String>[
'codesign',
'--force',
'--sign',
@@ -672,6 +717,15 @@
],
),
FakeCommand(
+ command: <String>[
+ 'xattr',
+ '-r',
+ '-d',
+ 'com.apple.provenance',
+ frameworkDirectoryBinary.path,
+ ],
+ ),
+ FakeCommand(
command: <String>['codesign', '--force', '--sign', '-', frameworkDirectoryBinary.path],
),
]);
diff --git a/packages/flutter_tools/test/general.shard/ios/ios_device_start_nonprebuilt_test.dart b/packages/flutter_tools/test/general.shard/ios/ios_device_start_nonprebuilt_test.dart
index 0b9be1e..6b54f04 100644
--- a/packages/flutter_tools/test/general.shard/ios/ios_device_start_nonprebuilt_test.dart
+++ b/packages/flutter_tools/test/general.shard/ios/ios_device_start_nonprebuilt_test.dart
@@ -40,8 +40,16 @@
import '../../src/package_config.dart';
import '../../src/throwing_pub.dart';
-List<String> _xattrArgs(FlutterProject flutterProject) {
- return <String>['xattr', '-r', '-d', 'com.apple.FinderInfo', flutterProject.directory.path];
+// Helper to generate xattr commands for removing specific extended attributes
+List<FakeCommand> xattrCommands(FlutterProject flutterProject) {
+ return <FakeCommand>[
+ FakeCommand(
+ command: <String>['xattr', '-r', '-d', 'com.apple.FinderInfo', flutterProject.directory.path],
+ ),
+ FakeCommand(
+ command: <String>['xattr', '-r', '-d', 'com.apple.provenance', flutterProject.directory.path],
+ ),
+ ];
}
const kRunReleaseArgs = <String>[
@@ -136,7 +144,7 @@
'My Super Awesome App',
);
- processManager.addCommand(FakeCommand(command: _xattrArgs(flutterProject)));
+ processManager.addCommands(xattrCommands(flutterProject));
processManager.addCommand(const FakeCommand(command: kRunReleaseArgs));
final LaunchResult launchResult = await iosDevice.startApp(
@@ -243,7 +251,7 @@
.directory('build/ios/Release-iphoneos/My Super Awesome App.app')
.createSync(recursive: true);
- processManager.addCommand(FakeCommand(command: _xattrArgs(flutterProject)));
+ processManager.addCommands(xattrCommands(flutterProject));
processManager.addCommand(const FakeCommand(command: kRunReleaseArgs));
processManager.addCommand(
const FakeCommand(
@@ -330,7 +338,7 @@
.directory('build/ios/Release-iphoneos/My Super Awesome App.app')
.createSync(recursive: true);
- processManager.addCommand(FakeCommand(command: _xattrArgs(flutterProject)));
+ processManager.addCommands(xattrCommands(flutterProject));
processManager.addCommand(
const FakeCommand(
command: <String>[
@@ -467,7 +475,7 @@
.childFile('FlutterPlugin.h')
.createSync(recursive: true);
processManager.addCommands([
- FakeCommand(command: _xattrArgs(flutterProject)),
+ ...xattrCommands(flutterProject),
FakeCommand(
command: const <String>[
'xcrun',
@@ -572,7 +580,7 @@
.childFile('FlutterPlugin.h')
.createSync(recursive: true);
processManager.addCommands([
- FakeCommand(command: _xattrArgs(flutterProject)),
+ ...xattrCommands(flutterProject),
const FakeCommand(
command: <String>[
'xcrun',
@@ -647,7 +655,7 @@
'My Super Awesome App',
);
- processManager.addCommand(FakeCommand(command: _xattrArgs(flutterProject)));
+ processManager.addCommands(xattrCommands(flutterProject));
// The first xcrun call should fail with a
// concurrent build exception.
processManager.addCommand(
diff --git a/packages/flutter_tools/test/general.shard/ios/mac_test.dart b/packages/flutter_tools/test/general.shard/ios/mac_test.dart
index dbfca57..8e1ec42 100644
--- a/packages/flutter_tools/test/general.shard/ios/mac_test.dart
+++ b/packages/flutter_tools/test/general.shard/ios/mac_test.dart
@@ -761,7 +761,7 @@
});
});
- group('remove Finder extended attributes', () {
+ group('remove extended attributes', () {
late Directory projectDirectory;
setUp(() {
final fs = MemoryFileSystem.test();
@@ -773,9 +773,12 @@
FakeCommand(
command: <String>['xattr', '-r', '-d', 'com.apple.FinderInfo', projectDirectory.path],
),
+ FakeCommand(
+ command: <String>['xattr', '-r', '-d', 'com.apple.provenance', projectDirectory.path],
+ ),
]);
- await removeFinderExtendedAttributes(
+ await removeExtendedAttributes(
projectDirectory,
ProcessUtils(processManager: processManager, logger: logger),
logger,
@@ -789,14 +792,19 @@
command: <String>['xattr', '-r', '-d', 'com.apple.FinderInfo', projectDirectory.path],
exitCode: 1,
),
+ FakeCommand(
+ command: <String>['xattr', '-r', '-d', 'com.apple.provenance', projectDirectory.path],
+ exitCode: 1,
+ ),
]);
- await removeFinderExtendedAttributes(
+ await removeExtendedAttributes(
projectDirectory,
ProcessUtils(processManager: processManager, logger: logger),
logger,
);
- expect(logger.traceText, contains('Failed to remove xattr com.apple.FinderInfo'));
+ expect(logger.traceText, contains('Failed to remove com.apple.FinderInfo'));
+ expect(logger.traceText, contains('Failed to remove com.apple.provenance'));
expect(processManager, hasNoRemainingExpectations);
});
});