WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Commit dcf5c33

Browse files
authored
dataconnect: fix updateJson task to find cli versions whose file name contains its target cpu architecture (#7600)
1 parent 6472706 commit dcf5c33

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)