Create VersionUtils class and unit tests and extract logic out of flutter.groovy (#163166)
Related to #162103 ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [ ] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing.
This commit is contained in:
parent
29d1e10a02
commit
b18b6a8665
@ -8,6 +8,7 @@ import com.flutter.gradle.BaseApplicationNameHandler
|
||||
import com.flutter.gradle.Deeplink
|
||||
import com.flutter.gradle.DependencyVersionChecker
|
||||
import com.flutter.gradle.IntentFilterCheck
|
||||
import com.flutter.gradle.VersionUtils
|
||||
import groovy.json.JsonGenerator
|
||||
import groovy.xml.QName
|
||||
import java.nio.file.Paths
|
||||
@ -789,50 +790,6 @@ class FlutterPlugin implements Plugin<Project> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares semantic versions ignoring labels.
|
||||
*
|
||||
* If the versions are equal (ignoring labels), returns one of the two strings arbitrarily.
|
||||
* If minor or patch are omitted (non-conformant to semantic versioning), they are considered zero.
|
||||
* If the provided versions in both are equal, the longest version string is returned.
|
||||
* For example, "2.8.0" vs "2.8" will always consider "2.8.0" to be the most recent version.
|
||||
* For another example, "8.7-rc-2" vs "8.7.2" will always consider "8.7.2" to be the most recent version.
|
||||
*/
|
||||
static String mostRecentSemanticVersion(String version1, String version2) {
|
||||
def v1Parts = version1.tokenize('.-')
|
||||
def v2Parts = version2.tokenize('.-')
|
||||
|
||||
for (int i = 0; i < Math.max(v1Parts.size(), v2Parts.size()); i++) {
|
||||
def v1Part = i < v1Parts.size() ? v1Parts[i] : '0'
|
||||
def v2Part = i < v2Parts.size() ? v2Parts[i] : '0'
|
||||
|
||||
def v1Num = v1Part.isNumber() ? v1Part.toInteger() : 0
|
||||
def v2Num = v2Part.isNumber() ? v2Part.toInteger() : 0
|
||||
|
||||
if (v1Num != v2Num) {
|
||||
return v1Num > v2Num ? version1 : version2
|
||||
}
|
||||
|
||||
if (v1Part.isNumber() && !v2Part.isNumber()) {
|
||||
return version1
|
||||
} else if (!v1Part.isNumber() && v2Part.isNumber()) {
|
||||
return version2
|
||||
} else if (v1Part != v2Part) {
|
||||
return comparePreReleaseIdentifiers(v1Part, v2Part) ? version1 : version2
|
||||
}
|
||||
}
|
||||
|
||||
// If versions are equal, return the longest version string
|
||||
return version1.length() >= version2.length() ? version1 : version2
|
||||
}
|
||||
|
||||
static boolean comparePreReleaseIdentifiers(String v1Part, String v2Part) {
|
||||
def v1PreRelease = v1Part.replaceAll("\\D", "")
|
||||
def v2PreRelease = v2Part.replaceAll("\\D", "")
|
||||
|
||||
return v1PreRelease < v2PreRelease
|
||||
}
|
||||
|
||||
private void forceNdkDownload(Project gradleProject, String flutterSdkRootPath) {
|
||||
// If the project is already configuring a native build, we don't need to do anything.
|
||||
Boolean forcingNotRequired = gradleProject.android.externalNativeBuild.cmake.path != null
|
||||
@ -900,7 +857,7 @@ class FlutterPlugin implements Plugin<Project> {
|
||||
}
|
||||
|
||||
String pluginNdkVersion = pluginProject.android.ndkVersion ?: ndkVersionIfUnspecified
|
||||
maxPluginNdkVersion = mostRecentSemanticVersion(pluginNdkVersion, maxPluginNdkVersion)
|
||||
maxPluginNdkVersion = VersionUtils.mostRecentSemanticVersion(pluginNdkVersion, maxPluginNdkVersion)
|
||||
if (pluginNdkVersion != projectNdkVersion) {
|
||||
pluginsWithDifferentNdkVersion.add(new Tuple(pluginProject.name, pluginNdkVersion))
|
||||
}
|
||||
|
@ -0,0 +1,67 @@
|
||||
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package com.flutter.gradle
|
||||
|
||||
import kotlin.math.max
|
||||
|
||||
object VersionUtils {
|
||||
/**
|
||||
* Compares semantic versions ignoring labels.
|
||||
*
|
||||
* If the versions are equal (ignoring labels), returns one of the two strings arbitrarily. If
|
||||
* minor or patch are omitted (non-conformant to semantic versioning), they are considered zero.
|
||||
* If the provided versions in both are equal, the longest version string is returned. For
|
||||
* example, "2.8.0" vs "2.8" will always consider "2.8.0" to be the most recent version. For
|
||||
* another example, "8.7-rc-2" vs "8.7.2" will always consider "8.7.2" to be the most recent
|
||||
* version.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun mostRecentSemanticVersion(
|
||||
version1: String,
|
||||
version2: String
|
||||
): String {
|
||||
val v1Parts = version1.split(".", "-")
|
||||
val v2Parts = version2.split(".", "-")
|
||||
val maxSize = max(v1Parts.size, v2Parts.size)
|
||||
|
||||
for (i in 0..maxSize - 1) {
|
||||
val v1Part: String = v1Parts.getOrNull(i) ?: "0"
|
||||
val v2Part: String = v2Parts.getOrNull(i) ?: "0"
|
||||
|
||||
val v1Num: Int? = v1Part.toIntOrNull()
|
||||
val v2Num: Int? = v2Part.toIntOrNull()
|
||||
when {
|
||||
v1Num != null && v2Num != null -> { // Both are numbers
|
||||
if (v1Num != v2Num) {
|
||||
return if (v1Num > v2Num) version1 else version2
|
||||
}
|
||||
}
|
||||
v1Num != null && v2Num == null ->
|
||||
return version1 // v1 is a number, v2 is not, so v1 is newer.
|
||||
v1Num == null && v2Num != null ->
|
||||
return version2 // v1 is not a number, v2 is, so v2 is newer.
|
||||
v1Num == null && v2Num == null -> { // Both are not numbers (pre-release identifiers)
|
||||
if (v1Part != v2Part) {
|
||||
return if (comparePreReleaseIdentifiers(v1Part, v2Part)) version1 else version2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If versions are equal, return the longest version string
|
||||
return if (version1.length >= version2.length) version1 else version2
|
||||
}
|
||||
|
||||
/** Compares only non digits and returns true if v1Part is than v2Part. */
|
||||
private fun comparePreReleaseIdentifiers(
|
||||
v1Part: String,
|
||||
v2Part: String
|
||||
): Boolean {
|
||||
val digits = Regex("\\d")
|
||||
val v1PreRelease = v1Part.replace(digits, "")
|
||||
val v2PreRelease = v2Part.replace(digits, "")
|
||||
return v1PreRelease < v2PreRelease
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package com.flutter.gradle
|
||||
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class VersionUtilsTest {
|
||||
@Test
|
||||
fun handles_documenation_examples() {
|
||||
versionComparison("2.8.0", "2.8", expected = "2.8.0")
|
||||
versionComparison("8.7-rc-2", "8.7.2", expected = "8.7.2")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun expanded_examples() {
|
||||
versionComparison("1.2", "1.2.0", expected = "1.2.0")
|
||||
versionComparison("1.0", "1", expected = "1.0")
|
||||
versionComparison("1.2.0-alpha", "1.2", expected = "1.2")
|
||||
versionComparison("1.2.3", "1.2.3", expected = "1.2.3")
|
||||
versionComparison("1.2.3-beta", "1.2.3", expected = "1.2.3")
|
||||
versionComparison("1.2.3", "1.2.3.4", expected = "1.2.3.4")
|
||||
versionComparison("rc-2", "rc-1", expected = "rc-2")
|
||||
versionComparison("8.7-rc-1", "8.7", expected = "8.7")
|
||||
versionComparison("8.7-rc-1", "8.7.2", expected = "8.7.2")
|
||||
versionComparison("8.7.2", "8.7.1", expected = "8.7.2")
|
||||
versionComparison("7.0.2", "8.7.1", expected = "8.7.1")
|
||||
versionComparison("8.1", "7.5", expected = "8.1")
|
||||
}
|
||||
|
||||
fun versionComparison(
|
||||
version1: String,
|
||||
version2: String,
|
||||
expected: String
|
||||
) {
|
||||
assertEquals(expected, VersionUtils.mostRecentSemanticVersion(version1, version2))
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user