mirror of
https://github.com/flutter/flutter
synced 2024-10-13 03:32:55 +00:00
Tool exit on xcodebuild -list when Xcode project is corrupted (#82476)
This commit is contained in:
parent
4adf36a07b
commit
8334fb0a1e
|
@ -235,6 +235,9 @@ class XcodeProjectInterpreter {
|
||||||
// * -project is passed and the given project isn't there, or
|
// * -project is passed and the given project isn't there, or
|
||||||
// * no -project is passed and there isn't a project.
|
// * no -project is passed and there isn't a project.
|
||||||
const int missingProjectExitCode = 66;
|
const int missingProjectExitCode = 66;
|
||||||
|
// The exit code returned by 'xcodebuild -list' when the project is corrupted.
|
||||||
|
const int corruptedProjectExitCode = 74;
|
||||||
|
bool _allowedFailures(int c) => c == missingProjectExitCode || c == corruptedProjectExitCode;
|
||||||
final RunResult result = await _processUtils.run(
|
final RunResult result = await _processUtils.run(
|
||||||
<String>[
|
<String>[
|
||||||
...xcrunCommand(),
|
...xcrunCommand(),
|
||||||
|
@ -243,10 +246,11 @@ class XcodeProjectInterpreter {
|
||||||
if (projectFilename != null) ...<String>['-project', projectFilename],
|
if (projectFilename != null) ...<String>['-project', projectFilename],
|
||||||
],
|
],
|
||||||
throwOnError: true,
|
throwOnError: true,
|
||||||
allowedFailures: (int c) => c == missingProjectExitCode,
|
allowedFailures: _allowedFailures,
|
||||||
workingDirectory: projectPath,
|
workingDirectory: projectPath,
|
||||||
);
|
);
|
||||||
if (result.exitCode == missingProjectExitCode) {
|
if (_allowedFailures(result.exitCode)) {
|
||||||
|
// User configuration error, tool exit instead of crashing.
|
||||||
throwToolExit('Unable to get Xcode project information:\n ${result.stderr}');
|
throwToolExit('Unable to get Xcode project information:\n ${result.stderr}');
|
||||||
}
|
}
|
||||||
return XcodeProjectInfo.fromXcodeBuildOutput(result.toString(), _logger);
|
return XcodeProjectInfo.fromXcodeBuildOutput(result.toString(), _logger);
|
||||||
|
|
|
@ -19,6 +19,7 @@ import 'package:flutter_tools/src/reporting/reporting.dart';
|
||||||
|
|
||||||
import '../../src/common.dart';
|
import '../../src/common.dart';
|
||||||
import '../../src/context.dart';
|
import '../../src/context.dart';
|
||||||
|
import '../../src/fake_process_manager.dart';
|
||||||
|
|
||||||
const String xcodebuild = '/usr/bin/xcodebuild';
|
const String xcodebuild = '/usr/bin/xcodebuild';
|
||||||
|
|
||||||
|
@ -80,7 +81,7 @@ void main() {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(xcodeProjectInterpreter.versionText, isNull);
|
expect(xcodeProjectInterpreter.versionText, isNull);
|
||||||
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
|
expect(fakeProcessManager, hasNoRemainingExpectations);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWithoutContext('xcodebuild versionText returns null when xcodebuild is not installed', () {
|
testWithoutContext('xcodebuild versionText returns null when xcodebuild is not installed', () {
|
||||||
|
@ -107,7 +108,7 @@ void main() {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(xcodeProjectInterpreter.versionText, 'Xcode 8.3.3, Build version 8E3004b');
|
expect(xcodeProjectInterpreter.versionText, 'Xcode 8.3.3, Build version 8E3004b');
|
||||||
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
|
expect(fakeProcessManager, hasNoRemainingExpectations);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWithoutContext('xcodebuild versionText handles Xcode version string with unexpected format', () {
|
testWithoutContext('xcodebuild versionText handles Xcode version string with unexpected format', () {
|
||||||
|
@ -121,7 +122,7 @@ void main() {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(xcodeProjectInterpreter.versionText, 'Xcode Ultra5000, Build version 8E3004b');
|
expect(xcodeProjectInterpreter.versionText, 'Xcode Ultra5000, Build version 8E3004b');
|
||||||
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
|
expect(fakeProcessManager, hasNoRemainingExpectations);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWithoutContext('xcodebuild version parts can be parsed', () {
|
testWithoutContext('xcodebuild version parts can be parsed', () {
|
||||||
|
@ -135,7 +136,7 @@ void main() {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(xcodeProjectInterpreter.version, Version(11, 4, 1));
|
expect(xcodeProjectInterpreter.version, Version(11, 4, 1));
|
||||||
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
|
expect(fakeProcessManager, hasNoRemainingExpectations);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWithoutContext('xcodebuild minor and patch version default to 0', () {
|
testWithoutContext('xcodebuild minor and patch version default to 0', () {
|
||||||
|
@ -149,7 +150,7 @@ void main() {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(xcodeProjectInterpreter.version, Version(11, 0, 0));
|
expect(xcodeProjectInterpreter.version, Version(11, 0, 0));
|
||||||
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
|
expect(fakeProcessManager, hasNoRemainingExpectations);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWithoutContext('xcodebuild version parts is null when version has unexpected format', () {
|
testWithoutContext('xcodebuild version parts is null when version has unexpected format', () {
|
||||||
|
@ -162,7 +163,7 @@ void main() {
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
expect(xcodeProjectInterpreter.version, isNull);
|
expect(xcodeProjectInterpreter.version, isNull);
|
||||||
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
|
expect(fakeProcessManager, hasNoRemainingExpectations);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWithoutContext('xcodebuild isInstalled is false when not on MacOS', () {
|
testWithoutContext('xcodebuild isInstalled is false when not on MacOS', () {
|
||||||
|
@ -177,14 +178,14 @@ void main() {
|
||||||
fileSystem.file(xcodebuild).deleteSync();
|
fileSystem.file(xcodebuild).deleteSync();
|
||||||
|
|
||||||
expect(xcodeProjectInterpreter.isInstalled, isFalse);
|
expect(xcodeProjectInterpreter.isInstalled, isFalse);
|
||||||
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
|
expect(fakeProcessManager, hasNoRemainingExpectations);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWithoutContext('xcodebuild isInstalled is false when xcodebuild does not exist', () {
|
testWithoutContext('xcodebuild isInstalled is false when xcodebuild does not exist', () {
|
||||||
fileSystem.file(xcodebuild).deleteSync();
|
fileSystem.file(xcodebuild).deleteSync();
|
||||||
|
|
||||||
expect(xcodeProjectInterpreter.isInstalled, isFalse);
|
expect(xcodeProjectInterpreter.isInstalled, isFalse);
|
||||||
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
|
expect(fakeProcessManager, hasNoRemainingExpectations);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWithoutContext(
|
testWithoutContext(
|
||||||
|
@ -202,7 +203,7 @@ void main() {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(xcodeProjectInterpreter.isInstalled, isFalse);
|
expect(xcodeProjectInterpreter.isInstalled, isFalse);
|
||||||
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
|
expect(fakeProcessManager, hasNoRemainingExpectations);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWithoutContext('xcodebuild isInstalled is false when version has unexpected format', () {
|
testWithoutContext('xcodebuild isInstalled is false when version has unexpected format', () {
|
||||||
|
@ -216,7 +217,7 @@ void main() {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(xcodeProjectInterpreter.isInstalled, isFalse);
|
expect(xcodeProjectInterpreter.isInstalled, isFalse);
|
||||||
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
|
expect(fakeProcessManager, hasNoRemainingExpectations);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWithoutContext('xcodebuild isInstalled is true when version has expected format', () {
|
testWithoutContext('xcodebuild isInstalled is true when version has expected format', () {
|
||||||
|
@ -230,7 +231,7 @@ void main() {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(xcodeProjectInterpreter.isInstalled, isTrue);
|
expect(xcodeProjectInterpreter.isInstalled, isTrue);
|
||||||
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
|
expect(fakeProcessManager, hasNoRemainingExpectations);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWithoutContext('xcrun runs natively on arm64', () {
|
testWithoutContext('xcrun runs natively on arm64', () {
|
||||||
|
@ -250,7 +251,7 @@ void main() {
|
||||||
'-arm64e',
|
'-arm64e',
|
||||||
'xcrun',
|
'xcrun',
|
||||||
]);
|
]);
|
||||||
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
|
expect(fakeProcessManager, hasNoRemainingExpectations);
|
||||||
});
|
});
|
||||||
|
|
||||||
testUsingContext('xcodebuild build settings is empty when xcodebuild failed to get the build settings', () async {
|
testUsingContext('xcodebuild build settings is empty when xcodebuild failed to get the build settings', () async {
|
||||||
|
@ -283,7 +284,7 @@ void main() {
|
||||||
expect(
|
expect(
|
||||||
await xcodeProjectInterpreter.getBuildSettings('', buildContext: const XcodeProjectBuildContext(scheme: 'Free')),
|
await xcodeProjectInterpreter.getBuildSettings('', buildContext: const XcodeProjectBuildContext(scheme: 'Free')),
|
||||||
const <String, String>{});
|
const <String, String>{});
|
||||||
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
|
expect(fakeProcessManager, hasNoRemainingExpectations);
|
||||||
}, overrides: <Type, Generator>{
|
}, overrides: <Type, Generator>{
|
||||||
FileSystem: () => fileSystem,
|
FileSystem: () => fileSystem,
|
||||||
ProcessManager: () => FakeProcessManager.any(),
|
ProcessManager: () => FakeProcessManager.any(),
|
||||||
|
@ -317,7 +318,7 @@ void main() {
|
||||||
),
|
),
|
||||||
const <String, String>{},
|
const <String, String>{},
|
||||||
);
|
);
|
||||||
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
|
expect(fakeProcessManager, hasNoRemainingExpectations);
|
||||||
}, overrides: <Type, Generator>{
|
}, overrides: <Type, Generator>{
|
||||||
FileSystem: () => fileSystem,
|
FileSystem: () => fileSystem,
|
||||||
ProcessManager: () => FakeProcessManager.any(),
|
ProcessManager: () => FakeProcessManager.any(),
|
||||||
|
@ -344,7 +345,7 @@ void main() {
|
||||||
|
|
||||||
expect(await xcodeProjectInterpreter.getBuildSettings('', buildContext: const XcodeProjectBuildContext()),
|
expect(await xcodeProjectInterpreter.getBuildSettings('', buildContext: const XcodeProjectBuildContext()),
|
||||||
const <String, String>{});
|
const <String, String>{});
|
||||||
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
|
expect(fakeProcessManager, hasNoRemainingExpectations);
|
||||||
}, overrides: <Type, Generator>{
|
}, overrides: <Type, Generator>{
|
||||||
FileSystem: () => fileSystem,
|
FileSystem: () => fileSystem,
|
||||||
ProcessManager: () => FakeProcessManager.any(),
|
ProcessManager: () => FakeProcessManager.any(),
|
||||||
|
@ -376,7 +377,7 @@ void main() {
|
||||||
expect(
|
expect(
|
||||||
await xcodeProjectInterpreter.getBuildSettings('', buildContext: const XcodeProjectBuildContext(scheme: 'Free')),
|
await xcodeProjectInterpreter.getBuildSettings('', buildContext: const XcodeProjectBuildContext(scheme: 'Free')),
|
||||||
const <String, String>{});
|
const <String, String>{});
|
||||||
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
|
expect(fakeProcessManager, hasNoRemainingExpectations);
|
||||||
}, overrides: <Type, Generator>{
|
}, overrides: <Type, Generator>{
|
||||||
FileSystem: () => fileSystem,
|
FileSystem: () => fileSystem,
|
||||||
ProcessManager: () => FakeProcessManager.any(),
|
ProcessManager: () => FakeProcessManager.any(),
|
||||||
|
@ -408,7 +409,7 @@ void main() {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await xcodeProjectInterpreter.cleanWorkspace('workspace_path', 'Free');
|
await xcodeProjectInterpreter.cleanWorkspace('workspace_path', 'Free');
|
||||||
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
|
expect(fakeProcessManager, hasNoRemainingExpectations);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWithoutContext('xcodebuild -list getInfo returns something when xcodebuild -list succeeds', () async {
|
testWithoutContext('xcodebuild -list getInfo returns something when xcodebuild -list succeeds', () async {
|
||||||
|
@ -430,7 +431,7 @@ void main() {
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(await xcodeProjectInterpreter.getInfo(workingDirectory), isNotNull);
|
expect(await xcodeProjectInterpreter.getInfo(workingDirectory), isNotNull);
|
||||||
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
|
expect(fakeProcessManager, hasNoRemainingExpectations);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWithoutContext('xcodebuild -list getInfo throws a tool exit when it is unable to find a project', () async {
|
testWithoutContext('xcodebuild -list getInfo throws a tool exit when it is unable to find a project', () async {
|
||||||
|
@ -455,10 +456,34 @@ void main() {
|
||||||
usage: TestUsage(),
|
usage: TestUsage(),
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(
|
expect(() => xcodeProjectInterpreter.getInfo(workingDirectory), throwsToolExit(message: stderr));
|
||||||
() async => xcodeProjectInterpreter.getInfo(workingDirectory),
|
expect(fakeProcessManager, hasNoRemainingExpectations);
|
||||||
throwsToolExit(message: stderr));
|
});
|
||||||
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
|
|
||||||
|
testWithoutContext('xcodebuild -list getInfo throws a tool exit when project is corrupted', () async {
|
||||||
|
const String workingDirectory = '/';
|
||||||
|
const String stderr = 'Useful Xcode failure message about corrupted project.';
|
||||||
|
|
||||||
|
fakeProcessManager.addCommands(const <FakeCommand>[
|
||||||
|
kWhichSysctlCommand,
|
||||||
|
kARMCheckCommand,
|
||||||
|
FakeCommand(
|
||||||
|
command: <String>['xcrun', 'xcodebuild', '-list'],
|
||||||
|
exitCode: 74,
|
||||||
|
stderr: stderr,
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
|
||||||
|
final XcodeProjectInterpreter xcodeProjectInterpreter = XcodeProjectInterpreter(
|
||||||
|
logger: logger,
|
||||||
|
fileSystem: fileSystem,
|
||||||
|
platform: platform,
|
||||||
|
processManager: fakeProcessManager,
|
||||||
|
usage: TestUsage(),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(() => xcodeProjectInterpreter.getInfo(workingDirectory), throwsToolExit(message: stderr));
|
||||||
|
expect(fakeProcessManager, hasNoRemainingExpectations);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWithoutContext('Xcode project properties from default project can be parsed', () {
|
testWithoutContext('Xcode project properties from default project can be parsed', () {
|
||||||
|
|
Loading…
Reference in a new issue