From 6078d0e75e91eb7a31bf6b3c8d571237d4ac763d Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Tue, 21 Sep 2021 19:06:05 +0300 Subject: [PATCH 1/4] Set Specification-Version attribute in kotlinx-coroutines-core for tests Fixes #2941 --- kotlinx-coroutines-core/build.gradle | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kotlinx-coroutines-core/build.gradle b/kotlinx-coroutines-core/build.gradle index c45ca08cef..f3d6d4cc55 100644 --- a/kotlinx-coroutines-core/build.gradle +++ b/kotlinx-coroutines-core/build.gradle @@ -215,10 +215,11 @@ jvmJar { setupManifest(it) } */ metadataJar { setupManifest(it) } -static def setupManifest(Jar jar) { +def setupManifest(Jar jar) { jar.manifest { attributes "Premain-Class": "kotlinx.coroutines.debug.AgentPremain" attributes "Can-Retransform-Classes": "true" + attributes "Specification-Version": rootProject.version } } From 9b3be57850f9696474a05b8eb2243ae55a0675be Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Fri, 24 Sep 2021 12:02:41 +0300 Subject: [PATCH 2/4] Add version file to each module resources * The approach with "Specification-Version" in Manifest doesn't work because Android merges all JARs into a single resource, trimming all the manifests Fixes #2941 --- build.gradle | 34 +++++++++++++++ integration-testing/build.gradle | 1 + ...t => MavenPublicationAtomicfuValidator.kt} | 2 +- .../MavenPublicationVersionValidator.kt | 42 +++++++++++++++++++ kotlinx-coroutines-core/build.gradle | 1 - 5 files changed, 78 insertions(+), 2 deletions(-) rename integration-testing/src/mavenTest/kotlin/{MavenPublicationValidator.kt => MavenPublicationAtomicfuValidator.kt} (97%) create mode 100644 integration-testing/src/mavenTest/kotlin/MavenPublicationVersionValidator.kt diff --git a/build.gradle b/build.gradle index e4b12ff3ad..47e6fadfd9 100644 --- a/build.gradle +++ b/build.gradle @@ -245,6 +245,40 @@ configure(subprojects.findAll { !unpublished.contains(it.name) }) { } } } + + def project = it + if (project.name in sourceless) { + return + } + + def versionFileTask = project.tasks.register("versionFileTask") { + def name = project.name.replace("-", "_") + def versionFile = project.layout.buildDirectory.file("${name}.version") + it.outputs.file(versionFile) + + it.doLast { + versionFile.get().asFile.text = "version=${version}" + } + } + + List jarTasks + if (it.name == "kotlinx-coroutines-core") { + jarTasks = ["jvmJar", "metadataJar"] + } else if (it.name == "kotlinx-coroutines-debug") { + // We shadow debug module instead of just packaging it + jarTasks = ["shadowJar"] + } else { + jarTasks = ["jar"] + } + + for (name in jarTasks) { + project.tasks.named(name, Jar) { + it.dependsOn versionFileTask + it.from(versionFileTask) { + into("META-INF") + } + } + } } // Report Kotlin compiler version when building project diff --git a/integration-testing/build.gradle b/integration-testing/build.gradle index 6efa3a14e6..d0286d7d55 100644 --- a/integration-testing/build.gradle +++ b/integration-testing/build.gradle @@ -58,6 +58,7 @@ task npmTest(type: Test) { } task mavenTest(type: Test) { + environment "version", version def sourceSet = sourceSets.mavenTest dependsOn(project(':').getTasksByName("publishToMavenLocal", true)) testClassesDirs = sourceSet.output.classesDirs diff --git a/integration-testing/src/mavenTest/kotlin/MavenPublicationValidator.kt b/integration-testing/src/mavenTest/kotlin/MavenPublicationAtomicfuValidator.kt similarity index 97% rename from integration-testing/src/mavenTest/kotlin/MavenPublicationValidator.kt rename to integration-testing/src/mavenTest/kotlin/MavenPublicationAtomicfuValidator.kt index 39d6598b55..dbb1921d80 100644 --- a/integration-testing/src/mavenTest/kotlin/MavenPublicationValidator.kt +++ b/integration-testing/src/mavenTest/kotlin/MavenPublicationAtomicfuValidator.kt @@ -8,7 +8,7 @@ import org.junit.* import org.junit.Assert.assertTrue import java.util.jar.* -class MavenPublicationValidator { +class MavenPublicationAtomicfuValidator { private val ATOMIC_FU_REF = "Lkotlinx/atomicfu/".toByteArray() @Test diff --git a/integration-testing/src/mavenTest/kotlin/MavenPublicationVersionValidator.kt b/integration-testing/src/mavenTest/kotlin/MavenPublicationVersionValidator.kt new file mode 100644 index 0000000000..28ae5df77c --- /dev/null +++ b/integration-testing/src/mavenTest/kotlin/MavenPublicationVersionValidator.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.coroutines.validator + +import org.junit.* +import org.junit.Test +import java.util.jar.* +import kotlin.test.* + +class MavenPublicationVersionValidator { + + @Test + fun testMppJar() { + val clazz = Class.forName("kotlinx.coroutines.Job") + JarFile(clazz.protectionDomain.codeSource.location.file).checkForVersion("kotlinx_coroutines_core.version") + } + + @Test + fun testAndroidJar() { + val clazz = Class.forName("kotlinx.coroutines.android.HandlerDispatcher") + JarFile(clazz.protectionDomain.codeSource.location.file).checkForVersion("kotlinx_coroutines_android.version") + } + + private fun JarFile.checkForVersion(file: String) { + val actualFile = "META-INF/$file" + val version = System.getenv("version") + try { + for (e in entries()) { + if (e.name == actualFile) { + val string = getInputStream(e).readAllBytes().decodeToString() + assertEquals("version=$version", string) + return + } + } + error("File $file not found") + } finally { + close() + } + } +} diff --git a/kotlinx-coroutines-core/build.gradle b/kotlinx-coroutines-core/build.gradle index f3d6d4cc55..e2f9c88bd5 100644 --- a/kotlinx-coroutines-core/build.gradle +++ b/kotlinx-coroutines-core/build.gradle @@ -219,7 +219,6 @@ def setupManifest(Jar jar) { jar.manifest { attributes "Premain-Class": "kotlinx.coroutines.debug.AgentPremain" attributes "Can-Retransform-Classes": "true" - attributes "Specification-Version": rootProject.version } } From 31796b727e6b5553b13bd637283028d553d8130b Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Fri, 24 Sep 2021 12:03:54 +0300 Subject: [PATCH 3/4] Return static back --- kotlinx-coroutines-core/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kotlinx-coroutines-core/build.gradle b/kotlinx-coroutines-core/build.gradle index e2f9c88bd5..c45ca08cef 100644 --- a/kotlinx-coroutines-core/build.gradle +++ b/kotlinx-coroutines-core/build.gradle @@ -215,7 +215,7 @@ jvmJar { setupManifest(it) } */ metadataJar { setupManifest(it) } -def setupManifest(Jar jar) { +static def setupManifest(Jar jar) { jar.manifest { attributes "Premain-Class": "kotlinx.coroutines.debug.AgentPremain" attributes "Can-Retransform-Classes": "true" From dd46fab77e127b0ad0529096387fbb88a2a1e7d6 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Fri, 24 Sep 2021 17:35:22 +0300 Subject: [PATCH 4/4] ~maintainable Gradle scripting, write version to file directly without key --- build.gradle | 14 +++++++------- .../kotlin/MavenPublicationVersionValidator.kt | 6 ++---- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/build.gradle b/build.gradle index 47e6fadfd9..3029e58bcc 100644 --- a/build.gradle +++ b/build.gradle @@ -246,18 +246,18 @@ configure(subprojects.findAll { !unpublished.contains(it.name) }) { } } - def project = it - if (project.name in sourceless) { + def thisProject = it + if (thisProject.name in sourceless) { return } - def versionFileTask = project.tasks.register("versionFileTask") { - def name = project.name.replace("-", "_") - def versionFile = project.layout.buildDirectory.file("${name}.version") + def versionFileTask = thisProject.tasks.register("versionFileTask") { + def name = thisProject.name.replace("-", "_") + def versionFile = thisProject.layout.buildDirectory.file("${name}.version") it.outputs.file(versionFile) it.doLast { - versionFile.get().asFile.text = "version=${version}" + versionFile.get().asFile.text = version.toString() } } @@ -272,7 +272,7 @@ configure(subprojects.findAll { !unpublished.contains(it.name) }) { } for (name in jarTasks) { - project.tasks.named(name, Jar) { + thisProject.tasks.named(name, Jar) { it.dependsOn versionFileTask it.from(versionFileTask) { into("META-INF") diff --git a/integration-testing/src/mavenTest/kotlin/MavenPublicationVersionValidator.kt b/integration-testing/src/mavenTest/kotlin/MavenPublicationVersionValidator.kt index 28ae5df77c..da87d4cc59 100644 --- a/integration-testing/src/mavenTest/kotlin/MavenPublicationVersionValidator.kt +++ b/integration-testing/src/mavenTest/kotlin/MavenPublicationVersionValidator.kt @@ -26,17 +26,15 @@ class MavenPublicationVersionValidator { private fun JarFile.checkForVersion(file: String) { val actualFile = "META-INF/$file" val version = System.getenv("version") - try { + use { for (e in entries()) { if (e.name == actualFile) { val string = getInputStream(e).readAllBytes().decodeToString() - assertEquals("version=$version", string) + assertEquals(version, string) return } } error("File $file not found") - } finally { - close() } } }