Skip to content

Commit c3c109b

Browse files
authored
Default duplicatesStrategy back to EXCLUDE
This strategy is consistent with 8.x series behavior, which is more compatible for most users upgrading.
1 parent 46d7be1 commit c3c109b

6 files changed

Lines changed: 55 additions & 28 deletions

File tree

docs/changes/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
### Changed
77

88
- Improve the error message for empty `mainClassName`. ([#1601](https://github.com/GradleUp/shadow/pull/1601))
9+
- Default `duplicatesStrategy` back to `EXCLUDE`. ([#1617](https://github.com/GradleUp/shadow/pull/1617))
10+
- This strategy is consistent with 8.x series behavior, which is more compatible for most users upgrading.
11+
- For most `ResourceTransformer` users, you need to override the strategy to `INCLUDE` to make them work.
12+
- See more details about the strategies at [Handling Duplicates Strategy](https://gradleup.com/shadow/configuration/merging/#handling-duplicates-strategy).
913

1014
### Fixed
1115

docs/configuration/merging/README.md

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,36 +22,35 @@ merging in additional data from dependencies.
2222
- `EXCLUDE`: Do not allow duplicates by ignoring subsequent items to be created at the same path.
2323
- `FAIL`: Throw a `DuplicateFileCopyingException` when subsequent items are to be created at the same path.
2424
- `INCLUDE`: Do not attempt to prevent duplicates.
25-
- `INHERIT`: Uses the same strategy as the parent copy specification.
25+
- `INHERIT`: Use the same strategy as the parent copy specification.
2626
- `WARN`: Do not attempt to prevent duplicates, but log a warning message when multiple items are to be created at the
2727
same path.
2828

2929
see more details about them in [`DuplicatesStrategy`][DuplicatesStrategy].
3030

31-
`ShadowJar` recognizes `DuplicatesStrategy.INCLUDE` as the default, if you want to change the strategy, you can
32-
override it like:
31+
`ShadowJar` recognizes `EXCLUDE` as the default, if you want to change the strategy, you can override it like:
3332

3433
=== "Kotlin"
3534

3635
```kotlin
3736
tasks.shadowJar {
38-
duplicatesStrategy = DuplicatesStrategy.EXCLUDE // Or something else.
37+
duplicatesStrategy = DuplicatesStrategy.INCLUDE // Or something else.
3938
}
4039
```
4140

4241
=== "Groovy"
4342

4443
```groovy
4544
tasks.named('shadowJar', com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) {
46-
duplicatesStrategy = DuplicatesStrategy.EXCLUDE // Or something else.
45+
duplicatesStrategy = DuplicatesStrategy.INCLUDE // Or something else.
4746
}
4847
```
4948

5049
Different strategies will lead to different results for `foo/bar` files in the JARs to be merged:
5150

5251
- `EXCLUDE`: The **first** `foo/bar` file will be included in the final JAR.
5352
- `FAIL`: **Fail** the build with a `DuplicateFileCopyingException` if there are duplicate `foo/bar` files.
54-
- `INCLUDE`: Duplicate `foo/bar` entries will be included in the final JAR.
53+
- `INCLUDE`: **Duplicate** `foo/bar` entries will be included in the final JAR.
5554
- `INHERIT`: **Fail** the build with an exception like
5655
`Entry .* is a duplicate but no duplicate handling strategy has been set`.
5756
- `WARN`: **Warn** about duplicates in the build log, this behaves exactly as `INHERIT` otherwise.
@@ -78,17 +77,18 @@ Different strategies will lead to different results for `foo/bar` files in the J
7877
```
7978

8079
The [`ResourceTransformer`][ResourceTransformer]s like [`ServiceFileTransformer`][ServiceFileTransformer] will not work
81-
as expected because the `duplicatesStrategy` will exclude the duplicate service files beforehand. However, this behavior might be what you expected for duplicate
82-
`foo/bar` files, preventing them from being included.
80+
as expected as the duplicate resource files fed for them are excluded beforehand. However, this behavior might be what you expected for duplicate `foo/bar` files, preventing them from being included.
8381

84-
Want [`ResourceTransformer`][ResourceTransformer]s and `duplicatesStrategy` to work together? There are several ways to
85-
do it:
82+
Want [`ResourceTransformer`][ResourceTransformer]s and `duplicatesStrategy` to work together? There are several steps
83+
to take:
8684

87-
- Use [`filesMatching`][Jar.filesMatching] to override the strategy for specific files.
88-
- Keep `duplicatesStrategy = INCLUDE` and write your own [`ResourceTransformer`][ResourceTransformer] to handle duplicates.
89-
90-
If you just want to keep the current behavior and preserve the first found resources, there is a simple built-in one
91-
called [`PreserveFirstFoundResourceTransformer`][PreserveFirstFoundResourceTransformer].
85+
1. Set the strategy to `INCLUDE` or `WARN`.
86+
2. Apply your [`ResourceTransformer`][ResourceTransformer]s.
87+
3. Remove duplicate entries by
88+
- overriding the default strategy for specific files using [`filesMatching`][Jar.filesMatching]
89+
- applying [`PreserveFirstFoundResourceTransformer`][PreserveFirstFoundResourceTransformer]
90+
- or something similar.
91+
4. Optionally, enable [`ShadowJar.failOnDuplicateEntries`][ShadowJar.failOnDuplicateEntries] to check duplicate entries in the final JAR.
9292

9393
## Basic ResourceTransformer Usage
9494

@@ -449,6 +449,7 @@ It must be added using the [`transform`][ShadowJar.transform] methods.
449449
[ServiceFileTransformer]: ../../api/shadow/com.github.jengelman.gradle.plugins.shadow.transformers/-service-file-transformer/index.html
450450
[PreserveFirstFoundResourceTransformer]: ../../api/shadow/com.github.jengelman.gradle.plugins.shadow.transformers/-preserve-first-found-resource-transformer/index.html
451451
[ShadowJar.append]: ../../api/shadow/com.github.jengelman.gradle.plugins.shadow.tasks/-shadow-jar/append.html
452+
[ShadowJar.failOnDuplicateEntries]: ../../api/shadow/com.github.jengelman.gradle.plugins.shadow.tasks/-shadow-jar/fail-on-duplicate-entries.html
452453
[ShadowJar.from]: https://docs.gradle.org/current/dsl/org.gradle.jvm.tasks.Jar.html#org.gradle.jvm.tasks.Jar:from(java.lang.Object,%20org.gradle.api.Action)
453454
[ShadowJar.transform]: ../../api/shadow/com.github.jengelman.gradle.plugins.shadow.tasks/-shadow-jar/transform.html
454455
[ShadowJar]: ../../api/shadow/com.github.jengelman.gradle.plugins.shadow.tasks/-shadow-jar/index.html

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ class JavaPluginsTest : BasePluginTest() {
7171

7272
// Check extended properties.
7373
with(shadowTask as Jar) {
74-
assertThat(duplicatesStrategy).isEqualTo(DuplicatesStrategy.INCLUDE)
74+
assertThat(duplicatesStrategy).isEqualTo(DuplicatesStrategy.EXCLUDE)
7575
assertThat(archiveAppendix.orNull).isNull()
7676
assertThat(archiveBaseName.get()).isEqualTo(projectName)
7777
assertThat(archiveClassifier.get()).isEqualTo("all")
@@ -825,7 +825,6 @@ class JavaPluginsTest : BasePluginTest() {
825825
${implementationFiles(fooJar)}
826826
}
827827
$shadowJarTask {
828-
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
829828
excludes.remove(
830829
'module-info.class'
831830
)
@@ -929,6 +928,7 @@ class JavaPluginsTest : BasePluginTest() {
929928
${implementationFiles(artifactAJar)}
930929
}
931930
$shadowJarTask {
931+
duplicatesStrategy = DuplicatesStrategy.INCLUDE
932932
failOnDuplicateEntries = $enable
933933
}
934934
""".trimIndent(),
@@ -955,6 +955,9 @@ class JavaPluginsTest : BasePluginTest() {
955955
dependencies {
956956
${implementationFiles(artifactAJar)}
957957
}
958+
$shadowJarTask {
959+
duplicatesStrategy = DuplicatesStrategy.INCLUDE
960+
}
958961
""".trimIndent(),
959962
)
960963

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,23 @@ package com.github.jengelman.gradle.plugins.shadow.transformers
33
import com.github.jengelman.gradle.plugins.shadow.BasePluginTest
44
import com.github.jengelman.gradle.plugins.shadow.util.JarBuilder
55
import java.nio.file.Path
6+
import kotlin.io.path.appendText
7+
import org.junit.jupiter.api.BeforeEach
68

79
abstract class BaseTransformerTest : BasePluginTest() {
10+
@BeforeEach
11+
override fun setup() {
12+
super.setup()
13+
projectScript.appendText(
14+
"""
15+
$shadowJarTask {
16+
// Most transformers in tests require this to handle duplicate resources.
17+
duplicatesStrategy = DuplicatesStrategy.INCLUDE
18+
}
19+
""".trimIndent() + lineSeparator,
20+
)
21+
}
22+
823
fun buildJarOne(
924
builder: JarBuilder.() -> Unit = {
1025
insert(ENTRY_SERVICES_SHADE, CONTENT_ONE)

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ class ServiceFileTransformerTest : BaseTransformerTest() {
230230
projectScript.appendText(
231231
"""
232232
$shadowJarTask {
233+
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
233234
filesMatching('$ENTRY_SERVICES_SHADE') {
234235
duplicatesStrategy = DuplicatesStrategy.INCLUDE
235236
}

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

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public abstract class ShadowJar : Jar() {
7171
description = "Create a combined JAR of project and runtime dependencies"
7272

7373
// https://github.com/gradle/gradle/blob/df5bc230c57db70aa3f6909403e5f89d7efde531/platforms/core-configuration/file-operations/src/main/java/org/gradle/api/internal/file/copy/DuplicateHandlingCopyActionDecorator.java#L55-L64
74-
duplicatesStrategy = INCLUDE
74+
duplicatesStrategy = EXCLUDE
7575
manifest = DefaultInheritManifest(services.get(FileResolver::class.java))
7676

7777
outputs.doNotCacheIf("Has one or more transforms or relocators that are not cacheable") {
@@ -176,6 +176,7 @@ public abstract class ShadowJar : Jar() {
176176
* This is related to setting [getDuplicatesStrategy] to [FAIL] but there are some differences:
177177
* - It only checks the entries in the shadowed jar, not the input files.
178178
* - It works with setting [getDuplicatesStrategy] to any value.
179+
* - Usually used with setting [getDuplicatesStrategy] to [INCLUDE] or [WARN].
179180
* - It provides a stricter check before the JAR is created.
180181
*
181182
* Defaults to `false`.
@@ -198,24 +199,26 @@ public abstract class ShadowJar : Jar() {
198199
*
199200
* This global strategy can be overridden for individual files by using [filesMatching].
200201
*
201-
* The default value is [INCLUDE]. Different strategies will lead to different results for `foo/bar` files in the JARs to be merged:
202+
* The default value is [EXCLUDE]. Different strategies will lead to different results for `foo/bar` files in the JARs to be merged:
202203
*
203204
* - [EXCLUDE]: The **first** `foo/bar` file will be included in the final JAR.
204205
* - [FAIL]: **Fail** the build with a `DuplicateFileCopyingException` if there are duplicate `foo/bar` files.
205-
* - [INCLUDE]: Duplicate `foo/bar` entries will be included in the final JAR.
206+
* - [INCLUDE]: **Duplicate** `foo/bar` entries will be included in the final JAR.
206207
* - [INHERIT]: **Fail** the build with an exception like `Entry .* is a duplicate but no duplicate handling strategy has been set`.
207208
* - [WARN]: **Warn** about duplicates in the build log, this behaves exactly as [INHERIT] otherwise.
208209
*
209210
* **NOTE:** The strategy takes precedence over transforming and relocating.
210-
* Some [ResourceTransformer]s like [ServiceFileTransformer] will not work as expected with setting the strategy to
211-
* [EXCLUDE], as the service files are excluded beforehand. Want [ResourceTransformer]s and the strategy to work
212-
* together? There are several ways to do it:
211+
* Some [ResourceTransformer]s like [ServiceFileTransformer] will not work as expected with setting the strategy to [EXCLUDE],
212+
* as the duplicate resource files fed for them are excluded beforehand.
213+
* Want [ResourceTransformer]s and the strategy to work together? There are several steps to take:
213214
*
214-
* - Use [filesMatching] to override the strategy for specific files.
215-
* - Keep `duplicatesStrategy = INCLUDE` and write your own [ResourceTransformer] to handle duplicates.
216-
*
217-
* If you just want to keep the current behavior and preserve the first found resources, there is a simple built-in one
218-
* called [PreserveFirstFoundResourceTransformer].
215+
* 1. Set the strategy to [INCLUDE] or [WARN].
216+
* 2. Apply your [ResourceTransformer]s.
217+
* 3. Remove duplicate entries by
218+
* - overriding the default strategy for specific files using [filesMatching]
219+
* - applying [PreserveFirstFoundResourceTransformer]
220+
* - or something similar.
221+
* 4. Optionally, enable [failOnDuplicateEntries] to check duplicate entries in the final JAR.
219222
*
220223
* @see [filesMatching]
221224
* @see [DuplicatesStrategy]

0 commit comments

Comments
 (0)