Unverified Commit 378387b1 authored by Victoria Ashworth's avatar Victoria Ashworth Committed by GitHub

when getting xcworkspace, exclude hidden files (#114099)

* exclude xcworkspace that begins with a period

* fix if spacing, add comment

* add unit test for when no xcworkspace found

* update to use xcodeWorkspace, make it nullable and refactor

* check if hostAppRoot exists before trying to get xcworkspace

* use local variables to take advantage of type promotion

* only check if not null, don't need to check if exists

* readd exist check for migrate

* readd missing line at end of file
parent 77c06c2c
......@@ -71,7 +71,8 @@ class CleanCommand extends FlutterCommand {
}
Future<void> _cleanXcode(XcodeBasedProject xcodeProject) async {
if (!xcodeProject.existsSync()) {
final Directory? xcodeWorkspace = xcodeProject.xcodeWorkspace;
if (xcodeWorkspace == null) {
return;
}
final Status xcodeStatus = globals.logger.startProgress(
......@@ -79,7 +80,6 @@ class CleanCommand extends FlutterCommand {
);
try {
final XcodeProjectInterpreter xcodeProjectInterpreter = globals.xcodeProjectInterpreter!;
final Directory xcodeWorkspace = xcodeProject.xcodeWorkspace;
final XcodeProjectInfo projectInfo = (await xcodeProjectInterpreter.getInfo(xcodeWorkspace.parent.path))!;
for (final String scheme in projectInfo.schemes) {
await xcodeProjectInterpreter.cleanWorkspace(xcodeWorkspace.path, scheme, verbose: _verbose);
......
......@@ -250,17 +250,14 @@ Future<XcodeBuildResult> buildXcodeProject({
buildCommands.add('-allowProvisioningDeviceRegistration');
}
final List<FileSystemEntity> contents = app.project.hostAppRoot.listSync();
for (final FileSystemEntity entity in contents) {
if (globals.fs.path.extension(entity.path) == '.xcworkspace') {
final Directory? workspacePath = app.project.xcodeWorkspace;
if (workspacePath != null) {
buildCommands.addAll(<String>[
'-workspace', globals.fs.path.basename(entity.path),
'-workspace', workspacePath.basename,
'-scheme', scheme,
if (buildAction != XcodeBuildAction.archive) // dSYM files aren't copied to the archive if BUILD_DIR is set.
'BUILD_DIR=${globals.fs.path.absolute(getIosBuildDirectory())}',
]);
break;
}
}
// Check if the project contains a watchOS companion app.
......
......@@ -15,16 +15,17 @@ class XcodeBuildSystemMigration extends ProjectMigrator {
super.logger,
) : _xcodeWorkspaceSharedSettings = project.xcodeWorkspaceSharedSettings;
final File _xcodeWorkspaceSharedSettings;
final File? _xcodeWorkspaceSharedSettings;
@override
void migrate() {
if (!_xcodeWorkspaceSharedSettings.existsSync()) {
final File? xcodeWorkspaceSharedSettings = _xcodeWorkspaceSharedSettings;
if (xcodeWorkspaceSharedSettings == null || !xcodeWorkspaceSharedSettings.existsSync()) {
logger.printTrace('Xcode workspace settings not found, skipping build system migration');
return;
}
final String contents = _xcodeWorkspaceSharedSettings.readAsStringSync();
final String contents = xcodeWorkspaceSharedSettings.readAsStringSync();
// Only delete this file when it is pointing to the legacy build system.
const String legacyBuildSettingsWorkspace = '''
......@@ -33,8 +34,8 @@ class XcodeBuildSystemMigration extends ProjectMigrator {
// contains instead of equals to ignore newline file ending variance.
if (contents.contains(legacyBuildSettingsWorkspace)) {
logger.printStatus('Legacy build system detected, removing ${_xcodeWorkspaceSharedSettings.path}');
_xcodeWorkspaceSharedSettings.deleteSync();
logger.printStatus('Legacy build system detected, removing ${xcodeWorkspaceSharedSettings.path}');
xcodeWorkspaceSharedSettings.deleteSync();
}
}
}
......@@ -36,7 +36,8 @@ Future<void> buildMacOS({
required bool verboseLogging,
SizeAnalyzer? sizeAnalyzer,
}) async {
if (!flutterProject.macos.xcodeWorkspace.existsSync()) {
final Directory? xcodeWorkspace = flutterProject.macos.xcodeWorkspace;
if (xcodeWorkspace == null) {
throwToolExit('No macOS desktop project configured. '
'See https://docs.flutter.dev/desktop#add-desktop-support-to-an-existing-flutter-app '
'to learn about adding macOS support to a project.');
......@@ -106,7 +107,7 @@ Future<void> buildMacOS({
'/usr/bin/env',
'xcrun',
'xcodebuild',
'-workspace', flutterProject.macos.xcodeWorkspace.path,
'-workspace', xcodeWorkspace.path,
'-configuration', configuration,
'-scheme', 'Runner',
'-derivedDataPath', flutterBuildDir.absolute.path,
......
......@@ -47,13 +47,26 @@ abstract class XcodeBasedProject extends FlutterProjectPlatform {
.childFile('contents.xcworkspacedata');
/// The Xcode workspace (.xcworkspace directory) of the host app.
Directory get xcodeWorkspace => hostAppRoot.childDirectory('$_hostAppProjectName.xcworkspace');
Directory? get xcodeWorkspace {
if (!hostAppRoot.existsSync()) {
return null;
}
final List<FileSystemEntity> contents = hostAppRoot.listSync();
for (final FileSystemEntity entity in contents) {
// On certain volume types, there is sometimes a stray `._Runner.xcworkspace` file.
// Find the first non-hidden xcworkspace and return the directory.
if (globals.fs.path.extension(entity.path) == '.xcworkspace' && !globals.fs.path.basename(entity.path).startsWith('.')) {
return hostAppRoot.childDirectory(entity.basename);
}
}
return null;
}
/// Xcode workspace shared data directory for the host app.
Directory get xcodeWorkspaceSharedData => xcodeWorkspace.childDirectory('xcshareddata');
Directory? get xcodeWorkspaceSharedData => xcodeWorkspace?.childDirectory('xcshareddata');
/// Xcode workspace shared workspace settings file for the host app.
File get xcodeWorkspaceSharedSettings => xcodeWorkspaceSharedData.childFile('WorkspaceSettings.xcsettings');
File? get xcodeWorkspaceSharedSettings => xcodeWorkspaceSharedData?.childFile('WorkspaceSettings.xcsettings');
/// Contains definitions for FLUTTER_ROOT, LOCAL_ENGINE, and more flags for
/// the Xcode build.
......
......@@ -99,7 +99,7 @@ void main() {
'/usr/bin/env',
'xcrun',
'xcodebuild',
'-workspace', flutterProject.macos.xcodeWorkspace.path,
'-workspace', flutterProject.macos.xcodeWorkspace!.path,
'-configuration', configuration,
'-scheme', 'Runner',
'-derivedDataPath', flutterBuildDir.absolute.path,
......@@ -337,6 +337,7 @@ STDERR STUFF
final FlutterProject flutterProject = FlutterProject.fromDirectory(fileSystem.currentDirectory);
final Directory flutterBuildDir = fileSystem.directory(getMacOSBuildDirectory());
createMinimalMockProjectFiles();
fakeProcessManager.addCommands(<FakeCommand>[
FakeCommand(
......@@ -344,7 +345,7 @@ STDERR STUFF
'/usr/bin/env',
'xcrun',
'xcodebuild',
'-workspace', flutterProject.macos.xcodeWorkspace.path,
'-workspace', flutterProject.macos.xcodeWorkspace!.path,
'-configuration', 'Debug',
'-scheme', 'Runner',
'-derivedDataPath', flutterBuildDir.absolute.path,
......@@ -359,7 +360,6 @@ STDERR STUFF
]);
final BuildCommand command = BuildCommand();
createMinimalMockProjectFiles();
await createTestCommandRunner(command).run(
const <String>['build', 'macos', '--debug', '--no-pub']
......
......@@ -44,7 +44,7 @@ void main() {
});
testUsingContext('$CleanCommand removes build and .dart_tool and ephemeral directories, cleans Xcode for iOS and macOS', () async {
final FlutterProject projectUnderTest = setupProjectUnderTest(fs.currentDirectory);
final FlutterProject projectUnderTest = setupProjectUnderTest(fs.currentDirectory, true);
// Xcode is installed and version satisfactory.
xcodeProjectInterpreter.isInstalled = true;
xcodeProjectInterpreter.version = Version(1000, 0, 0);
......@@ -81,8 +81,23 @@ void main() {
XcodeProjectInterpreter: () => xcodeProjectInterpreter,
});
testUsingContext('$CleanCommand does not run when there is no xcworkspace', () async {
setupProjectUnderTest(fs.currentDirectory, false);
// Xcode is installed and version satisfactory.
xcodeProjectInterpreter.isInstalled = true;
xcodeProjectInterpreter.version = Version(1000, 0, 0);
await CleanCommand().runCommand();
expect(xcodeProjectInterpreter.workspaces, const <CleanWorkspaceCall>[]);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
Xcode: () => xcode,
XcodeProjectInterpreter: () => xcodeProjectInterpreter,
});
testUsingContext('$CleanCommand cleans Xcode verbosely for iOS and macOS', () async {
setupProjectUnderTest(fs.currentDirectory);
setupProjectUnderTest(fs.currentDirectory, true);
// Xcode is installed and version satisfactory.
xcodeProjectInterpreter.isInstalled = true;
xcodeProjectInterpreter.version = Version(1000, 0, 0);
......@@ -154,12 +169,13 @@ void main() {
});
}
FlutterProject setupProjectUnderTest(Directory currentDirectory) {
FlutterProject setupProjectUnderTest(Directory currentDirectory, bool setupXcodeWorkspace) {
// This needs to be run within testWithoutContext and not setUp since FlutterProject uses context.
final FlutterProject projectUnderTest = FlutterProject.fromDirectory(currentDirectory);
projectUnderTest.ios.xcodeWorkspace.createSync(recursive: true);
projectUnderTest.macos.xcodeWorkspace.createSync(recursive: true);
if (setupXcodeWorkspace == true) {
projectUnderTest.ios.hostAppRoot.childDirectory('Runner.xcworkspace').createSync(recursive: true);
projectUnderTest.macos.hostAppRoot.childDirectory('Runner.xcworkspace').createSync(recursive: true);
}
projectUnderTest.dartTool.createSync(recursive: true);
projectUnderTest.packagesFile.createSync(recursive: true);
projectUnderTest.android.ephemeralDirectory.createSync(recursive: true);
......
......@@ -208,6 +208,20 @@ keep this 2
expect(testLogger.statusText, isEmpty);
});
testWithoutContext('skipped if _xcodeWorkspaceSharedSettings is null', () {
final XcodeBuildSystemMigration iosProjectMigration = XcodeBuildSystemMigration(
project,
testLogger,
);
project.xcodeWorkspaceSharedSettings = null;
iosProjectMigration.migrate();
expect(xcodeWorkspaceSharedSettings.existsSync(), isFalse);
expect(testLogger.traceText, contains('Xcode workspace settings not found, skipping build system migration'));
expect(testLogger.statusText, isEmpty);
});
testWithoutContext('skipped if nothing to upgrade', () {
const String contents = '''
<?xml version="1.0" encoding="UTF-8"?>
......@@ -995,7 +1009,7 @@ class FakeIosProject extends Fake implements IosProject {
File xcodeProjectWorkspaceData = MemoryFileSystem.test().file('xcodeProjectWorkspaceData');
@override
File xcodeWorkspaceSharedSettings = MemoryFileSystem.test().file('xcodeWorkspaceSharedSettings');
File? xcodeWorkspaceSharedSettings = MemoryFileSystem.test().file('xcodeWorkspaceSharedSettings');
@override
File xcodeProjectInfoFile = MemoryFileSystem.test().file('xcodeProjectInfoFile');
......
......@@ -350,6 +350,19 @@ void main() {
expect(versionInfo['build_number'],'3');
expect(versionInfo['package_name'],'test');
});
_testInMemory('gets xcworkspace directory', () async {
final FlutterProject project = await someProject();
project.ios.xcodeProject.createSync();
project.ios.hostAppRoot.childFile('._Runner.xcworkspace').createSync(recursive: true);
project.ios.hostAppRoot.childFile('Runner.xcworkspace').createSync(recursive: true);
expect(project.ios.xcodeWorkspace?.basename, 'Runner.xcworkspace');
});
_testInMemory('no xcworkspace directory found', () async {
final FlutterProject project = await someProject();
project.ios.xcodeProject.createSync();
expect(project.ios.xcodeWorkspace?.basename, null);
});
});
group('module status', () {
......
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