Unverified Commit ddf63a8b authored by Jenn Magder's avatar Jenn Magder Committed by GitHub

Remove Finder extended attributes from iOS project files (#54488)

parent f646e26e
......@@ -105,6 +105,8 @@ Future<XcodeBuildResult> buildXcodeProject({
return XcodeBuildResult(success: false);
}
await removeFinderExtendedAttributes(app.project.hostAppRoot, processUtils, globals.logger);
final XcodeProjectInfo projectInfo = await globals.xcodeProjectInterpreter.getInfo(app.project.hostAppRoot.path);
if (!projectInfo.targets.contains('Runner')) {
globals.printError('The Xcode project does not define target "Runner" which is needed by Flutter tooling.');
......@@ -405,6 +407,25 @@ Future<XcodeBuildResult> buildXcodeProject({
}
}
/// Extended attributes applied by Finder can cause code signing errors. Remove them.
/// https://developer.apple.com/library/archive/qa/qa1940/_index.html
@visibleForTesting
Future<void> removeFinderExtendedAttributes(Directory iosProjectDirectory, ProcessUtils processUtils, Logger logger) async {
final bool success = await processUtils.exitsHappy(
<String>[
'xattr',
'-r',
'-d',
'com.apple.FinderInfo',
iosProjectDirectory.path,
]
);
// Ignore all errors, for example if directory is missing.
if (!success) {
logger.printTrace('Failed to remove xattr com.apple.FinderInfo from ${iosProjectDirectory.path}');
}
}
Future<RunResult> _runBuildWithRetries(List<String> buildCommands, BuildableIOSApp app) async {
int buildRetryDelaySeconds = 1;
int remainingTries = 8;
......
......@@ -22,6 +22,16 @@ import '../../src/common.dart';
import '../../src/context.dart';
import '../../src/fake_process_manager.dart';
List<String> _xattrArgs(FlutterProject flutterProject) {
return <String>[
'xattr',
'-r',
'-d',
'com.apple.FinderInfo',
flutterProject.ios.hostAppRoot.path,
];
}
const List<String> kRunReleaseArgs = <String>[
'/usr/bin/env',
'xcrun',
......@@ -74,6 +84,7 @@ void main() {
final FlutterProject flutterProject = FlutterProject.fromDirectory(fileSystem.currentDirectory);
final BuildableIOSApp buildableIOSApp = BuildableIOSApp(flutterProject.ios, 'flutter');
processManager.addCommand(FakeCommand(command: _xattrArgs(flutterProject)));
processManager.addCommand(const FakeCommand(command: kRunReleaseArgs));
processManager.addCommand(const FakeCommand(command: <String>[...kRunReleaseArgs, '-showBuildSettings']));
processManager.addCommand(FakeCommand(
......@@ -123,6 +134,7 @@ void main() {
final FlutterProject flutterProject = FlutterProject.fromDirectory(fileSystem.currentDirectory);
final BuildableIOSApp buildableIOSApp = BuildableIOSApp(flutterProject.ios, 'flutter');
processManager.addCommand(FakeCommand(command: _xattrArgs(flutterProject)));
processManager.addCommand(const FakeCommand(command: kRunReleaseArgs));
// The first showBuildSettings call should timeout.
processManager.addCommand(
......@@ -194,6 +206,7 @@ void main() {
final FlutterProject flutterProject = FlutterProject.fromDirectory(fileSystem.currentDirectory);
final BuildableIOSApp buildableIOSApp = BuildableIOSApp(flutterProject.ios, 'flutter');
processManager.addCommand(FakeCommand(command: _xattrArgs(flutterProject)));
// The first xcrun call should fail with a
// concurrent build exception.
processManager.addCommand(
......
......@@ -5,10 +5,12 @@
import 'dart:async';
import 'package:file/file.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/artifacts.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart' show ProcessResult;
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/process.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/ios/mac.dart';
import 'package:flutter_tools/src/ios/xcodeproj.dart';
......@@ -428,6 +430,46 @@ Exited (sigterm)''',
);
});
});
group('remove Finder extended attributes', () {
Directory iosProjectDirectory;
setUp(() {
final MemoryFileSystem fs = MemoryFileSystem.test();
iosProjectDirectory = fs.directory('ios');
});
testWithoutContext('removes xattr', () async {
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
FakeCommand(command: <String>[
'xattr',
'-r',
'-d',
'com.apple.FinderInfo',
iosProjectDirectory.path,
])
]);
await removeFinderExtendedAttributes(iosProjectDirectory, ProcessUtils(processManager: processManager, logger: logger), logger);
expect(processManager.hasRemainingExpectations, false);
});
testWithoutContext('ignores errors', () async {
final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
FakeCommand(command: <String>[
'xattr',
'-r',
'-d',
'com.apple.FinderInfo',
iosProjectDirectory.path,
], exitCode: 1,
)
]);
await removeFinderExtendedAttributes(iosProjectDirectory, ProcessUtils(processManager: processManager, logger: logger), logger);
expect(logger.traceText, contains('Failed to remove xattr com.apple.FinderInfo'));
expect(processManager.hasRemainingExpectations, false);
});
});
}
class MockUsage extends Mock implements Usage {}
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