diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.kt new file mode 100644 index 000000000..a050dd1f5 --- /dev/null +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.kt @@ -0,0 +1,164 @@ +package com.github.jengelman.gradle.plugins.shadow.transformers + +import assertk.assertThat +import assertk.assertions.contains +import assertk.assertions.isEqualTo +import com.github.jengelman.gradle.plugins.shadow.transformers.PropertiesFileTransformer.MergeStrategy +import com.github.jengelman.gradle.plugins.shadow.util.Issue +import com.github.jengelman.gradle.plugins.shadow.util.getContent +import kotlin.io.path.appendText +import org.junit.jupiter.api.Test +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.EnumSource + +class PropertiesFileTransformerTest : BaseTransformerTest() { + + @ParameterizedTest + @EnumSource(MergeStrategy::class) + fun mergePropertiesWithDifferentStrategies(strategy: MergeStrategy) { + val one = buildJarOne { + insert("META-INF/test.properties", "key1=one\nkey2=one") + } + val two = buildJarTwo { + insert("META-INF/test.properties", "key2=two\nkey3=two") + } + projectScriptPath.appendText( + transform( + dependenciesBlock = implementationFiles(one, two), + transformerBlock = """ + mergeStrategy = $mergeStrategyClassName.$strategy + mergeSeparator = ";" + paths = ["META-INF/test.properties"] + """.trimIndent(), + ), + ) + + run(shadowJarTask) + + val expected = when (strategy) { + MergeStrategy.First -> arrayOf("key1=one", "key2=one", "key3=two") + MergeStrategy.Latest -> arrayOf("key1=one", "key2=two", "key3=two") + MergeStrategy.Append -> arrayOf("key1=one", "key2=one;two", "key3=two") + } + val content = outputShadowJar.use { it.getContent("META-INF/test.properties") } + assertThat(content).contains(*expected) + } + + @Test + fun mergePropertiesWithKeyTransformer() { + val one = buildJarOne { + insert("META-INF/test.properties", "foo=bar") + } + val two = buildJarTwo { + insert("META-INF/test.properties", "FOO=baz") + } + projectScriptPath.appendText( + transform( + dependenciesBlock = implementationFiles(one, two), + transformerBlock = """ + mergeStrategy = $mergeStrategyClassName.Append + keyTransformer = { key -> key.toUpperCase() } + paths = ["META-INF/test.properties"] + """.trimIndent(), + ), + ) + + run(shadowJarTask) + + val content = outputShadowJar.use { it.getContent("META-INF/test.properties") } + assertThat(content).contains("FOO=bar,baz") + } + + @Test + fun mergePropertiesWithSpecifiedCharset() { + val one = buildJarOne { + insert("META-INF/utf8.properties", "foo=第一") + } + val two = buildJarTwo { + insert("META-INF/utf8.properties", "foo=第二") + } + projectScriptPath.appendText( + transform( + dependenciesBlock = implementationFiles(one, two), + transformerBlock = """ + mergeStrategy = $mergeStrategyClassName.Append + charsetName = "utf-8" + paths = ["META-INF/utf8.properties"] + """.trimIndent(), + ), + ) + + run(shadowJarTask) + + val content = outputShadowJar.use { it.getContent("META-INF/utf8.properties") } + assertThat(content).contains("foo=第一,第二") + } + + @Test + fun mergePropertiesWithMappings() { + val one = buildJarOne { + insert("META-INF/foo.properties", "foo=1") + insert("META-INF/bar.properties", "bar=2") + } + val two = buildJarTwo { + insert("META-INF/foo.properties", "foo=3") + insert("META-INF/bar.properties", "bar=4") + } + projectScriptPath.appendText( + transform( + dependenciesBlock = implementationFiles(one, two), + transformerBlock = """ + mappings = [ + "META-INF/foo.properties": ["mergeStrategy": "append", "mergeSeparator": ";"], + "META-INF/bar.properties": ["mergeStrategy": "latest"] + ] + """.trimIndent(), + ), + ) + + run(shadowJarTask) + + assertThat(outputShadowJar).useAll { + getContent("META-INF/foo.properties").contains("foo=1;3") + getContent("META-INF/bar.properties").contains("bar=4") + } + } + + @Issue( + "https://github.com/GradleUp/shadow/issues/622", + "https://github.com/GradleUp/shadow/issues/856", + ) + @Test + fun mergedPropertiesDontContainDateComment() { + val one = buildJarOne { + insert("META-INF/test.properties", "foo=one") + } + val two = buildJarTwo { + insert("META-INF/test.properties", "foo=two") + } + projectScriptPath.appendText( + transform( + dependenciesBlock = implementationFiles(one, two), + transformerBlock = """ + mergeStrategy = $mergeStrategyClassName.Append + paths = ["META-INF/test.properties"] + """.trimIndent(), + ), + ) + + run(shadowJarTask) + + val content = outputShadowJar.use { it.getContent("META-INF/test.properties") } + assertThat(content.trimIndent()).isEqualTo( + """ + # + + foo=one,two + """.trimIndent(), + ) + } + + private companion object { + val mergeStrategyClassName = requireNotNull(MergeStrategy::class.java.canonicalName) + } +} diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/TransformersTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/TransformersTest.kt index 2ed0f9019..6940adad5 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/TransformersTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/TransformersTest.kt @@ -195,7 +195,6 @@ class TransformersTest : BaseTransformerTest() { "{ resource.set(\"test.file\"); file.fileValue(file(\"test/some.file\")) }" to IncludeResourceTransformer::class, "" to ManifestAppenderTransformer::class, "" to ManifestResourceTransformer::class, - "{ keyTransformer = { it.toLowerCase() } }" to PropertiesFileTransformer::class, ) } } diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/CleanProperties.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/CleanProperties.kt index 13f6730f7..624aa422d 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/CleanProperties.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/CleanProperties.kt @@ -6,6 +6,9 @@ import java.io.Writer import java.util.Date import java.util.Properties +/** + * Introduced in order to remove prepended timestamp when creating output stream. + */ internal class CleanProperties : Properties() { @Throws(IOException::class) override fun store(writer: Writer, comments: String) {