Implement 'CommonizerTarget.fileName' and limit fileName length

^KT-46856 Fixed
This commit is contained in:
sebastian.sellmair
2021-05-21 12:03:44 +02:00
committed by Space
parent 0749443f7e
commit 14eca72913
3 changed files with 95 additions and 16 deletions
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.gradle.targets.native.internal
import org.gradle.api.DefaultTask
import org.gradle.api.Project
import org.gradle.api.tasks.*
import org.jetbrains.kotlin.commonizer.CommonizerLogLevel
import org.jetbrains.kotlin.commonizer.HierarchicalCommonizerOutputLayout.fileName
import org.jetbrains.kotlin.commonizer.SharedCommonizerTarget
import org.jetbrains.kotlin.commonizer.identityString
import org.jetbrains.kotlin.commonizer.isAncestorOf
@@ -21,8 +21,7 @@ import org.jetbrains.kotlin.konan.library.KONAN_DISTRIBUTION_COMMON_LIBS_DIR
import org.jetbrains.kotlin.konan.library.KONAN_DISTRIBUTION_KLIB_DIR
import org.jetbrains.kotlin.konan.library.KONAN_DISTRIBUTION_PLATFORM_LIBS_DIR
import java.io.File
import java.nio.charset.StandardCharsets
import java.util.*
import java.net.URLEncoder
internal open class HierarchicalNativeDistributionCommonizerTask : DefaultTask() {
@@ -78,16 +77,11 @@ internal open class HierarchicalNativeDistributionCommonizerTask : DefaultTask()
internal fun getRootOutputDirectory(target: SharedCommonizerTarget): File {
val kotlinVersion = project.getKotlinPluginVersion()
val discriminator = buildString {
append(target.identityString)
append("-")
append(kotlinVersion.toLowerCase().base64)
}
return project.file(konanHome)
.resolve(KONAN_DISTRIBUTION_KLIB_DIR)
.resolve(KONAN_DISTRIBUTION_COMMONIZED_LIBS_DIR)
.resolve(discriminator)
.resolve(urlEncode(kotlinVersion))
.resolve(target.fileName)
}
@TaskAction
@@ -121,8 +115,4 @@ private fun Project.getRootCommonizerTargets(): Set<SharedCommonizerTarget> {
return allTargets.filter { target -> allTargets.none { otherTarget -> otherTarget isAncestorOf target } }.toSet()
}
private val String.base64
get() = base64Encoder.encodeToString(toByteArray(StandardCharsets.UTF_8))
private val base64Encoder = Base64.getEncoder().withoutPadding()
private fun urlEncode(value: String): String = URLEncoder.encode(value, Charsets.UTF_8.name())
@@ -8,6 +8,8 @@ package org.jetbrains.kotlin.commonizer
import org.jetbrains.kotlin.konan.library.KONAN_DISTRIBUTION_COMMON_LIBS_DIR
import org.jetbrains.kotlin.konan.library.KONAN_DISTRIBUTION_PLATFORM_LIBS_DIR
import java.io.File
import java.security.MessageDigest
import java.util.*
public fun interface CommonizerOutputLayout {
@@ -24,7 +26,27 @@ public object NativeDistributionCommonizerOutputLayout : CommonizerOutputLayout
}
public object HierarchicalCommonizerOutputLayout : CommonizerOutputLayout {
internal const val maxFileNameLength = 150
override fun getTargetDirectory(root: File, target: CommonizerTarget): File {
return root.resolve(target.identityString)
return root.resolve(target.fileName)
}
public val CommonizerTarget.fileName: String
get() {
val identityString = identityString
return if (identityString.length <= maxFileNameLength) identityString
else {
val hashSuffix = "[--$identityStringHash]"
return identityString.take(maxFileNameLength - hashSuffix.length) + hashSuffix
}
}
private val CommonizerTarget.identityStringHash: String
get() {
val sha = MessageDigest.getInstance("SHA-1")
val base64 = Base64.getUrlEncoder()
return base64.encode(sha.digest(identityString.encodeToByteArray())).decodeToString()
}
}
@@ -0,0 +1,67 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.commonizer
import org.jetbrains.kotlin.commonizer.HierarchicalCommonizerOutputLayout.fileName
import org.jetbrains.kotlin.commonizer.HierarchicalCommonizerOutputLayout.maxFileNameLength
import org.junit.Rule
import org.junit.rules.TemporaryFolder
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue
class CommonizerTargetFileNameTest {
private val longCommonizerTarget = parseCommonizerTarget(
buildString {
append("(")
append(
sequence {
var i = 0
while (true) {
yield(i.toString())
i++
}
}.take(maxFileNameLength).joinToString(", ")
)
append(")")
}
)
@get:Rule
val temporaryFolder = TemporaryFolder()
@Test
fun `small targets will use identityString`() {
val target = parseCommonizerTarget("((a, b), c)")
assertEquals(target.identityString, target.fileName)
}
@OptIn(ExperimentalStdlibApi::class)
@Test
fun `longCommonizerTarget respect maximum fileName length`() {
assertTrue(
longCommonizerTarget.identityString.length > maxFileNameLength,
"Expected test target's identityString to exceed maxFileNameLength"
)
assertEquals(
longCommonizerTarget.fileName.length, maxFileNameLength,
"Expected test target's fileName to be exactly match the maximum"
)
}
@Test
fun `longCommonizerTarget fileName can create new file`() {
val longCommonizerTargetFile = temporaryFolder.root.resolve(longCommonizerTarget.fileName)
assertTrue(longCommonizerTargetFile.createNewFile(), "Expected being able to create file $longCommonizerTargetFile")
longCommonizerTargetFile.writeText(longCommonizerTarget.identityString)
assertEquals(
longCommonizerTarget, parseCommonizerTarget(longCommonizerTargetFile.readText()),
"Expected being able to read and write to $longCommonizerTargetFile"
)
}
}