| // 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 until maxSize) { |
| 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. |
| else -> { // 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 |
| } |
| } |