diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/CompositeMetadataJar.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/CompositeMetadataJar.kt index 1894ca7167c..3e0bd3ee21a 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/CompositeMetadataJar.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/CompositeMetadataJar.kt @@ -71,20 +71,17 @@ private class CompositeMetadataJarImpl( val artifactFile = getArtifactFile(sourceSetName) val moduleOutputDirectory = outputDirectory.resolve(moduleIdentifier).also(File::mkdirs) - ZipFile(getArtifactFile(sourceSetName)).use { compoundMetadataArtifactZipFile -> - val cinteropRootDirectory = compoundMetadataArtifactZipFile.entries().asSequence() - .firstOrNull { zipEntry -> zipEntry.name == "$sourceSetName-cinterop/" && zipEntry.isDirectory } - ?: return emptySet() - - val cinterops = compoundMetadataArtifactZipFile.listChildren(cinteropRootDirectory) - - val cinteropsByOutputFile = cinterops.associateBy { cinteropZipEntry -> - moduleOutputDirectory.resolve("${cinteropZipEntry.name.removePrefix(cinteropRootDirectory.name).removeSuffix("/")}.klib") - } + ZipFile(getArtifactFile(sourceSetName)).use { artifactZipFile -> + val cinteropRootPath = "$sourceSetName-cinterop/" + val cinteropEntries = artifactZipFile.listChildren(cinteropRootPath) + val cinteropNames = cinteropEntries.map { entry -> + entry.name.removePrefix(cinteropRootPath).split("/", limit = 2).first() + }.toSet() + val cinteropsByOutputFile = cinteropNames.associateBy { cinteropName -> moduleOutputDirectory.resolve("$cinteropName.klib") } if (materializeFiles) { - cinteropsByOutputFile.forEach { (cinteropOutputFile, cinteropZipEntry) -> - copyZipFilePartially(artifactFile, cinteropOutputFile, cinteropZipEntry.name) + cinteropsByOutputFile.forEach { (cinteropOutputFile, cinteropName) -> + copyZipFilePartially(artifactFile, cinteropOutputFile, "$cinteropRootPath$cinteropName/") } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/utils/zipUtils.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/utils/zipUtils.kt index 0aaacfa4551..a6cf4917b04 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/utils/zipUtils.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/utils/zipUtils.kt @@ -11,7 +11,7 @@ import java.util.zip.ZipFile import java.util.zip.ZipOutputStream internal fun copyZipFilePartially(sourceZipFile: File, destinationZipFile: File, path: String) { - require(path.endsWith("/")) { "Expected path to end with '/', found '$path'" } + requireValidZipPath(path) ZipFile(sourceZipFile).use { zip -> val entries = zip.entries().asSequence() @@ -35,11 +35,23 @@ internal fun copyZipFilePartially(sourceZipFile: File, destinationZipFile: File, } } +internal fun ZipFile.listDescendants(path: String): Sequence { + requireValidZipPath(path) + return entries().asSequence().filter { entry -> + entry.name != path && entry.name.startsWith(path) + } +} + +internal fun ZipFile.listChildren(path: String): Sequence { + requireValidZipPath(path) + return listDescendants(path).filter { entry -> + entry.name.removePrefix(path).count { it == '/' } == 1 + } +} + internal fun ZipFile.listDescendants(zipEntry: ZipEntry): Sequence { require(zipEntry.isDirectory) - return entries().asSequence().filter { entry -> - entry.name != zipEntry.name && entry.name.startsWith(zipEntry.name) - } + return listDescendants(zipEntry.name) } internal fun ZipFile.listChildren(zipEntry: ZipEntry): Sequence { @@ -47,3 +59,5 @@ internal fun ZipFile.listChildren(zipEntry: ZipEntry): Sequence { entry.name.removePrefix(zipEntry.name).count { it == '/' } == 1 } } + +private fun requireValidZipPath(path: String) = require(path.endsWith("/")) { "Expected path to end with '/', found '$path'" }