diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/CompositeMetadataArtifactImpl.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/CompositeMetadataArtifactImpl.kt index f74974354f8..7407f87b34b 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/CompositeMetadataArtifactImpl.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/CompositeMetadataArtifactImpl.kt @@ -73,7 +73,7 @@ internal class CompositeMetadataArtifactImpl( In this case, return null */ - if (artifactFile.containsDirectory(sourceSetName)) MetadataBinaryImpl(this, artifactFile) else null + if (artifactFile.containsKlibDirectory(sourceSetName)) MetadataBinaryImpl(this, artifactFile) else null } override val cinteropMetadataBinaries: List by lazy { @@ -131,7 +131,7 @@ internal class CompositeMetadataArtifactImpl( } val libraryPath = "${containingSourceSetContent.sourceSetName}/" - if (!artifactFile.containsDirectory(libraryPath)) return false + if (!artifactFile.containsKlibDirectory(libraryPath)) return false file.parentFile.mkdirs() artifactFile.zip.copyPartially(file, libraryPath) @@ -176,7 +176,7 @@ internal class CompositeMetadataArtifactImpl( val cinteropMetadataDirectoryPath = ensureValidZipDirectoryPath(cinteropMetadataDirectory) val libraryPath = "$cinteropMetadataDirectoryPath$cinteropLibraryName/" - if (!artifactFile.containsDirectory(libraryPath)) return false + if (!artifactFile.containsKlibDirectory(libraryPath)) return false file.parentFile.mkdirs() artifactFile.zip.copyPartially(file, "$cinteropMetadataDirectoryPath$cinteropLibraryName/") @@ -186,7 +186,7 @@ internal class CompositeMetadataArtifactImpl( /** * Interface to the underlying [zip][file] that only opens the file lazily and keeps references to - * all [entries] and infers all potential directory paths (see [directoryPaths] and [containsDirectory]) + * all [entries] and infers all potential directory paths (see [directoryPaths] and [containsKlibDirectory]) */ private class ArtifactFile(private val file: File) : Closeable { @@ -210,21 +210,18 @@ internal class CompositeMetadataArtifactImpl( } /** - * All potential directory paths, including inferred directory paths when the [zip] file does - * not include directory entries. - * @see collectAllDirectoryPaths - */ - val directoryPaths: Set by lazy { collectAllDirectoryPaths(entries) } - - /** - * Check if the underlying [zip] file contains this directory. - * Note: This check also works for zip files that did not include directory entries. + * Check if the underlying [zip] file contains klib at [path]. + * Note: This check also works for zip files that did not include any klibs. * This will return true, if any other zip-entry is placed inside this directory [path] */ - fun containsDirectory(path: String): Boolean { - val validPath = ensureValidZipDirectoryPath(path) - if (zip.getEntry(validPath) != null) return true - return validPath in directoryPaths + fun containsKlibDirectory(path: String): Boolean { + // Checking for manifest file in "default" folder is considered "good enough" to say that it is a KLIB + // There are three possible states of content in the subdirectory of Composite Metadata Artifact + // 1. Klib + // 2. resources or mix klib + resources (FIXME: KT-66563) + // 3. empty directory. In case if something went wrong with publication. Like Task was skipped for some reason. + val pathToTheManifestFile = ensureValidZipDirectoryPath(path) + "default/manifest" + return zip.getEntry(pathToTheManifestFile) != null } private fun ensureNotClosed() { @@ -238,33 +235,4 @@ internal class CompositeMetadataArtifactImpl( } } } -} - -/** - * Zip files are not **forced** to include entries for directories. - * In order to do preliminary checks, if some directory is present in Zip Files it is - * often useful to infer the directories included in any Zip File by looking into file entries - * and inferring their directories. - */ -private fun collectAllDirectoryPaths(entries: List): Set { - /* - The 'root' directory is represented as empty String in ZipFile - */ - val set = hashSetOf("") - - entries.forEach { entry -> - if (entry.isDirectory) { - set.add(entry.name) - return@forEach - } - - /* Collect all 'intermediate' directories found by looking at the files path */ - val pathParts = entry.name.split("/") - pathParts.runningReduce { currentPath, nextPart -> - set.add("$currentPath/") - "$currentPath/$nextPart" - } - } - return set -} - +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/CompositeMetadataArtifactTest.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/CompositeMetadataArtifactTest.kt index 2cc18c83ed2..ff6e0bc39e3 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/CompositeMetadataArtifactTest.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/CompositeMetadataArtifactTest.kt @@ -20,6 +20,8 @@ class CompositeMetadataArtifactTest { @get:Rule val temporaryFolder = TemporaryFolder() + private val KLIB_MANIFEST_PATH = "default/manifest" + @Test fun `empty jar - contains no metadataBinary and no cinteropMetadataBinaries`() { val primaryArtifactContent = temporaryFolder.newFolder() @@ -59,7 +61,7 @@ class CompositeMetadataArtifactTest { fun `stub metadata library - can be unzipped`() { val testSourceSetName = "testSourceSetName" val primaryArtifactContent = temporaryFolder.newFolder() - val stubFile = primaryArtifactContent.resolve(testSourceSetName).resolve("stub.txt") + val stubFile = primaryArtifactContent.resolve(testSourceSetName).resolve(KLIB_MANIFEST_PATH) stubFile.parentFile.mkdirs() stubFile.writeText("stub!") @@ -93,8 +95,9 @@ class CompositeMetadataArtifactTest { val unzippedMetadataFile = metadataOutputDirectory.resolve("unzipped") unzipTo(unzippedMetadataFile, metadataFile) - assertEquals(setOf(unzippedMetadataFile.resolve("stub.txt")), unzippedMetadataFile.listFiles().orEmpty().toSet()) - assertEquals("stub!", unzippedMetadataFile.resolve("stub.txt").readText()) + val actualUnzippedFiles = unzippedMetadataFile.walkTopDown().filter { it.isFile }.toSet() + assertEquals(setOf(unzippedMetadataFile.resolve(KLIB_MANIFEST_PATH)), actualUnzippedFiles) + assertEquals("stub!", unzippedMetadataFile.resolve(KLIB_MANIFEST_PATH).readText()) } } @@ -128,21 +131,21 @@ class CompositeMetadataArtifactTest { /* Setup Artifact content */ val primaryArtifactContent = temporaryFolder.newFolder() - primaryArtifactContent.resolve("sourceSetA/sourceSetAStub1.txt") + primaryArtifactContent.resolve("sourceSetA/$KLIB_MANIFEST_PATH") .withParentDirectoriesCreated() - .writeText("Content of sourceSetA stub1") + .writeText("Content of sourceSetA Metadata KLIB") - primaryArtifactContent.resolve("sourceSetA/nested/sourceSetAStub2.txt") + primaryArtifactContent.resolve("sourceSetA/sourceSetAStub.txt") .withParentDirectoriesCreated() - .writeText("Content of sourceSetB stub2") + .writeText("Resource file mixed with sourceSetA Metadata KLIB") - primaryArtifactContent.resolve("sourceSetB/sourceSetBStub1.txt") + primaryArtifactContent.resolve("sourceSetB/$KLIB_MANIFEST_PATH") .withParentDirectoriesCreated() .writeText("Content of sourceSetB stub1") - primaryArtifactContent.resolve("sourceSetB/nested/sourceSetBStub2.txt") + primaryArtifactContent.resolve("sourceSetWithResourcesOnly/stub.txt") .withParentDirectoriesCreated() - .writeText("Content of sourceSetB stub2") + .writeText("Resource file with klib content") /* Create metadata jar */ val primaryArtifactFile = temporaryFolder.newFile("metadata.jar") @@ -154,7 +157,8 @@ class CompositeMetadataArtifactTest { kotlinProjectStructureMetadata = createProjectStructureMetadata( sourceSetBinaryLayout = mapOf( "sourceSetA" to SourceSetMetadataLayout.KLIB, - "sourceSetB" to SourceSetMetadataLayout.METADATA + "sourceSetB" to SourceSetMetadataLayout.METADATA, + "sourceSetWithResourcesOnly" to SourceSetMetadataLayout.KLIB, ) ), primaryArtifactFile = primaryArtifactFile, @@ -195,6 +199,9 @@ class CompositeMetadataArtifactTest { "Expected correct content of extracted 'sourceSetA'" ) } + + /* even though there is sourceSetWithResourcesOnly directory, there is no metadata KLIB in it */ + assertNull(artifactContent.getSourceSet("sourceSetWithResourcesOnly").metadataBinary) } } @@ -203,7 +210,7 @@ class CompositeMetadataArtifactTest { /* Setup Artifact content */ val primaryArtifactContent = temporaryFolder.newFolder() - primaryArtifactContent.resolve("sourceSetA-cinterop/interopA0/stub0") + primaryArtifactContent.resolve("sourceSetA-cinterop/interopA0/$KLIB_MANIFEST_PATH") .withParentDirectoriesCreated() .writeText("stub0 content") @@ -211,11 +218,11 @@ class CompositeMetadataArtifactTest { .withParentDirectoriesCreated() .writeText("stub1 content") - primaryArtifactContent.resolve("sourceSetA-cinterop/interopA1/stub2") + primaryArtifactContent.resolve("sourceSetA-cinterop/interopA1/$KLIB_MANIFEST_PATH") .withParentDirectoriesCreated() .writeText("stub2 content") - primaryArtifactContent.resolve("nested/sourceSetB/interops/interopB0/stub3") + primaryArtifactContent.resolve("nested/sourceSetB/interops/interopB0/$KLIB_MANIFEST_PATH") .withParentDirectoriesCreated() .writeText("stub3 content")