@@ -23,9 +23,8 @@ import java.util.regex.Pattern
23
23
import kotlin.time.Duration.Companion.seconds
24
24
import kotlin.time.DurationUnit
25
25
import kotlin.time.toDuration
26
- import kotlinx.serialization.encodeToString
27
- import kotlinx.serialization.json.Json
28
26
import org.gradle.api.DefaultTask
27
+ import org.gradle.api.Task
29
28
import org.gradle.api.file.DirectoryProperty
30
29
import org.gradle.api.file.RegularFileProperty
31
30
import org.gradle.api.provider.Property
@@ -42,6 +41,8 @@ abstract class DataConnectExecutableDownloadTask : DefaultTask() {
42
41
43
42
@get:Input @get:Optional abstract val version: Property <String >
44
43
44
+ @get:Input @get:Optional abstract val operatingSystem: Property <OperatingSystem >
45
+
45
46
@get:Internal abstract val buildDirectory: DirectoryProperty
46
47
47
48
@get:OutputFile abstract val outputFile: RegularFileProperty
@@ -50,11 +51,13 @@ abstract class DataConnectExecutableDownloadTask : DefaultTask() {
50
51
fun run () {
51
52
val inputFile: File ? = inputFile.orNull?.asFile
52
53
val version: String? = version.orNull
54
+ val operatingSystem: OperatingSystem = operatingSystem.get()
53
55
val buildDirectory: File = buildDirectory.get().asFile
54
56
val outputFile: File = outputFile.get().asFile
55
57
56
58
logger.info(" inputFile: {}" , inputFile)
57
59
logger.info(" version: {}" , version)
60
+ logger.info(" operatingSystem: {}" , operatingSystem)
58
61
logger.info(" buildDirectory: {}" , buildDirectory)
59
62
logger.info(" outputFile: {}" , outputFile)
60
63
@@ -71,8 +74,8 @@ abstract class DataConnectExecutableDownloadTask : DefaultTask() {
71
74
} else if (inputFile != = null ) {
72
75
runWithFile(inputFile = inputFile, outputFile = outputFile)
73
76
} else if (version != = null ) {
74
- runWithVersion (version = version, outputFile = outputFile)
75
- verifyOutputFile(outputFile, version)
77
+ downloadDataConnectExecutable (version, operatingSystem, outputFile)
78
+ verifyOutputFile(outputFile, operatingSystem, version)
76
79
} else {
77
80
throw DataConnectGradleException (
78
81
" chc94cq7vx" ,
@@ -82,66 +85,73 @@ abstract class DataConnectExecutableDownloadTask : DefaultTask() {
82
85
}
83
86
}
84
87
85
- private fun verifyOutputFile (outputFile : File , version : String ) {
88
+ private fun verifyOutputFile (
89
+ outputFile : File ,
90
+ operatingSystem : OperatingSystem ,
91
+ version : String
92
+ ) {
86
93
logger.info(" Verifying file size and SHA512 digest of file: {}" , outputFile)
87
94
val fileInfo = FileInfo .forFile(outputFile)
88
95
89
- val verificationInfoJsonString =
90
- jsonPrettyPrint.encodeToString(
91
- DataConnectExecutable .VersionsJson .VerificationInfo (
92
- size = fileInfo.sizeInBytes,
93
- sha512DigestHex = fileInfo.sha512DigestHex,
94
- )
95
- )
96
+ val allVersions = DataConnectExecutableVersionsRegistry .load().versions
97
+ val allVersionNames =
98
+ allVersions
99
+ .asSequence()
100
+ .filter { it.os == operatingSystem }
101
+ .map { it.version }
102
+ .distinct()
103
+ .sorted()
104
+ .joinToString(" , " )
105
+ val applicableVersions =
106
+ allVersions.filter { it.version == version && it.os == operatingSystem }
96
107
97
- val verificationInfoByVersion = DataConnectExecutable .VersionsJson .load().versions
98
- val verificationInfo = verificationInfoByVersion[version]
99
- if (verificationInfo == = null ) {
108
+ if (applicableVersions.isEmpty()) {
100
109
val message =
101
- " verification information for ${outputFile.absolutePath} " +
102
- " (version $version ) is not known; known versions are: " +
103
- verificationInfoByVersion.keys.sorted().joinToString(" , " )
110
+ " verification information for Data Connect toolkit executable" +
111
+ " version $version for $operatingSystem is not known;" +
112
+ " known versions for $operatingSystem are: $allVersionNames " +
113
+ " (loaded from ${DataConnectExecutableVersionsRegistry .PATH } )"
104
114
logger.error(" ERROR: $message " )
105
- logger.error(
106
- " To update ${DataConnectExecutable .VersionsJson .RESOURCE_PATH } with" +
107
- " information about this version, add this JSON blob: $verificationInfoJsonString "
108
- )
109
115
throw DataConnectGradleException (" ym8assbfgw" , message)
116
+ } else if (applicableVersions.size > 1 ) {
117
+ val message =
118
+ " INTERNAL ERROR: ${applicableVersions.size} verification information records for" +
119
+ " Data Connect toolkit executable version $version for $operatingSystem were found in" +
120
+ " ${DataConnectExecutableVersionsRegistry .PATH } , but expected exactly 1"
121
+ logger.error(" ERROR: $message " )
122
+ throw DataConnectGradleException (" zyw5xrky6e" , message)
110
123
}
111
124
125
+ val versionInfo = applicableVersions.single()
112
126
val verificationErrors = mutableListOf<String >()
113
- if (fileInfo.sizeInBytes != verificationInfo .size) {
127
+ if (fileInfo.sizeInBytes != versionInfo .size) {
114
128
logger.error(
115
129
" ERROR: File ${outputFile.absolutePath} has an unexpected size (in bytes): actual is " +
116
130
fileInfo.sizeInBytes.toStringWithThousandsSeparator() +
117
131
" but expected " +
118
- verificationInfo .size.toStringWithThousandsSeparator()
132
+ versionInfo .size.toStringWithThousandsSeparator()
119
133
)
120
134
verificationErrors.add(" file size mismatch" )
121
135
}
122
- if (fileInfo.sha512DigestHex != verificationInfo .sha512DigestHex) {
136
+ if (fileInfo.sha512DigestHex != versionInfo .sha512DigestHex) {
123
137
logger.error(
124
138
" ERROR: File ${outputFile.absolutePath} has an unexpected SHA512 digest:" +
125
139
" actual is ${fileInfo.sha512DigestHex} " +
126
- " but expected ${verificationInfo .sha512DigestHex} "
140
+ " but expected ${versionInfo .sha512DigestHex} "
127
141
)
128
142
verificationErrors.add(" SHA512 digest mismatch" )
129
143
}
130
144
131
- if (verificationErrors.isEmpty()) {
132
- logger.info(" Verifying file size and SHA512 digest succeeded" )
133
- return
145
+ if (verificationErrors.isNotEmpty()) {
146
+ val errorMessage =
147
+ " Verification of ${outputFile.absolutePath} " +
148
+ " (version=${versionInfo.version} os=${versionInfo.os} ) failed:" +
149
+ " ${verificationErrors.joinToString(" , " )} "
150
+ logger.error(errorMessage)
151
+ throw DataConnectGradleException (" x9dfwhjr9c" , errorMessage)
134
152
}
135
153
136
- logger.error(
137
- " To update ${DataConnectExecutable .VersionsJson .RESOURCE_PATH } with" +
138
- " information about this version, add this JSON blob: $verificationInfoJsonString "
139
- )
140
-
141
- throw DataConnectGradleException (
142
- " x9dfwhjr9c" ,
143
- " Verification of ${outputFile.absolutePath} failed: ${verificationErrors.joinToString(" , " )} "
144
- )
154
+ logger.info(" Verifying file size and SHA512 digest succeeded" )
145
155
}
146
156
147
157
data class FileInfo (val sizeInBytes : Long , val sha512DigestHex : String ) {
@@ -181,62 +191,73 @@ abstract class DataConnectExecutableDownloadTask : DefaultTask() {
181
191
}
182
192
}
183
193
184
- private fun runWithVersion (version : String , outputFile : File ) {
185
- val fileName = " dataconnect-emulator-linux-v$version "
186
- val url = URL (" https://storage.googleapis.com/firemat-preview-drop/emulator/$fileName " )
194
+ companion object {
195
+ fun Task.downloadDataConnectExecutable (
196
+ version : String ,
197
+ operatingSystem : OperatingSystem ,
198
+ outputFile : File
199
+ ) {
200
+ val osName =
201
+ when (operatingSystem) {
202
+ OperatingSystem .Windows -> " windows"
203
+ OperatingSystem .MacOS -> " macos"
204
+ OperatingSystem .Linux -> " linux"
205
+ }
206
+ val downloadFileName = " dataconnect-emulator-$osName -v$version "
207
+ val url =
208
+ URL (" https://storage.googleapis.com/firemat-preview-drop/emulator/$downloadFileName " )
187
209
188
- logger.info(" Downloading {} to {}" , url, outputFile)
189
- project.mkdir(outputFile.parentFile)
210
+ logger.info(" Downloading {} to {}" , url, outputFile)
211
+ project.mkdir(outputFile.parentFile)
190
212
191
- val connection = url.openConnection() as HttpURLConnection
192
- connection.requestMethod = " GET"
213
+ val connection = url.openConnection() as HttpURLConnection
214
+ connection.requestMethod = " GET"
193
215
194
- val responseCode = connection.responseCode
195
- if (responseCode != HttpURLConnection .HTTP_OK ) {
196
- throw DataConnectGradleException (
197
- " n3mj6ahxwt" ,
198
- " Downloading Data Connect executable from $url failed with HTTP response code" +
199
- " $responseCode : ${connection.responseMessage} " +
200
- " (expected HTTP response code ${HttpURLConnection .HTTP_OK } )"
201
- )
202
- }
203
-
204
- val startTime = System .nanoTime()
205
- val debouncer = Debouncer (5 .seconds)
206
- outputFile.outputStream().use { oStream ->
207
- var downloadByteCount: Long = 0
208
- fun logDownloadedBytes () {
209
- val elapsedTime = (System .nanoTime() - startTime).toDuration(DurationUnit .NANOSECONDS )
210
- logger.info(
211
- " Downloaded {} bytes in {}" ,
212
- downloadByteCount.toStringWithThousandsSeparator(),
213
- elapsedTime
216
+ val responseCode = connection.responseCode
217
+ if (responseCode != HttpURLConnection .HTTP_OK ) {
218
+ throw DataConnectGradleException (
219
+ " n3mj6ahxwt" ,
220
+ " Downloading Data Connect executable from $url failed with HTTP response code" +
221
+ " $responseCode : ${connection.responseMessage} " +
222
+ " (expected HTTP response code ${HttpURLConnection .HTTP_OK } )"
214
223
)
215
224
}
216
- connection.inputStream.use { iStream ->
217
- val buffer = ByteArray (8192 )
218
- while (true ) {
219
- val readCount = iStream.read(buffer)
220
- if (readCount < 0 ) {
221
- break
225
+
226
+ val startTime = System .nanoTime()
227
+ val debouncer = Debouncer (5 .seconds)
228
+ outputFile.outputStream().use { oStream ->
229
+ var downloadByteCount: Long = 0
230
+ fun logDownloadedBytes () {
231
+ val elapsedTime = (System .nanoTime() - startTime).toDuration(DurationUnit .NANOSECONDS )
232
+ logger.info(
233
+ " Downloaded {} bytes in {}" ,
234
+ downloadByteCount.toStringWithThousandsSeparator(),
235
+ elapsedTime
236
+ )
237
+ }
238
+ connection.inputStream.use { iStream ->
239
+ val buffer = ByteArray (8192 )
240
+ while (true ) {
241
+ val readCount = iStream.read(buffer)
242
+ if (readCount < 0 ) {
243
+ break
244
+ }
245
+ downloadByteCount + = readCount
246
+ debouncer.maybeRun(::logDownloadedBytes)
247
+ oStream.write(buffer, 0 , readCount)
222
248
}
223
- downloadByteCount + = readCount
224
- debouncer.maybeRun(::logDownloadedBytes)
225
- oStream.write(buffer, 0 , readCount)
226
249
}
250
+ logDownloadedBytes()
227
251
}
228
- logDownloadedBytes()
229
- }
230
252
231
- project.exec { execSpec ->
232
- execSpec.run {
233
- executable = " chmod"
234
- args = listOf (" a+x" , outputFile.absolutePath)
253
+ if (operatingSystem != OperatingSystem .Windows ) {
254
+ project.exec { execSpec ->
255
+ execSpec.run {
256
+ executable = " chmod"
257
+ args = listOf (" a+x" , outputFile.absolutePath)
258
+ }
259
+ }
235
260
}
236
261
}
237
262
}
238
-
239
- private companion object {
240
- val jsonPrettyPrint = Json { prettyPrint = true }
241
- }
242
263
}
0 commit comments