Support Xcode patch version comparison (#61484)
This commit is contained in:
parent
a1a5a8f635
commit
4fba77476d
@ -138,8 +138,8 @@ class UserMessages {
|
|||||||
|
|
||||||
// Messages used in XcodeValidator
|
// Messages used in XcodeValidator
|
||||||
String xcodeLocation(String location) => 'Xcode at $location';
|
String xcodeLocation(String location) => 'Xcode at $location';
|
||||||
String xcodeOutdated(int versionMajor, int versionMinor) =>
|
String xcodeOutdated(int versionMajor, int versionMinor, int versionPatch) =>
|
||||||
'Flutter requires a minimum Xcode version of $versionMajor.$versionMinor.0.\n'
|
'Flutter requires a minimum Xcode version of $versionMajor.$versionMinor.$versionPatch.\n'
|
||||||
'Download the latest version or update via the Mac App Store.';
|
'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 xcodeEula => "Xcode end user license agreement not signed; open Xcode or run the command 'sudo xcodebuild -license'.";
|
||||||
String get xcodeMissingSimct =>
|
String get xcodeMissingSimct =>
|
||||||
|
@ -600,7 +600,7 @@ class XcodeBuildExecution {
|
|||||||
final Map<String, String> buildSettings;
|
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() {
|
bool _checkXcodeVersion() {
|
||||||
if (!globals.platform.isMacOS) {
|
if (!globals.platform.isMacOS) {
|
||||||
|
@ -261,13 +261,15 @@ class XcodeProjectInterpreter {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
final RunResult result = _processUtils.runSync(
|
if (_versionText == null) {
|
||||||
<String>[_executable, '-version'],
|
final RunResult result = _processUtils.runSync(
|
||||||
);
|
<String>[_executable, '-version'],
|
||||||
if (result.exitCode != 0) {
|
);
|
||||||
return;
|
if (result.exitCode != 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_versionText = result.stdout.trim().replaceAll('\n', ', ');
|
||||||
}
|
}
|
||||||
_versionText = result.stdout.trim().replaceAll('\n', ', ');
|
|
||||||
final Match match = _versionRegex.firstMatch(versionText);
|
final Match match = _versionRegex.firstMatch(versionText);
|
||||||
if (match == null) {
|
if (match == null) {
|
||||||
return;
|
return;
|
||||||
@ -275,7 +277,8 @@ class XcodeProjectInterpreter {
|
|||||||
final String version = match.group(1);
|
final String version = match.group(1);
|
||||||
final List<String> components = version.split('.');
|
final List<String> components = version.split('.');
|
||||||
_majorVersion = int.parse(components[0]);
|
_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 {
|
} on ProcessException {
|
||||||
// Ignored, leave values null.
|
// Ignored, leave values null.
|
||||||
}
|
}
|
||||||
@ -307,6 +310,14 @@ class XcodeProjectInterpreter {
|
|||||||
return _minorVersion;
|
return _minorVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int _patchVersion;
|
||||||
|
int get patchVersion {
|
||||||
|
if (_patchVersion == null) {
|
||||||
|
_updateVersion();
|
||||||
|
}
|
||||||
|
return _patchVersion;
|
||||||
|
}
|
||||||
|
|
||||||
/// Asynchronously retrieve xcode build settings. This one is preferred for
|
/// Asynchronously retrieve xcode build settings. This one is preferred for
|
||||||
/// new call-sites.
|
/// new call-sites.
|
||||||
///
|
///
|
||||||
|
@ -27,6 +27,7 @@ import '../reporting/reporting.dart';
|
|||||||
|
|
||||||
const int kXcodeRequiredVersionMajor = 11;
|
const int kXcodeRequiredVersionMajor = 11;
|
||||||
const int kXcodeRequiredVersionMinor = 0;
|
const int kXcodeRequiredVersionMinor = 0;
|
||||||
|
const int kXcodeRequiredVersionPatch = 0;
|
||||||
|
|
||||||
enum SdkType {
|
enum SdkType {
|
||||||
iPhone,
|
iPhone,
|
||||||
@ -97,8 +98,8 @@ class Xcode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int get majorVersion => _xcodeProjectInterpreter.majorVersion;
|
int get majorVersion => _xcodeProjectInterpreter.majorVersion;
|
||||||
|
|
||||||
int get minorVersion => _xcodeProjectInterpreter.minorVersion;
|
int get minorVersion => _xcodeProjectInterpreter.minorVersion;
|
||||||
|
int get patchVersion => _xcodeProjectInterpreter.patchVersion;
|
||||||
|
|
||||||
String get versionText => _xcodeProjectInterpreter.versionText;
|
String get versionText => _xcodeProjectInterpreter.versionText;
|
||||||
|
|
||||||
@ -151,6 +152,9 @@ class Xcode {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (majorVersion == kXcodeRequiredVersionMajor) {
|
if (majorVersion == kXcodeRequiredVersionMajor) {
|
||||||
|
if (minorVersion == kXcodeRequiredVersionMinor) {
|
||||||
|
return patchVersion >= kXcodeRequiredVersionPatch;
|
||||||
|
}
|
||||||
return minorVersion >= kXcodeRequiredVersionMinor;
|
return minorVersion >= kXcodeRequiredVersionMinor;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -39,7 +39,7 @@ class XcodeValidator extends DoctorValidator {
|
|||||||
if (!_xcode.isInstalledAndMeetsVersionCheck) {
|
if (!_xcode.isInstalledAndMeetsVersionCheck) {
|
||||||
xcodeStatus = ValidationType.partial;
|
xcodeStatus = ValidationType.partial;
|
||||||
messages.add(ValidationMessage.error(
|
messages.add(ValidationMessage.error(
|
||||||
_userMessages.xcodeOutdated(kXcodeRequiredVersionMajor, kXcodeRequiredVersionMinor)
|
_userMessages.xcodeOutdated(kXcodeRequiredVersionMajor, kXcodeRequiredVersionMinor, kXcodeRequiredVersionPatch)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,49 +136,38 @@ void main() {
|
|||||||
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
|
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWithoutContext('xcodebuild majorVersion returns major version', () {
|
testWithoutContext('xcodebuild version parts can be parsed', () {
|
||||||
fakeProcessManager.addCommand(const FakeCommand(
|
fakeProcessManager.addCommand(const FakeCommand(
|
||||||
command: <String>[xcodebuild, '-version'],
|
command: <String>[xcodebuild, '-version'],
|
||||||
stdout: 'Xcode 11.4.1\nBuild version 11N111s',
|
stdout: 'Xcode 11.4.1\nBuild version 11N111s',
|
||||||
));
|
));
|
||||||
|
|
||||||
expect(xcodeProjectInterpreter.majorVersion, 11);
|
expect(xcodeProjectInterpreter.majorVersion, 11);
|
||||||
|
expect(xcodeProjectInterpreter.minorVersion, 4);
|
||||||
|
expect(xcodeProjectInterpreter.patchVersion, 1);
|
||||||
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
|
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(
|
fakeProcessManager.addCommand(const FakeCommand(
|
||||||
command: <String>[xcodebuild, '-version'],
|
command: <String>[xcodebuild, '-version'],
|
||||||
stdout: 'Xcode Ultra5000\nBuild version 8E3004b',
|
stdout: 'Xcode Ultra5000\nBuild version 8E3004b',
|
||||||
));
|
));
|
||||||
expect(xcodeProjectInterpreter.majorVersion, isNull);
|
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.minorVersion, isNull);
|
||||||
|
expect(xcodeProjectInterpreter.patchVersion, isNull);
|
||||||
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
|
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -157,6 +157,7 @@ void main() {
|
|||||||
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
|
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
|
||||||
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(9);
|
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(9);
|
||||||
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(0);
|
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(0);
|
||||||
|
when(mockXcodeProjectInterpreter.patchVersion).thenReturn(0);
|
||||||
|
|
||||||
expect(xcode.isVersionSatisfactory, isFalse);
|
expect(xcode.isVersionSatisfactory, isFalse);
|
||||||
});
|
});
|
||||||
@ -171,6 +172,7 @@ void main() {
|
|||||||
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
|
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
|
||||||
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(11);
|
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(11);
|
||||||
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(0);
|
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(0);
|
||||||
|
when(mockXcodeProjectInterpreter.patchVersion).thenReturn(0);
|
||||||
|
|
||||||
expect(xcode.isVersionSatisfactory, isTrue);
|
expect(xcode.isVersionSatisfactory, isTrue);
|
||||||
});
|
});
|
||||||
@ -179,6 +181,7 @@ void main() {
|
|||||||
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
|
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
|
||||||
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(12);
|
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(12);
|
||||||
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(0);
|
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(0);
|
||||||
|
when(mockXcodeProjectInterpreter.patchVersion).thenReturn(0);
|
||||||
|
|
||||||
expect(xcode.isVersionSatisfactory, isTrue);
|
expect(xcode.isVersionSatisfactory, isTrue);
|
||||||
});
|
});
|
||||||
@ -187,6 +190,16 @@ void main() {
|
|||||||
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
|
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
|
||||||
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(11);
|
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(11);
|
||||||
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(3);
|
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);
|
expect(xcode.isVersionSatisfactory, isTrue);
|
||||||
});
|
});
|
||||||
@ -219,6 +232,7 @@ void main() {
|
|||||||
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
|
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
|
||||||
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(11);
|
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(11);
|
||||||
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(0);
|
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(0);
|
||||||
|
when(mockXcodeProjectInterpreter.patchVersion).thenReturn(0);
|
||||||
|
|
||||||
expect(xcode.isInstalledAndMeetsVersionCheck, isFalse);
|
expect(xcode.isInstalledAndMeetsVersionCheck, isFalse);
|
||||||
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
|
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
|
||||||
@ -233,6 +247,7 @@ void main() {
|
|||||||
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
|
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
|
||||||
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(10);
|
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(10);
|
||||||
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(2);
|
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(2);
|
||||||
|
when(mockXcodeProjectInterpreter.patchVersion).thenReturn(0);
|
||||||
|
|
||||||
expect(xcode.isInstalledAndMeetsVersionCheck, isFalse);
|
expect(xcode.isInstalledAndMeetsVersionCheck, isFalse);
|
||||||
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
|
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
|
||||||
@ -247,6 +262,7 @@ void main() {
|
|||||||
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
|
when(mockXcodeProjectInterpreter.isInstalled).thenReturn(true);
|
||||||
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(11);
|
when(mockXcodeProjectInterpreter.majorVersion).thenReturn(11);
|
||||||
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(0);
|
when(mockXcodeProjectInterpreter.minorVersion).thenReturn(0);
|
||||||
|
when(mockXcodeProjectInterpreter.patchVersion).thenReturn(0);
|
||||||
|
|
||||||
expect(xcode.isInstalledAndMeetsVersionCheck, isTrue);
|
expect(xcode.isInstalledAndMeetsVersionCheck, isTrue);
|
||||||
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
|
expect(fakeProcessManager.hasRemainingExpectations, isFalse);
|
||||||
|
@ -394,6 +394,9 @@ class FakeXcodeProjectInterpreter implements XcodeProjectInterpreter {
|
|||||||
@override
|
@override
|
||||||
int get minorVersion => 0;
|
int get minorVersion => 0;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get patchVersion => 0;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Map<String, String>> getBuildSettings(
|
Future<Map<String, String>> getBuildSettings(
|
||||||
String projectPath, {
|
String projectPath, {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user