Skip to content

Commit 8300f91

Browse files
authored
Support configuring separator in AppendingTransformer (#1169)
1 parent 1845e43 commit 8300f91

File tree

7 files changed

+136
-7
lines changed

7 files changed

+136
-7
lines changed

api/shadow.api

+9
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,8 @@ public abstract class com/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar
297297
public fun <init> ()V
298298
public fun append (Ljava/lang/String;)Lcom/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar;
299299
public synthetic fun append (Ljava/lang/String;)Lcom/github/jengelman/gradle/plugins/shadow/tasks/ShadowSpec;
300+
public fun append (Ljava/lang/String;Ljava/lang/String;)Lcom/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar;
301+
public synthetic fun append (Ljava/lang/String;Ljava/lang/String;)Lcom/github/jengelman/gradle/plugins/shadow/tasks/ShadowSpec;
300302
protected fun copy ()V
301303
protected fun createCopyAction ()Lorg/gradle/api/internal/file/copy/CopyAction;
302304
public fun dependencies (Lorg/gradle/api/Action;)Lcom/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar;
@@ -349,6 +351,7 @@ public abstract class com/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar
349351

350352
public abstract interface class com/github/jengelman/gradle/plugins/shadow/tasks/ShadowSpec : org/gradle/api/file/CopySpec {
351353
public abstract fun append (Ljava/lang/String;)Lcom/github/jengelman/gradle/plugins/shadow/tasks/ShadowSpec;
354+
public abstract fun append (Ljava/lang/String;Ljava/lang/String;)Lcom/github/jengelman/gradle/plugins/shadow/tasks/ShadowSpec;
352355
public abstract fun dependencies (Lorg/gradle/api/Action;)Lcom/github/jengelman/gradle/plugins/shadow/tasks/ShadowSpec;
353356
public abstract fun getStats ()Lcom/github/jengelman/gradle/plugins/shadow/ShadowStats;
354357
public abstract fun mergeGroovyExtensionModules ()Lcom/github/jengelman/gradle/plugins/shadow/tasks/ShadowSpec;
@@ -397,15 +400,21 @@ public class com/github/jengelman/gradle/plugins/shadow/transformers/ApacheNotic
397400
}
398401

399402
public class com/github/jengelman/gradle/plugins/shadow/transformers/AppendingTransformer : com/github/jengelman/gradle/plugins/shadow/transformers/Transformer {
403+
public static final field Companion Lcom/github/jengelman/gradle/plugins/shadow/transformers/AppendingTransformer$Companion;
404+
public static final field DEFAULT_SEPARATOR Ljava/lang/String;
400405
public fun <init> (Lorg/gradle/api/model/ObjectFactory;)V
401406
public fun canTransformResource (Lorg/gradle/api/file/FileTreeElement;)Z
402407
public final fun getObjectFactory ()Lorg/gradle/api/model/ObjectFactory;
403408
public fun getResource ()Lorg/gradle/api/provider/Property;
409+
public fun getSeparator ()Lorg/gradle/api/provider/Property;
404410
public fun hasTransformedResource ()Z
405411
public fun modifyOutputStream (Lorg/apache/tools/zip/ZipOutputStream;Z)V
406412
public fun transform (Lcom/github/jengelman/gradle/plugins/shadow/transformers/TransformerContext;)V
407413
}
408414

415+
public final class com/github/jengelman/gradle/plugins/shadow/transformers/AppendingTransformer$Companion {
416+
}
417+
409418
public abstract interface annotation class com/github/jengelman/gradle/plugins/shadow/transformers/CacheableTransformer : java/lang/annotation/Annotation {
410419
}
411420

src/docs/changes/README.md

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
- **BREAKING CHANGE:** Migrate all `ListProperty` usages to `SetProperty`. ([#1103](https://github.com/GradleUp/shadow/pull/1103))
1313
Some public `List` parameters are also changed to `Set`.
1414
- Replace deprecated `SelfResolvingDependency` with `FileCollectionDependency`. ([#1114](https://github.com/GradleUp/shadow/pull/1114))
15+
- Support configuring `separator` in `AppendingTransformer`. ([#1169](https://github.com/GradleUp/shadow/pull/1169))
16+
This is useful for handling files like `resources/application.yml`.
1517

1618
**Fixed**
1719

src/docs/configuration/merging/README.md

+15-1
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ tasks.named('shadowJar', com.github.jengelman.gradle.plugins.shadow.tasks.Shadow
180180

181181
Generic text files can be appended together using the
182182
[`AppendingTransformer`](https://gradleup.com/shadow/api/com/github/jengelman/gradle/plugins/shadow/transformers/AppendingTransformer.html).
183-
Each file is appended using new lines to separate content.
183+
Each file is appended using separators (defaults to `\n`) to separate content.
184184
The [`ShadowJar`](https://gradleup.com/shadow/api/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar.html) task provides a short syntax
185185
method of
186186
[`append(String)`](https://gradleup.com/shadow/api/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar.html#append(java.lang.String)) to
@@ -193,6 +193,20 @@ tasks.named('shadowJar', com.github.jengelman.gradle.plugins.shadow.tasks.Shadow
193193
}
194194
```
195195

196+
```groovy
197+
// Appending application.yml files
198+
tasks.named('shadowJar', com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) {
199+
// short syntax
200+
append('resources/application.yml', '\n---\n')
201+
// full syntax
202+
transform(com.github.jengelman.gradle.plugins.shadow.transformers.AppendingTransformer.class) {
203+
resource = 'resources/custom-config/application.yml'
204+
separator = '\n---\n'
205+
}
206+
}
207+
```
208+
209+
196210
## Appending XML Files
197211

198212
XML files require a special transformer for merging.

src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/AppendingTransformerTest.kt

+82-4
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ package com.github.jengelman.gradle.plugins.shadow.transformers
33
import assertk.assertThat
44
import assertk.assertions.isEqualTo
55
import com.github.jengelman.gradle.plugins.shadow.util.getContent
6+
import java.nio.file.Path
67
import kotlin.io.path.appendText
78
import org.junit.jupiter.api.Test
89

910
class AppendingTransformerTest : BaseTransformerTest() {
1011
@Test
11-
fun appendingTransformer() {
12+
fun appendTestProperties() {
1213
val one = buildJarOne {
1314
insert(ENTRY_TEST_PROPERTIES, CONTENT_ONE)
1415
}
@@ -26,12 +27,12 @@ class AppendingTransformerTest : BaseTransformerTest() {
2627

2728
run(shadowJarTask)
2829

29-
val content = outputShadowJar.use { it.getContent(ENTRY_TEST_PROPERTIES) }.trimIndent()
30+
val content = outputShadowJar.use { it.getContent(ENTRY_TEST_PROPERTIES) }
3031
assertThat(content).isEqualTo(CONTENT_ONE_TWO)
3132
}
3233

3334
@Test
34-
fun appendingTransformerShortSyntax() {
35+
fun appendTestPropertiesShortSyntax() {
3536
val one = buildJarOne {
3637
insert(ENTRY_TEST_PROPERTIES, CONTENT_ONE)
3738
}
@@ -49,7 +50,84 @@ class AppendingTransformerTest : BaseTransformerTest() {
4950

5051
run(shadowJarTask)
5152

52-
val content = outputShadowJar.use { it.getContent(ENTRY_TEST_PROPERTIES) }.trimIndent()
53+
val content = outputShadowJar.use { it.getContent(ENTRY_TEST_PROPERTIES) }
5354
assertThat(content).isEqualTo(CONTENT_ONE_TWO)
5455
}
56+
57+
@Test
58+
fun appendApplicationYaml() {
59+
val (one, two) = writeApplicationYamlJars()
60+
61+
projectScriptPath.appendText(
62+
transform<AppendingTransformer>(
63+
shadowJarBlock = fromJar(one, two),
64+
transformerBlock = """
65+
resource = 'resources/$APPLICATION_YML_FILE'
66+
separator = '$APPLICATION_YML_SEPARATOR'
67+
""".trimIndent(),
68+
),
69+
)
70+
71+
run(shadowJarTask)
72+
73+
val content = outputShadowJar.use { it.getContent("resources/$APPLICATION_YML_FILE") }
74+
assertThat(content).isEqualTo(
75+
"""
76+
$CONTENT_ONE
77+
---
78+
$CONTENT_TWO
79+
""".trimIndent(),
80+
)
81+
}
82+
83+
@Test
84+
fun appendApplicationYamlShortSyntax() {
85+
val (one, two) = writeApplicationYamlJars()
86+
87+
projectScriptPath.appendText(
88+
"""
89+
$shadowJar {
90+
${fromJar(one, two)}
91+
append('resources/$APPLICATION_YML_FILE', '$APPLICATION_YML_SEPARATOR')
92+
append('resources/config/$APPLICATION_YML_FILE', '$APPLICATION_YML_SEPARATOR')
93+
}
94+
""".trimIndent(),
95+
)
96+
97+
run(shadowJarTask)
98+
99+
val content1 = outputShadowJar.use { it.getContent("resources/$APPLICATION_YML_FILE") }
100+
assertThat(content1).isEqualTo(
101+
"""
102+
$CONTENT_ONE
103+
---
104+
$CONTENT_TWO
105+
""".trimIndent(),
106+
)
107+
val content2 = outputShadowJar.use { it.getContent("resources/config/$APPLICATION_YML_FILE") }
108+
assertThat(content2).isEqualTo(
109+
"""
110+
$CONTENT_TWO
111+
---
112+
$CONTENT_THREE
113+
""".trimIndent(),
114+
)
115+
}
116+
117+
private fun writeApplicationYamlJars(): Pair<Path, Path> {
118+
val one = buildJarOne {
119+
insert("resources/$APPLICATION_YML_FILE", CONTENT_ONE)
120+
insert("resources/config/$APPLICATION_YML_FILE", CONTENT_TWO)
121+
}
122+
val two = buildJarTwo {
123+
insert("resources/$APPLICATION_YML_FILE", CONTENT_TWO)
124+
insert("resources/config/$APPLICATION_YML_FILE", CONTENT_THREE)
125+
}
126+
return one to two
127+
}
128+
129+
private companion object {
130+
const val APPLICATION_YML_FILE = "application.yml"
131+
const val APPLICATION_YML_SEPARATOR = "\\n---\\n"
132+
}
55133
}

src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar.kt

+14
Original file line numberDiff line numberDiff line change
@@ -209,9 +209,23 @@ public abstract class ShadowJar :
209209
}
210210

211211
override fun append(resourcePath: String): ShadowJar {
212+
return append(resourcePath, AppendingTransformer.DEFAULT_SEPARATOR)
213+
}
214+
215+
/**
216+
* Append contents to a resource in the jar.
217+
*
218+
* e.g. `append("resources/application.yml", "\n---\n")` for merging `resources/application.yml` files.
219+
*
220+
* @param resourcePath The path to the resource in the jar.
221+
* @param separator The separator to use between the original content and the appended content,
222+
* defaults to `\n` ([AppendingTransformer.DEFAULT_SEPARATOR]).
223+
*/
224+
override fun append(resourcePath: String, separator: String): ShadowJar {
212225
return runCatching {
213226
transform(AppendingTransformer::class.java) {
214227
it.resource.set(resourcePath)
228+
it.separator.set(separator)
215229
}
216230
}.getOrDefault(this)
217231
}

src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowSpec.kt

+2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ public interface ShadowSpec : CopySpec {
4545

4646
public fun append(resourcePath: String): ShadowSpec
4747

48+
public fun append(resourcePath: String, separator: String): ShadowSpec
49+
4850
public fun relocate(pattern: String, destination: String): ShadowSpec
4951

5052
public fun relocate(pattern: String, destination: String, action: Action<SimpleRelocator>?): ShadowSpec

src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/AppendingTransformer.kt

+12-2
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,26 @@ public open class AppendingTransformer @Inject constructor(
2727
* Defer initialization, see [issue 763](https://github.com/GradleUp/shadow/issues/763).
2828
*/
2929
private var _data: ByteArrayOutputStream? = null
30-
private inline val data get() = if (_data == null) ByteArrayOutputStream().also { _data = it } else _data!!
30+
private inline val data get() = _data ?: ByteArrayOutputStream().also { _data = it }
3131

3232
@get:Optional
3333
@get:Input
3434
public open val resource: Property<String> = objectFactory.property()
3535

36+
@get:Input
37+
public open val separator: Property<String> = objectFactory.property(DEFAULT_SEPARATOR)
38+
3639
override fun canTransformResource(element: FileTreeElement): Boolean {
3740
return resource.orNull.equals(element.relativePath.pathString, ignoreCase = true)
3841
}
3942

4043
override fun transform(context: TransformerContext) {
4144
context.inputStream.use {
45+
if (data.size() > 0) {
46+
// Append the separator before the new content to ensure the separator is not at the end of the file.
47+
data.write(separator.get().toByteArray())
48+
}
4249
it.copyTo(data)
43-
data.write('\n'.code)
4450
}
4551
}
4652

@@ -57,4 +63,8 @@ public open class AppendingTransformer @Inject constructor(
5763
data.toByteArray().inputStream().copyTo(os)
5864
data.reset()
5965
}
66+
67+
public companion object {
68+
public const val DEFAULT_SEPARATOR: String = "\n"
69+
}
6070
}

0 commit comments

Comments
 (0)