From 60a8458c3689964ef2b7e133df108e84134a1b81 Mon Sep 17 00:00:00 2001 From: "J.T. McQuigg" Date: Wed, 27 Jul 2022 20:23:47 -0400 Subject: [PATCH 01/43] Update Gradle Wrapper to 7.5 --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f371643ee..8049c684f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From bd49ddeff6f9988e4133d51de4955b12b9e7e43d Mon Sep 17 00:00:00 2001 From: "J.T. McQuigg" Date: Wed, 27 Jul 2022 20:30:00 -0400 Subject: [PATCH 02/43] Update dependencies --- gradle/dependencies.gradle | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index 48746f644..9a7882cf3 100644 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -4,24 +4,24 @@ dependencies { shadow gradleApi() shadow 'org.codehaus.groovy:groovy-backports-compat23:3.0.8' - implementation 'org.jdom:jdom2:2.0.6' + implementation 'org.jdom:jdom2:2.0.6.1' implementation 'org.ow2.asm:asm:9.3' implementation 'org.ow2.asm:asm-commons:9.3' implementation 'commons-io:commons-io:2.11.0' - implementation 'org.apache.ant:ant:1.10.11' - implementation 'org.codehaus.plexus:plexus-utils:3.4.1' - implementation "org.apache.logging.log4j:log4j-core:2.17.1" + implementation 'org.apache.ant:ant:1.10.12' + implementation 'org.codehaus.plexus:plexus-utils:3.4.2' + implementation "org.apache.logging.log4j:log4j-core:2.18.0" implementation('org.vafer:jdependency:2.7.0') { exclude group: 'org.ow2.asm' } - testImplementation('org.spockframework:spock-core:2.0-groovy-3.0') { + testImplementation('org.spockframework:spock-core:2.1-groovy-3.0') { exclude group: 'org.codehaus.groovy' } - testImplementation 'org.spockframework:spock-junit4:2.0-groovy-3.0' + testImplementation 'org.spockframework:spock-junit4:2.1-groovy-3.0' testImplementation 'xmlunit:xmlunit:1.6' testImplementation 'org.apache.commons:commons-lang3:3.12.0' - testImplementation 'com.google.guava:guava:31.0.1-jre' - testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1' - testRuntimeOnly 'org.junit.vintage:junit-vintage-engine:5.8.1' + testImplementation 'com.google.guava:guava:31.1-jre' + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2' + testRuntimeOnly 'org.junit.vintage:junit-vintage-engine:5.8.2' } From c00320e76b2b2ca92d34447c2a8e3c1f64fa5857 Mon Sep 17 00:00:00 2001 From: Heizi Date: Thu, 8 Sep 2022 23:00:56 +0800 Subject: [PATCH 03/43] update gradle version to 7.5.1 and fix hash utils deprecated --- gradle/wrapper/gradle-wrapper.properties | 2 +- .../shadow/util/repo/AbstractModule.groovy | 20 ++++++++++++++----- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8049c684f..ae04661ee 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/repo/AbstractModule.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/repo/AbstractModule.groovy index 4b9be7c67..88c697c15 100644 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/repo/AbstractModule.groovy +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/repo/AbstractModule.groovy @@ -1,7 +1,7 @@ package com.github.jengelman.gradle.plugins.shadow.util.repo import com.github.jengelman.gradle.plugins.shadow.util.file.TestFile -import org.gradle.internal.hash.HashUtil +import org.gradle.internal.impldep.org.apache.commons.codec.digest.DigestUtils abstract class AbstractModule { @@ -66,8 +66,7 @@ abstract class AbstractModule { private TestFile hashFile(TestFile file, String algorithm, int len) { def hashFile = getHashFile(file, algorithm) - def hash = getHash(file, algorithm) - hashFile.text = String.format("%0${len}x", hash) + hashFile.text = getHash(file, algorithm) return hashFile } @@ -75,7 +74,18 @@ abstract class AbstractModule { file.parentFile.file("${file.name}.${algorithm}") } - protected BigInteger getHash(TestFile file, String algorithm) { - HashUtil.createHash(file, algorithm.toUpperCase()).asBigInteger() + protected String getHash(TestFile file, String algorithm) { + file.newInputStream().withCloseable { + switch (algorithm) { + case 'sha1': + DigestUtils.sha1Hex(it) + break + case 'md5' : + DigestUtils.md5Hex(it) + break + default: + throw new IOException("Unsupported algorithm " + algorithm) + } + } } } From 79d5d8d00aa1d5a18a4669060a743b7aac64543a Mon Sep 17 00:00:00 2001 From: Heizi Date: Thu, 8 Sep 2022 23:12:07 +0800 Subject: [PATCH 04/43] update dependents --- gradle/dependencies.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index 9a7882cf3..381819b01 100644 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -11,7 +11,7 @@ dependencies { implementation 'org.apache.ant:ant:1.10.12' implementation 'org.codehaus.plexus:plexus-utils:3.4.2' implementation "org.apache.logging.log4j:log4j-core:2.18.0" - implementation('org.vafer:jdependency:2.7.0') { + implementation('org.vafer:jdependency:2.8.0') { exclude group: 'org.ow2.asm' } @@ -22,6 +22,6 @@ dependencies { testImplementation 'xmlunit:xmlunit:1.6' testImplementation 'org.apache.commons:commons-lang3:3.12.0' testImplementation 'com.google.guava:guava:31.1-jre' - testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2' - testRuntimeOnly 'org.junit.vintage:junit-vintage-engine:5.8.2' + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.0' + testRuntimeOnly 'org.junit.vintage:junit-vintage-engine:5.9.0' } From ac8697f035e5fe007540beab29a2391c9fe2c410 Mon Sep 17 00:00:00 2001 From: Heizi Date: Thu, 8 Sep 2022 23:26:15 +0800 Subject: [PATCH 05/43] update gradle enterprise version --- settings.gradle | 2 +- .../jengelman/gradle/plugins/shadow/ShadowExtension.groovy | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/settings.gradle b/settings.gradle index f82018015..cd178262b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,5 +1,5 @@ plugins { - id 'com.gradle.enterprise' version '3.1.1' + id 'com.gradle.enterprise' version '3.11.1' } rootProject.name = 'shadow' \ No newline at end of file diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowExtension.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowExtension.groovy index 22ff62f80..f69425c74 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowExtension.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowExtension.groovy @@ -28,8 +28,7 @@ class ShadowExtension { publication.pom { MavenPom pom -> pom.withXml { xml -> - def dependenciesNode = xml.asNode().get('dependencies')?.get(0) ?: xml.asNode().appendNode('dependencies') - dependenciesNode.value = "" + def dependenciesNode = xml.asNode().appendNode('dependencies') project.configurations.shadow.allDependencies.each { if ((it instanceof ProjectDependency) || ! (it instanceof SelfResolvingDependency)) { def dependencyNode = dependenciesNode.appendNode('dependency') From fa66cd529e910dce0efcc885c59dd277451cae7c Mon Sep 17 00:00:00 2001 From: Heizi Date: Thu, 8 Sep 2022 23:42:47 +0800 Subject: [PATCH 06/43] fix java doc --- gradle/docs.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/docs.gradle b/gradle/docs.gradle index 1f8150538..47d49c055 100644 --- a/gradle/docs.gradle +++ b/gradle/docs.gradle @@ -1,4 +1,4 @@ -def javaApiUrl = 'http://docs.oracle.com/javase/1.7.0/docs/api' +def javaApiUrl = 'http://docs.oracle.com/javase/17/docs/api' def groovyApiUrl = "http://docs.groovy-lang.org/2.4.7/html/gapi/" tasks.withType(Javadoc) { From 9a1997917904cc96f9d598020dfbf9dd2fc43e7a Mon Sep 17 00:00:00 2001 From: netomi Date: Tue, 11 Oct 2022 14:10:12 +0200 Subject: [PATCH 07/43] Fix retrieval of dependencies node when publishing. --- .../jengelman/gradle/plugins/shadow/ShadowExtension.groovy | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowExtension.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowExtension.groovy index 22ff62f80..743e566a8 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowExtension.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowExtension.groovy @@ -28,8 +28,7 @@ class ShadowExtension { publication.pom { MavenPom pom -> pom.withXml { xml -> - def dependenciesNode = xml.asNode().get('dependencies')?.get(0) ?: xml.asNode().appendNode('dependencies') - dependenciesNode.value = "" + def dependenciesNode = xml.asNode().get('dependencies') ?: xml.asNode().appendNode('dependencies') project.configurations.shadow.allDependencies.each { if ((it instanceof ProjectDependency) || ! (it instanceof SelfResolvingDependency)) { def dependencyNode = dependenciesNode.appendNode('dependency') From 5ce34760edba086e329780db8a22377f845e5526 Mon Sep 17 00:00:00 2001 From: Jeb Nix <115509264+jebnix@users.noreply.github.com> Date: Fri, 28 Oct 2022 18:41:37 +0300 Subject: [PATCH 08/43] Fix a typo of code comment in the minimizing page --- src/docs/configuration/minimizing/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/docs/configuration/minimizing/README.md b/src/docs/configuration/minimizing/README.md index 0636d1bee..450a3ca0f 100644 --- a/src/docs/configuration/minimizing/README.md +++ b/src/docs/configuration/minimizing/README.md @@ -3,7 +3,7 @@ Shadow can automatically remove all classes of dependencies that are not used by the project, thereby minimizing the resulting shadowed JAR. ```groovy -// Minimizing an shadow JAR +// Minimizing a shadow JAR shadowJar { minimize() } @@ -36,4 +36,4 @@ shadowJar { ``` > When excluding a `project`, all dependencies of the excluded `project` are automatically - excluded as well. \ No newline at end of file + excluded as well. From 7d8cffa92ecf9201429c9a2e264a5b2a24ac1109 Mon Sep 17 00:00:00 2001 From: Peter Gafert Date: Thu, 2 Feb 2023 20:32:18 +0700 Subject: [PATCH 09/43] upgrade dependency ASM from `9.3` to `9.4` ... to support upcoming release of JDK 20 (see https://asm.ow2.io/versions.html). --- gradle/dependencies.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index 48746f644..a6de08d85 100644 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -5,8 +5,8 @@ dependencies { shadow 'org.codehaus.groovy:groovy-backports-compat23:3.0.8' implementation 'org.jdom:jdom2:2.0.6' - implementation 'org.ow2.asm:asm:9.3' - implementation 'org.ow2.asm:asm-commons:9.3' + implementation 'org.ow2.asm:asm:9.4' + implementation 'org.ow2.asm:asm-commons:9.4' implementation 'commons-io:commons-io:2.11.0' implementation 'org.apache.ant:ant:1.10.11' implementation 'org.codehaus.plexus:plexus-utils:3.4.1' From d2ab17c25469a94b3b8919acb967feba3edd1159 Mon Sep 17 00:00:00 2001 From: Goooler Date: Tue, 14 Feb 2023 15:14:02 +0800 Subject: [PATCH 10/43] Add .gitattributes --- .gitattributes | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..7e3c475f2 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,4 @@ +* text=auto eol=lf + +gradlew binary +gradlew.bat binary \ No newline at end of file From e46bd204917bc004c1a92c7d1ffa36250b192904 Mon Sep 17 00:00:00 2001 From: Simon Podlipsky Date: Thu, 10 Dec 2020 14:29:26 +0100 Subject: [PATCH 11/43] Introduce CleanProperties PropertiesFileTransformer uses `java.utils.Properties` internally as a storage. `java.utils.Properties` `store0()` contains `bw.write("#" + new Date().toString());` that prepends current timestamp before any content (after comments). This effectively breaks reproducible builds that use PropertiesFileTransformer because every new build has different timestamp in transformed files. CleanProperties implementation is introduced in order to remove prepended timestamp when creating output stream. --- .../shadow/internal/CleanProperties.groovy | 32 ++++++++ .../PropertiesFileTransformer.groovy | 11 ++- .../PropertiesFileTransformerTest.groovy | 76 +++++++++++++++++++ 3 files changed, 115 insertions(+), 4 deletions(-) create mode 100644 src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/CleanProperties.groovy create mode 100644 src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.groovy diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/CleanProperties.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/CleanProperties.groovy new file mode 100644 index 000000000..f81b64a2b --- /dev/null +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/CleanProperties.groovy @@ -0,0 +1,32 @@ +/* + * Source https://stackoverflow.com/a/39043903/519333 + */ +package com.github.jengelman.gradle.plugins.shadow.internal + +class CleanProperties extends Properties { + private static class StripFirstLineStream extends FilterOutputStream { + + private boolean firstLineSeen = false + + StripFirstLineStream(final OutputStream out) { + super(out) + } + + @Override + void write(final int b) throws IOException { + if (firstLineSeen) { + super.write(b); + } else if (b == '\n') { + super.write(b); + + firstLineSeen = true; + } + } + + } + + @Override + void store(final OutputStream out, final String comments) throws IOException { + super.store(new StripFirstLineStream(out), null) + } +} diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformer.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformer.groovy index 31e1a5452..2d113ac2f 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformer.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformer.groovy @@ -19,6 +19,7 @@ package com.github.jengelman.gradle.plugins.shadow.transformers +import com.github.jengelman.gradle.plugins.shadow.internal.CleanProperties import org.apache.tools.zip.ZipEntry import org.apache.tools.zip.ZipOutputStream import org.codehaus.plexus.util.IOUtil @@ -117,7 +118,7 @@ import static groovy.lang.Closure.IDENTITY class PropertiesFileTransformer implements Transformer { private static final String PROPERTIES_SUFFIX = '.properties' - private Map propertiesEntries = [:] + private Map propertiesEntries = [:] @Input List paths = [] @@ -179,15 +180,17 @@ class PropertiesFileTransformer implements Transformer { } private Properties loadAndTransformKeys(InputStream is) { - Properties props = new Properties() - props.load(is) + Properties props = new CleanProperties() + if (is != null) { + props.load(is) + } return transformKeys(props) } private Properties transformKeys(Properties properties) { if (keyTransformer == IDENTITY) return properties - def result = new Properties() + def result = new CleanProperties() properties.each { key, value -> result.put(keyTransformer.call(key), value) } diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.groovy new file mode 100644 index 000000000..ff23aed96 --- /dev/null +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.groovy @@ -0,0 +1,76 @@ +package com.github.jengelman.gradle.plugins.shadow.transformers + +import com.github.jengelman.gradle.plugins.shadow.ShadowStats +import com.github.jengelman.gradle.plugins.shadow.relocation.Relocator +import org.apache.tools.zip.ZipOutputStream +import org.junit.Before +import org.junit.Test + +import java.util.zip.ZipFile + +import static java.util.Arrays.asList +import static org.junit.Assert.* + +/** + * Test for {@link PropertiesFileTransformer}. + */ +final class PropertiesFileTransformerTest extends TransformerTestSupport { + static final String MANIFEST_NAME = "META-INF/MANIFEST.MF" + + private PropertiesFileTransformer transformer + + @Before + void setUp() { + transformer = new PropertiesFileTransformer() + } + + @Test + void testHasTransformedResource() { + transformer.transform(new TransformerContext(MANIFEST_NAME)) + + assertTrue(transformer.hasTransformedResource()) + } + + @Test + void testHasNotTransformedResource() { + assertFalse(transformer.hasTransformedResource()) + } + + @Test + void testTransformation() { + transformer.transform(new TransformerContext(MANIFEST_NAME, getResourceStream(MANIFEST_NAME), Collections.emptyList(), new ShadowStats())) + + def testableZipFile = File.createTempFile("testable-zip-file-", ".jar") + def fileOutputStream = new FileOutputStream(testableZipFile) + def bufferedOutputStream = new BufferedOutputStream(fileOutputStream) + def zipOutputStream = new ZipOutputStream(bufferedOutputStream) + + try { + transformer.modifyOutputStream(zipOutputStream, false) + } finally { + zipOutputStream.close() + } + def targetLines = readFrom(testableZipFile, MANIFEST_NAME) + + assertFalse(targetLines.isEmpty()) + + assertTrue(targetLines.contains("Manifest-Version=1.0")) + } + + static List readFrom(File jarFile, String resourceName) { + def zip = new ZipFile(jarFile) + try { + def entry = zip.getEntry(resourceName) + if (!entry) { + return Collections.emptyList() + } + return zip.getInputStream(entry).readLines() + } finally { + zip.close() + } + } + + InputStream getResourceStream(String resource) { + this.class.classLoader.getResourceAsStream(resource) + } +} From 1d186f88745eff610dab393098b707deb830fb92 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Mon, 20 Feb 2023 18:19:54 +0100 Subject: [PATCH 12/43] Prefer using plugin extensions over deprecated conventions See https://docs.gradle.org/current/userguide/upgrading_version_7.html#all_convention_deprecation --- .../shadow/ShadowApplicationPlugin.groovy | 36 +++++-------------- .../plugins/shadow/ShadowJavaPlugin.groovy | 6 ++-- 2 files changed, 12 insertions(+), 30 deletions(-) diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowApplicationPlugin.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowApplicationPlugin.groovy index ef83ff3b5..6b3c9515c 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowApplicationPlugin.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowApplicationPlugin.groovy @@ -9,7 +9,6 @@ import org.gradle.api.distribution.Distribution import org.gradle.api.distribution.DistributionContainer import org.gradle.api.file.CopySpec import org.gradle.api.plugins.ApplicationPlugin -import org.gradle.api.plugins.ApplicationPluginConvention import org.gradle.api.plugins.JavaApplication import org.gradle.api.plugins.JavaPluginExtension import org.gradle.api.provider.Provider @@ -26,12 +25,12 @@ class ShadowApplicationPlugin implements Plugin { public static final String SHADOW_INSTALL_TASK_NAME = 'installShadowDist' private Project project - private ApplicationPluginConvention pluginConvention + private JavaApplication javaApplication @Override void apply(Project project) { this.project = project - this.pluginConvention = (ApplicationPluginConvention) project.convention.plugins.application + this.javaApplication = project.extensions.getByType(JavaApplication) DistributionContainer distributions = project.extensions.getByName("distributions") Distribution distribution = distributions.create("shadow") @@ -46,7 +45,7 @@ class ShadowApplicationPlugin implements Plugin { } protected void configureJarMainClass(Project project) { - def classNameProvider = project.provider { getMainClassName() } + def classNameProvider = javaApplication.mainClass jar.configure { jar -> jar.inputs.property('mainClassName', classNameProvider) jar.doFirst { @@ -55,18 +54,7 @@ class ShadowApplicationPlugin implements Plugin { } } - private Object getMainClassName() { - def mainClassName = project.convention.plugins.application.mainClassName - if (Objects.nonNull(mainClassName)) { - return mainClassName - } - - return project.extensions.getByType(JavaApplication.class).mainClass.get() - } - protected void addRunTask(Project project) { - ApplicationPluginConvention pluginConvention = ( - ApplicationPluginConvention) project.convention.plugins.application project.tasks.register(SHADOW_RUN_TASK_NAME, JavaJarExec) { run -> def install = project.tasks.named(SHADOW_INSTALL_TASK_NAME, Sync) @@ -74,7 +62,7 @@ class ShadowApplicationPlugin implements Plugin { run.mainClass.set('-jar') run.description = 'Runs this project as a JVM application using the shadow jar' run.group = ApplicationPlugin.APPLICATION_GROUP - run.conventionMapping.jvmArgs = { pluginConvention.applicationDefaultJvmArgs } + run.conventionMapping.jvmArgs = { javaApplication.applicationDefaultJvmArgs } run.conventionMapping.jarFile = { project.file("${install.get().destinationDir.path}/lib/${jar.get().archivePath.name}") } @@ -90,32 +78,26 @@ class ShadowApplicationPlugin implements Plugin { } protected void addCreateScriptsTask(Project project) { - ApplicationPluginConvention pluginConvention = - (ApplicationPluginConvention) project.convention.plugins.application - project.tasks.register(SHADOW_SCRIPTS_TASK_NAME, CreateStartScripts) { startScripts -> startScripts.unixStartScriptGenerator.template = project.resources.text.fromString(this.class.getResource("internal/unixStartScript.txt").text) startScripts.windowsStartScriptGenerator.template = project.resources.text.fromString(this.class.getResource("internal/windowsStartScript.txt").text) startScripts.description = 'Creates OS specific scripts to run the project as a JVM application using the shadow jar' startScripts.group = ApplicationPlugin.APPLICATION_GROUP startScripts.classpath = project.files(jar) - startScripts.conventionMapping.mainClassName = { pluginConvention.mainClassName } - startScripts.conventionMapping.applicationName = { pluginConvention.applicationName } + startScripts.conventionMapping.mainClassName = { javaApplication.mainClass.get() } + startScripts.conventionMapping.applicationName = { javaApplication.applicationName } startScripts.conventionMapping.outputDir = { new File(project.buildDir, 'scriptsShadow') } - startScripts.conventionMapping.defaultJvmOpts = { pluginConvention.applicationDefaultJvmArgs } + startScripts.conventionMapping.defaultJvmOpts = { javaApplication.applicationDefaultJvmArgs } startScripts.inputs.files project.objects.fileCollection().from { -> jar } } } protected void configureInstallTask(Project project) { - ApplicationPluginConvention pluginConvention = - (ApplicationPluginConvention) project.convention.plugins.application - project.tasks.named(SHADOW_INSTALL_TASK_NAME).configure { installTask -> installTask.doFirst { Sync task -> if (task.destinationDir.directory) { if (task.destinationDir.listFiles().size() != 0 && (!new File(task.destinationDir, 'lib').directory || !new File(task.destinationDir, 'bin').directory)) { - throw new GradleException("The specified installation directory '${task.destinationDir}' is neither empty nor does it contain an installation for '${pluginConvention.applicationName}'.\n" + + throw new GradleException("The specified installation directory '${task.destinationDir}' is neither empty nor does it contain an installation for '${javaApplication.applicationName}'.\n" + "If you really want to install to this directory, delete it and run the install task again.\n" + "Alternatively, choose a different installation directory." ) @@ -123,7 +105,7 @@ class ShadowApplicationPlugin implements Plugin { } } installTask.doLast { Sync task -> - project.ant.chmod(file: "${task.destinationDir.absolutePath}/bin/${pluginConvention.applicationName}", perm: 'ugo+x') + project.ant.chmod(file: "${task.destinationDir.absolutePath}/bin/${javaApplication.applicationName}", perm: 'ugo+x') } } } diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.groovy index 3123bca5e..09a147d93 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.groovy @@ -7,7 +7,7 @@ import org.gradle.api.attributes.Bundling import org.gradle.api.attributes.Category import org.gradle.api.attributes.LibraryElements import org.gradle.api.attributes.Usage -import org.gradle.api.plugins.JavaPluginConvention +import org.gradle.api.tasks.SourceSetContainer import org.gradle.configuration.project.ProjectConfigurationActionContainer import org.gradle.util.GradleVersion @@ -55,7 +55,7 @@ class ShadowJavaPlugin implements Plugin { } protected void configureShadowTask(Project project) { - JavaPluginConvention convention = project.convention.getPlugin(JavaPluginConvention) + SourceSetContainer sourceSets = project.extensions.getByType(SourceSetContainer) project.tasks.register(SHADOW_JAR_TASK_NAME, ShadowJar) { shadow -> shadow.group = SHADOW_GROUP shadow.description = 'Create a combined JAR of project and runtime dependencies' @@ -80,7 +80,7 @@ class ShadowJavaPlugin implements Plugin { manifest.attributes 'Class-Path': libs.findAll { it }.join(' ') } } - shadow.from(convention.sourceSets.main.output) + shadow.from(sourceSets.main.output) shadow.configurations = [project.configurations.findByName('runtimeClasspath') ? project.configurations.runtimeClasspath : project.configurations.runtime] shadow.exclude('META-INF/INDEX.LIST', 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA', 'module-info.class') From c3dc9a7a31ef4eb16c99fadb601690860840145f Mon Sep 17 00:00:00 2001 From: Goooler Date: Tue, 14 Feb 2023 15:16:50 +0800 Subject: [PATCH 13/43] Bump Gradle to 8.0.1 https://docs.gradle.org/8.0.1/release-notes.html --- gradle/wrapper/gradle-wrapper.jar | Bin 59203 -> 61608 bytes gradle/wrapper/gradle-wrapper.properties | 3 +- gradlew | 269 ++++++++++++++--------- gradlew.bat | 15 +- 4 files changed, 175 insertions(+), 112 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e708b1c023ec8b20f512888fe07c5bd3ff77bb8f..ccebba7710deaf9f98673a68957ea02138b60d0a 100644 GIT binary patch delta 42019 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 delta 39521 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 R149saZvb8 \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -106,80 +140,105 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=`expr $i + 1` + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index ac1b06f93..6689b85be 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,8 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal From 10e32495c81166461734ec82c00616faa62fade6 Mon Sep 17 00:00:00 2001 From: Goooler Date: Wed, 29 Sep 2021 13:24:20 +0800 Subject: [PATCH 14/43] Add missing HashUtil & HashValue --- .../gradle/plugins/shadow/util/HashUtil.java | 92 +++++++++++++++++++ .../gradle/plugins/shadow/util/HashValue.java | 75 +++++++++++++++ .../shadow/util/repo/AbstractModule.groovy | 3 +- 3 files changed, 168 insertions(+), 2 deletions(-) create mode 100644 src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/HashUtil.java create mode 100644 src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/HashValue.java diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/HashUtil.java b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/HashUtil.java new file mode 100644 index 000000000..c3c41596d --- /dev/null +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/HashUtil.java @@ -0,0 +1,92 @@ +package com.github.jengelman.gradle.plugins.shadow.util; + +import org.gradle.api.UncheckedIOException; +import org.gradle.internal.UncheckedException; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public class HashUtil { + public static HashValue createHash(File file, String algorithm) { + try { + return createHash(new FileInputStream(file), algorithm); + } catch (UncheckedIOException e) { + // Catch any unchecked io exceptions and add the file path for troubleshooting + throw new UncheckedIOException(String.format("Failed to create %s hash for file %s.", algorithm, file.getAbsolutePath()), e.getCause()); + } catch (FileNotFoundException e) { + throw new UncheckedIOException(e); + } + } + + private static HashValue createHash(InputStream instr, String algorithm) { + MessageDigest messageDigest; + try { + messageDigest = createMessageDigest(algorithm); + byte[] buffer = new byte[4096]; + try { + while (true) { + int nread = instr.read(buffer); + if (nread < 0) { + break; + } + messageDigest.update(buffer, 0, nread); + } + } finally { + instr.close(); + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + return new HashValue(messageDigest.digest()); + } + + private static MessageDigest createMessageDigest(String algorithm) { + try { + return MessageDigest.getInstance(algorithm); + } catch (NoSuchAlgorithmException e) { + throw UncheckedException.throwAsUncheckedException(e); + } + } + + public static HashValue sha1(byte[] bytes) { + return createHash(new ByteArrayInputStream(bytes), "SHA1"); + } + + public static HashValue sha1(InputStream inputStream) { + return createHash(inputStream, "SHA1"); + } + + public static HashValue md5(File file) { + return createHash(file, "MD5"); + } + + public static HashValue sha1(File file) { + return createHash(file, "SHA1"); + } + + public static HashValue sha256(byte[] bytes) { + return createHash(new ByteArrayInputStream(bytes), "SHA-256"); + } + + public static HashValue sha256(InputStream inputStream) { + return createHash(inputStream, "SHA-256"); + } + + public static HashValue sha256(File file) { + return createHash(file, "SHA-256"); + } + + public static HashValue sha512(InputStream inputStream) { + return createHash(inputStream, "SHA-512"); + } + + public static HashValue sha512(File file) { + return createHash(file, "SHA-512"); + } +} + diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/HashValue.java b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/HashValue.java new file mode 100644 index 000000000..0812eeb1a --- /dev/null +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/HashValue.java @@ -0,0 +1,75 @@ +package com.github.jengelman.gradle.plugins.shadow.util; + +import java.math.BigInteger; + +public class HashValue { + private final BigInteger digest; + + public HashValue(byte[] digest) { + this.digest = new BigInteger(1, digest); + } + + public HashValue(String hexString) { + this.digest = new BigInteger(hexString, 16); + } + + public static HashValue parse(String inputString) { + if (inputString == null || inputString.length() == 0) { + return null; + } + return new HashValue(parseInput(inputString)); + } + + private static String parseInput(String inputString) { + if (inputString == null) { + return null; + } + String cleaned = inputString.trim().toLowerCase(); + int spaceIndex = cleaned.indexOf(' '); + if (spaceIndex != -1) { + String firstPart = cleaned.substring(0, spaceIndex); + if (firstPart.startsWith("md") || firstPart.startsWith("sha")) { + cleaned = cleaned.substring(cleaned.lastIndexOf(' ') + 1); + } else if (firstPart.endsWith(":")) { + cleaned = cleaned.substring(spaceIndex + 1).replace(" ", ""); + } else { + cleaned = cleaned.substring(0, spaceIndex); + } + } + return cleaned; + } + + public String asCompactString() { + return digest.toString(36); + } + + public String asHexString() { + return digest.toString(16); + } + + public byte[] asByteArray() { + return digest.toByteArray(); + } + + public BigInteger asBigInteger() { + return digest; + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (!(other instanceof HashValue)) { + return false; + } + + HashValue otherHashValue = (HashValue) other; + return digest.equals(otherHashValue.digest); + } + + @Override + public int hashCode() { + return digest.hashCode(); + } +} diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/repo/AbstractModule.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/repo/AbstractModule.groovy index 4b9be7c67..9bf6891f3 100644 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/repo/AbstractModule.groovy +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/repo/AbstractModule.groovy @@ -1,8 +1,7 @@ package com.github.jengelman.gradle.plugins.shadow.util.repo +import com.github.jengelman.gradle.plugins.shadow.util.HashUtil import com.github.jengelman.gradle.plugins.shadow.util.file.TestFile -import org.gradle.internal.hash.HashUtil - abstract class AbstractModule { /** From 9116f4bc6bfdd9e966b6b709109dac7264b951a5 Mon Sep 17 00:00:00 2001 From: Goooler Date: Tue, 14 Feb 2023 15:42:14 +0800 Subject: [PATCH 15/43] Migrate properties - destinationDir to destinationDirectory - archivePath to archiveFile - baseName to archiveBaseName - classifier to archiveClassifier - version to archiveVersion - extension to archiveExtension --- build.gradle | 2 +- .../plugins/shadow/ShadowApplicationPlugin.groovy | 2 +- .../gradle/plugins/shadow/ShadowPluginSpec.groovy | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build.gradle b/build.gradle index c538f5ccd..2a1bf9412 100644 --- a/build.gradle +++ b/build.gradle @@ -79,7 +79,7 @@ jar { jar.enabled = false shadowJar { - classifier = '' + archiveClassifier = '' } idea { diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowApplicationPlugin.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowApplicationPlugin.groovy index ef83ff3b5..f39b41b40 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowApplicationPlugin.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowApplicationPlugin.groovy @@ -76,7 +76,7 @@ class ShadowApplicationPlugin implements Plugin { run.group = ApplicationPlugin.APPLICATION_GROUP run.conventionMapping.jvmArgs = { pluginConvention.applicationDefaultJvmArgs } run.conventionMapping.jarFile = { - project.file("${install.get().destinationDir.path}/lib/${jar.get().archivePath.name}") + project.file("${install.get().destinationDir.path}/lib/${jar.get().archiveFile.get().asFile.name}") } configureJavaLauncher(run) } diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowPluginSpec.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowPluginSpec.groovy index 65e150537..6bd827718 100644 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowPluginSpec.groovy +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowPluginSpec.groovy @@ -40,16 +40,16 @@ class ShadowPluginSpec extends PluginSpecification { then: ShadowJar shadow = project.tasks.findByName('shadowJar') assert shadow - assert shadow.baseName == projectName - assert shadow.destinationDir == new File(project.buildDir, 'libs') - assert shadow.version == version - assert shadow.classifier == 'all' - assert shadow.extension == 'jar' + assert shadow.archiveBaseName.get() == projectName + assert shadow.destinationDirectory.get().asFile == new File(project.buildDir, 'libs') + assert shadow.archiveVersion.get() == version + assert shadow.archiveClassifier.get() == 'all' + assert shadow.archiveExtension.get() == 'jar' and: Configuration shadowConfig = project.configurations.findByName('shadow') assert shadowConfig - shadowConfig.artifacts.file.contains(shadow.archivePath) + shadowConfig.artifacts.file.contains(shadow.archiveFile.get().asFile) } From ccf5c463d23f7457519a4a4b1ab9addd1b1ca35e Mon Sep 17 00:00:00 2001 From: Goooler Date: Thu, 23 Feb 2023 21:58:14 +0800 Subject: [PATCH 16/43] Bump GE plugin to 3.12.3 --- build.gradle | 17 ----------------- settings.gradle | 22 +++++++++++++++++++++- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/build.gradle b/build.gradle index 2a1bf9412..c3cc3f203 100644 --- a/build.gradle +++ b/build.gradle @@ -31,23 +31,6 @@ gradlePlugin { apply plugin: 'com.github.johnrengelman.shadow' -buildScan { - termsOfServiceUrl = 'https://gradle.com/terms-of-service' - termsOfServiceAgree = 'yes' - if (System.env.CI == 'true') { - tag 'CI' - if (System.env.CIRCLE_TAG) { - link 'VCS', "https://github.com/johnrengelman/shadow/tree/${System.env.CIRCLE_TAG}" - } else { - link 'VCS', "https://github.com/johnrengelman/shadow/tree/${System.env.CIRCLE_BRANCH}" - } - link 'VCS Commit', "https://github.com/johnrengelman/shadow/commit/${System.env.CIRCLE_SHA1}" - if (System.env.CI_PULL_REQUEST) { - link 'Pull Request', "${System.env.CI_PULL_REQUEST}" - } - } -} - apply from: file('gradle/docs.gradle') apply from: file('gradle/publish.gradle') apply from: file('gradle/vuepress.gradle') diff --git a/settings.gradle b/settings.gradle index f82018015..1d59b7d5f 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,5 +1,25 @@ plugins { - id 'com.gradle.enterprise' version '3.1.1' + id 'com.gradle.enterprise' version '3.12.3' +} + +gradleEnterprise { + buildScan { + termsOfServiceUrl = 'https://gradle.com/terms-of-service' + termsOfServiceAgree = 'yes' + publishAlways() + if (System.env.CI == 'true') { + tag 'CI' + if (System.env.CIRCLE_TAG) { + link 'VCS', "https://github.com/johnrengelman/shadow/tree/${System.env.CIRCLE_TAG}" + } else { + link 'VCS', "https://github.com/johnrengelman/shadow/tree/${System.env.CIRCLE_BRANCH}" + } + link 'VCS Commit', "https://github.com/johnrengelman/shadow/commit/${System.env.CIRCLE_SHA1}" + if (System.env.CI_PULL_REQUEST) { + link 'Pull Request', "${System.env.CI_PULL_REQUEST}" + } + } + } } rootProject.name = 'shadow' \ No newline at end of file From c67634a716090e42fee82545916703eb09cb8e4a Mon Sep 17 00:00:00 2001 From: Goooler Date: Thu, 23 Feb 2023 22:26:54 +0800 Subject: [PATCH 17/43] Fix toolchain test --- .../gradle/plugins/shadow/ApplicationSpec.groovy | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/ApplicationSpec.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/ApplicationSpec.groovy index 4ec08237a..b972c2e28 100644 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/ApplicationSpec.groovy +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/ApplicationSpec.groovy @@ -98,7 +98,7 @@ class ApplicationSpec extends PluginSpecification { java { toolchain { - languageVersion = JavaLanguageVersion.of(16) + languageVersion = JavaLanguageVersion.of(17) } } @@ -110,13 +110,20 @@ class ApplicationSpec extends PluginSpecification { } """.stripIndent() - settingsFile << "rootProject.name = 'myapp'" + settingsFile.write """ + plugins { + // https://docs.gradle.org/8.0.1/userguide/toolchains.html#sub:download_repositories + id("org.gradle.toolchains.foojay-resolver-convention") version("0.4.0") + } + + rootProject.name = 'myapp' + """.stripIndent() when: BuildResult result = run('runShadow', '--stacktrace') then: 'tests that runShadow executed and exited' - assert result.output.contains('Running application with JDK 16') + assert result.output.contains('Running application with JDK 17') assert result.output.contains('TestApp: Hello World! (foo)') and: 'Check that the proper jar file was installed' From 60896b4145f6837f9dc2d35f90c06267b6f7c335 Mon Sep 17 00:00:00 2001 From: Goooler Date: Thu, 23 Feb 2023 22:28:00 +0800 Subject: [PATCH 18/43] Tweak Gradle flags --- gradle.properties | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 40ca366b2..24bc86380 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,3 @@ +org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=2g org.gradle.parallel=true -org.gradle.daemon=true +org.gradle.caching=true \ No newline at end of file From dde539f1bdcb81810e443e3e60a3257f6af104bd Mon Sep 17 00:00:00 2001 From: John Engelman Date: Fri, 24 Feb 2023 17:52:08 -0600 Subject: [PATCH 19/43] update verison --- src/main/resources/shadow-version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/shadow-version.txt b/src/main/resources/shadow-version.txt index 1996c5044..ae9a76b92 100644 --- a/src/main/resources/shadow-version.txt +++ b/src/main/resources/shadow-version.txt @@ -1 +1 @@ -7.1.3 +8.0.0 From 4c2f7b039aed7024df7d6dc849be88e8f79c2773 Mon Sep 17 00:00:00 2001 From: John Engelman Date: Fri, 24 Feb 2023 18:02:07 -0600 Subject: [PATCH 20/43] exclude bin/ --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index c7be03627..b2098737c 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ yarn-error.log src/docs/.vuepress/dist/ .DS_Store jd-gui.cfg +bin/ From c24d6d0d79c51e78a93abb8f84bd6079421df100 Mon Sep 17 00:00:00 2001 From: John Engelman Date: Fri, 24 Feb 2023 18:07:13 -0600 Subject: [PATCH 21/43] exclude .vscode --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index b2098737c..646e97241 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ src/docs/.vuepress/dist/ .DS_Store jd-gui.cfg bin/ +.vscode/ From 572f6ff98ec03318bdf66c974fcc771d12997e23 Mon Sep 17 00:00:00 2001 From: John Engelman Date: Fri, 24 Feb 2023 18:07:26 -0600 Subject: [PATCH 22/43] chore: require Gradle 8+ --- .../jengelman/gradle/plugins/shadow/ShadowBasePlugin.groovy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowBasePlugin.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowBasePlugin.groovy index 795afbee5..b367957d7 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowBasePlugin.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowBasePlugin.groovy @@ -13,8 +13,8 @@ class ShadowBasePlugin implements Plugin { @Override void apply(Project project) { - if (GradleVersion.current() < GradleVersion.version("7.0")) { - throw new GradleException("This version of Shadow supports Gradle 7.0+ only. Please upgrade.") + if (GradleVersion.current() < GradleVersion.version("8.0")) { + throw new GradleException("This version of Shadow supports Gradle 8.0+ only. Please upgrade.") } project.extensions.create(EXTENSION_NAME, ShadowExtension, project) createShadowConfiguration(project) From 88a38b9a8d7abb7f9341733fada822b6945b2222 Mon Sep 17 00:00:00 2001 From: John Engelman Date: Fri, 24 Feb 2023 18:21:57 -0600 Subject: [PATCH 23/43] chore: update compat checks in tests --- .../jengelman/gradle/plugins/shadow/ShadowPluginSpec.groovy | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowPluginSpec.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowPluginSpec.groovy index 6bd827718..ab9ab0c7b 100644 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowPluginSpec.groovy +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowPluginSpec.groovy @@ -86,13 +86,13 @@ class ShadowPluginSpec extends PluginSpecification { assert output.exists() where: - version << ['7.0'] + version << ['8.0'] } - def 'Error in Gradle versions < 7.0'() { + def 'Error in Gradle versions < 8.0'() { given: GradleRunner versionRunner = GradleRunner.create() - .withGradleVersion('6.9') + .withGradleVersion('7.0') .withArguments('--stacktrace') .withProjectDir(dir.root) .forwardOutput() From 38bc31f811f5359b305eb3652c7667f10bfa0644 Mon Sep 17 00:00:00 2001 From: John Engelman Date: Fri, 24 Feb 2023 18:26:07 -0600 Subject: [PATCH 24/43] chore: update ci image --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index e8a658754..270148055 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,7 +1,7 @@ defaults: &defaults working_directory: ~/shadow docker: - - image: circleci/openjdk:11-jdk + - image: cimg/openjdk:17.0 environment: - TERM: "dumb" - GRADLE_OPTS: "-Xmx1024m" From 684bde3f64a44fdfae484b6b1dc6c184daf7af28 Mon Sep 17 00:00:00 2001 From: John Engelman Date: Fri, 24 Feb 2023 18:27:38 -0600 Subject: [PATCH 25/43] bug: fix bad merge --- .../shadow/util/repo/AbstractModule.groovy | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/repo/AbstractModule.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/repo/AbstractModule.groovy index b12a79a46..ff62a315c 100644 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/repo/AbstractModule.groovy +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/repo/AbstractModule.groovy @@ -65,7 +65,8 @@ abstract class AbstractModule { private TestFile hashFile(TestFile file, String algorithm, int len) { def hashFile = getHashFile(file, algorithm) - hashFile.text = getHash(file, algorithm) + def hash = getHash(file, algorithm) + hashFile.text = String.format("%0${len}x", hash) return hashFile } @@ -73,18 +74,7 @@ abstract class AbstractModule { file.parentFile.file("${file.name}.${algorithm}") } - protected String getHash(TestFile file, String algorithm) { - file.newInputStream().withCloseable { - switch (algorithm) { - case 'sha1': - DigestUtils.sha1Hex(it) - break - case 'md5' : - DigestUtils.md5Hex(it) - break - default: - throw new IOException("Unsupported algorithm " + algorithm) - } - } + protected BigInteger getHash(TestFile file, String algorithm) { + HashUtil.createHash(file, algorithm.toUpperCase()).asBigInteger() } -} +} \ No newline at end of file From 59817c287759c890702ea9d483ef0fa3cedc231d Mon Sep 17 00:00:00 2001 From: John Engelman Date: Fri, 24 Feb 2023 19:13:50 -0600 Subject: [PATCH 26/43] update changes --- src/docs/changes/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/docs/changes/README.md b/src/docs/changes/README.md index 16434a1b8..a0a8d18d7 100644 --- a/src/docs/changes/README.md +++ b/src/docs/changes/README.md @@ -1,4 +1,8 @@ # Change Log +## v8.0.0 (2023-02-24) + +[Release Notes](https://github.com/johnrengelman/shadow/releases/tag/8.0.0) + ## v7.1.3 (unreleased) * The GroovyExtensionModuleTransformer now also works for Groovy 2.5+. From 3d8fd5171c014ec40fc908c1d5109d10e386d3f3 Mon Sep 17 00:00:00 2001 From: Goooler Date: Sat, 25 Feb 2023 16:02:11 +0800 Subject: [PATCH 27/43] Groovy cleanups --- build.gradle | 12 +-- buildSrc/build.gradle | 4 +- gradle/docs.gradle | 15 +-- gradle/ghPages.gradle | 6 +- gradle/publish.gradle | 6 +- .../shadow/ShadowApplicationPlugin.groovy | 2 +- .../plugins/shadow/ShadowBasePlugin.groovy | 2 +- .../plugins/shadow/ShadowJavaPlugin.groovy | 4 +- .../gradle/plugins/shadow/ShadowStats.groovy | 2 +- .../shadow/internal/CleanProperties.groovy | 6 +- .../shadow/internal/GradleVersionUtil.groovy | 10 +- .../shadow/internal/JavaJarExec.groovy | 2 +- .../internal/MinimizeDependencyFilter.groovy | 2 +- .../shadow/internal/ZipCompressor.groovy | 2 +- .../tasks/DefaultInheritManifest.groovy | 2 +- .../shadow/tasks/ShadowCopyAction.groovy | 8 +- .../plugins/shadow/tasks/ShadowJar.java | 99 ++++++------------- .../ApacheNoticeResourceTransformer.groovy | 4 +- .../ComponentsXmlResourceTransformer.groovy | 2 +- .../IncludeResourceTransformer.groovy | 10 +- .../Log4j2PluginsCacheFileTransformer.groovy | 2 +- .../ServiceFileTransformer.groovy | 6 +- .../ConfigureShadowRelocationSpec.groovy | 1 - .../docs/executer/GradleBuildExecuter.groovy | 2 +- .../snippets/DefaultCodeSnippetTests.groovy | 2 +- .../fixture/GroovyScriptFixture.groovy | 2 +- .../SimpleRelocatorParameterTest.groovy | 4 +- ...ceResourceTransformerParameterTests.groovy | 2 +- .../util/AppendableMavenFileModule.groovy | 2 +- .../util/file/TestDirectoryProvider.java | 2 +- .../plugins/shadow/util/file/TestFile.java | 34 +++---- .../shadow/util/file/TestFileHelper.groovy | 30 +++--- .../file/TestNameTestDirectoryProvider.java | 13 +-- .../util/file/TestWorkspaceBuilder.groovy | 4 +- .../shadow/util/repo/AbstractModule.groovy | 14 +-- .../repo/maven/AbstractMavenModule.groovy | 4 +- .../util/repo/maven/MavenDependency.groovy | 2 +- .../util/repo/maven/MavenFileModule.groovy | 6 +- .../util/repo/maven/MavenMetaData.groovy | 2 +- 39 files changed, 139 insertions(+), 195 deletions(-) diff --git a/build.gradle b/build.gradle index c3cc3f203..f098659f7 100644 --- a/build.gradle +++ b/build.gradle @@ -74,29 +74,29 @@ idea { sourceCompatibility = '1.8' targetCompatibility = '1.8' -task downloadDependencies(type: Exec) { +tasks.register('downloadDependencies', Exec) { dependsOn configurations.testRuntimeClasspath commandLine 'echo', 'Downloaded all dependencies' } -tasks.build.dependsOn tasks.shadowJar +tasks.named('build') { dependsOn tasks.named('shadowJar') } -project.tasks.withType(JavaCompile) { +tasks.withType(JavaCompile).configureEach { // This will be the default in Gradle 5.0 if (!options.compilerArgs.contains("-processor")) { options.compilerArgs << '-proc:none' } } -project.tasks.withType(GroovyCompile) { +tasks.withType(GroovyCompile).configureEach { // This will be the default in Gradle 5.0 if (!options.compilerArgs.contains("-processor")) { options.compilerArgs << '-proc:none' } } -task relocateShadowJar(type: ConfigureShadowRelocation) { +tasks.register('relocateShadowJar', ConfigureShadowRelocation) { target = tasks.shadowJar } -tasks.shadowJar.dependsOn tasks.relocateShadowJar +tasks.named('shadowJar') { dependsOn tasks.relocateShadowJar } diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index 395af0a91..689ee9bcc 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -53,14 +53,14 @@ sourceSets { } } -project.tasks.withType(JavaCompile) { +tasks.withType(JavaCompile).configureEach { // This will be the default in Gradle 5.0 if (!options.compilerArgs.contains("-processor")) { options.compilerArgs << '-proc:none' } } -project.tasks.withType(GroovyCompile) { +tasks.withType(GroovyCompile).configureEach { // This will be the default in Gradle 5.0 if (!options.compilerArgs.contains("-processor")) { options.compilerArgs << '-proc:none' diff --git a/gradle/docs.gradle b/gradle/docs.gradle index 47d49c055..10c1eaaff 100644 --- a/gradle/docs.gradle +++ b/gradle/docs.gradle @@ -1,7 +1,7 @@ -def javaApiUrl = 'http://docs.oracle.com/javase/17/docs/api' -def groovyApiUrl = "http://docs.groovy-lang.org/2.4.7/html/gapi/" +def javaApiUrl = 'https://docs.oracle.com/javase/17/docs/api' +def groovyApiUrl = "https://docs.groovy-lang.org/2.4.7/html/gapi/" -tasks.withType(Javadoc) { +tasks.withType(Javadoc).configureEach { classpath += project.configurations.shadow options.links(javaApiUrl, groovyApiUrl) if (JavaVersion.current().java8Compatible) { @@ -9,18 +9,19 @@ tasks.withType(Javadoc) { } } -task javadocJar(type: Jar, dependsOn: javadoc) { +tasks.register('javadocJar', Jar) { + dependsOn javadoc archiveClassifier.set('javadoc') from 'build/docs/javadoc' } -task sourcesJar(type: Jar) { +tasks.register('sourcesJar', Jar) { archiveClassifier.set('sources') from sourceSets.main.allSource } -project.tasks.groovydoc { +tasks.named('groovydoc') { classpath += project.configurations.shadow } -build.dependsOn javadocJar, sourcesJar +tasks.named('build') { dependsOn javadocJar, sourcesJar } diff --git a/gradle/ghPages.gradle b/gradle/ghPages.gradle index 2910f2ef1..fa1526860 100644 --- a/gradle/ghPages.gradle +++ b/gradle/ghPages.gradle @@ -3,7 +3,7 @@ import org.apache.tools.ant.filters.ReplaceTokens apply plugin: 'org.ajoberstar.git-publish' if (project.hasProperty('githubToken')) { - System.setProperty('org.ajoberstar.grgit.auth.username', project.githubToken) + System.setProperty('org.ajoberstar.grgit.auth.username', project.githubToken) } gitPublish { @@ -23,5 +23,5 @@ gitPublish { } } -tasks.gitPublishCopy.dependsOn yarn_build -tasks.gitPublishCopy.dependsOn groovydoc +tasks.named('gitPublishCopy') { dependsOn yarn_build } +tasks.named('gitPublishCopy') { dependsOn groovydoc } diff --git a/gradle/publish.gradle b/gradle/publish.gradle index 4a946ba00..cb5dc8639 100644 --- a/gradle/publish.gradle +++ b/gradle/publish.gradle @@ -55,7 +55,7 @@ publishing { afterEvaluate { publishing { publications { - withType(MavenPublication) { + withType(MavenPublication).configureEach { // Special workaround to publish shadow jar instead of normal one. Name to override peeked here: // https://github.com/gradle/gradle/blob/master/subprojects/plugin-development/src/main/java/org/gradle/plugin/devel/plugins/MavenPluginPublishPlugin.java#L73 if (name == "pluginMaven") { @@ -70,7 +70,7 @@ afterEvaluate { } } -tasks.whenTaskAdded { +tasks.configureEach { if (name == "publishPluginJar" || name == "generateMetadataFileForPluginMavenPublication") { dependsOn(tasks.named("shadowJar")) } @@ -111,6 +111,6 @@ signing { sign publishing.publications.plugin } -task release() { +tasks.register('release') { dependsOn 'assemble', 'publishPlugins', 'gitPublishPush' } diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowApplicationPlugin.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowApplicationPlugin.groovy index d0000a6b0..cc60e8649 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowApplicationPlugin.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowApplicationPlugin.groovy @@ -32,7 +32,7 @@ class ShadowApplicationPlugin implements Plugin { this.project = project this.javaApplication = project.extensions.getByType(JavaApplication) - DistributionContainer distributions = project.extensions.getByName("distributions") + DistributionContainer distributions = project.extensions.getByName("distributions") as DistributionContainer Distribution distribution = distributions.create("shadow") addRunTask(project) diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowBasePlugin.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowBasePlugin.groovy index b367957d7..1f7a3a7d4 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowBasePlugin.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowBasePlugin.groovy @@ -25,7 +25,7 @@ class ShadowBasePlugin implements Plugin { } } - private void createShadowConfiguration(Project project) { + private static void createShadowConfiguration(Project project) { project.configurations.create(CONFIGURATION_NAME) } } diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.groovy index 09a147d93..22f791066 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.groovy @@ -18,7 +18,7 @@ class ShadowJavaPlugin implements Plugin { public static final String SHADOW_JAR_TASK_NAME = 'shadowJar' public static final String SHADOW_GROUP = 'Shadow' - private final ProjectConfigurationActionContainer configurationActionContainer; + private final ProjectConfigurationActionContainer configurationActionContainer @Inject ShadowJavaPlugin(ProjectConfigurationActionContainer configurationActionContainer) { @@ -54,7 +54,7 @@ class ShadowJavaPlugin implements Plugin { } } - protected void configureShadowTask(Project project) { + protected static void configureShadowTask(Project project) { SourceSetContainer sourceSets = project.extensions.getByType(SourceSetContainer) project.tasks.register(SHADOW_JAR_TASK_NAME, ShadowJar) { shadow -> shadow.group = SHADOW_GROUP diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowStats.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowStats.groovy index 4cfdb23c5..2e7815d82 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowStats.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowStats.groovy @@ -22,7 +22,7 @@ class ShadowStats { relocations.collect { k, v -> "${k} ${separator(k, maxLength)} ${v}"}.sort().join("\n") } - String separator(String key, int max) { + static String separator(String key, int max) { return "→" } diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/CleanProperties.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/CleanProperties.groovy index f81b64a2b..5bed7a56d 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/CleanProperties.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/CleanProperties.groovy @@ -15,11 +15,11 @@ class CleanProperties extends Properties { @Override void write(final int b) throws IOException { if (firstLineSeen) { - super.write(b); + super.write(b) } else if (b == '\n') { - super.write(b); + super.write(b) - firstLineSeen = true; + firstLineSeen = true } } diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/GradleVersionUtil.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/GradleVersionUtil.groovy index 4e54a32cd..91606a31d 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/GradleVersionUtil.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/GradleVersionUtil.groovy @@ -9,17 +9,11 @@ import org.gradle.util.GradleVersion class GradleVersionUtil { - private final GradleVersion version - - GradleVersionUtil(String version) { - this.version = GradleVersion.version(version) - } - - PatternSet getRootPatternSet(CopySpecInternal mainSpec) { + static PatternSet getRootPatternSet(CopySpecInternal mainSpec) { return mainSpec.buildRootResolver().getPatternSet() } - ZipCompressor getInternalCompressor(ZipEntryCompression entryCompression, Jar jar) { + static ZipCompressor getInternalCompressor(ZipEntryCompression entryCompression, Jar jar) { switch (entryCompression) { case ZipEntryCompression.DEFLATED: return new DefaultZipCompressor(jar.zip64, ZipOutputStream.DEFLATED) diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/JavaJarExec.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/JavaJarExec.groovy index 890b3fb82..2affa9fbe 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/JavaJarExec.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/JavaJarExec.groovy @@ -11,7 +11,7 @@ class JavaJarExec extends JavaExec { @Override @TaskAction - public void exec() { + void exec() { List allArgs = [getJarFile().path] + getArgs() setArgs(allArgs) super.exec() diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/MinimizeDependencyFilter.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/MinimizeDependencyFilter.groovy index 762005ffc..4853c3a77 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/MinimizeDependencyFilter.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/MinimizeDependencyFilter.groovy @@ -23,7 +23,7 @@ class MinimizeDependencyFilter extends AbstractDependencyFilter { } } - private boolean isParentExcluded(Set excludedDependencies, ResolvedDependency dependency) { + private static boolean isParentExcluded(Set excludedDependencies, ResolvedDependency dependency) { excludedDependencies.any { dependency.parents.contains(it) } } } \ No newline at end of file diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/ZipCompressor.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/ZipCompressor.groovy index 5bd6a5055..b93be9ff3 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/ZipCompressor.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/ZipCompressor.groovy @@ -18,7 +18,7 @@ package com.github.jengelman.gradle.plugins.shadow.internal import org.apache.tools.zip.ZipOutputStream import org.gradle.api.internal.file.archive.compression.ArchiveOutputStreamFactory -public interface ZipCompressor extends ArchiveOutputStreamFactory { +interface ZipCompressor extends ArchiveOutputStreamFactory { ZipOutputStream createArchiveOutputStream(File destination) diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/tasks/DefaultInheritManifest.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/tasks/DefaultInheritManifest.groovy index 59aab7207..a215d49fa 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/tasks/DefaultInheritManifest.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/tasks/DefaultInheritManifest.groovy @@ -59,7 +59,7 @@ class DefaultInheritManifest implements InheritManifest { } @Override - public DefaultManifest getEffectiveManifest() { + DefaultManifest getEffectiveManifest() { DefaultManifest base = new DefaultManifest(fileResolver) inheritMergeSpecs.each { base = it.merge(base, fileResolver) diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowCopyAction.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowCopyAction.groovy index 3b7747085..69f8f129d 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowCopyAction.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowCopyAction.groovy @@ -53,14 +53,13 @@ class ShadowCopyAction implements CopyAction { private final PatternSet patternSet private final ShadowStats stats private final String encoding - private final GradleVersionUtil versionUtil private final boolean preserveFileTimestamps private final boolean minimizeJar private final UnusedTracker unusedTracker ShadowCopyAction(File zipFile, ZipCompressor compressor, DocumentationRegistry documentationRegistry, String encoding, List transformers, List relocators, - PatternSet patternSet, ShadowStats stats, GradleVersionUtil util, + PatternSet patternSet, ShadowStats stats, boolean preserveFileTimestamps, boolean minimizeJar, UnusedTracker unusedTracker) { this.zipFile = zipFile @@ -71,7 +70,6 @@ class ShadowCopyAction implements CopyAction { this.patternSet = patternSet this.stats = stats this.encoding = encoding - this.versionUtil = util this.preserveFileTimestamps = preserveFileTimestamps this.minimizeJar = minimizeJar this.unusedTracker = unusedTracker @@ -154,7 +152,7 @@ class ShadowCopyAction implements CopyAction { } catch(Throwable t) { try { resource.close() - } catch (IOException e) { + } catch (IOException ignored) { // Ignored } throw UncheckedException.throwAsUncheckedException(t) @@ -373,7 +371,7 @@ class ShadowCopyAction implements CopyAction { zipOutStr.putNextEntry(archiveEntry) IOUtils.copyLarge(bis, zipOutStr) zipOutStr.closeEntry() - } catch (ZipException e) { + } catch (ZipException ignored) { log.warn("We have a duplicate " + mappedName + " in source project") } finally { bis.close() diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar.java b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar.java index 1b42c6b94..2f32f1672 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar.java +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar.java @@ -7,18 +7,16 @@ import com.github.jengelman.gradle.plugins.shadow.relocation.SimpleRelocator; import com.github.jengelman.gradle.plugins.shadow.transformers.*; import org.gradle.api.Action; -import org.gradle.api.Task; -import org.gradle.api.artifacts.Configuration; import org.gradle.api.file.ConfigurableFileCollection; import org.gradle.api.file.DuplicatesStrategy; import org.gradle.api.file.FileCollection; import org.gradle.api.internal.DocumentationRegistry; import org.gradle.api.internal.file.FileResolver; import org.gradle.api.internal.file.copy.CopyAction; -import org.gradle.api.specs.Spec; import org.gradle.api.tasks.*; import org.gradle.api.tasks.bundling.Jar; import org.gradle.api.tasks.util.PatternSet; +import org.jetbrains.annotations.NotNull; import java.io.File; import java.lang.reflect.InvocationTargetException; @@ -35,18 +33,17 @@ public class ShadowJar extends Jar implements ShadowSpec { private transient DependencyFilter dependencyFilter; private boolean minimizeJar; - private transient DependencyFilter dependencyFilterForMinimize; + private final transient DependencyFilter dependencyFilterForMinimize; private FileCollection toMinimize; private FileCollection apiJars; private FileCollection sourceSetsClassesDirs; private final ShadowStats shadowStats = new ShadowStats(); - private final GradleVersionUtil versionUtil; private final ConfigurableFileCollection includedDependencies = getProject().files(new Callable() { @Override - public FileCollection call() throws Exception { + public FileCollection call() { return dependencyFilter.resolve(configurations); } }); @@ -54,7 +51,6 @@ public FileCollection call() throws Exception { public ShadowJar() { super(); setDuplicatesStrategy(DuplicatesStrategy.INCLUDE); //shadow filters out files later. This was the default behavior in Gradle < 6.x - versionUtil = new GradleVersionUtil(getProject().getGradle().getGradleVersion()); dependencyFilter = new DefaultDependencyFilter(getProject()); dependencyFilterForMinimize = new MinimizeDependencyFilter(getProject()); setManifest(new DefaultInheritManifest(getServices().get(FileResolver.class))); @@ -62,27 +58,19 @@ public ShadowJar() { relocators = new ArrayList<>(); configurations = new ArrayList<>(); - this.getInputs().property("minimize", new Callable() { - @Override - public Boolean call() throws Exception { - return minimizeJar; - } - }); - this.getOutputs().doNotCacheIf("Has one or more transforms or relocators that are not cacheable", new Spec() { - @Override - public boolean isSatisfiedBy(Task task) { - for (Transformer transformer : transformers) { - if (!isCacheableTransform(transformer.getClass())) { - return true; - } + this.getInputs().property("minimize", (Callable) () -> minimizeJar); + this.getOutputs().doNotCacheIf("Has one or more transforms or relocators that are not cacheable", task -> { + for (Transformer transformer : transformers) { + if (!isCacheableTransform(transformer.getClass())) { + return true; } - for (Relocator relocator : relocators) { - if (!isCacheableRelocator(relocator.getClass())) { - return true; - } + } + for (Relocator relocator : relocators) { + if (!isCacheableRelocator(relocator.getClass())) { + return true; } - return false; } + return false; }); } @@ -111,12 +99,13 @@ public InheritManifest getManifest() { } @Override + @NotNull protected CopyAction createCopyAction() { DocumentationRegistry documentationRegistry = getServices().get(DocumentationRegistry.class); final UnusedTracker unusedTracker = minimizeJar ? UnusedTracker.forProject(getApiJars(), getSourceSetsClassesDirs().getFiles(), getToMinimize()) : null; return new ShadowCopyAction(getArchiveFile().get().getAsFile(), getInternalCompressor(), documentationRegistry, this.getMetadataCharset(), transformers, relocators, getRootPatternSet(), shadowStats, - versionUtil, isPreserveFileTimestamps(), minimizeJar, unusedTracker); + isPreserveFileTimestamps(), minimizeJar, unusedTracker); } @Classpath @@ -152,19 +141,14 @@ FileCollection getSourceSetsClassesDirs() { allClassesDirs.from(classesDirs); } } - sourceSetsClassesDirs = allClassesDirs.filter(new Spec() { - @Override - public boolean isSatisfiedBy(File file) { - return file.isDirectory(); - } - }); + sourceSetsClassesDirs = allClassesDirs.filter(File::isDirectory); } return sourceSetsClassesDirs; } @Internal protected ZipCompressor getInternalCompressor() { - return versionUtil.getInternalCompressor(getEntryCompression(), this); + return GradleVersionUtil.getInternalCompressor(getEntryCompression(), this); } @TaskAction @@ -186,7 +170,7 @@ public FileCollection getIncludedDependencies() { */ @Internal protected PatternSet getRootPatternSet() { - return versionUtil.getRootPatternSet(getMainSpec()); + return GradleVersionUtil.getRootPatternSet(getMainSpec()); } /** @@ -256,10 +240,8 @@ private void addTransform(T transformer, Action c) { public ShadowJar mergeServiceFiles() { try { transform(ServiceFileTransformer.class); - } catch (IllegalAccessException e) { - } catch (InstantiationException e) { - } catch (NoSuchMethodException e) { - } catch (InvocationTargetException e) { + } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException | + InstantiationException ignored) { } return this; } @@ -271,17 +253,9 @@ public ShadowJar mergeServiceFiles() { */ public ShadowJar mergeServiceFiles(final String rootPath) { try { - transform(ServiceFileTransformer.class, new Action() { - - @Override - public void execute(ServiceFileTransformer serviceFileTransformer) { - serviceFileTransformer.setPath(rootPath); - } - }); - } catch (IllegalAccessException e) { - } catch (InstantiationException e) { - } catch (NoSuchMethodException e) { - } catch (InvocationTargetException e) { + transform(ServiceFileTransformer.class, serviceFileTransformer -> serviceFileTransformer.setPath(rootPath)); + } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException | + InstantiationException ignored) { } return this; } @@ -294,10 +268,8 @@ public void execute(ServiceFileTransformer serviceFileTransformer) { public ShadowJar mergeServiceFiles(Action configureClosure) { try { transform(ServiceFileTransformer.class, configureClosure); - } catch (IllegalAccessException e) { - } catch (InstantiationException e) { - } catch (NoSuchMethodException e) { - } catch (InvocationTargetException e) { + } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException | + InstantiationException ignored) { } return this; } @@ -310,10 +282,8 @@ public ShadowJar mergeServiceFiles(Action configureClosu public ShadowJar mergeGroovyExtensionModules() { try { transform(GroovyExtensionModuleTransformer.class); - } catch (IllegalAccessException e) { - } catch (InstantiationException e) { - } catch (NoSuchMethodException e) { - } catch (InvocationTargetException e) { + } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException | + InstantiationException ignored) { } return this; } @@ -325,16 +295,9 @@ public ShadowJar mergeGroovyExtensionModules() { */ public ShadowJar append(final String resourcePath) { try { - transform(AppendingTransformer.class, new Action() { - @Override - public void execute(AppendingTransformer transformer) { - transformer.setResource(resourcePath); - } - }); - } catch (IllegalAccessException e) { - } catch (InstantiationException e) { - } catch (NoSuchMethodException e) { - } catch (InvocationTargetException e) { + transform(AppendingTransformer.class, transformer -> transformer.setResource(resourcePath)); + } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException | + InstantiationException ignored) { } return this; } @@ -359,7 +322,7 @@ public ShadowJar relocate(String pattern, String destination) { * @return this */ public ShadowJar relocate(String pattern, String destination, Action configure) { - SimpleRelocator relocator = new SimpleRelocator(pattern, destination, new ArrayList(), new ArrayList()); + SimpleRelocator relocator = new SimpleRelocator(pattern, destination, new ArrayList<>(), new ArrayList<>()); addRelocator(relocator, configure); return this; } diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheNoticeResourceTransformer.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheNoticeResourceTransformer.groovy index 1db0f3fd1..0daf571a2 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheNoticeResourceTransformer.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheNoticeResourceTransformer.groovy @@ -94,7 +94,7 @@ class ApacheNoticeResourceTransformer implements Transformer { void transform(TransformerContext context) { if (entries.isEmpty()) { String year = new SimpleDateFormat("yyyy").format(new Date()) - if (!inceptionYear.equals(year)) { + if (inceptionYear != year) { year = inceptionYear + "-" + year } @@ -190,7 +190,7 @@ class ApacheNoticeResourceTransformer implements Transformer { int count = 0 for (String line : entries) { ++count - if (line.equals(copyright) && count != 2) { + if (line == copyright && count != 2) { continue } diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/ComponentsXmlResourceTransformer.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/ComponentsXmlResourceTransformer.groovy index 0c91e8fb9..788d0530b 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/ComponentsXmlResourceTransformer.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/ComponentsXmlResourceTransformer.groovy @@ -46,7 +46,7 @@ class ComponentsXmlResourceTransformer implements Transformer { boolean canTransformResource(FileTreeElement element) { def path = element.relativePath.pathString - return COMPONENTS_XML_PATH.equals(path) + return COMPONENTS_XML_PATH == path } void transform(TransformerContext context) { diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/IncludeResourceTransformer.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/IncludeResourceTransformer.groovy index 14dabee7b..3980ee1f5 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/IncludeResourceTransformer.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/IncludeResourceTransformer.groovy @@ -36,7 +36,7 @@ import org.gradle.api.tasks.PathSensitivity * * @author John Engelman */ -public class IncludeResourceTransformer implements Transformer { +class IncludeResourceTransformer implements Transformer { @InputFile @PathSensitive(PathSensitivity.NONE) @@ -45,19 +45,19 @@ public class IncludeResourceTransformer implements Transformer { @Input String resource - public boolean canTransformResource(FileTreeElement element) { + boolean canTransformResource(FileTreeElement element) { return false } - public void transform(TransformerContext context) { + void transform(TransformerContext context) { // no op } - public boolean hasTransformedResource() { + boolean hasTransformedResource() { return file != null ? file.exists() : false } - public void modifyOutputStream(ZipOutputStream os, boolean preserveFileTimestamps) { + void modifyOutputStream(ZipOutputStream os, boolean preserveFileTimestamps) { ZipEntry entry = new ZipEntry(resource) entry.time = TransformerContext.getEntryTimestamp(preserveFileTimestamps, entry.time) os.putNextEntry(entry) diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/Log4j2PluginsCacheFileTransformer.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/Log4j2PluginsCacheFileTransformer.groovy index 7f90dff1b..69bf20d2f 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/Log4j2PluginsCacheFileTransformer.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/Log4j2PluginsCacheFileTransformer.groovy @@ -30,7 +30,7 @@ import org.apache.tools.zip.ZipEntry import org.apache.tools.zip.ZipOutputStream import org.gradle.api.file.FileTreeElement -import static org.apache.logging.log4j.core.config.plugins.processor.PluginProcessor.PLUGIN_CACHE_FILE; +import static org.apache.logging.log4j.core.config.plugins.processor.PluginProcessor.PLUGIN_CACHE_FILE /** * Modified from the maven equivalent to work with gradle diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformer.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformer.groovy index 37a1a4450..b2153a3f9 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformer.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformer.groovy @@ -102,11 +102,11 @@ class ServiceFileTransformer implements Transformer, PatternFilterable { static class ServiceStream extends ByteArrayOutputStream { - public ServiceStream(){ + ServiceStream(){ super( 1024 ) } - public void append( InputStream is ) throws IOException { + void append(InputStream is ) throws IOException { if ( super.count > 0 && super.buf[super.count - 1] != '\n' && super.buf[super.count - 1] != '\r' ) { byte[] newline = '\n'.bytes write(newline, 0, newline.length) @@ -114,7 +114,7 @@ class ServiceFileTransformer implements Transformer, PatternFilterable { IOUtil.copy(is, this) } - public InputStream toInputStream() { + InputStream toInputStream() { return new ByteArrayInputStream( super.buf, 0, super.count ) } } diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/ConfigureShadowRelocationSpec.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/ConfigureShadowRelocationSpec.groovy index 2768ac347..9267366a9 100644 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/ConfigureShadowRelocationSpec.groovy +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/ConfigureShadowRelocationSpec.groovy @@ -23,7 +23,6 @@ class ConfigureShadowRelocationSpec extends PluginSpecification { when: run('shadowJar', '-s') - then: then: contains(output, [ 'META-INF/MANIFEST.MF', diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/docs/executer/GradleBuildExecuter.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/docs/executer/GradleBuildExecuter.groovy index 493794264..f8ce6e65a 100644 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/docs/executer/GradleBuildExecuter.groovy +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/docs/executer/GradleBuildExecuter.groovy @@ -65,7 +65,7 @@ include 'api', 'main' } - private void addSubProject(File dir) { + private static void addSubProject(File dir) { File api = new File(dir, "api") api.mkdirs() File build = new File(api, "build.gradle") diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/docs/internal/snippets/DefaultCodeSnippetTests.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/docs/internal/snippets/DefaultCodeSnippetTests.groovy index ec613c8e4..45cde6580 100644 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/docs/internal/snippets/DefaultCodeSnippetTests.groovy +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/docs/internal/snippets/DefaultCodeSnippetTests.groovy @@ -1,6 +1,6 @@ package com.github.jengelman.gradle.plugins.shadow.docs.internal.snippets -import com.github.jengelman.gradle.plugins.shadow.docs.internal.snippets.junit.SnippetRunner; +import com.github.jengelman.gradle.plugins.shadow.docs.internal.snippets.junit.SnippetRunner import org.junit.runner.Runner class DefaultCodeSnippetTests implements CodeSnippetTests { diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/docs/internal/snippets/fixture/GroovyScriptFixture.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/docs/internal/snippets/fixture/GroovyScriptFixture.groovy index 2bd9dd765..deff8e9f0 100644 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/docs/internal/snippets/fixture/GroovyScriptFixture.groovy +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/docs/internal/snippets/fixture/GroovyScriptFixture.groovy @@ -1,4 +1,4 @@ -package com.github.jengelman.gradle.plugins.shadow.docs.internal.snippets.fixture; +package com.github.jengelman.gradle.plugins.shadow.docs.internal.snippets.fixture class GroovyScriptFixture extends SnippetFixture { diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/relocation/SimpleRelocatorParameterTest.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/relocation/SimpleRelocatorParameterTest.groovy index 7cd0eec4c..730e351d8 100644 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/relocation/SimpleRelocatorParameterTest.groovy +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/relocation/SimpleRelocatorParameterTest.groovy @@ -42,11 +42,11 @@ class SimpleRelocatorParameterTest extends TestCase { constructThenFailOnNullPointerException("", null) } - private void constructThenFailOnNullPointerException(String pattern, String shadedPattern) { + private static void constructThenFailOnNullPointerException(String pattern, String shadedPattern) { try { new SimpleRelocator(pattern, shadedPattern, Collections. emptyList(), Collections. emptyList()) } - catch (NullPointerException e) { + catch (NullPointerException ignored) { fail("Constructor should not throw null pointer exceptions") } } diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheNoticeResourceTransformerParameterTests.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheNoticeResourceTransformerParameterTests.groovy index 055ed8503..df38dc5cf 100644 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheNoticeResourceTransformerParameterTests.groovy +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheNoticeResourceTransformerParameterTests.groovy @@ -74,7 +74,7 @@ class ApacheNoticeResourceTransformerParameterTests extends TestCase { final List emptyList = Collections.emptyList() subject.transform(TransformerContext.builder().path(NOTICE_RESOURCE).is(noticeInputStream).relocators(emptyList).stats(stats).build()) } - catch (NullPointerException e) { + catch (NullPointerException ignored) { fail("Null pointer should not be thrown when no parameters are set.") } } diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/AppendableMavenFileModule.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/AppendableMavenFileModule.groovy index 7d6040058..0a4414128 100644 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/AppendableMavenFileModule.groovy +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/AppendableMavenFileModule.groovy @@ -48,7 +48,7 @@ class AppendableMavenFileModule extends MavenFileModule { return artifactFile } - void writeJar(OutputStream os, Map contents) { + static void writeJar(OutputStream os, Map contents) { if (contents) { JarBuilder builder = new JarBuilder(os) contents.each { path, content -> diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/file/TestDirectoryProvider.java b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/file/TestDirectoryProvider.java index 179781612..9aacdbd8a 100644 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/file/TestDirectoryProvider.java +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/file/TestDirectoryProvider.java @@ -2,7 +2,7 @@ /** * Implementations provide a working space to be used in tests. - * + *

* The client is not responsible for removing any files. */ public interface TestDirectoryProvider { diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/file/TestFile.java b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/file/TestFile.java index b6d395d90..5e1254b38 100644 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/file/TestFile.java +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/file/TestFile.java @@ -106,7 +106,7 @@ public TestFile file(Object... path) { } public List files(Object... paths) { - List files = new ArrayList(); + List files = new ArrayList<>(); for (Object path : paths) { files.add(file(path)); } @@ -163,16 +163,13 @@ public Map getProperties() { assertIsFile(); Properties properties = new Properties(); try { - FileInputStream inStream = new FileInputStream(this); - try { + try (FileInputStream inStream = new FileInputStream(this)) { properties.load(inStream); - } finally { - inStream.close(); } } catch (IOException e) { throw new RuntimeException(e); } - Map map = new HashMap(); + Map map = new HashMap<>(); for (Object key : properties.keySet()) { map.put(key.toString(), properties.getProperty(key.toString())); } @@ -182,11 +179,8 @@ public Map getProperties() { public Manifest getManifest() { assertIsFile(); try { - JarFile jarFile = new JarFile(this); - try { + try (JarFile jarFile = new JarFile(this)) { return jarFile.getManifest(); - } finally { - jarFile.close(); } } catch (IOException e) { throw new RuntimeException(e); @@ -195,9 +189,8 @@ public Manifest getManifest() { public List linesThat(Matcher matcher) { try { - BufferedReader reader = new BufferedReader(new FileReader(this)); - try { - List lines = new ArrayList(); + try (BufferedReader reader = new BufferedReader(new FileReader(this))) { + List lines = new ArrayList<>(); String line; while ((line = reader.readLine()) != null) { if (matcher.matches(line)) { @@ -205,8 +198,6 @@ public List linesThat(Matcher matcher) { } } return lines; - } finally { - reader.close(); } } catch (IOException e) { throw new RuntimeException(e); @@ -383,14 +374,14 @@ public int getMode() { * Asserts that this file contains exactly the given set of descendants. */ public TestFile assertHasDescendants(String... descendants) { - Set actual = new TreeSet(); + Set actual = new TreeSet<>(); assertIsDir(); visit(actual, "", this); - Set expected = new TreeSet(Arrays.asList(descendants)); + Set expected = new TreeSet<>(Arrays.asList(descendants)); - Set extras = new TreeSet(actual); + Set extras = new TreeSet<>(actual); extras.removeAll(expected); - Set missing = new TreeSet(expected); + Set missing = new TreeSet<>(expected); missing.removeAll(actual); assertEquals(String.format("For dir: %s, extra files: %s, missing files: %s, expected: %s", this, extras, missing, expected), expected, actual); @@ -544,11 +535,8 @@ public void writeProperties(Map properties) { Properties props = new Properties(); props.putAll(properties); try { - FileOutputStream stream = new FileOutputStream(this); - try { + try (FileOutputStream stream = new FileOutputStream(this)) { props.store(stream, "comment"); - } finally { - stream.close(); } } catch (IOException e) { throw new RuntimeException(e); diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/file/TestFileHelper.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/file/TestFileHelper.groovy index c1515095f..03dc96c9f 100644 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/file/TestFileHelper.groovy +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/file/TestFileHelper.groovy @@ -1,4 +1,4 @@ -package com.github.jengelman.gradle.plugins.shadow.util.file; +package com.github.jengelman.gradle.plugins.shadow.util.file import org.apache.commons.io.FileUtils import org.apache.commons.lang3.StringUtils @@ -81,7 +81,7 @@ class TestFileHelper { untar.execute() } - private boolean isUnix() { + private static boolean isUnix() { return !System.getProperty('os.name').toLowerCase().contains('windows') } @@ -119,7 +119,7 @@ class TestFileHelper { } } - private int toMode(String permissions) { + private static int toMode(String permissions) { int m = [6, 3, 0].inject(0) { mode, pos -> mode |= permissions[9 - pos - 3] == 'r' ? 4 << pos : 0 mode |= permissions[9 - pos - 2] == 'w' ? 2 << pos : 0 @@ -142,7 +142,7 @@ class TestFileHelper { throw new RuntimeException("Could not delete '$file': $error") } } else { - FileUtils.deleteQuietly(file); + FileUtils.deleteQuietly(file) } } @@ -170,32 +170,32 @@ class TestFileHelper { return new ExecOutput(output, error) } - public void zipTo(TestFile zipFile, boolean nativeTools) { + void zipTo(TestFile zipFile, boolean nativeTools) { if (nativeTools && isUnix()) { def process = ['zip', zipFile.absolutePath, "-r", file.name].execute(null, zipFile.parentFile) process.consumeProcessOutput(System.out, System.err) assert process.waitFor() == 0 } else { - Zip zip = new Zip(); - zip.setBasedir(file); - zip.setDestFile(zipFile); - zip.setProject(new Project()); + Zip zip = new Zip() + zip.setBasedir(file) + zip.setDestFile(zipFile) + zip.setProject(new Project()) def whenEmpty = new Zip.WhenEmpty() whenEmpty.setValue("create") - zip.setWhenempty(whenEmpty); - zip.execute(); + zip.setWhenempty(whenEmpty) + zip.execute() } } - public void tarTo(TestFile tarFile, boolean nativeTools) { + void tarTo(TestFile tarFile, boolean nativeTools) { if (nativeTools && isUnix()) { def process = ['tar', "-cf", tarFile.absolutePath, file.name].execute(null, tarFile.parentFile) process.consumeProcessOutput(System.out, System.err) assert process.waitFor() == 0 } else { - Tar tar = new Tar(); - tar.setBasedir(file); - tar.setDestFile(tarFile); + Tar tar = new Tar() + tar.setBasedir(file) + tar.setDestFile(tarFile) tar.setProject(new Project()) tar.execute() } diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/file/TestNameTestDirectoryProvider.java b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/file/TestNameTestDirectoryProvider.java index 59f9642a8..8af8fd1ec 100644 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/file/TestNameTestDirectoryProvider.java +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/file/TestNameTestDirectoryProvider.java @@ -2,6 +2,7 @@ import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.NotNull; import org.junit.rules.MethodRule; import org.junit.rules.TestRule; import org.junit.runner.Description; @@ -17,8 +18,8 @@ public class TestNameTestDirectoryProvider implements MethodRule, TestRule, TestDirectoryProvider { private TestFile dir; private String prefix; - private static TestFile root; - private static AtomicInteger testCounter = new AtomicInteger(1); + private static final TestFile root; + private static final AtomicInteger testCounter = new AtomicInteger(1); static { // NOTE: the space in the directory name is intentional @@ -47,7 +48,7 @@ public void evaluate() throws Throwable { }; } - public Statement apply(final Statement base, Description description) { + public Statement apply(final @NotNull Statement base, Description description) { init(description.getMethodName(), description.getTestClass().getSimpleName()); return new Statement() { @Override @@ -101,14 +102,14 @@ public TestFile getTestDirectory() { } public TestFile file(Object... path) { - return getTestDirectory().file((Object[]) path); + return getTestDirectory().file(path); } public TestFile createFile(Object... path) { - return file((Object[]) path).createFile(); + return file(path).createFile(); } public TestFile createDir(Object... path) { - return file((Object[]) path).createDir(); + return file(path).createDir(); } } diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/file/TestWorkspaceBuilder.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/file/TestWorkspaceBuilder.groovy index ef54d933a..34ca1ff23 100644 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/file/TestWorkspaceBuilder.groovy +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/file/TestWorkspaceBuilder.groovy @@ -6,9 +6,9 @@ package com.github.jengelman.gradle.plugins.shadow.util.file * Should be inner class of TestFile, but can't because Groovy has issues with inner classes as delegates. */ class TestWorkspaceBuilder { - def TestFile baseDir + TestFile baseDir - def TestWorkspaceBuilder(TestFile baseDir) { + TestWorkspaceBuilder(TestFile baseDir) { this.baseDir = baseDir } diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/repo/AbstractModule.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/repo/AbstractModule.groovy index ff62a315c..ea5504ec7 100644 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/repo/AbstractModule.groovy +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/repo/AbstractModule.groovy @@ -47,34 +47,34 @@ abstract class AbstractModule { protected abstract onPublish(TestFile file) - TestFile getSha1File(TestFile file) { + static TestFile getSha1File(TestFile file) { getHashFile(file, "sha1") } - TestFile sha1File(TestFile file) { + static TestFile sha1File(TestFile file) { hashFile(file, "sha1", 40) } - TestFile getMd5File(TestFile file) { + static TestFile getMd5File(TestFile file) { getHashFile(file, "md5") } - TestFile md5File(TestFile file) { + static TestFile md5File(TestFile file) { hashFile(file, "md5", 32) } - private TestFile hashFile(TestFile file, String algorithm, int len) { + private static TestFile hashFile(TestFile file, String algorithm, int len) { def hashFile = getHashFile(file, algorithm) def hash = getHash(file, algorithm) hashFile.text = String.format("%0${len}x", hash) return hashFile } - private TestFile getHashFile(TestFile file, String algorithm) { + private static TestFile getHashFile(TestFile file, String algorithm) { file.parentFile.file("${file.name}.${algorithm}") } - protected BigInteger getHash(TestFile file, String algorithm) { + private static BigInteger getHash(TestFile file, String algorithm) { HashUtil.createHash(file, algorithm.toUpperCase()).asBigInteger() } } \ No newline at end of file diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/repo/maven/AbstractMavenModule.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/repo/maven/AbstractMavenModule.groovy index 837755074..6d0ff135a 100644 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/repo/maven/AbstractMavenModule.groovy +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/repo/maven/AbstractMavenModule.groovy @@ -228,7 +228,7 @@ abstract class AbstractMavenModule extends AbstractModule implements MavenModule } publish(pomFile) { Writer writer -> - def pomPackaging = packaging ?: type; + def pomPackaging = packaging ?: type writer << """ @@ -271,7 +271,7 @@ abstract class AbstractMavenModule extends AbstractModule implements MavenModule private void updateRootMavenMetaData(TestFile rootMavenMetaData) { def allVersions = rootMavenMetaData.exists() ? new XmlParser().parseText(rootMavenMetaData.text).versioning.versions.version*.value().flatten() : [] - allVersions << version; + allVersions << version publish(rootMavenMetaData) { Writer writer -> def builder = new MarkupBuilder(writer) builder.metadata { diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/repo/maven/MavenDependency.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/repo/maven/MavenDependency.groovy index 789251310..56db25320 100644 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/repo/maven/MavenDependency.groovy +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/repo/maven/MavenDependency.groovy @@ -13,7 +13,7 @@ class MavenDependency { } @Override - public String toString() { + String toString() { return String.format("MavenDependency %s:%s:%s:%s@%s", groupId, artifactId, version, classifier, type) } } diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/repo/maven/MavenFileModule.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/repo/maven/MavenFileModule.groovy index 7696ee177..064e53a7f 100644 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/repo/maven/MavenFileModule.groovy +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/repo/maven/MavenFileModule.groovy @@ -3,7 +3,7 @@ package com.github.jengelman.gradle.plugins.shadow.util.repo.maven import com.github.jengelman.gradle.plugins.shadow.util.file.TestFile class MavenFileModule extends AbstractMavenModule { - private boolean uniqueSnapshots = true; + private boolean uniqueSnapshots = true MavenFileModule(TestFile moduleDir, String groupId, String artifactId, String version) { super(moduleDir, groupId, artifactId, version) @@ -14,8 +14,8 @@ class MavenFileModule extends AbstractMavenModule { } MavenModule withNonUniqueSnapshots() { - uniqueSnapshots = false; - return this; + uniqueSnapshots = false + return this } @Override diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/repo/maven/MavenMetaData.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/repo/maven/MavenMetaData.groovy index bdceb46f6..0a3b49b11 100644 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/repo/maven/MavenMetaData.groovy +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/repo/maven/MavenMetaData.groovy @@ -1,6 +1,6 @@ package com.github.jengelman.gradle.plugins.shadow.util.repo.maven -public interface MavenMetaData { +interface MavenMetaData { List getVersions(); } From b21427caded2ab04b41ac93cf0c9e3e994381f4d Mon Sep 17 00:00:00 2001 From: Goooler Date: Sat, 25 Feb 2023 22:30:02 +0800 Subject: [PATCH 28/43] Apply all plugins in plugins block --- build.gradle | 15 +++------------ gradle/vuepress.gradle | 6 ++++-- settings.gradle | 7 +++++++ 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/build.gradle b/build.gradle index f098659f7..5199a01fb 100644 --- a/build.gradle +++ b/build.gradle @@ -1,23 +1,14 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation -buildscript { - repositories { - gradlePluginPortal() - mavenCentral() - } - dependencies { - classpath "com.gradle.publish:plugin-publish-plugin:0.16.0" - classpath 'org.ajoberstar:gradle-git-publish:3.0.0' - classpath "com.github.node-gradle:gradle-node-plugin:3.1.1" - } -} - plugins { id 'groovy' id 'project-report' id 'idea' id 'java-gradle-plugin' id 'signing' + id 'com.gradle.plugin-publish' version '0.16.0' + id 'org.ajoberstar.git-publish' version '3.0.0' + id 'com.github.node-gradle.node' version '3.0.0' } // Remove the gradleApi so it isn't merged into the jar file. diff --git a/gradle/vuepress.gradle b/gradle/vuepress.gradle index de87a4a16..da01b2f1c 100644 --- a/gradle/vuepress.gradle +++ b/gradle/vuepress.gradle @@ -4,5 +4,7 @@ node { yarnVersion = '1.5.1' } -tasks.yarn_build.inputs.files project.fileTree('src/docs') -tasks.yarn_build.outputs.dir project.file('build/site') \ No newline at end of file +tasks.named('yarn_build') { + inputs.files project.fileTree('src/docs') + outputs.dir project.file('build/site') +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 1d59b7d5f..5d3598e3e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,3 +1,10 @@ +pluginManagement { + repositories { + mavenCentral() + gradlePluginPortal() + } +} + plugins { id 'com.gradle.enterprise' version '3.12.3' } From ac80df1bd1ee6fbd4864c68e24390e00c57cf9fd Mon Sep 17 00:00:00 2001 From: Goooler Date: Sat, 25 Feb 2023 22:31:49 +0800 Subject: [PATCH 29/43] Update gradle-git-publish 4.1.1 https://github.com/ajoberstar/gradle-git-publish/releases/tag/4.0.0 https://github.com/ajoberstar/gradle-git-publish/releases/tag/4.1.1 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 5199a01fb..dfc21ae07 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { id 'java-gradle-plugin' id 'signing' id 'com.gradle.plugin-publish' version '0.16.0' - id 'org.ajoberstar.git-publish' version '3.0.0' + id 'org.ajoberstar.git-publish' version '4.1.1' id 'com.github.node-gradle.node' version '3.0.0' } From cd1e952b210c227f7f1061d3d0608f246f0d581f Mon Sep 17 00:00:00 2001 From: Goooler Date: Sat, 25 Feb 2023 22:32:54 +0800 Subject: [PATCH 30/43] Update com.github.node-gradle.node 3.5.1 https://github.com/node-gradle/gradle-node-plugin/releases/tag/3.5.1 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index dfc21ae07..bd49343bc 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'signing' id 'com.gradle.plugin-publish' version '0.16.0' id 'org.ajoberstar.git-publish' version '4.1.1' - id 'com.github.node-gradle.node' version '3.0.0' + id 'com.github.node-gradle.node' version '3.5.1' } // Remove the gradleApi so it isn't merged into the jar file. From 6ae6cbdc48204e576a36aa37c0e0cc8de0204898 Mon Sep 17 00:00:00 2001 From: Goooler Date: Sat, 25 Feb 2023 22:46:04 +0800 Subject: [PATCH 31/43] Update com.gradle.plugin-publish 1.1.0 https://plugins.gradle.org/plugin/com.gradle.plugin-publish/1.1.0 https://plugins.gradle.org/plugin/com.gradle.plugin-publish/1.0.0 --- build.gradle | 9 +-- gradle/publish.gradle | 76 ++----------------- ...com.github.johnrengelman.shadow.properties | 16 ---- 3 files changed, 11 insertions(+), 90 deletions(-) delete mode 100644 src/main/resources/META-INF/gradle-plugins/com.github.johnrengelman.shadow.properties diff --git a/build.gradle b/build.gradle index bd49343bc..f2927abb2 100644 --- a/build.gradle +++ b/build.gradle @@ -1,3 +1,4 @@ +import com.github.jengelman.gradle.plugins.shadow.ShadowPlugin import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation plugins { @@ -6,7 +7,7 @@ plugins { id 'idea' id 'java-gradle-plugin' id 'signing' - id 'com.gradle.plugin-publish' version '0.16.0' + id 'com.gradle.plugin-publish' version '1.1.0' id 'org.ajoberstar.git-publish' version '4.1.1' id 'com.github.node-gradle.node' version '3.5.1' } @@ -16,11 +17,7 @@ configurations.named(JavaPlugin.API_CONFIGURATION_NAME) { dependencies.remove(project.dependencies.gradleApi()) } -gradlePlugin { - automatedPublishing = false -} - -apply plugin: 'com.github.johnrengelman.shadow' +apply plugin: ShadowPlugin apply from: file('gradle/docs.gradle') apply from: file('gradle/publish.gradle') diff --git a/gradle/publish.gradle b/gradle/publish.gradle index cb5dc8639..db1d66455 100644 --- a/gradle/publish.gradle +++ b/gradle/publish.gradle @@ -1,98 +1,40 @@ -apply plugin: 'maven-publish' apply plugin: "com.gradle.plugin-publish" group = 'com.github.johnrengelman' -def versionString = file('src/main/resources/shadow-version.txt').text.trim() if (System.env.CIRCLE_TAG && System.env.CIRCLE_TAG =~ /^\d\.\d\.\d$/) { version = System.env.CIRCLE_TAG } else { - version = versionString + version = file('src/main/resources/shadow-version.txt').text.trim() if (!version.endsWith("-SNAPSHOT")) { version = version + "-SNAPSHOT" } } -ext.isSnapshot = version.endsWith("SNAPSHOT") - -def pomConfig = { - licenses { - license { - name 'The Apache Software License, Version 2.0' - url 'http://www.apache.org/licenses/LICENSE-2.0.txt' - distribution 'repo' - } - } - developers { - developer { - id 'jengelman' - name 'John Engelman' - email 'john.r.engelman@gmail.com' - } - } -} - -publishing { - publications { - plugin(MavenPublication) { - shadow.component(it) - artifact sourcesJar - artifact javadocJar - - pom.withXml { - def root = asNode() - root.appendNode('description', 'Gradle plugin to combine/relocate dependencies in a single Jar.') - root.children().last() + pomConfig - } - } - } -} - -// Workaround for configuring the artifact that publish-plugins uses: https://github.com/JLLeitschuh/ktlint-gradle/blob/master/plugin/build.gradle.kts -// Need to move publishing configuration into afterEvaluate {} -// to override changes done by "com.gradle.plugin-publish" plugin in afterEvaluate {} block -// See PublishPlugin class for details -afterEvaluate { - publishing { - publications { - withType(MavenPublication).configureEach { - // Special workaround to publish shadow jar instead of normal one. Name to override peeked here: - // https://github.com/gradle/gradle/blob/master/subprojects/plugin-development/src/main/java/org/gradle/plugin/devel/plugins/MavenPluginPublishPlugin.java#L73 - if (name == "pluginMaven") { - setArtifacts([ - tasks.shadowJar, - tasks.sourcesJar, - tasks.javadocJar - ]) - } - } - } - } -} - tasks.configureEach { if (name == "publishPluginJar" || name == "generateMetadataFileForPluginMavenPublication") { dependsOn(tasks.named("shadowJar")) } } -pluginBundle { +gradlePlugin { website = 'https://github.com/johnrengelman/shadow' vcsUrl = 'https://github.com/johnrengelman/shadow' - tags = ['onejar', 'shade', 'fatjar', 'uberjar'] plugins { shadowPlugin { id = 'com.github.johnrengelman.shadow' + implementationClass = 'com.github.jengelman.gradle.plugins.shadow.ShadowPlugin' displayName = 'Shadow Plugin' description = "Gradle plugin to create fat/uber JARs, apply file transforms, and relocate packages for applications and libraries. Gradle version of Maven's Shade plugin." + tags.set(['onejar', 'shade', 'fatjar', 'uberjar']) } } } -publishPlugins { task -> +tasks.named('publishPlugins') { doFirst { - if (isSnapshot) { + if (version.endsWith("SNAPSHOT")) { throw new GradleException('Cannot publish SNAPSHOT versions to Plugin Portal!') } } @@ -105,10 +47,8 @@ signing { def signingPassword = findProperty("signingPassword") useInMemoryPgpKeys(signingKey, signingPassword) } - required { - gradle.taskGraph.hasTask("artifactoryPublish") - } - sign publishing.publications.plugin + required = gradle.taskGraph.hasTask("artifactoryPublish") + sign(publishing.publications) } tasks.register('release') { diff --git a/src/main/resources/META-INF/gradle-plugins/com.github.johnrengelman.shadow.properties b/src/main/resources/META-INF/gradle-plugins/com.github.johnrengelman.shadow.properties deleted file mode 100644 index e77803a7e..000000000 --- a/src/main/resources/META-INF/gradle-plugins/com.github.johnrengelman.shadow.properties +++ /dev/null @@ -1,16 +0,0 @@ -# -# Copyright 2011 the original author or authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -implementation-class=com.github.jengelman.gradle.plugins.shadow.ShadowPlugin From 3be2003e5b5efea8744131adfd55f243e09ac616 Mon Sep 17 00:00:00 2001 From: Goooler Date: Sat, 25 Feb 2023 22:54:40 +0800 Subject: [PATCH 32/43] Update README for Shadow 8 compatibility --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5518409b9..6056f4f62 100644 --- a/README.md +++ b/README.md @@ -15,8 +15,9 @@ Read the [User Guide](https://imperceptiblethoughts.com/shadow/)! | Gradle Version | Shadow Version | |----------------|----------------| -| 5.x | 5.2.0 - 6.0.0 | -| 6.x | 5.2.0 - 6.1.0 | -| 7.x | 7.0.0+ | +| 5.x | 5.2.0 - 6.0.0 | +| 6.x | 5.2.0 - 6.1.0 | +| 7.x | 7.0.0+ | +| 8.x | 8.0.0+ | **NOTE**: Shadow v5.+ is compatible with Gradle 5.x - 6.x and Java 7 - 15 _only_, v6.1.0+ requires Java 8+. From 7b3a15838d8f41a65b30f897c55332d1b64e9ecf Mon Sep 17 00:00:00 2001 From: Goooler Date: Sat, 25 Feb 2023 23:21:09 +0800 Subject: [PATCH 33/43] Enable config cache https://docs.gradle.org/8.0/userguide/configuration_cache.html --- build.gradle | 4 ++++ gradle.properties | 3 ++- gradle/publish.gradle | 5 +++++ settings.gradle | 2 ++ 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index f2927abb2..492c6998f 100644 --- a/build.gradle +++ b/build.gradle @@ -59,6 +59,10 @@ idea { } } +tasks.named('ideaModule') { + notCompatibleWithConfigurationCache("https://github.com/gradle/gradle/issues/13480") +} + sourceCompatibility = '1.8' targetCompatibility = '1.8' diff --git a/gradle.properties b/gradle.properties index 24bc86380..c4cb586e5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,4 @@ org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=2g org.gradle.parallel=true -org.gradle.caching=true \ No newline at end of file +org.gradle.caching=true +org.gradle.unsafe.configuration-cache=true \ No newline at end of file diff --git a/gradle/publish.gradle b/gradle/publish.gradle index db1d66455..404d76a59 100644 --- a/gradle/publish.gradle +++ b/gradle/publish.gradle @@ -38,6 +38,7 @@ tasks.named('publishPlugins') { throw new GradleException('Cannot publish SNAPSHOT versions to Plugin Portal!') } } + notCompatibleWithConfigurationCache("https://github.com/gradle/gradle/issues/21283") } signing { @@ -51,6 +52,10 @@ signing { sign(publishing.publications) } +tasks.withType(Sign).configureEach { + notCompatibleWithConfigurationCache("https://github.com/gradle/gradle/issues/13470") +} + tasks.register('release') { dependsOn 'assemble', 'publishPlugins', 'gitPublishPush' } diff --git a/settings.gradle b/settings.gradle index 5d3598e3e..afcef171e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -29,4 +29,6 @@ gradleEnterprise { } } +enableFeaturePreview("STABLE_CONFIGURATION_CACHE") + rootProject.name = 'shadow' \ No newline at end of file From 04b3c3c10bb1719e79fbddea636e258a53163cba Mon Sep 17 00:00:00 2001 From: Goooler Date: Sat, 25 Feb 2023 23:32:05 +0800 Subject: [PATCH 34/43] Support config cache --- build.gradle | 8 ++- src/docs/configuration/relocation/README.md | 11 ++-- src/docs/plugins/README.md | 8 ++- .../plugins/shadow/PluginShadowPlugin.groovy | 24 --------- .../shadow/internal/RelocationUtil.groovy | 25 +++++++++ .../tasks/ConfigureShadowRelocation.groovy | 51 ------------------- .../plugins/shadow/tasks/ShadowJar.java | 24 ++++++++- .../ConfigureShadowRelocationSpec.groovy | 7 +-- 8 files changed, 60 insertions(+), 98 deletions(-) delete mode 100644 src/main/groovy/com/github/jengelman/gradle/plugins/shadow/PluginShadowPlugin.groovy create mode 100644 src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/RelocationUtil.groovy delete mode 100644 src/main/groovy/com/github/jengelman/gradle/plugins/shadow/tasks/ConfigureShadowRelocation.groovy diff --git a/build.gradle b/build.gradle index 492c6998f..b98d8a9b0 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ import com.github.jengelman.gradle.plugins.shadow.ShadowPlugin -import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar plugins { id 'groovy' @@ -87,8 +87,6 @@ tasks.withType(GroovyCompile).configureEach { } } -tasks.register('relocateShadowJar', ConfigureShadowRelocation) { - target = tasks.shadowJar +tasks.named('shadowJar', ShadowJar) { + enableRelocation true } - -tasks.named('shadowJar') { dependsOn tasks.relocateShadowJar } diff --git a/src/docs/configuration/relocation/README.md b/src/docs/configuration/relocation/README.md index 0bce9ae22..f4835602c 100644 --- a/src/docs/configuration/relocation/README.md +++ b/src/docs/configuration/relocation/README.md @@ -72,15 +72,12 @@ dependency so the tasks execute in the correct order. ```groovy // Configure Auto Relocation -import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation - -task relocateShadowJar(type: ConfigureShadowRelocation) { - target = tasks.shadowJar - prefix = "myapp" // Default value is "shadow" +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +tasks.named('shadowJar', ShadowJar) { + enableRelocation true + relocationPrefix "myapp" } - -tasks.shadowJar.dependsOn tasks.relocateShadowJar ``` > Configuring package auto relocation can add significant time to the shadow process as it will process all dependencies diff --git a/src/docs/plugins/README.md b/src/docs/plugins/README.md index 42120c463..4f3ca3fcb 100644 --- a/src/docs/plugins/README.md +++ b/src/docs/plugins/README.md @@ -19,7 +19,7 @@ A simple Gradle plugin can use this feature by applying the `shadow` plugin and to execute before the `shadowJar` tasks: ```groovy no-plugins -import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar plugins { id 'com.github.johnrengelman.shadow' version '@version@' @@ -38,11 +38,9 @@ dependencies { implementation 'org.codehaus.plexus:plexus-utils:2.0.6' } -task relocateShadowJar(type: ConfigureShadowRelocation) { - target = tasks.shadowJar +tasks.named('shadowJar', ShadowJar) { + enableRelocation true } - -tasks.shadowJar.dependsOn tasks.relocateShadowJar ``` Note that the `localGroovy()` and `gradleApi()` dependencies are added to the `shadow` configuration instead of the diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/PluginShadowPlugin.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/PluginShadowPlugin.groovy deleted file mode 100644 index 4ccef51d7..000000000 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/PluginShadowPlugin.groovy +++ /dev/null @@ -1,24 +0,0 @@ -package com.github.jengelman.gradle.plugins.shadow - -import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation -import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar -import org.gradle.api.Plugin -import org.gradle.api.Project - -class PluginShadowPlugin implements Plugin { - - @Override - void apply(Project project) { - project.plugins.apply(ShadowPlugin) - - project.tasks.withType(ShadowJar).configureEach { ShadowJar task -> - if (task.name == ShadowJavaPlugin.SHADOW_JAR_TASK_NAME) { - project.tasks.register(ConfigureShadowRelocation.taskName(task), ConfigureShadowRelocation) { relocate -> - relocate.target = (ShadowJar) task - - task.dependsOn relocate - } - } - } - } -} diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/RelocationUtil.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/RelocationUtil.groovy new file mode 100644 index 000000000..f94ab89ed --- /dev/null +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/RelocationUtil.groovy @@ -0,0 +1,25 @@ +package com.github.jengelman.gradle.plugins.shadow.internal + +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import java.util.jar.JarFile + +class RelocationUtil { + + static void configureRelocation(ShadowJar target, String prefix) { + def packages = [] as Set + target.configurations.each { configuration -> + configuration.files.each { jar -> + JarFile jf = new JarFile(jar) + jf.entries().each { entry -> + if (entry.name.endsWith(".class") && entry.name != "module-info.class") { + packages << entry.name[0..entry.name.lastIndexOf('/') - 1].replaceAll('/', '.') + } + } + jf.close() + } + } + packages.each { + target.relocate(it, "${prefix}.${it}") + } + } +} diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/tasks/ConfigureShadowRelocation.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/tasks/ConfigureShadowRelocation.groovy deleted file mode 100644 index 674cd9954..000000000 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/tasks/ConfigureShadowRelocation.groovy +++ /dev/null @@ -1,51 +0,0 @@ -package com.github.jengelman.gradle.plugins.shadow.tasks - -import org.gradle.api.DefaultTask -import org.gradle.api.Task -import org.gradle.api.artifacts.Configuration -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.InputFiles -import org.gradle.api.tasks.Optional -import org.gradle.api.tasks.TaskAction - -import java.util.jar.JarFile - - -class ConfigureShadowRelocation extends DefaultTask { - - @Input - ShadowJar target - - @Input - String prefix = "shadow" - - @InputFiles @Optional - List getConfigurations() { - return target.configurations - } - - @TaskAction - void configureRelocation() { - def packages = [] as Set - configurations.each { configuration -> - configuration.files.each { jar -> - JarFile jf = new JarFile(jar) - jf.entries().each { entry -> - if (entry.name.endsWith(".class") && entry.name != "module-info.class") { - packages << entry.name[0..entry.name.lastIndexOf('/')-1].replaceAll('/', '.') - } - } - jf.close() - } - } - packages.each { - target.relocate(it, "${prefix}.${it}") - } - - } - - static String taskName(Task task) { - return "configureRelocation${task.name.capitalize()}" - } - -} diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar.java b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar.java index 2f32f1672..9dc21742d 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar.java +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar.java @@ -31,7 +31,8 @@ public class ShadowJar extends Jar implements ShadowSpec { private List relocators; private List configurations; private transient DependencyFilter dependencyFilter; - + private boolean enableRelocation; + private String relocationPrefix = "shadow"; private boolean minimizeJar; private final transient DependencyFilter dependencyFilterForMinimize; private FileCollection toMinimize; @@ -153,6 +154,9 @@ protected ZipCompressor getInternalCompressor() { @TaskAction protected void copy() { + if (enableRelocation) { + RelocationUtil.configureRelocation(this, relocationPrefix); + } from(getIncludedDependencies()); super.copy(); getLogger().info(shadowStats.toString()); @@ -408,4 +412,22 @@ public DependencyFilter getDependencyFilter() { public void setDependencyFilter(DependencyFilter filter) { this.dependencyFilter = filter; } + + @Input + public boolean isEnableRelocation() { + return enableRelocation; + } + + public void setEnableRelocation(boolean enableRelocation) { + this.enableRelocation = enableRelocation; + } + + @Input + public String getRelocationPrefix() { + return relocationPrefix; + } + + public void setRelocationPrefix(String relocationPrefix) { + this.relocationPrefix = relocationPrefix; + } } diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/ConfigureShadowRelocationSpec.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/ConfigureShadowRelocationSpec.groovy index 9267366a9..bcb1a6981 100644 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/ConfigureShadowRelocationSpec.groovy +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/ConfigureShadowRelocationSpec.groovy @@ -8,13 +8,10 @@ class ConfigureShadowRelocationSpec extends PluginSpecification { def "auto relocate plugin dependencies"() { given: buildFile << """ - - task relocateShadowJar(type: com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation) { - target = tasks.shadowJar + tasks.named('shadowJar', com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) { + enableRelocation true } - tasks.shadowJar.dependsOn tasks.relocateShadowJar - dependencies { implementation 'junit:junit:3.8.2' } From 059a64557be87bcbd73f3329364fbe07e3e126f5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 25 Feb 2023 19:43:40 +0000 Subject: [PATCH 35/43] Add renovate.json (cherry picked from commit 06a7775d40529991d03ae2370f3f997d3718b4fa) --- renovate.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 renovate.json diff --git a/renovate.json b/renovate.json new file mode 100644 index 000000000..39a2b6e9a --- /dev/null +++ b/renovate.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:base" + ] +} From 2242e7cd0dafb2c527049549fc542e81ca993a93 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 25 Feb 2023 19:45:07 +0000 Subject: [PATCH 36/43] fix(deps): update dependency org.apache.ant:ant to v1.10.13 (cherry picked from commit 85af67314f65aa2ba7dd9df7e81d6954e4b3d0da) --- gradle/dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index be08708bd..fc285a209 100644 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -8,7 +8,7 @@ dependencies { implementation 'org.ow2.asm:asm:9.4' implementation 'org.ow2.asm:asm-commons:9.4' implementation 'commons-io:commons-io:2.11.0' - implementation 'org.apache.ant:ant:1.10.12' + implementation 'org.apache.ant:ant:1.10.13' implementation 'org.codehaus.plexus:plexus-utils:3.4.2' implementation "org.apache.logging.log4j:log4j-core:2.18.0" implementation('org.vafer:jdependency:2.8.0') { From 266548656f96c0fc1b2886e270a107104b573c6d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 25 Feb 2023 19:45:12 +0000 Subject: [PATCH 37/43] fix(deps): update junit5 monorepo to v5.9.2 (cherry picked from commit 7e3f08d0bf64997db7e935a7d71a8febaa344647) --- gradle/dependencies.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index fc285a209..5e2c45e3a 100644 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -22,6 +22,6 @@ dependencies { testImplementation 'xmlunit:xmlunit:1.6' testImplementation 'org.apache.commons:commons-lang3:3.12.0' testImplementation 'com.google.guava:guava:31.1-jre' - testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.0' - testRuntimeOnly 'org.junit.vintage:junit-vintage-engine:5.9.0' + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.2' + testRuntimeOnly 'org.junit.vintage:junit-vintage-engine:5.9.2' } From 602109256755007d7ade6f1628cf2eb9ca80a1a5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 25 Feb 2023 20:58:52 +0000 Subject: [PATCH 38/43] fix(deps): update dependency org.codehaus.plexus:plexus-utils to v3.5.0 (cherry picked from commit 55b1064c008e7ae84f6c0ae99d06b40514da9eb4) --- gradle/dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index 5e2c45e3a..e6e1a28d5 100644 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -9,7 +9,7 @@ dependencies { implementation 'org.ow2.asm:asm-commons:9.4' implementation 'commons-io:commons-io:2.11.0' implementation 'org.apache.ant:ant:1.10.13' - implementation 'org.codehaus.plexus:plexus-utils:3.4.2' + implementation 'org.codehaus.plexus:plexus-utils:3.5.0' implementation "org.apache.logging.log4j:log4j-core:2.18.0" implementation('org.vafer:jdependency:2.8.0') { exclude group: 'org.ow2.asm' From 23b61afb595d917d3475cb8dedc7a84ff22b1b9e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 25 Feb 2023 20:59:02 +0000 Subject: [PATCH 39/43] chore(deps): update actions/checkout action to v3 (cherry picked from commit 71f93255f065011c534cfeec62e799ab7be8fe3d) --- .github/workflows/gradle-wrapper-validation.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index 405a2b306..8bfd0dcf5 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -6,5 +6,5 @@ jobs: name: "Validation" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: gradle/wrapper-validation-action@v1 From 7fa6c72a0b579e0e34b46219b7a4580a160c5350 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 26 Feb 2023 05:12:51 +0800 Subject: [PATCH 40/43] fix(deps): update spock monorepo to v2.3-groovy-3.0 (cherry picked from commit eb1970750a1b12c2c66d81500d98119539c51458) --- gradle/dependencies.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index e6e1a28d5..ba48d5da1 100644 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -15,10 +15,10 @@ dependencies { exclude group: 'org.ow2.asm' } - testImplementation('org.spockframework:spock-core:2.1-groovy-3.0') { + testImplementation('org.spockframework:spock-core:2.3-groovy-3.0') { exclude group: 'org.codehaus.groovy' } - testImplementation 'org.spockframework:spock-junit4:2.1-groovy-3.0' + testImplementation 'org.spockframework:spock-junit4:2.3-groovy-3.0' testImplementation 'xmlunit:xmlunit:1.6' testImplementation 'org.apache.commons:commons-lang3:3.12.0' testImplementation 'com.google.guava:guava:31.1-jre' From a518bfdad5ca368d47c1c2e0c5d3d94539df1817 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 25 Feb 2023 21:06:27 +0000 Subject: [PATCH 41/43] fix(deps): update dependency org.apache.logging.log4j:log4j-core to v2.20.0 (cherry picked from commit 34c6b759236708b6d1628ec4d7c12ada30cad779) --- gradle/dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index ba48d5da1..46d57b906 100644 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -10,7 +10,7 @@ dependencies { implementation 'commons-io:commons-io:2.11.0' implementation 'org.apache.ant:ant:1.10.13' implementation 'org.codehaus.plexus:plexus-utils:3.5.0' - implementation "org.apache.logging.log4j:log4j-core:2.18.0" + implementation "org.apache.logging.log4j:log4j-core:2.20.0" implementation('org.vafer:jdependency:2.8.0') { exclude group: 'org.ow2.asm' } From 7d654e4de15fec41eb8030651cca4d0c3263abdf Mon Sep 17 00:00:00 2001 From: Goooler Date: Sun, 26 Feb 2023 05:16:31 +0800 Subject: [PATCH 42/43] Trigger gradle/wrapper-validation-action after related files changed --- .github/workflows/gradle-wrapper-validation.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index 8bfd0dcf5..e18701c6e 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -1,5 +1,15 @@ name: "Validate Gradle Wrapper" -on: [push, pull_request] +on: + push: + paths: + - 'gradlew' + - 'gradlew.bat' + - 'gradle/wrapper/' + pull_request: + paths: + - 'gradlew' + - 'gradlew.bat' + - 'gradle/wrapper/' jobs: validation: From 98e666dbf97c099acbb01c59681574b53a33e877 Mon Sep 17 00:00:00 2001 From: John Engelman Date: Sun, 26 Feb 2023 16:28:01 -0600 Subject: [PATCH 43/43] chore: add site link for 8.1.0 --- src/docs/changes/README.md | 360 ++++++++++++++++++++----------------- 1 file changed, 191 insertions(+), 169 deletions(-) diff --git a/src/docs/changes/README.md b/src/docs/changes/README.md index a0a8d18d7..971ab3fe5 100644 --- a/src/docs/changes/README.md +++ b/src/docs/changes/README.md @@ -1,34 +1,45 @@ # Change Log + +## v8.1.0 (2023-02-26) + +[Release Notes](https://github.com/johnrengelman/shadow/releases/tag/8.1.0) + ## v8.0.0 (2023-02-24) [Release Notes](https://github.com/johnrengelman/shadow/releases/tag/8.0.0) ## v7.1.3 (unreleased) -* The GroovyExtensionModuleTransformer now also works for Groovy 2.5+. + +- The GroovyExtensionModuleTransformer now also works for Groovy 2.5+. ## v7.1.2 (2021-12-28) -* Upgrade log4j to 2.17.1 due to CVE-2021-45105 and CVE-2021-44832 + +- Upgrade log4j to 2.17.1 due to CVE-2021-45105 and CVE-2021-44832 ## v7.1.1 (2021-12-14) -* Upgrade log4j to 2.16.0 due to CVE-2021-44228 and CVE-2021-45046 + +- Upgrade log4j to 2.16.0 due to CVE-2021-44228 and CVE-2021-45046 ## v7.1.0 (2021-10-04) -* **BREAKING** - The maven coordinates for the plugins have changed as of this version. The proper `group:artifact` is `gradle.plugin.com.github.johnrengelman:shadow` -* [Jeff](https://github.com/mathjeff) - Fix `shadowJar` Out-Of-Date with configuration caching [#708](https://github.com/johnrengelman/shadow/pull/708) -* [Fiouz](https://github.com/Fiouz) - Better support for statically typed languages. This change may require code changes if you are utilizing the Groovy generated getters for properties in some Shadow transformers [#706](https://github.com/johnrengelman/shadow/pull/706) -* [Helder Pereira](https://github.com/helfper) - Various cleanups [#672](https://github.com/johnrengelman/shadow/pull/672), [#700](https://github.com/johnrengelman/shadow/pull/700), [#701](https://github.com/johnrengelman/shadow/pull/701), [#702](https://github.com/johnrengelman/shadow/pull/702) -* [Roberto Perez Alcolea](https://github.com/rpalcolea) - Support JVM Toolchains [#691](https://github.com/johnrengelman/shadow/pull/691) -* [mjulianotq](https://github.com/mjulianotq) - Fix `Project.afterEvaluate` conflicts [#675](https://github.com/johnrengelman/shadow/pull/675) -* [Ilya Muradyan](https://github.com/ileasile) - Fix relocation for `ComponentsXmlResourceTransformer` [#678](https://github.com/johnrengelman/shadow/pull/678) -* [Vaidotas Valuckas](https://github.com/rieske) - Fix `JavaExec.main` deprecation [#686](https://github.com/johnrengelman/shadow/pull/686) -* [Dmitry Vyazelenko](https://github.com/vyazelenko) - Support Java 18 with ASM 9.2 [#698](https://github.com/johnrengelman/shadow/pull/698) -* [Jason](https://github.com/jpenilla) - Support Records with JDependency 2.7.0 [#681](https://github.com/johnrengelman/shadow/pull/681) + +- **BREAKING** - The maven coordinates for the plugins have changed as of this version. The proper `group:artifact` is `gradle.plugin.com.github.johnrengelman:shadow` +- [Jeff](https://github.com/mathjeff) - Fix `shadowJar` Out-Of-Date with configuration caching [#708](https://github.com/johnrengelman/shadow/pull/708) +- [Fiouz](https://github.com/Fiouz) - Better support for statically typed languages. This change may require code changes if you are utilizing the Groovy generated getters for properties in some Shadow transformers [#706](https://github.com/johnrengelman/shadow/pull/706) +- [Helder Pereira](https://github.com/helfper) - Various cleanups [#672](https://github.com/johnrengelman/shadow/pull/672), [#700](https://github.com/johnrengelman/shadow/pull/700), [#701](https://github.com/johnrengelman/shadow/pull/701), [#702](https://github.com/johnrengelman/shadow/pull/702) +- [Roberto Perez Alcolea](https://github.com/rpalcolea) - Support JVM Toolchains [#691](https://github.com/johnrengelman/shadow/pull/691) +- [mjulianotq](https://github.com/mjulianotq) - Fix `Project.afterEvaluate` conflicts [#675](https://github.com/johnrengelman/shadow/pull/675) +- [Ilya Muradyan](https://github.com/ileasile) - Fix relocation for `ComponentsXmlResourceTransformer` [#678](https://github.com/johnrengelman/shadow/pull/678) +- [Vaidotas Valuckas](https://github.com/rieske) - Fix `JavaExec.main` deprecation [#686](https://github.com/johnrengelman/shadow/pull/686) +- [Dmitry Vyazelenko](https://github.com/vyazelenko) - Support Java 18 with ASM 9.2 [#698](https://github.com/johnrengelman/shadow/pull/698) +- [Jason](https://github.com/jpenilla) - Support Records with JDependency 2.7.0 [#681](https://github.com/johnrengelman/shadow/pull/681) ## v7.0.0 (2021-04-26) -* Required Gradle 7.0+ -* Support for Java 16 -* Removes JCenter references -* **Breaking Change!** - The maven group coordinate has changed to be `gradle.plugin.com.github.jengelman.gradle.plugins`. Users explicitly declaring the buildscript classpath will need to update their configuration. + +- Required Gradle 7.0+ +- Support for Java 16 +- Removes JCenter references +- **Breaking Change!** - The maven group coordinate has changed to be `gradle.plugin.com.github.jengelman.gradle.plugins`. Users explicitly declaring the buildscript classpath will need to update their configuration. + ``` buildscript { repositories { @@ -43,263 +54,274 @@ apply plugin: "com.github.johnrengelman.shadow" ``` -* [Cédric Champeau](https://github.com/melix) - Support Gradle 7 [#624](https://github.com/johnrengelman/shadow/pull/624) -* [Daniel Oakey](https://github.com/danieloakey) - Close `FileInputStream` when remapping close to avoid classloader locks [#642](https://github.com/johnrengelman/shadow/pull/642) -* [Maximilian Müller](https://github.com/maxm123) - Groovy error in `ServiceFileTransformer` in Gradle 3 [#655](https://github.com/johnrengelman/shadow/pull/655) -* [Helder Pereira](https://github.com/helfper) - Fix deprecations errors in transformers and add CI testing around future deprecations [#647](https://github.com/johnrengelman/shadow/pull/647) -* [Nicolas Humblot](https://github.com/nhumblot) - Handle deprecation of `mainClassName` configuration [#609](https://github.com/johnrengelman/shadow/pull/609), [#612](https://github.com/johnrengelman/shadow/pull/612) -* [Bernie Schelberg](https://github.com/bschelberg) - Exclude `api` and `implementations` from legacy `maven` POM [#615](https://github.com/johnrengelman/shadow/pull/615) + +- [Cédric Champeau](https://github.com/melix) - Support Gradle 7 [#624](https://github.com/johnrengelman/shadow/pull/624) +- [Daniel Oakey](https://github.com/danieloakey) - Close `FileInputStream` when remapping close to avoid classloader locks [#642](https://github.com/johnrengelman/shadow/pull/642) +- [Maximilian Müller](https://github.com/maxm123) - Groovy error in `ServiceFileTransformer` in Gradle 3 [#655](https://github.com/johnrengelman/shadow/pull/655) +- [Helder Pereira](https://github.com/helfper) - Fix deprecations errors in transformers and add CI testing around future deprecations [#647](https://github.com/johnrengelman/shadow/pull/647) +- [Nicolas Humblot](https://github.com/nhumblot) - Handle deprecation of `mainClassName` configuration [#609](https://github.com/johnrengelman/shadow/pull/609), [#612](https://github.com/johnrengelman/shadow/pull/612) +- [Bernie Schelberg](https://github.com/bschelberg) - Exclude `api` and `implementations` from legacy `maven` POM [#615](https://github.com/johnrengelman/shadow/pull/615) ## v6.1.0 (2020-10-05) -* As of this version, Shadow is compiled with Java 8 source and target compatibility. This aligns the plugin with the minimum required Java version + +- As of this version, Shadow is compiled with Java 8 source and target compatibility. This aligns the plugin with the minimum required Java version for Gradle 6.0 (https://docs.gradle.org/6.0/release-notes.html). -* Update ASM to 9.0 to support JDK 16. -* [Tim Yates](https://github.com/timyates), [Benedikt Ritter](https://github.com/britter) - Enable Configuration Caching for Gradle 6.6+ [#591](https://github.com/johnrengelman/shadow/pull/591) -* [Caleb Larsen](https://github.com/MuffinTheMan) - doc updates [#583](https://github.com/johnrengelman/shadow/pull/593) -* [Schalk W. Cronjé](https://github.com/ysb33r) - log4j version update for CVE-2020-9488 [#590](https://github.com/johnrengelman/shadow/pull/590) -* [Victor Tso](https://github.com/roxchkplusony) - Input stream handling for large projects [#587](https://github.com/johnrengelman/shadow/pull/587) -* [Matthew Haughton](https://github.com/3flex) - Implement Task Configuration Avoidance pattern [#597](https://github.com/johnrengelman/shadow/pull/597) +- Update ASM to 9.0 to support JDK 16. +- [Tim Yates](https://github.com/timyates), [Benedikt Ritter](https://github.com/britter) - Enable Configuration Caching for Gradle 6.6+ [#591](https://github.com/johnrengelman/shadow/pull/591) +- [Caleb Larsen](https://github.com/MuffinTheMan) - doc updates [#583](https://github.com/johnrengelman/shadow/pull/593) +- [Schalk W. Cronjé](https://github.com/ysb33r) - log4j version update for CVE-2020-9488 [#590](https://github.com/johnrengelman/shadow/pull/590) +- [Victor Tso](https://github.com/roxchkplusony) - Input stream handling for large projects [#587](https://github.com/johnrengelman/shadow/pull/587) +- [Matthew Haughton](https://github.com/3flex) - Implement Task Configuration Avoidance pattern [#597](https://github.com/johnrengelman/shadow/pull/597) ## v6.0.0 (2020-06-15) -* Required Gradle 6.0+ -* *NEW*: Support for Gradle Metadata publication via the `shadowRuntimeElements` configuration. This is a _beta_ feature + +- Required Gradle 6.0+ +- _NEW_: Support for Gradle Metadata publication via the `shadowRuntimeElements` configuration. This is a _beta_ feature the hasn't been tested extensively. Feedback is appreciated. -* Fix Gradle 7 deprecation warnings [#530](https://github.com/johnrengelman/shadow/issues/530) -* Fix to generated start script to correctly use `optsEnvironmentVar`[#518](https://github.com/johnrengelman/shadow/commit/7e99c02957773205c3babdd23f4bbf883330c975) -* [Yahor Berdnikau](https://github.com/Tapchicoma) - Fix issues with Gradle API being embedded into published JAR [#527](https://github.com/johnrengelman/shadow/issues/527) -* [Dmitry Vyazelenko](https://github.com/vyazelenko) - ASM updates to support latest Java versions [#549](https://github.com/johnrengelman/shadow/pull/549) -* [ejjcase](https://github.com/ejjcase) - Support exposing shadowed project dependencies via POM [#543](https://github.com/johnrengelman/shadow/pull/543) -* [Artem Chubaryan](https://github.com/Armaxis) - Performance optimizations [#535](https://github.com/johnrengelman/shadow/pull/535) -* [Trask Stalnaker](https://github.com/trask) - Fix exclude patterns on Windows [#539](https://github.com/johnrengelman/shadow/pull/539) -* [Artem Chubaryan](https://github.com/Armaxis) - Allow usage of true regex patterns for include/exclude by the `%regex[]` syntax [#536](https://github.com/johnrengelman/shadow/pull/536) +- Fix Gradle 7 deprecation warnings [#530](https://github.com/johnrengelman/shadow/issues/530) +- Fix to generated start script to correctly use `optsEnvironmentVar`[#518](https://github.com/johnrengelman/shadow/commit/7e99c02957773205c3babdd23f4bbf883330c975) +- [Yahor Berdnikau](https://github.com/Tapchicoma) - Fix issues with Gradle API being embedded into published JAR [#527](https://github.com/johnrengelman/shadow/issues/527) +- [Dmitry Vyazelenko](https://github.com/vyazelenko) - ASM updates to support latest Java versions [#549](https://github.com/johnrengelman/shadow/pull/549) +- [ejjcase](https://github.com/ejjcase) - Support exposing shadowed project dependencies via POM [#543](https://github.com/johnrengelman/shadow/pull/543) +- [Artem Chubaryan](https://github.com/Armaxis) - Performance optimizations [#535](https://github.com/johnrengelman/shadow/pull/535) +- [Trask Stalnaker](https://github.com/trask) - Fix exclude patterns on Windows [#539](https://github.com/johnrengelman/shadow/pull/539) +- [Artem Chubaryan](https://github.com/Armaxis) - Allow usage of true regex patterns for include/exclude by the `%regex[]` syntax [#536](https://github.com/johnrengelman/shadow/pull/536) ## v5.2.0 (2019-11-10) -* [Inez Korczyński](https://github.com/inez) - Performance optimization when evaluating relocation paths [#507](https://github.com/johnrengelman/shadow/pull/507) -* [Jeff Adler](https://github.com/jeffalder) - Fix remapping issues with multi release JARS [#526](https://github.com/johnrengelman/shadow/pull/526) -* [Gary Hale](https://github.com/ghale) - Implement support for Gradle build cache [#524](https://github.com/johnrengelman/shadow/pull/524) -* [Roberto Perez Alcolea](https://github.com/rpalcolea) - Gradle 6.x support [#517](https://github.com/johnrengelman/shadow/pull/517) -* [Konstantin Gribov](https://github.com/grossws) - Return support for 5.0 for convention mapping [#502](https://github.com/johnrengelman/shadow/pull/502) -* [Lai Jiang](https://github.com/jianglai) - Documentation updates on how to reconfigure `classifier` and `version` [#512](https://github.com/johnrengelman/shadow/pull/512) + +- [Inez Korczyński](https://github.com/inez) - Performance optimization when evaluating relocation paths [#507](https://github.com/johnrengelman/shadow/pull/507) +- [Jeff Adler](https://github.com/jeffalder) - Fix remapping issues with multi release JARS [#526](https://github.com/johnrengelman/shadow/pull/526) +- [Gary Hale](https://github.com/ghale) - Implement support for Gradle build cache [#524](https://github.com/johnrengelman/shadow/pull/524) +- [Roberto Perez Alcolea](https://github.com/rpalcolea) - Gradle 6.x support [#517](https://github.com/johnrengelman/shadow/pull/517) +- [Konstantin Gribov](https://github.com/grossws) - Return support for 5.0 for convention mapping [#502](https://github.com/johnrengelman/shadow/pull/502) +- [Lai Jiang](https://github.com/jianglai) - Documentation updates on how to reconfigure `classifier` and `version` [#512](https://github.com/johnrengelman/shadow/pull/512) ## v5.1.0 (2019-06-29) -* [Chris Rankin](https://github.com/chrisr3) - Add `ManifestAppenderTransformer` to support appending to Jar manifest [#474](https://github.com/johnrengelman/shadow/pull/474) -* [Min-Ken Lai](https://github.com/minkenlai) - Additional escaping fixes in start script [#487](https://github.com/johnrengelman/shadow/pull/487) -* [Alan D. Cabrera](https://github.com/maguro) - Automatically remove `gradleApi` from `compile` scope in the presence of `shadow` [#459](https://github.com/johnrengelman/shadow/pull/459) -* [Christian Stein](https://github.com/sormuras) - Do not initialize `UnusedTracker` when not requested [#480](https://github.com/johnrengelman/shadow/pull/480), [#479](https://github.com/johnrengelman/shadow/issues/479) -* [Attila Kelemen](https://github.com/kelemen) - Fix `NullPointerException` when using java minimization and api project dependency with version [#477](https://github.com/johnrengelman/shadow/pull/477) + +- [Chris Rankin](https://github.com/chrisr3) - Add `ManifestAppenderTransformer` to support appending to Jar manifest [#474](https://github.com/johnrengelman/shadow/pull/474) +- [Min-Ken Lai](https://github.com/minkenlai) - Additional escaping fixes in start script [#487](https://github.com/johnrengelman/shadow/pull/487) +- [Alan D. Cabrera](https://github.com/maguro) - Automatically remove `gradleApi` from `compile` scope in the presence of `shadow` [#459](https://github.com/johnrengelman/shadow/pull/459) +- [Christian Stein](https://github.com/sormuras) - Do not initialize `UnusedTracker` when not requested [#480](https://github.com/johnrengelman/shadow/pull/480), [#479](https://github.com/johnrengelman/shadow/issues/479) +- [Attila Kelemen](https://github.com/kelemen) - Fix `NullPointerException` when using java minimization and api project dependency with version [#477](https://github.com/johnrengelman/shadow/pull/477) ## v5.0.0 (2019-02-28) -* Require Gradle 5.0+ -* Fix issue with build classifier `-all` being dropped in Gradle 5.1+ -* [Roberto Perez Alcolea](https://github.com/rpalcolea) - Exclude project dependencies from minimization [#420](https://github.com/johnrengelman/shadow/pull/420) -* [Matt King](https://github.com/kyrrigle), [Richard Marbach](https://github.com/RichardMarbach) - Fix escaping in start script [#453](https://github.com/johnrengelman/shadow/pull/454), [#455](https://github.com/johnrengelman/shadow/pull/455) -* [Dennis Schumann](https://github.com/Hillkorn) - Fix Gradle 5.2 incompatibility with `ShadowJar.getMetaClass()` [#456](https://github.com/johnrengelman/shadow/pull/456) -* [Brane F. Gračnar](https://github.com/bfg) - Fix compatibility with `com.palantir.docker` [#460](https://github.com/johnrengelman/shadow/pull/460) + +- Require Gradle 5.0+ +- Fix issue with build classifier `-all` being dropped in Gradle 5.1+ +- [Roberto Perez Alcolea](https://github.com/rpalcolea) - Exclude project dependencies from minimization [#420](https://github.com/johnrengelman/shadow/pull/420) +- [Matt King](https://github.com/kyrrigle), [Richard Marbach](https://github.com/RichardMarbach) - Fix escaping in start script [#453](https://github.com/johnrengelman/shadow/pull/454), [#455](https://github.com/johnrengelman/shadow/pull/455) +- [Dennis Schumann](https://github.com/Hillkorn) - Fix Gradle 5.2 incompatibility with `ShadowJar.getMetaClass()` [#456](https://github.com/johnrengelman/shadow/pull/456) +- [Brane F. Gračnar](https://github.com/bfg) - Fix compatibility with `com.palantir.docker` [#460](https://github.com/johnrengelman/shadow/pull/460) ## v4.0.4 (2019-01-19) -* When using `shadow`, `application`, and `maven` plugins together, remove `shadowDistZip` and `shadowDistTar` from + +- When using `shadow`, `application`, and `maven` plugins together, remove `shadowDistZip` and `shadowDistTar` from `configurations.archives` so they are not published or installed by default with the `uploadArchives` or `install` - tasks. [#347](https://github.com/johnrengelman/shadow/issues/347) -* [James Nelson](https://github.com/JamesXNelson) - Fix `null` path when using Jar minimization and Gradle's `api` configuration. [#424](https://github.com/johnrengelman/shadow/issues/424), [#425](https://github.com/johnrengelman/shadow/issues/425) - + tasks. [#347](https://github.com/johnrengelman/shadow/issues/347) +- [James Nelson](https://github.com/JamesXNelson) - Fix `null` path when using Jar minimization and Gradle's `api` configuration. [#424](https://github.com/johnrengelman/shadow/issues/424), [#425](https://github.com/johnrengelman/shadow/issues/425) + ## v4.0.3 (2018-11-21) -* [Mark Vieira](https://github.com/mark-vieira) - Don't leak plugin classes to Gradle's Spec cache [#430](https://github.com/johnrengelman/shadow/pull/430) + +- [Mark Vieira](https://github.com/mark-vieira) - Don't leak plugin classes to Gradle's Spec cache [#430](https://github.com/johnrengelman/shadow/pull/430) ## v4.0.2 (2018-10-27) -* [Petar Petrov](https://github.com/petarov) - Update to ASM 7.0-beta and jdependency 2.1.1 to support Java 11, [#415](https://github.com/johnrengelman/shadow/pull/415) -* [Victor Tso](https://github.com/roxchkplusony) - Ensure input streams are closed, [#411](https://github.com/johnrengelman/shadow/pull/411) -* [Osip Fatkullin](https://github.com/osipxd) - Exclude `api` configuration from minimization, [#405](https://github.com/johnrengelman/shadow/pull/405) + +- [Petar Petrov](https://github.com/petarov) - Update to ASM 7.0-beta and jdependency 2.1.1 to support Java 11, [#415](https://github.com/johnrengelman/shadow/pull/415) +- [Victor Tso](https://github.com/roxchkplusony) - Ensure input streams are closed, [#411](https://github.com/johnrengelman/shadow/pull/411) +- [Osip Fatkullin](https://github.com/osipxd) - Exclude `api` configuration from minimization, [#405](https://github.com/johnrengelman/shadow/pull/405) ## v4.0.1 (2018-09-30) -* **Breaking Change!** `Transform.modifyOutputStream(ZipOutputStream os)` to `Transform.modifyOutputStream(ZipOutputStream jos, boolean preserveFileTimestamps)`. + +- **Breaking Change!** `Transform.modifyOutputStream(ZipOutputStream os)` to `Transform.modifyOutputStream(ZipOutputStream jos, boolean preserveFileTimestamps)`. Typically breaking changes are reserved for major version releases, but this change was necessary for `preserverFileTimestamps` (introduced in v4.0.0) to work correctly in the presence of transformers, [#404](https://github.com/johnrengelman/shadow/issues/404) -* Fix regression in support Java 10+ during relocation, [#403](https://github.com/johnrengelman/shadow/issues/403) +- Fix regression in support Java 10+ during relocation, [#403](https://github.com/johnrengelman/shadow/issues/403) ## v4.0.0 (2018-09-25) -* **Breaking Change!** Restrict Plugin to Gradle 4.0+. Shadow major versions will align with Gradle major versions going forward. -* **Breaking Change!** For clarity purposes `com.github.johnrengelman.plugin-shadow` has been removed. If you intend to use this feature, you will need to declare your own `ConfigureShadowRelocation` task. See section [2.9.2](http://imperceptiblethoughts.com/shadow/#automatically_relocating_dependencies) of the User Guide -* [Sergey Tselovalnikov](https://github.com/SerCeMan) - Upgrade to ASM 6.2.1 to support Java 11 -* [Chris Cowan](https://github.com/Macil) - Add support for `shadowJar.preserveFileTimestamps` property. See [Jar.preserveFileTimestamps](https://docs.gradle.org/current/dsl/org.gradle.api.tasks.bundling.Jar.html#org.gradle.api.tasks.bundling.Jar:preserveFileTimestamps) -* [Paul N. Baker](https://github.com/paul-nelson-baker) - Add `Log4j2PluginsCacheFileTransformer` to process Log4j DAT files during merge. -* [Felipe Lima](https://github.com/felipecsl) - Fix the long standing "No property `mainClassName`" issue. -* [debanne](https://github.com/debanne) - Implement JAR minimization actions. This will attempt to exclude unused classes in your shadowed JAR. -* Configure exclusion of `module-info.class` from `shadowJar` when using the Shadow the Java plugin, [#352](https://github.com/johnrengelman/shadow/issues/352) +- **Breaking Change!** Restrict Plugin to Gradle 4.0+. Shadow major versions will align with Gradle major versions going forward. +- **Breaking Change!** For clarity purposes `com.github.johnrengelman.plugin-shadow` has been removed. If you intend to use this feature, you will need to declare your own `ConfigureShadowRelocation` task. See section [2.9.2](http://imperceptiblethoughts.com/shadow/#automatically_relocating_dependencies) of the User Guide +- [Sergey Tselovalnikov](https://github.com/SerCeMan) - Upgrade to ASM 6.2.1 to support Java 11 +- [Chris Cowan](https://github.com/Macil) - Add support for `shadowJar.preserveFileTimestamps` property. See [Jar.preserveFileTimestamps](https://docs.gradle.org/current/dsl/org.gradle.api.tasks.bundling.Jar.html#org.gradle.api.tasks.bundling.Jar:preserveFileTimestamps) +- [Paul N. Baker](https://github.com/paul-nelson-baker) - Add `Log4j2PluginsCacheFileTransformer` to process Log4j DAT files during merge. +- [Felipe Lima](https://github.com/felipecsl) - Fix the long standing "No property `mainClassName`" issue. +- [debanne](https://github.com/debanne) - Implement JAR minimization actions. This will attempt to exclude unused classes in your shadowed JAR. +- Configure exclusion of `module-info.class` from `shadowJar` when using the Shadow the Java plugin, [#352](https://github.com/johnrengelman/shadow/issues/352) ## v2.0.4 (2018-04-27) -* Update to ASM 6.1.1 to address performance issues - [ASM Issue 317816](https://gitlab.ow2.org/asm/asm/issues/317816) -* Close InputStreams after using them, [#364](https://github.com/johnrengelman/shadow/issues/364) -* Remove usage of Gradle internal `AbstractFileCollection`. -* Add task annotations to remove warnings when validating plugin. +- Update to ASM 6.1.1 to address performance issues - [ASM Issue 317816](https://gitlab.ow2.org/asm/asm/issues/317816) +- Close InputStreams after using them, [#364](https://github.com/johnrengelman/shadow/issues/364) +- Remove usage of Gradle internal `AbstractFileCollection`. +- Add task annotations to remove warnings when validating plugin. ## v2.0.3 (2018-03-24) -* [Martin Sadowski](https://github.com/ttsiebzehntt) - Update to ASM 6.1 -* [Scott Newson](https://github.com/sgnewson) - Fix deprecated Gradle warnings, [#356](https://github.com/johnrengelman/shadow/pull/356) +- [Martin Sadowski](https://github.com/ttsiebzehntt) - Update to ASM 6.1 +- [Scott Newson](https://github.com/sgnewson) - Fix deprecated Gradle warnings, [#356](https://github.com/johnrengelman/shadow/pull/356) ## v2.0.2 (2017-12-12) -* [Ben Adazza](https://github.com/ben-adazza), [Tyler Benson](https://github.com/tylerbenson) - documentation -* [Marke Vieira](https://github.com/mark-vieira) - Support multi-project builds with Build-Scan integration -* Upgrade to ASM 6, [#294]https://github.com/johnrengelman/shadow/issues/294, [#303](https://github.com/johnrengelman/shadow/issues/303) -* [Rob Spieldenner](https://github.com/rspieldenner) - Fix integration with `application` plugin in Gradle 4.3, [#339](https://github.com/johnrengelman/shadow/issues/339) -* Fixed deprecation warning from Gradle 4.2+, [#326](https://github.com/johnrengelman/shadow/issues/326) +- [Ben Adazza](https://github.com/ben-adazza), [Tyler Benson](https://github.com/tylerbenson) - documentation +- [Marke Vieira](https://github.com/mark-vieira) - Support multi-project builds with Build-Scan integration +- Upgrade to ASM 6, [#294]https://github.com/johnrengelman/shadow/issues/294, [#303](https://github.com/johnrengelman/shadow/issues/303) +- [Rob Spieldenner](https://github.com/rspieldenner) - Fix integration with `application` plugin in Gradle 4.3, [#339](https://github.com/johnrengelman/shadow/issues/339) +- Fixed deprecation warning from Gradle 4.2+, [#326](https://github.com/johnrengelman/shadow/issues/326) ## v2.0.1 (2017-06-23) -* Fix `null+configuration` error, [#297](https://github.com/johnrengelman/shadow/issues/297) +- Fix `null+configuration` error, [#297](https://github.com/johnrengelman/shadow/issues/297) ## v2.0.0 (2017-05-09) -* **Breaking Change!** Restrict Plugin to Gradle 3.0+ -* **Breaking Change!** Build with Java 7 -* **Breaking Change!** Updated `Transformer` interface to accept `TransformerContext` object instead of individual values -* **Breaking Change!** Updated `Relocator` interface to accept `RelocatePathContext` and `RelocateClassContext` objects -* **Breaking Change!** Distribution tasks `distShadowZip` and `distShadowTar` have been removed and replaced with the standard `shadowDistZip` and `shadowDistTar` from the Gradle Distribution plugin. -* **Breaking Change!** The `installShadowApp` task has been removed and replaced with the standard `installShadowDist` task from the Gradle Distribution plugin. -* **Breaking Change!** The new `installShadowDist` task outputs to `build/install/-shadow` per the standard (formerly was `build/installShadow`) -* **Breaking Change!** `component.shadow` removed in favor of `project.shadow.component(publication)` so as to remove dependency on internal Gradle APIs. -* _NEW_ Introducing `ConfigureShadowRelocation` task and `com.github.johnrengelman.plugin-shadow` plugin to automatically configure package relocation for Gradle plugins. -* _NEW_ Integration with Gradle Build Scans. When running a `ShadowJar` task with Build Scans, custom values including dependencies merged anc package relocations are published in the scan. -* Build Shadow w/ Shadow. This will help prevent any future classpath conflicts with Gradle. -* Replace `startShadowScripts` tasks with Gradle's built-in `CreateStartScripts` type. -* Build with Gradle 3.1 -* [Marc Philipp](https://github.com/marcphilipp) - Add `keyTransformer` property to `PropertiesFileTransformer` -* Update to ASM 5.2 -* [Piotr Kubowicz](https://github.com/pkubowicz) - Support `api`, `implementation`, `runtimeOnly` dependency configurations introdcued in Gradle 3.3 +- **Breaking Change!** Restrict Plugin to Gradle 3.0+ +- **Breaking Change!** Build with Java 7 +- **Breaking Change!** Updated `Transformer` interface to accept `TransformerContext` object instead of individual values +- **Breaking Change!** Updated `Relocator` interface to accept `RelocatePathContext` and `RelocateClassContext` objects +- **Breaking Change!** Distribution tasks `distShadowZip` and `distShadowTar` have been removed and replaced with the standard `shadowDistZip` and `shadowDistTar` from the Gradle Distribution plugin. +- **Breaking Change!** The `installShadowApp` task has been removed and replaced with the standard `installShadowDist` task from the Gradle Distribution plugin. +- **Breaking Change!** The new `installShadowDist` task outputs to `build/install/-shadow` per the standard (formerly was `build/installShadow`) +- **Breaking Change!** `component.shadow` removed in favor of `project.shadow.component(publication)` so as to remove dependency on internal Gradle APIs. +- _NEW_ Introducing `ConfigureShadowRelocation` task and `com.github.johnrengelman.plugin-shadow` plugin to automatically configure package relocation for Gradle plugins. +- _NEW_ Integration with Gradle Build Scans. When running a `ShadowJar` task with Build Scans, custom values including dependencies merged anc package relocations are published in the scan. +- Build Shadow w/ Shadow. This will help prevent any future classpath conflicts with Gradle. +- Replace `startShadowScripts` tasks with Gradle's built-in `CreateStartScripts` type. +- Build with Gradle 3.1 +- [Marc Philipp](https://github.com/marcphilipp) - Add `keyTransformer` property to `PropertiesFileTransformer` +- Update to ASM 5.2 +- [Piotr Kubowicz](https://github.com/pkubowicz) - Support `api`, `implementation`, `runtimeOnly` dependency configurations introdcued in Gradle 3.3 ## v1.2.4 (2016-11-03) -* Don't resolve dependency configurations during config phase, [#128](https://github.com/johnrengelman/shadow/issues/129) -* Build plugin with Gradle 2.14 -* Fix docs regarding inheriting Jar manifest, [#251](https://github.com/johnrengelman/shadow/issues/251) -* [Ethan Hall](https://github.com/ethankhall) - Support projects that configure uploading to Ivy repositories, [#256](https://github.com/johnrengelman/shadow/pull/256) -* Force task to depend on dependency configuration, [#152](https://github.com/johnrengelman/shadow/issues/152) -* Do not explode ZIP files into shadow jar, [#196](https://github.com/johnrengelman/shadow/issues/196) -* [John Szakmeister](https://github.com/jszakmeister) - Preserve timestamps on merged jar entries, [#260](https://github.com/johnrengelman/shadow/pull/260) + +- Don't resolve dependency configurations during config phase, [#128](https://github.com/johnrengelman/shadow/issues/129) +- Build plugin with Gradle 2.14 +- Fix docs regarding inheriting Jar manifest, [#251](https://github.com/johnrengelman/shadow/issues/251) +- [Ethan Hall](https://github.com/ethankhall) - Support projects that configure uploading to Ivy repositories, [#256](https://github.com/johnrengelman/shadow/pull/256) +- Force task to depend on dependency configuration, [#152](https://github.com/johnrengelman/shadow/issues/152) +- Do not explode ZIP files into shadow jar, [#196](https://github.com/johnrengelman/shadow/issues/196) +- [John Szakmeister](https://github.com/jszakmeister) - Preserve timestamps on merged jar entries, [#260](https://github.com/johnrengelman/shadow/pull/260) ## v1.2.3 (2016-01-25) -* Support for Gradle 2.11-rc-1, [#177](https://github.com/johnrengelman/shadow/issues/177) -* Convert internal framework to [Gradle TestKit](https://docs.gradle.org/current/userguide/test_kit.html) -* [Fedor Korotkov](https://github.com/fkorotkov) - Use BufferedOutputStream when writing the Zip file, [#171](https://github.com/johnrengelman/shadow/pull/171[) -* [Haw-Bin Chai](https://github.com/hbchai) - Quote Jar path in Windows start script as it may contain spaces, [#170](https://github.com/johnrengelman/shadow/pull/170) -* [Serban Iordache](https://github.com/siordache) - Evaluate relocation specs when merging service descriptors, [#165](https://github.com/johnrengelman/shadow/pull/165) +- Support for Gradle 2.11-rc-1, [#177](https://github.com/johnrengelman/shadow/issues/177) +- Convert internal framework to [Gradle TestKit](https://docs.gradle.org/current/userguide/test_kit.html) +- [Fedor Korotkov](https://github.com/fkorotkov) - Use BufferedOutputStream when writing the Zip file, [#171](https://github.com/johnrengelman/shadow/pull/171[) +- [Haw-Bin Chai](https://github.com/hbchai) - Quote Jar path in Windows start script as it may contain spaces, [#170](https://github.com/johnrengelman/shadow/pull/170) +- [Serban Iordache](https://github.com/siordache) - Evaluate relocation specs when merging service descriptors, [#165](https://github.com/johnrengelman/shadow/pull/165) ## v1.2.2 (2015-07-17) -* [Minecrell](https://github.com/Minecrell) - Gradle 2.5 compatibility, [#147](https://github.com/johnrengelman/shadow/issues/147) +- [Minecrell](https://github.com/Minecrell) - Gradle 2.5 compatibility, [#147](https://github.com/johnrengelman/shadow/issues/147) ## v1.2.1 (2015-01-23) -* Apply package relocations to dependency resources, [#114](https://github.com/johnrengelman/shadow/issues/114) +- Apply package relocations to dependency resources, [#114](https://github.com/johnrengelman/shadow/issues/114) ## v1.2.0 (2014-11-24) -* Re-organize some code to remove need for forcing the Gradle API ClassLoader to allow the `org.apache.tools.zip` package. -* Upgrade JDOM library from 1.1 to 2.0.5 (change dependency from `jdom:jdom:1.1` to `org.jdom:jdom2:2.0.5`), [#98](https://github.com/johnrengelman/shadow/issues/98) -* Convert ShadowJar.groovy to ShadowJar.java to workaround binary incompatibility introduced by Gradle 2.2, [#106](https://github.com/johnrengelman/shadow/issues/106) -* Updated ASM library to `5.0.3` to support JDK8, [#97](https://github.com/johnrengelman/shadow/issues/97) -* Allows for regex pattern matching in the `dependency` string when including/excluding, [#83](https://github.com/johnrengelman/shadow/issues/83) -* Apply package relocations to resource files, [#93](https://github.com/johnrengelman/shadow/issues/93) +- Re-organize some code to remove need for forcing the Gradle API ClassLoader to allow the `org.apache.tools.zip` package. +- Upgrade JDOM library from 1.1 to 2.0.5 (change dependency from `jdom:jdom:1.1` to `org.jdom:jdom2:2.0.5`), [#98](https://github.com/johnrengelman/shadow/issues/98) +- Convert ShadowJar.groovy to ShadowJar.java to workaround binary incompatibility introduced by Gradle 2.2, [#106](https://github.com/johnrengelman/shadow/issues/106) +- Updated ASM library to `5.0.3` to support JDK8, [#97](https://github.com/johnrengelman/shadow/issues/97) +- Allows for regex pattern matching in the `dependency` string when including/excluding, [#83](https://github.com/johnrengelman/shadow/issues/83) +- Apply package relocations to resource files, [#93](https://github.com/johnrengelman/shadow/issues/93) ## v1.1.2 (2014-09-09) -* fix bug in `runShadow` where dependencies from the `shadow` configuration are not available, [#94](https://github.com/johnrengelman/shadow/issues/94) +- fix bug in `runShadow` where dependencies from the `shadow` configuration are not available, [#94](https://github.com/johnrengelman/shadow/issues/94) ## v1.1.1 (2014-08-27) -* Fix bug in `'createStartScripts'` task that was causing it to not execute `'shadowJar'` task, [#90](https://github.com/johnrengelman/shadow/issues/90) -* Do not include `null` in ShadowJar Manifest `'Class-Path'` value when `jar` task does not specify a value for it, [#92](https://github.com/johnrengelman/shadow/issues/92) -* ShadowJar Manifest `'Class-Path'` should reference jars from `'shadow'` config as relative to location of `shadowJar` output, [#91](https://github.com/johnrengelman/shadow/issues/91) +- Fix bug in `'createStartScripts'` task that was causing it to not execute `'shadowJar'` task, [#90](https://github.com/johnrengelman/shadow/issues/90) +- Do not include `null` in ShadowJar Manifest `'Class-Path'` value when `jar` task does not specify a value for it, [#92](https://github.com/johnrengelman/shadow/issues/92) +- ShadowJar Manifest `'Class-Path'` should reference jars from `'shadow'` config as relative to location of `shadowJar` output, [#91](https://github.com/johnrengelman/shadow/issues/91) ## v1.1.0 (2014-08-26) -* **Breaking Change!** Fix leaking of `shadowJar.manifest` into `jar.manifest`, [#82](https://github.com/johnrengelman/shadow/issues/82) +- **Breaking Change!** Fix leaking of `shadowJar.manifest` into `jar.manifest`, [#82](https://github.com/johnrengelman/shadow/issues/82) To simplify behavior, the `shadowJar.appendManifest` method has been removed. Replace uses with `shadowJar.manifest` -* `ShadowTask` now has a `configurations` property that is resolved to the files in the resolved configuration before +- `ShadowTask` now has a `configurations` property that is resolved to the files in the resolved configuration before being added to the copy spec. This allows for an easier implementation for filtering. The default 'shadowJar' task has the convention of adding the `'runtime'` scope to this list. Manually created instances of `ShadowTask` have no configurations added by default and can be configured by setting `task.configurations`. -* Properly configure integration with the `'maven'` plugin when added. When adding `'maven'` the `'uploadShadow'` task +- Properly configure integration with the `'maven'` plugin when added. When adding `'maven'` the `'uploadShadow'` task will now properly configure the POM dependencies by removing the `'compile'` and `'runtime'` configurations from the POM and adding the `'shadow'` configuration as a `RUNTIME` scope in the POM. This behavior matches the behavior when using the `'maven-publish'` plugin. -* [Matt Hurne](https://github.com/mhurne) - Allow `ServiceFileTransformer` to specify include/exclude patterns for +- [Matt Hurne](https://github.com/mhurne) - Allow `ServiceFileTransformer` to specify include/exclude patterns for files within the configured path to merge. -* [Matt Hurne](https://github.com/mhurne) - Added `GroovyExtensionModuleTransformer` for merging Groovy Extension module +- [Matt Hurne](https://github.com/mhurne) - Added `GroovyExtensionModuleTransformer` for merging Groovy Extension module descriptor files. The existing `ServiceFileTransformer` now excludes Groovy Extension Module descriptors by default. -* `distShadowZip` and `distShadowZip` now contain the shadow library and run scripts instead of the default from the +- `distShadowZip` and `distShadowZip` now contain the shadow library and run scripts instead of the default from the `'application'` plugin, [#89](https://github.com/johnrengelman/shadow/issues/89) ## v1.0.3 (2014-07-29) -* Make service files root path configurable for `ServiceFileTransformer`, [#72](https://github.com/johnrengelman/shadow/issues/72) -* [Andres Almiray](https://github.com/aalmiray - Added PropertiesFileTransformer, [#73](https://github.com/johnrengelman/shadow/issues/73) -* [Brandon Kearby](https://github.com/brandonkearby) - Fixed StackOverflow when a cycle occurs in the resolved dependency grap, [#69](https://github.com/johnrengelman/shadow/pull/69) -* Apply Transformers to project resources, [#70](https://github.com/johnrengelman/shadow/issues/70), [#71](https://github.com/johnrengelman/shadow/issues/71) -* [Minecrell](https://github.com/Minecrell) - Do not drop non-class files from dependencies when relocation is enabled, [#61](https://github.com/johnrengelman/shadow/issues/61) -* Remove support for applying individual sub-plugins by Id (easier maintenance and cleaner presentation in Gradle Portal) +- Make service files root path configurable for `ServiceFileTransformer`, [#72](https://github.com/johnrengelman/shadow/issues/72) +- [Andres Almiray](https://github.com/aalmiray - Added PropertiesFileTransformer, [#73](https://github.com/johnrengelman/shadow/issues/73) +- [Brandon Kearby](https://github.com/brandonkearby) - Fixed StackOverflow when a cycle occurs in the resolved dependency grap, [#69](https://github.com/johnrengelman/shadow/pull/69) +- Apply Transformers to project resources, [#70](https://github.com/johnrengelman/shadow/issues/70), [#71](https://github.com/johnrengelman/shadow/issues/71) +- [Minecrell](https://github.com/Minecrell) - Do not drop non-class files from dependencies when relocation is enabled, [#61](https://github.com/johnrengelman/shadow/issues/61) +- Remove support for applying individual sub-plugins by Id (easier maintenance and cleaner presentation in Gradle Portal) ## v1.0.2 (2014-07-07) -* Do not add an empty Class-Path attribute to the manifest when the `shadow` configuration contains no dependencies. -* `runShadow` now registers `shadowJar` as an input. Previously, `runShadow` did not execute `shadowJar` and an error occurred. -* Support Gradle 2.0, [#66](https://github.com/johnrengelman/shadow/issues/66) -* Do not override existing 'Class-Path' Manifest attribute settings from Jar configuration. Instead combine, [#65](https://github.com/johnrengelman/shadow/issues/65) +- Do not add an empty Class-Path attribute to the manifest when the `shadow` configuration contains no dependencies. +- `runShadow` now registers `shadowJar` as an input. Previously, `runShadow` did not execute `shadowJar` and an error occurred. +- Support Gradle 2.0, [#66](https://github.com/johnrengelman/shadow/issues/66) +- Do not override existing 'Class-Path' Manifest attribute settings from Jar configuration. Instead combine, [#65](https://github.com/johnrengelman/shadow/issues/65) ## v1.0.1 (2014-06-28) -* Fix issue where non-class files are dropped when using relocation, [#58](https://github.com/johnrengelman/shadow/issues/58) -* Do not create a `/` directory inside the output jar. -* Fix `runShadow` task to evaluate the `shadowJar.archiveFile` property at execution time, [#60](https://github.com/johnrengelman/shadow/issues/60) +- Fix issue where non-class files are dropped when using relocation, [#58](https://github.com/johnrengelman/shadow/issues/58) +- Do not create a `/` directory inside the output jar. +- Fix `runShadow` task to evaluate the `shadowJar.archiveFile` property at execution time, [#60](https://github.com/johnrengelman/shadow/issues/60) ## v1.0.0 (2014-06-27) -* Previously known as v0.9.0 -* All changes from 0.9.0-M1 to 0.9.0-M5 -* Properly configure the ShadowJar task inputs to observe the include/excludes from the `dependencies` block. This +- Previously known as v0.9.0 +- All changes from 0.9.0-M1 to 0.9.0-M5 +- Properly configure the ShadowJar task inputs to observe the include/excludes from the `dependencies` block. This allows UP-TO-DATE checking to work properly when changing the `dependencies` rulea, [#54](https://github.com/johnrengelman/shadow/issues/54) -* Apply relocation remappings to classes and imports in source project, [#55](https://github.com/johnrengelman/shadow/issues/55) -* Do not create directories in jar for source of remapped class, created directories in jar for destination of remapped classes, [#53](https://github.com/johnrengelman/shadow/issues/53) +- Apply relocation remappings to classes and imports in source project, [#55](https://github.com/johnrengelman/shadow/issues/55) +- Do not create directories in jar for source of remapped class, created directories in jar for destination of remapped classes, [#53](https://github.com/johnrengelman/shadow/issues/53) ## v0.9.0-M5 -* Add commons-io to compile classpath -* Update asm library to 4.1 +- Add commons-io to compile classpath +- Update asm library to 4.1 ## v0.9.0-M4 -* Break plugin into multiple sub-plugins. `ShadowBasePlugin` is always applied. +- Break plugin into multiple sub-plugins. `ShadowBasePlugin` is always applied. `ShadowJavaPlugin` and `ShadowApplicationPlugin` are applied in reaction to applying the `java` and `application` plugins respectively. -* Shadow does not applied `java` plugin automatically. `java` or `groovy` must be applied in conjunction with `shadow`. -* Moved artifact filtering to `dependencies {}` block underneath `shadowJar`. This allows better include/exclude control +- Shadow does not applied `java` plugin automatically. `java` or `groovy` must be applied in conjunction with `shadow`. +- Moved artifact filtering to `dependencies {}` block underneath `shadowJar`. This allows better include/exclude control for dependencies. -* Dependencies added to the `shadow` configuration are automatically added to the `Class-Path` attribute in the manifest +- Dependencies added to the `shadow` configuration are automatically added to the `Class-Path` attribute in the manifest for `shadowJar` -* Applying `application` plugin and settings `mainClassName` automatically configures the `Main-Class` attribute in +- Applying `application` plugin and settings `mainClassName` automatically configures the `Main-Class` attribute in the manifest for `shadowJar` -* `runShadow` now utilizes the output of the `shadowJar` and executes using `java -jar ` -* Start Scripts for shadow distribution now utilize `java -jar` to execute instead of placing all files on classpath +- `runShadow` now utilizes the output of the `shadowJar` and executes using `java -jar ` +- Start Scripts for shadow distribution now utilize `java -jar` to execute instead of placing all files on classpath and executing main class. -* Excluding/Including dependencies no longer includes transitive dependencies. All dependencies for inclusion/exclusion +- Excluding/Including dependencies no longer includes transitive dependencies. All dependencies for inclusion/exclusion must be explicitly configured via a spec. ## v0.9.0-M3 -* Use commons.io FilenameUtils to determine name of resolved jars for including/excluding +- Use commons.io FilenameUtils to determine name of resolved jars for including/excluding ## v0.9.0-M2 -* Added integration with `application` plugin to replace old `OutputSignedJars` task -* Fixed bug that resulted in duplicate file entries in the resulting Jar -* Changed plugin id to 'com.github.johnrengelman.shadow' to support Gradle 2.x plugin infrastructure. +- Added integration with `application` plugin to replace old `OutputSignedJars` task +- Fixed bug that resulted in duplicate file entries in the resulting Jar +- Changed plugin id to 'com.github.johnrengelman.shadow' to support Gradle 2.x plugin infrastructure. ## v0.9.0-M1 -* Rewrite based on Gradle Jar Task -* `ShadowJar` now extends `Jar` -* Removed `signedCompile` and `signedRuntime` configurations in favor of `shadow` configuration -* Removed `OutputSignedJars` task +- Rewrite based on Gradle Jar Task +- `ShadowJar` now extends `Jar` +- Removed `signedCompile` and `signedRuntime` configurations in favor of `shadow` configuration +- Removed `OutputSignedJars` task