diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 52751c37d..09a95beb4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,8 +12,14 @@ jobs: strategy: matrix: os: [ ubuntu-latest, windows-latest ] - # Always test on the latest version and all LTS. - java: [ 11, 17, 21, 23 ] + # Always test on the latest version and some LTS. + java: [ 17, 21, 24 ] + # Test on the minimum Gradle version and the latest. + gradle: [ 8.3, current ] + exclude: + # Gradle 8.3 doesn't support Java 24. + - gradle: 8.3 + java: 24 runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 @@ -22,7 +28,7 @@ jobs: distribution: 'zulu' java-version: ${{ matrix.java }} - uses: gradle/actions/setup-gradle@v4 - - run: ./gradlew build + - run: ./gradlew build --info "-PtestGradleVersion=${{ matrix.gradle }}" publish-snapshot: needs: build diff --git a/build.gradle.kts b/build.gradle.kts index 535838950..cf83f8152 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -84,7 +84,7 @@ dependencies { implementation("org.apache.logging.log4j:log4j-core:2.24.1") implementation("org.vafer:jdependency:2.13") - testImplementation("org.spockframework:spock-core:2.3-groovy-3.0") { + testImplementation("org.spockframework:spock-core:2.3-groovy-4.0") { exclude(group = "org.codehaus.groovy") exclude(group = "org.hamcrest") } @@ -111,6 +111,12 @@ val isCI = providers.environmentVariable("CI").isPresent tasks.withType().configureEach { useJUnitPlatform() + val testGradleVersion = providers.gradleProperty("testGradleVersion").orNull.let { + if (it == null || it == "current") GradleVersion.current().version else it + } + logger.info("Using test Gradle version: $testGradleVersion") + systemProperty("TEST_GRADLE_VERSION", testGradleVersion) + maxParallelForks = Runtime.getRuntime().availableProcessors() if (isCI) { diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index a4b76b953..8bdaf60c7 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ff23a68d7..407c905d9 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-rc-1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index f3b75f3b0..ef07e0162 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -114,7 +114,7 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar +CLASSPATH="\\\"\\\"" # Determine the Java command to use to start the JVM. @@ -205,7 +205,7 @@ fi DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # and any embedded shellness will be escaped. # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # treated as '${Hostname}' itself on the command line. @@ -213,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/gradlew.bat b/gradlew.bat index 9b42019c7..5eed7ee84 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -70,11 +70,11 @@ goto fail :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar +set CLASSPATH= @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell diff --git a/src/docs/changes/README.md b/src/docs/changes/README.md index 057ebe57f..d3b52123f 100644 --- a/src/docs/changes/README.md +++ b/src/docs/changes/README.md @@ -3,6 +3,10 @@ ## [Unreleased] +**Fixed** + +- Fix compatibility for Gradle 9.0.0 RC1. ([#1470](https://github.com/GradleUp/shadow/pull/1470)) + ## [v8.3.6] (2025-02-02) 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 7a57952ae..3da91aab1 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 @@ -84,7 +84,7 @@ class ShadowApplicationPlugin implements Plugin { 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 = { javaApplication.mainClass.get() } + startScripts.mainClass.set(javaApplication.mainClass) startScripts.conventionMapping.applicationName = { javaApplication.applicationName } startScripts.conventionMapping.outputDir = { new File(project.layout.buildDirectory.asFile.get(), 'scriptsShadow') } startScripts.conventionMapping.defaultJvmOpts = { javaApplication.applicationDefaultJvmArgs } diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/impl/RelocatorRemapper.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/impl/RelocatorRemapper.groovy index 5e23269e4..31fafab21 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/impl/RelocatorRemapper.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/impl/RelocatorRemapper.groovy @@ -24,6 +24,7 @@ import com.github.jengelman.gradle.plugins.shadow.relocation.RelocateClassContex import com.github.jengelman.gradle.plugins.shadow.relocation.RelocatePathContext import com.github.jengelman.gradle.plugins.shadow.relocation.Relocator import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowCopyAction.RelativeArchivePath +import groovy.transform.CompileStatic import org.objectweb.asm.commons.Remapper import java.util.regex.Matcher @@ -34,6 +35,7 @@ import java.util.regex.Pattern * * @author John Engelman */ +@CompileStatic class RelocatorRemapper extends Remapper { private final Pattern classPattern = Pattern.compile("(\\[*)?L(.+)") diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/DefaultZipCompressor.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/DefaultZipCompressor.groovy index a2248e6a2..829ab294c 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/DefaultZipCompressor.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/DefaultZipCompressor.groovy @@ -17,7 +17,6 @@ package com.github.jengelman.gradle.plugins.shadow.internal import org.apache.tools.zip.Zip64Mode import org.apache.tools.zip.ZipOutputStream -import org.gradle.api.UncheckedIOException class DefaultZipCompressor implements ZipCompressor { private final int entryCompressionMethod 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 2affa9fbe..28ed02308 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 @@ -4,7 +4,7 @@ import org.gradle.api.tasks.InputFile import org.gradle.api.tasks.JavaExec import org.gradle.api.tasks.TaskAction -class JavaJarExec extends JavaExec { +abstract class JavaJarExec extends JavaExec { @InputFile File jarFile 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 index f94ab89ed..f3d55385b 100644 --- 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 @@ -12,7 +12,10 @@ class RelocationUtil { 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('/', '.') + def i = entry.name.lastIndexOf('/') + if (i != -1) { + packages << entry.name.take(i).replaceAll('/', '.') + } } } jf.close() diff --git a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/UnusedTracker.groovy b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/UnusedTracker.groovy index fcfbe6ea1..5ff88aec2 100644 --- a/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/UnusedTracker.groovy +++ b/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/internal/UnusedTracker.groovy @@ -3,10 +3,11 @@ package com.github.jengelman.gradle.plugins.shadow.internal import org.gradle.api.Project import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.Dependency +import org.gradle.api.artifacts.FileCollectionDependency import org.gradle.api.artifacts.ProjectDependency -import org.gradle.api.artifacts.SelfResolvingDependency import org.gradle.api.file.FileCollection import org.gradle.api.tasks.InputFiles +import org.gradle.util.GradleVersion import org.vafer.jdependency.Clazz import org.vafer.jdependency.Clazzpath import org.vafer.jdependency.ClazzpathUnit @@ -70,10 +71,10 @@ class UnusedTracker { def apiJars = new LinkedList() apiDependencies.each { dep -> if (dep instanceof ProjectDependency) { - apiJars.addAll(getApiJarsFromProject(dep.dependencyProject)) + apiJars.addAll(getApiJarsFromProject(dependencyProjectCompat(dep, project))) addJar(runtimeConfiguration, dep, apiJars) - } else if (dep instanceof SelfResolvingDependency) { - apiJars.addAll(dep.resolve()) + } else if (dep instanceof FileCollectionDependency) { + apiJars.addAll(dep.files) } else { addJar(runtimeConfiguration, dep, apiJars) apiJars.add(runtimeConfiguration.find { it.name.startsWith("${dep.name}-") } as File) @@ -82,4 +83,14 @@ class UnusedTracker { return project.files(apiJars) } + + /** + * TODO: this could be removed after bumping the min Gradle requirement to 8.11 or above. + */ + private static dependencyProjectCompat(ProjectDependency projectDependency, Project project) { + if (GradleVersion.current() >= GradleVersion.version("8.11")) { + return project.project(projectDependency.path) + } + return projectDependency.dependencyProject + } } 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 128dc3cce..3fb9eaef4 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 @@ -17,7 +17,6 @@ import org.apache.tools.zip.ZipFile import org.apache.tools.zip.ZipOutputStream import org.gradle.api.Action import org.gradle.api.GradleException -import org.gradle.api.UncheckedIOException import org.gradle.api.file.FileCopyDetails import org.gradle.api.file.FilePermissions import org.gradle.api.file.FileTreeElement @@ -460,7 +459,7 @@ class ShadowCopyAction implements CopyAction { return null } else { //Parent is always a directory so add / to the end of the path - String path = segments[0..-2].join('/') + '/' + String path = segments.take(segments.length - 1).join('/') + '/' return new RelativeArchivePath(setArchiveTimes(new ZipEntry(path))) } } @@ -528,7 +527,9 @@ class ShadowCopyAction implements CopyAction { return archivePath } - @Override + /** + * This method should be annotated with @Override, but the parent has been removed from Gradle 9. + */ int getMode() { return archivePath.entry.unixMode } 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 dc4cfe9e3..ab45dbee9 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 @@ -25,7 +25,7 @@ import java.util.concurrent.Callable; @CacheableTask -public class ShadowJar extends Jar implements ShadowSpec { +public abstract class ShadowJar extends Jar implements ShadowSpec { private List transformers; private List relocators; 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 5e5bfd63e..579e7dc5f 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 @@ -54,7 +54,11 @@ include 'api', 'main' buildFile.text = replaceTokens(fullSnippet) - GradleRunner runner = GradleRunner.create().withProjectDir(tempDir).withPluginClasspath().forwardOutput() + GradleRunner runner = GradleRunner.create() + .withGradleVersion(PluginSpecification.TEST_GRADLE_VERSION) + .withProjectDir(tempDir) + .withPluginClasspath() + .forwardOutput() runner.withArguments(":main:build", "-m").build() 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 7f93dca88..dce305c9d 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 @@ -77,7 +77,7 @@ class ApacheNoticeResourceTransformerParameterTests extends TransformerTestSuppo processAndFailOnNullPointer("\n") } - private static void processAndFailOnNullPointer(final String noticeText) { + private void processAndFailOnNullPointer(final String noticeText) { try { final ByteArrayInputStream noticeInputStream = new ByteArrayInputStream(noticeText.getBytes()) final List emptyList = Collections.emptyList() diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/TransformerTestSupport.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/TransformerTestSupport.groovy index dda89681d..15b67798f 100644 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/TransformerTestSupport.groovy +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/transformers/TransformerTestSupport.groovy @@ -5,7 +5,7 @@ import org.gradle.api.file.RelativePath import org.gradle.api.internal.file.DefaultFileTreeElement abstract class TransformerTestSupport { - protected static T transformer + protected T transformer protected static FileTreeElement getFileElement(String path) { return new DefaultFileTreeElement(null, RelativePath.parse(true, path), null, null) 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 index c3c41596d..0df14fa09 100644 --- 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 @@ -1,6 +1,5 @@ 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; @@ -8,6 +7,7 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.io.UncheckedIOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; diff --git a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/PluginSpecification.groovy b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/PluginSpecification.groovy index 04514ec69..aa7d6967c 100644 --- a/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/PluginSpecification.groovy +++ b/src/test/groovy/com/github/jengelman/gradle/plugins/shadow/util/PluginSpecification.groovy @@ -18,6 +18,8 @@ abstract class PluginSpecification extends Specification { public static final String SHADOW_VERSION = System.getProperty("shadowVersion") + public static final String TEST_GRADLE_VERSION = System.getProperty("TEST_GRADLE_VERSION") + AppendableMavenFileRepository repo def setup() { @@ -55,6 +57,7 @@ abstract class PluginSpecification extends Specification { GradleRunner getRunner() { GradleRunner.create() + .withGradleVersion(TEST_GRADLE_VERSION) .withProjectDir(dir.toFile()) .forwardOutput() .withPluginClasspath()