1 /*
2 * Copyright 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package androidx.build
18
19 import java.io.File
20 import java.util.Locale
21 import java.util.regex.Matcher
22 import java.util.regex.Pattern
23 import org.gradle.api.Project
24
25 /** Utility class which represents a version */
26 data class Version(val major: Int, val minor: Int, val patch: Int, val extra: String? = null) :
27 Comparable<Version>, java.io.Serializable {
28
29 constructor(
30 versionString: String
31 ) : this(
32 Integer.parseInt(checkedMatcher(versionString).group(1)),
33 Integer.parseInt(checkedMatcher(versionString).group(2)),
34 Integer.parseInt(checkedMatcher(versionString).group(3)),
35 if (checkedMatcher(versionString).groupCount() == 4) checkedMatcher(versionString).group(4)
36 else null
37 )
38
isPatchnull39 fun isPatch(): Boolean = patch != 0
40
41 fun isSnapshot(): Boolean = "-SNAPSHOT" == extra
42
43 fun isAlpha(): Boolean = extra?.lowercase(Locale.getDefault())?.startsWith("-alpha") ?: false
44
45 fun isBeta(): Boolean = extra?.lowercase(Locale.getDefault())?.startsWith("-beta") ?: false
46
47 fun isDev(): Boolean = extra?.lowercase(Locale.getDefault())?.startsWith("-dev") ?: false
48
49 fun isRC(): Boolean = extra?.lowercase(Locale.getDefault())?.startsWith("-rc") ?: false
50
51 fun isStable(): Boolean = (extra == null)
52
53 // Returns whether the API surface is allowed to change within the current revision (see
54 // go/androidx/versioning for policy definition)
55 fun isFinalApi(): Boolean = !(isSnapshot() || isAlpha() || isDev())
56
57 override fun compareTo(other: Version) =
58 compareValuesBy(
59 this,
60 other,
61 { it.major },
<lambda>null62 { it.minor },
<lambda>null63 { it.patch },
<lambda>null64 { it.extra == null }, // False (no extra) sorts above true (has extra)
<lambda>null65 { it.extra } // gradle uses lexicographic ordering
66 )
67
toStringnull68 override fun toString(): String {
69 return if (extra != null) {
70 "$major.$minor.$patch$extra"
71 } else "$major.$minor.$patch"
72 }
73
74 companion object {
75 private const val serialVersionUID = 345435634563L
76
77 private val VERSION_FILE_REGEX = Pattern.compile("^(res-)?(.*).txt$")
78 private val VERSION_REGEX = Pattern.compile("^(\\d+)\\.(\\d+)\\.(\\d+)(-.+)?$")
79
checkedMatchernull80 private fun checkedMatcher(versionString: String): Matcher {
81 val matcher = VERSION_REGEX.matcher(versionString)
82 if (!matcher.matches()) {
83 throw IllegalArgumentException("Can not parse version: $versionString")
84 }
85 return matcher
86 }
87
88 /** @return Version or null, if a name of the given file doesn't match */
parseOrNullnull89 fun parseOrNull(file: File): Version? {
90 if (!file.isFile) return null
91 return parseFilenameOrNull(file.name)
92 }
93
94 /** @return Version or null, if a name of the given file doesn't match */
parseFilenameOrNullnull95 fun parseFilenameOrNull(filename: String): Version? {
96 val matcher = VERSION_FILE_REGEX.matcher(filename)
97 return if (matcher.matches()) parseOrNull(matcher.group(2)) else null
98 }
99
100 /** @return Version or null, if the given string doesn't match */
parseOrNullnull101 fun parseOrNull(versionString: String): Version? {
102 val matcher = VERSION_REGEX.matcher(versionString)
103 return if (matcher.matches()) Version(versionString) else null
104 }
105
106 /** Tells whether a version string would refer to a dependency range */
isDependencyRangenull107 fun isDependencyRange(version: String): Boolean {
108 if (
109 (version.startsWith("[") || version.startsWith("(")) &&
110 version.contains(",") &&
111 (version.endsWith("]") || version.endsWith(")"))
112 ) {
113 return true
114 }
115 if (version.endsWith("+")) {
116 return true
117 }
118 return false
119 }
120 }
121 }
122
Projectnull123 fun Project.isVersionSet() = project.version is Version
124
125 fun Project.version(): Version {
126 return if (project.version is Version) {
127 project.version as Version
128 } else {
129 throw IllegalStateException("Tried to use project version for $name that was never set.")
130 }
131 }
132