Skip to content

Commit 1f1ea59

Browse files
committed
dataconnect: fix updateJson task to find Data Connect executables whose file name is updated to also include the cpu architecture.
This naming change started with Data Connect executable version 2.16.0, which started to be published in both x86_64 and arm64 variants. For example, the file name for the macos emulator version 2.15.1 was `dataconnect-emulator-macos-v2.15.1` but in 2.16.0 there were two executables named `dataconnect-emulator-macos-amd64-v2.16.0` and `dataconnect-emulator-macos-arm64-v2.16.0` (the only difference being one is named "amd64" and the other "arm64").
1 parent 0d508f8 commit 1f1ea59

File tree

3 files changed

+137
-17
lines changed

3 files changed

+137
-17
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright 2024 Google LLC
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 com.google.firebase.dataconnect.gradle.plugin
18+
19+
import java.util.Locale
20+
21+
enum class CpuArchitecture {
22+
AMD64,
23+
ARM64;
24+
25+
companion object {
26+
fun current(): CpuArchitecture? {
27+
val arch = System.getProperty("os.arch")
28+
return if (arch === null) null else forName(arch)
29+
}
30+
31+
fun forName(arch: String): CpuArchitecture? =
32+
forNameWithLowercaseArch(arch.lowercase(Locale.ROOT))
33+
34+
// This logic was adapted from
35+
// https://github.com/gradle/gradle/blob/4457734e73fc567a43ccf96185341432b636bc47/platforms/core-runtime/base-services/src/main/java/org/gradle/internal/os/OperatingSystem.java#L357-L369
36+
private fun forNameWithLowercaseArch(arch: String): CpuArchitecture? =
37+
when (arch) {
38+
"x86_64",
39+
"amd64" -> CpuArchitecture.AMD64
40+
"aarch64" -> CpuArchitecture.ARM64
41+
else -> null
42+
}
43+
}
44+
}

firebase-dataconnect/gradleplugin/plugin/src/main/kotlin/com/google/firebase/dataconnect/gradle/plugin/DataConnectExecutableVersionRegistry.kt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ object DataConnectExecutableVersionsRegistry {
7070
data class VersionInfo(
7171
@Serializable(with = LooseVersionSerializer::class) val version: Version,
7272
@Serializable(with = OperatingSystemSerializer::class) val os: OperatingSystem,
73+
@Serializable(with = CpuArchitectureSerializer::class) val arch: CpuArchitecture? = null,
7374
val size: Long,
7475
val sha512DigestHex: String,
7576
)
@@ -95,11 +96,39 @@ object DataConnectExecutableVersionsRegistry {
9596
encoder.encodeString(value.serializedValue)
9697
}
9798

99+
private object CpuArchitectureSerializer : KSerializer<CpuArchitecture> {
100+
override val descriptor =
101+
PrimitiveSerialDescriptor(
102+
"com.google.firebase.dataconnect.gradle.plugin.CpuArchitecture",
103+
PrimitiveKind.STRING,
104+
)
105+
106+
override fun deserialize(decoder: Decoder): CpuArchitecture =
107+
decoder.decodeString().let { serializedValue ->
108+
CpuArchitecture.entries.singleOrNull { it.serializedValue == serializedValue }
109+
?: throw DataConnectGradleException(
110+
"yxnvjm2nxe",
111+
"Unknown CPU architecture: $serializedValue " +
112+
"(must be one of ${CpuArchitecture.entries.joinToString { it.serializedValue }})"
113+
)
114+
}
115+
116+
override fun serialize(encoder: Encoder, value: CpuArchitecture) =
117+
encoder.encodeString(value.serializedValue)
118+
}
119+
98120
val OperatingSystem.serializedValue: String
99121
get() =
100122
when (this) {
101123
OperatingSystem.Windows -> "windows"
102124
OperatingSystem.MacOS -> "macos"
103125
OperatingSystem.Linux -> "linux"
104126
}
127+
128+
val CpuArchitecture.serializedValue: String
129+
get() =
130+
when (this) {
131+
CpuArchitecture.AMD64 -> "amd64"
132+
CpuArchitecture.ARM64 -> "arm64"
133+
}
105134
}

firebase-dataconnect/gradleplugin/plugin/src/main/kotlin/com/google/firebase/dataconnect/gradle/plugin/UpdateDataConnectExecutableVersionsTask.kt

Lines changed: 64 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ abstract class UpdateDataConnectExecutableVersionsTask : DefaultTask() {
130130
private data class CloudStorageVersionInfo(
131131
val version: Version,
132132
val operatingSystem: OperatingSystem,
133+
val cpuArchitecture: CpuArchitecture?,
133134
val blob: Blob,
134135
)
135136

@@ -171,7 +172,7 @@ abstract class UpdateDataConnectExecutableVersionsTask : DefaultTask() {
171172
return null
172173
}
173174

174-
val versionString = match.groups[2]?.value
175+
val versionString = match.groups["version"]?.value
175176
val version = versionString?.toVersionOrNull(strict = false)
176177
if (version === null) {
177178
logger.info(
@@ -205,7 +206,7 @@ abstract class UpdateDataConnectExecutableVersionsTask : DefaultTask() {
205206
}
206207

207208
val operatingSystem =
208-
when (val operatingSystemString = match.groups[1]?.value) {
209+
when (val operatingSystemString = match.groups["os"]?.value) {
209210
"linux" -> OperatingSystem.Linux
210211
"macos" -> OperatingSystem.MacOS
211212
"windows" -> OperatingSystem.Windows
@@ -221,15 +222,32 @@ abstract class UpdateDataConnectExecutableVersionsTask : DefaultTask() {
221222
}
222223
}
223224

224-
return CloudStorageVersionInfo(version, operatingSystem, blob = this)
225+
val cpuArchitecture =
226+
when (val cpuArchitectureString = match.groups["arch"]?.value) {
227+
null -> null
228+
"amd64" -> CpuArchitecture.AMD64
229+
"arm64" -> CpuArchitecture.ARM64
230+
else -> {
231+
logger.info(
232+
"WARNING: Ignoring Data Connect executable file: {} " +
233+
"(unknown CPU architecture name: {} (in match for regex {}))",
234+
name,
235+
cpuArchitectureString,
236+
fileNameRegex
237+
)
238+
return null
239+
}
240+
}
241+
242+
return CloudStorageVersionInfo(version, operatingSystem, cpuArchitecture, blob = this)
225243
}
226244

227245
private fun CloudStorageVersionInfo.toRegistryVersionInfo(workDirectory: File): VersionInfo {
228246
val dateFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG)
229247

230248
logger.lifecycle(
231249
"Downloading version {} ({} bytes, created {})",
232-
"$version-${operatingSystem.serializedValue}",
250+
toLogString(),
233251
blob.size.toStringWithThousandsSeparator(),
234252
dateFormatter.format(blob.createTimeOffsetDateTime.atZoneSameInstant(ZoneId.systemDefault()))
235253
)
@@ -244,31 +262,58 @@ abstract class UpdateDataConnectExecutableVersionsTask : DefaultTask() {
244262
"never happen; if it _does_ happen it _could_ indicate a compromised " +
245263
"downloaded binary [y5967yd2cf]"
246264
}
247-
return VersionInfo(version, operatingSystem, fileInfo.sizeInBytes, fileInfo.sha512DigestHex)
265+
return VersionInfo(
266+
version,
267+
operatingSystem,
268+
cpuArchitecture,
269+
fileInfo.sizeInBytes,
270+
fileInfo.sha512DigestHex
271+
)
248272
}
249273

250274
private companion object {
251275

252276
val versionInfoComparator =
253-
compareBy<VersionInfo> { it.version }.thenByDescending { it.os.serializedValue }
277+
compareBy<VersionInfo> { it.version }
278+
.thenByDescending { it.os.serializedValue }
279+
.thenBy { it.arch?.serializedValue }
254280

255281
val cloudStorageVersionInfoComparator =
256282
compareBy<CloudStorageVersionInfo> { it.version }
257283
.thenByDescending { it.operatingSystem.serializedValue }
258-
259-
@JvmName("toLogStringCloudStorageVersionInfo")
260-
fun Iterable<CloudStorageVersionInfo>.toLogString(): String = joinToString {
261-
"${it.version}-${it.operatingSystem.serializedValue}"
262-
}
263-
264-
@JvmName("toLogStringVersionInfo")
265-
fun Iterable<VersionInfo>.toLogString(): String = joinToString {
266-
"${it.version}-${it.os.serializedValue}"
284+
.thenBy { it.cpuArchitecture?.serializedValue }
285+
286+
@JvmName("iterableOfCloudStorageVersionInfoToLogString")
287+
fun Iterable<CloudStorageVersionInfo>.toLogString(): String = joinToString { it.toLogString() }
288+
289+
@JvmName("cloudStorageVersionInfoToLogString")
290+
fun CloudStorageVersionInfo.toLogString(): String =
291+
createLogStringFromVersionOsArch(version, operatingSystem, cpuArchitecture)
292+
293+
@JvmName("iterableOfVersionInfoToLogString")
294+
fun Iterable<VersionInfo>.toLogString(): String = joinToString { it.toLogString() }
295+
296+
@JvmName("versionInfoToLogString")
297+
fun VersionInfo.toLogString(): String = createLogStringFromVersionOsArch(version, os, arch)
298+
299+
fun createLogStringFromVersionOsArch(
300+
version: Version,
301+
operatingSystem: OperatingSystem,
302+
cpuArchitecture: CpuArchitecture?
303+
): String = buildString {
304+
append(version)
305+
append('-')
306+
append(operatingSystem.serializedValue)
307+
if (cpuArchitecture !== null) {
308+
append('-')
309+
append(cpuArchitecture.serializedValue)
310+
}
267311
}
268312

269313
val invalidVersions = setOf("1.15.0".toVersion())
270314
val minVersion = "1.3.4".toVersion()
271-
val fileNameRegex = ".*dataconnect-emulator-([^-]+)-v(.*)".toRegex()
315+
val fileNameRegex =
316+
".*dataconnect-emulator-(?<os>[^-]+)(-(?<arch>[^-]+))?-v(?<version>.*)".toRegex()
272317

273318
/**
274319
* Creates and returns a new list that contains all elements of the receiving [Iterable] that
@@ -278,7 +323,9 @@ abstract class UpdateDataConnectExecutableVersionsTask : DefaultTask() {
278323
registry: DataConnectExecutableVersionsRegistry.Root
279324
): List<CloudStorageVersionInfo> = filterNot { cloudStorageVersion ->
280325
registry.versions.any {
281-
it.version == cloudStorageVersion.version && it.os == cloudStorageVersion.operatingSystem
326+
it.version == cloudStorageVersion.version &&
327+
it.os == cloudStorageVersion.operatingSystem &&
328+
it.arch == cloudStorageVersion.cpuArchitecture
282329
}
283330
}
284331

0 commit comments

Comments
 (0)