Support Xcode patch version comparison (#61484)

This commit is contained in:
Jenn Magder 2020-07-14 17:16:02 -07:00 committed by GitHub
parent a1a5a8f635
commit 4fba77476d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 63 additions and 40 deletions

View file

@ -138,8 +138,8 @@ class UserMessages {
// Messages used in XcodeValidator
String xcodeLocation(String location) => 'Xcode at $location';
String xcodeOutdated(int versionMajor, int versionMinor) =>
'Flutter requires a minimum Xcode version of $versionMajor.$versionMinor.0.\n'
String xcodeOutdated(int versionMajor, int versionMinor, int versionPatch) =>
'Flutter requires a minimum Xcode version of $versionMajor.$versionMinor.$versionPatch.\n'
'Download the latest version or update via the Mac App Store.';
String get xcodeEula => "Xcode end user license agreement not signed; open Xcode or run the command 'sudo xcodebuild -license'.";
String get xcodeMissingSimct =>

View file

@ -600,7 +600,7 @@ class XcodeBuildExecution {
final Map<String, String> buildSettings;
}
const String _xcodeRequirement = 'Xcode $kXcodeRequiredVersionMajor.$kXcodeRequiredVersionMinor or greater is required to develop for iOS.';
const String _xcodeRequirement = 'Xcode $kXcodeRequiredVersionMajor.$kXcodeRequiredVersionMinor.$kXcodeRequiredVersionPatch or greater is required to develop for iOS.';
bool _checkXcodeVersion() {
if (!globals.platform.isMacOS) {

View file

@ -261,13 +261,15 @@ class XcodeProjectInterpreter {
return;
}
try {
final RunResult result = _processUtils.runSync(
<String>[_executable, '-version'],
);
if (result.exitCode != 0) {
return;
if (_versionText == null) {
final RunResult result = _processUtils.runSync(
<String>[_executable, '-version'],
);
if (result.exitCode != 0) {
return;
}
_versionText = result.stdout.trim().replaceAll('\n', ', ');
}
_versionText = result.stdout.trim().replaceAll('\n', ', ');
final Match match = _versionRegex.firstMatch(versionText);
if (match == null) {
return;
@ -275,7 +277,8 @@ class XcodeProjectInterpreter {
final String version = match.group(1);
final List<String> components = version.split('.');
_majorVersion = int.parse(components[0]);
_minorVersion = components.length == 1 ? 0 : int.parse(components[1]);
_minorVersion = components.length < 2 ? 0 : int.parse(components[1]);
_patchVersion = components.length < 3 ? 0 : int.parse(components[2]);
} on ProcessException {
// Ignored, leave values null.
}
@ -307,6 +310,14 @@ class XcodeProjectInterpreter {
return _minorVersion;
}
int _patchVersion;
int get patchVersion {
if (_patchVersion == null) {
_updateVersion();
}
return _patchVersion;
}
/// Asynchronously retrieve xcode build settings. This one is preferred for
/// new call-sites.
///

View file

@ -27,6 +27,7 @@ import '../reporting/reporting.dart';
const int kXcodeRequiredVersionMajor = 11;
const int kXcodeRequiredVersionMinor = 0;
const int kXcodeRequiredVersionPatch = 0;
enum SdkType {
iPhone,
@ -97,8 +98,8 @@ class Xcode {
}
int get majorVersion => _xcodeProjectInterpreter.majorVersion;
int get minorVersion => _xcodeProjectInterpreter.minorVersion;
int get patchVersion => _xcodeProjectInterpreter.patchVersion;
String get versionText => _xcodeProjectInterpreter.versionText;
@ -151,6 +152,9 @@ class Xcode {
return true;
}
if (majorVersion == kXcodeRequiredVersionMajor) {
if (minorVersion == kXcodeRequiredVersionMinor) {
return patchVersion >= kXcodeRequiredVersionPatch;
}
return minorVersion >= kXcodeRequiredVersionMinor;
}
return false;

View file

@ -39,7 +39,7 @@ class XcodeValidator extends DoctorValidator {
if (!_xcode.isInstalledAndMeetsVersionCheck) {
xcodeStatus = ValidationType.partial;
messages.add(ValidationMessage.error(
_userMessages.xcodeOutdated(kXcodeRequiredVersionMajor, kXcodeRequiredVersionMinor)
_userMessages.xcodeOutdated(kXcodeRequiredVersionMajor, kXcodeRequiredVersionMinor, kXcodeRequiredVersionPatch)
));
}

View file

@ -136,49 +136,38 @@ void main() {
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
});
testWithoutContext('xcodebuild majorVersion returns major version', () {
testWithoutContext('xcodebuild version parts can be parsed', () {
fakeProcessManager.addCommand(const FakeCommand(
command: <String>[xcodebuild, '-version'],
stdout: 'Xcode 11.4.1\nBuild version 11N111s',
));
expect(xcodeProjectInterpreter.majorVersion, 11);
expect(xcodeProjectInterpreter.minorVersion, 4);
expect(xcodeProjectInterpreter.patchVersion, 1);
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
});
testWithoutContext('xcodebuild majorVersion is null when version has unexpected format', () {
testWithoutContext('xcodebuild minor and patch version default to 0', () {
fakeProcessManager.addCommand(const FakeCommand(
command: <String>[xcodebuild, '-version'],
stdout: 'Xcode 11\nBuild version 11N111s',
));
expect(xcodeProjectInterpreter.majorVersion, 11);
expect(xcodeProjectInterpreter.minorVersion, 0);
expect(xcodeProjectInterpreter.patchVersion, 0);
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
});
testWithoutContext('xcodebuild version parts is null when version has unexpected format', () {
fakeProcessManager.addCommand(const FakeCommand(
command: <String>[xcodebuild, '-version'],
stdout: 'Xcode Ultra5000\nBuild version 8E3004b',
));
expect(xcodeProjectInterpreter.majorVersion, isNull);
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
});
testWithoutContext('xcodebuild minorVersion returns minor version', () {
fakeProcessManager.addCommand(const FakeCommand(
command: <String>[xcodebuild, '-version'],
stdout: 'Xcode 8.3.3\nBuild version 8E3004b',
));
expect(xcodeProjectInterpreter.minorVersion, 3);
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
});
testWithoutContext('xcodebuild minorVersion returns 0 when minor version is unspecified', () {
fakeProcessManager.addCommand(const FakeCommand(
command: <String>[xcodebuild, '-version'],
stdout: 'Xcode 8\nBuild version 8E3004b',
));
expect(xcodeProjectInterpreter.minorVersion, 0);
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
});
testWithoutContext('xcodebuild minorVersion is null when version has unexpected format', () {
fakeProcessManager.addCommand(const FakeCommand(
command: <String>[xcodebuild, '-version'],
stdout: 'Xcode Ultra5000\nBuild version 8E3004b',
));
expect(xcodeProjectInterpreter.minorVersion, isNull);
expect(xcodeProjectInterpreter.patchVersion, isNull);
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
});

View file

@ -157,6 +157,7 @@ void main() {
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(9);
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(0);
when(mockXcodeProjectInterpreter.patchVersion).thenReturn(0);
expect(xcode.isVersionSatisfactory, isFalse);
});
@ -171,6 +172,7 @@ void main() {
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(11);
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(0);
when(mockXcodeProjectInterpreter.patchVersion).thenReturn(0);
expect(xcode.isVersionSatisfactory, isTrue);
});
@ -179,6 +181,7 @@ void main() {
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(12);
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(0);
when(mockXcodeProjectInterpreter.patchVersion).thenReturn(0);
expect(xcode.isVersionSatisfactory, isTrue);
});
@ -187,6 +190,16 @@ void main() {
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(11);
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(3);
when(mockXcodeProjectInterpreter.patchVersion).thenReturn(0);
expect(xcode.isVersionSatisfactory, isTrue);
});
testWithoutContext('xcodeVersionSatisfactory is true when patch version exceeds minimum', () {
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(11);
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(0);
when(mockXcodeProjectInterpreter.patchVersion).thenReturn(1);
expect(xcode.isVersionSatisfactory, isTrue);
});
@ -219,6 +232,7 @@ void main() {
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(11);
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(0);
when(mockXcodeProjectInterpreter.patchVersion).thenReturn(0);
expect(xcode.isInstalledAndMeetsVersionCheck, isFalse);
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
@ -233,6 +247,7 @@ void main() {
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(10);
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(2);
when(mockXcodeProjectInterpreter.patchVersion).thenReturn(0);
expect(xcode.isInstalledAndMeetsVersionCheck, isFalse);
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
@ -247,6 +262,7 @@ void main() {
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(11);
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(0);
when(mockXcodeProjectInterpreter.patchVersion).thenReturn(0);
expect(xcode.isInstalledAndMeetsVersionCheck, isTrue);
expect(fakeProcessManager.hasRemainingExpectations, isFalse);

View file

@ -394,6 +394,9 @@ class FakeXcodeProjectInterpreter implements XcodeProjectInterpreter {
@override
int get minorVersion => 0;
@override
int get patchVersion => 0;
@override
Future<Map<String, String>> getBuildSettings(
String projectPath, {