From d93b8165ebeae867e913c06a2b915be3be6ad673 Mon Sep 17 00:00:00 2001 From: Goooler Date: Tue, 6 Jan 2026 10:23:11 +0800 Subject: [PATCH] Migrate to ktfmt --- .editorconfig | 3 - build.gradle.kts | 105 ++- gradle/libs.versions.toml | 2 +- settings.gradle.kts | 4 +- .../plugins/shadow/DocCodeSnippetTest.kt | 8 +- .../shadow/snippet/CodeSnippetExtractor.kt | 25 +- .../gradle/plugins/shadow/snippet/DslLang.kt | 3 +- .../shadow/snippet/GroovyBuildExecutable.kt | 12 +- .../shadow/snippet/KotlinBuildExecutable.kt | 12 +- .../shadow/snippet/SnippetExecutable.kt | 71 +- .../plugins/shadow/ApplicationPluginTest.kt | 200 ++--- .../gradle/plugins/shadow/BasePluginTest.kt | 276 +++---- .../gradle/plugins/shadow/CachingTest.kt | 296 +++----- .../gradle/plugins/shadow/FilteringTest.kt | 135 ++-- .../shadow/FindResourceInClasspathTest.kt | 26 +- .../gradle/plugins/shadow/JavaPluginsTest.kt | 579 +++++++-------- .../plugins/shadow/KotlinPluginsTest.kt | 94 ++- .../gradle/plugins/shadow/MinimizeTest.kt | 250 +++---- .../gradle/plugins/shadow/PublishingTest.kt | 681 ++++++++++-------- .../gradle/plugins/shadow/RelocationTest.kt | 420 ++++++----- .../transformers/AppendingTransformerTest.kt | 92 ++- .../transformers/BaseTransformerTest.kt | 7 +- .../GroovyExtensionModuleTransformerTest.kt | 100 +-- .../PropertiesFileTransformerTest.kt | 152 ++-- .../ServiceFileTransformerTest.kt | 175 +++-- .../shadow/transformers/TransformersTest.kt | 219 +++--- .../XmlAppendingTransformerTest.kt | 68 +- .../shadow/util/AppendableMavenRepository.kt | 151 ++-- .../shadow/util/GradleModuleMetadata.kt | 41 +- .../gradle/plugins/shadow/util/Issue.kt | 11 +- .../gradle/plugins/shadow/util/JarBuilder.kt | 8 +- .../gradle/plugins/shadow/util/JvmLang.kt | 7 +- .../gradle/plugins/shadow/util/RunProcess.kt | 8 +- .../plugins/shadow/ShadowApplicationPlugin.kt | 50 +- .../gradle/plugins/shadow/ShadowBasePlugin.kt | 18 +- .../gradle/plugins/shadow/ShadowExtension.kt | 13 +- .../gradle/plugins/shadow/ShadowJavaPlugin.kt | 110 +-- .../gradle/plugins/shadow/ShadowKmpPlugin.kt | 33 +- .../gradle/plugins/shadow/ShadowPlugin.kt | 58 +- .../internal/DefaultDependencyFilter.kt | 8 +- .../shadow/internal/DefaultInheritManifest.kt | 15 +- .../plugins/shadow/internal/GradleCompat.kt | 79 +- .../internal/MinimizeDependencyFilter.kt | 16 +- .../shadow/internal/RelocatorRemapper.kt | 14 +- .../shadow/internal/ReproducibleProperties.kt | 26 +- .../plugins/shadow/internal/UnusedTracker.kt | 11 +- .../gradle/plugins/shadow/internal/Utils.kt | 36 +- .../shadow/relocation/RelocationContext.kt | 8 +- .../plugins/shadow/relocation/Relocator.kt | 12 +- .../shadow/relocation/SimpleRelocator.kt | 115 +-- .../plugins/shadow/tasks/DependencyFilter.kt | 83 +-- .../shadow/tasks/FindResourceInClasspath.kt | 14 +- .../plugins/shadow/tasks/ShadowCopyAction.kt | 242 ++++--- .../gradle/plugins/shadow/tasks/ShadowJar.kt | 368 +++++----- .../ApacheLicenseResourceTransformer.kt | 18 +- .../ApacheNoticeResourceTransformer.kt | 82 ++- .../transformers/AppendingTransformer.kt | 25 +- .../ComponentsXmlResourceTransformer.kt | 45 +- .../DeduplicatingResourceTransformer.kt | 64 +- .../DontIncludeResourceTransformer.kt | 13 +- .../GroovyExtensionModuleTransformer.kt | 49 +- .../IncludeResourceTransformer.kt | 17 +- .../Log4j2PluginsCacheFileTransformer.kt | 15 +- .../ManifestAppenderTransformer.kt | 13 +- .../ManifestResourceTransformer.kt | 32 +- .../MergeLicenseResourceTransformer.kt | 52 +- .../PatternFilterableResourceTransformer.kt | 5 +- .../PreserveFirstFoundResourceTransformer.kt | 28 +- .../transformers/PropertiesFileTransformer.kt | 101 +-- .../transformers/ResourceTransformer.kt | 34 +- .../transformers/ServiceFileTransformer.kt | 37 +- .../shadow/transformers/TransformerContext.kt | 29 +- .../transformers/XmlAppendingTransformer.kt | 42 +- .../plugins/shadow/ShadowPropertiesTest.kt | 347 ++++----- .../internal/ReproduciblePropertiesTest.kt | 102 +-- .../relocation/RelocatorRemapperTest.kt | 65 +- .../shadow/relocation/SimpleRelocatorTest.kt | 265 ++++--- .../ApacheLicenseResourceTransformerTest.kt | 6 +- .../ApacheNoticeResourceTransformerTest.kt | 3 +- .../transformers/AppendingTransformerTest.kt | 3 +- .../transformers/BaseTransformerTest.kt | 49 +- .../ComponentsXmlResourceTransformerTest.kt | 15 +- .../DeduplicatingResourceTransformerTest.kt | 137 ++-- .../Log4j2PluginsCacheFileTransformerTest.kt | 32 +- .../ManifestAppenderTransformerTest.kt | 47 +- .../MergeLicenseResourceTransformerTest.kt | 191 ++--- .../PropertiesFileTransformerTest.kt | 341 ++++----- .../ServiceFileTransformerTest.kt | 33 +- .../plugins/shadow/testkit/GradleRunner.kt | 65 +- .../gradle/plugins/shadow/testkit/JarPath.kt | 56 +- .../gradle/plugins/shadow/testkit/Resource.kt | 5 +- .../gradle/plugins/shadow/testkit/Strings.kt | 6 +- 92 files changed, 4098 insertions(+), 3941 deletions(-) diff --git a/.editorconfig b/.editorconfig index 379e533b4..a40d649a0 100755 --- a/.editorconfig +++ b/.editorconfig @@ -16,9 +16,6 @@ ij_kotlin_line_break_after_multiline_when_entry = false ij_kotlin_name_count_to_use_star_import = 2147483647 ij_kotlin_name_count_to_use_star_import_for_members = 2147483647 ij_kotlin_packages_to_use_import_on_demand = unset -ktlint_code_style = intellij_idea -ktlint_standard_function-expression-body = disabled -ktlint_standard_mixed-condition-operators = disabled [*.md] trim_trailing_whitespace = false diff --git a/build.gradle.kts b/build.gradle.kts index 3024a2327..d335434ad 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -19,21 +19,16 @@ plugins { } version = providers.gradleProperty("VERSION_NAME").get() + group = providers.gradleProperty("GROUP").get() + description = providers.gradleProperty("POM_DESCRIPTION").get() -dokka { - dokkaPublications.html { - outputDirectory = rootDir.resolve("docs/api") - } -} +dokka { dokkaPublications.html { outputDirectory = rootDir.resolve("docs/api") } } kotlin { explicitApi() - @OptIn(ExperimentalAbiValidation::class) - abiValidation { - enabled = true - } + @OptIn(ExperimentalAbiValidation::class) abiValidation { enabled = true } compilerOptions { allWarningsAsErrors = true // https://docs.gradle.org/current/userguide/compatibility.html#kotlin @@ -56,18 +51,15 @@ lint { } spotless { - kotlin { - ktlint(libs.ktlint.get().version) - } - kotlinGradle { - ktlint(libs.ktlint.get().version) - } + kotlin { ktfmt(libs.ktfmt.get().version).googleStyle() } + kotlinGradle { ktfmt(libs.ktfmt.get().version).googleStyle() } } -val testPluginClasspath by configurations.registering { - isCanBeResolved = true - description = "Plugins used in integration tests could be resolved in classpath." -} +val testPluginClasspath by + configurations.registering { + isCanBeResolved = true + description = "Plugins used in integration tests could be resolved in classpath." + } val testKit by sourceSets.creating val testKitImplementation by configurations.getting @@ -77,18 +69,18 @@ configurations.configureEach { API_ELEMENTS_CONFIGURATION_NAME, RUNTIME_ELEMENTS_CONFIGURATION_NAME, JAVADOC_ELEMENTS_CONFIGURATION_NAME, - SOURCES_ELEMENTS_CONFIGURATION_NAME, - -> outgoing { - // Main/current capability. - capability("com.gradleup.shadow:shadow-gradle-plugin:$version") - - // Historical capabilities. - capability("io.github.goooler.shadow:shadow-gradle-plugin:$version") - capability("com.github.johnrengelman:shadow:$version") - capability("gradle.plugin.com.github.jengelman.gradle.plugins:shadow:$version") - capability("gradle.plugin.com.github.johnrengelman:shadow:$version") - capability("com.github.jengelman.gradle.plugins:shadow:$version") - } + SOURCES_ELEMENTS_CONFIGURATION_NAME -> + outgoing { + // Main/current capability. + capability("com.gradleup.shadow:shadow-gradle-plugin:$version") + + // Historical capabilities. + capability("io.github.goooler.shadow:shadow-gradle-plugin:$version") + capability("com.github.johnrengelman:shadow:$version") + capability("gradle.plugin.com.github.jengelman.gradle.plugins:shadow:$version") + capability("gradle.plugin.com.github.johnrengelman:shadow:$version") + capability("com.github.jengelman.gradle.plugins:shadow:$version") + } } } @@ -108,11 +100,12 @@ configurations.named(API_ELEMENTS_CONFIGURATION_NAME) { ) } -val testGradleVersion: String = providers.gradleProperty("testGradleVersion").orNull.let { - val value = if (it == null || it == "current") GradleVersion.current().version else it - logger.lifecycle("Using Gradle $value in tests") - value -} +val testGradleVersion: String = + providers.gradleProperty("testGradleVersion").orNull.let { + val value = if (it == null || it == "current") GradleVersion.current().version else it + logger.lifecycle("Using Gradle $value in tests") + value + } dependencies { compileOnly(libs.develocity) @@ -141,17 +134,15 @@ dependencies { } testing.suites { - getByName("test") { - dependencies { - implementation(libs.xmlunit) - } - } + getByName("test") { dependencies { implementation(libs.xmlunit) } } register("documentTest") { targets.configureEach { testTask { - val docsDir = file("docs").also { - if (!it.exists() || !it.isDirectory) error("Docs dir $it does not exist or is not a directory.") - } + val docsDir = + file("docs").also { + if (!it.exists() || !it.isDirectory) + error("Docs dir $it does not exist or is not a directory.") + } // Add docs as an input directory to trigger ManualCodeSnippetTests re-run on changes. inputs.dir(docsDir) systemProperty("DOCS_DIR", docsDir.absolutePath) @@ -215,10 +206,7 @@ gradlePlugin { } } - testSourceSets( - sourceSets["functionalTest"], - sourceSets["documentTest"], - ) + testSourceSets(sourceSets["functionalTest"], sourceSets["documentTest"]) } // This part should be placed after testing.suites to ensure the test sourceSets are created. @@ -234,11 +222,7 @@ tasks.withType().configureEach { options.release = libs.versions.jdkRelease.get().toInt() } -tasks.pluginUnderTestMetadata { - pluginClasspath.from( - testPluginClasspath, - ) -} +tasks.pluginUnderTestMetadata { pluginClasspath.from(testPluginClasspath) } tasks.validatePlugins { // TODO: https://github.com/gradle/gradle/issues/22600 @@ -254,11 +238,12 @@ tasks.check { } tasks.clean { - delete += listOf( - projectDir.resolve(".gradle"), - projectDir.resolve(".kotlin"), - dokka.dokkaPublications.html.map { it.outputDirectory }, - // Generated by MkDocs. - rootDir.resolve("site"), - ) + delete += + listOf( + projectDir.resolve(".gradle"), + projectDir.resolve(".kotlin"), + dokka.dokkaPublications.html.map { it.outputDirectory }, + // Generated by MkDocs. + rootDir.resolve("site"), + ) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 429aef440..c3ed3ce93 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -30,7 +30,7 @@ pluginPublish = { module = "com.gradle.publish:plugin-publish-plugin", version.r androidx-gradlePluginLints = "androidx.lint:lint-gradle:1.0.0-alpha05" # Dummy to get renovate updates, the version is used in rootProject build.gradle with spotless. -ktlint = "com.pinterest.ktlint:ktlint-cli:1.8.0" +ktfmt = "com.facebook:ktfmt:0.59" junit-bom = "org.junit:junit-bom:6.0.1" assertk = "com.willowtreeapps.assertk:assertk:0.28.1" diff --git a/settings.gradle.kts b/settings.gradle.kts index af496d121..93027b77d 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -12,9 +12,7 @@ pluginManagement { } } -plugins { - id("com.gradle.develocity") version "4.3" -} +plugins { id("com.gradle.develocity") version "4.3" } develocity { buildScan { diff --git a/src/documentTest/kotlin/com/github/jengelman/gradle/plugins/shadow/DocCodeSnippetTest.kt b/src/documentTest/kotlin/com/github/jengelman/gradle/plugins/shadow/DocCodeSnippetTest.kt index bfc913a80..d9b271dc2 100644 --- a/src/documentTest/kotlin/com/github/jengelman/gradle/plugins/shadow/DocCodeSnippetTest.kt +++ b/src/documentTest/kotlin/com/github/jengelman/gradle/plugins/shadow/DocCodeSnippetTest.kt @@ -12,13 +12,9 @@ class DocCodeSnippetTest { @TestFactory fun provideDynamicTests(@TempDir root: Path): List { - val langExecutables = DslLang.entries.map { executor -> - CodeSnippetExtractor.extract(executor) - } + val langExecutables = DslLang.entries.map { executor -> CodeSnippetExtractor.extract(executor) } - check(langExecutables.sumOf { it.size } > 0) { - "No code snippets found." - } + check(langExecutables.sumOf { it.size } > 0) { "No code snippets found." } check(langExecutables.size == DslLang.entries.size) { "We must provide build script snippets for all languages." } diff --git a/src/documentTest/kotlin/com/github/jengelman/gradle/plugins/shadow/snippet/CodeSnippetExtractor.kt b/src/documentTest/kotlin/com/github/jengelman/gradle/plugins/shadow/snippet/CodeSnippetExtractor.kt index b63095985..b5d253816 100644 --- a/src/documentTest/kotlin/com/github/jengelman/gradle/plugins/shadow/snippet/CodeSnippetExtractor.kt +++ b/src/documentTest/kotlin/com/github/jengelman/gradle/plugins/shadow/snippet/CodeSnippetExtractor.kt @@ -13,28 +13,21 @@ object CodeSnippetExtractor { private val docRoot = Path(System.getProperty("DOCS_DIR")) @OptIn(ExperimentalPathApi::class) - private val markdownPaths = docRoot.walk() - .filter { it.name.endsWith(".md", ignoreCase = true) } - .toList() + private val markdownPaths = + docRoot.walk().filter { it.name.endsWith(".md", ignoreCase = true) }.toList() fun extract(lang: DslLang): List { - return markdownPaths.flatMap { path -> - createExecutables(lang, path) - } + return markdownPaths.flatMap { path -> createExecutables(lang, path) } } - private fun createExecutables( - lang: DslLang, - markdownPath: Path, - ): List { + private fun createExecutables(lang: DslLang, markdownPath: Path): List { val relativeDocPath = markdownPath.relativeTo(docRoot).toString() return createSnippets(markdownPath.readText(), lang).map { (lineNumber, snippet) -> - SnippetExecutable.create( - lang, - snippet, - "$relativeDocPath:$lineNumber", - ) { - RuntimeException("The error line in the doc is near ${markdownPath.toUri()}:$lineNumber", it) + SnippetExecutable.create(lang, snippet, "$relativeDocPath:$lineNumber") { + RuntimeException( + "The error line in the doc is near ${markdownPath.toUri()}:$lineNumber", + it, + ) } } } diff --git a/src/documentTest/kotlin/com/github/jengelman/gradle/plugins/shadow/snippet/DslLang.kt b/src/documentTest/kotlin/com/github/jengelman/gradle/plugins/shadow/snippet/DslLang.kt index 8179417cc..87384d08c 100644 --- a/src/documentTest/kotlin/com/github/jengelman/gradle/plugins/shadow/snippet/DslLang.kt +++ b/src/documentTest/kotlin/com/github/jengelman/gradle/plugins/shadow/snippet/DslLang.kt @@ -2,8 +2,7 @@ package com.github.jengelman.gradle.plugins.shadow.snippet enum class DslLang { Kotlin, - Groovy, - ; + Groovy; override fun toString(): String = name.lowercase() } diff --git a/src/documentTest/kotlin/com/github/jengelman/gradle/plugins/shadow/snippet/GroovyBuildExecutable.kt b/src/documentTest/kotlin/com/github/jengelman/gradle/plugins/shadow/snippet/GroovyBuildExecutable.kt index 044d312e7..c3bf8e672 100644 --- a/src/documentTest/kotlin/com/github/jengelman/gradle/plugins/shadow/snippet/GroovyBuildExecutable.kt +++ b/src/documentTest/kotlin/com/github/jengelman/gradle/plugins/shadow/snippet/GroovyBuildExecutable.kt @@ -10,16 +10,20 @@ class GroovyBuildExecutable( override val buildScriptName: String = "build.gradle" - override val pluginsBlock: String = """ + override val pluginsBlock: String = + """ plugins { id 'java' id 'com.gradleup.shadow' } - """.trimIndent() + """ + .trimIndent() - override val assembleDependsOn: String = """ + override val assembleDependsOn: String = + """ tasks.named('assemble') { dependsOn tasks.withType(Jar) // ShadowJar is a subtype of Jar. } - """.trimIndent() + """ + .trimIndent() } diff --git a/src/documentTest/kotlin/com/github/jengelman/gradle/plugins/shadow/snippet/KotlinBuildExecutable.kt b/src/documentTest/kotlin/com/github/jengelman/gradle/plugins/shadow/snippet/KotlinBuildExecutable.kt index 43e04aabc..7dcdfe2fb 100644 --- a/src/documentTest/kotlin/com/github/jengelman/gradle/plugins/shadow/snippet/KotlinBuildExecutable.kt +++ b/src/documentTest/kotlin/com/github/jengelman/gradle/plugins/shadow/snippet/KotlinBuildExecutable.kt @@ -10,16 +10,20 @@ class KotlinBuildExecutable( override val buildScriptName: String = "build.gradle.kts" - override val pluginsBlock: String = """ + override val pluginsBlock: String = + """ plugins { java id("com.gradleup.shadow") } - """.trimIndent() + """ + .trimIndent() - override val assembleDependsOn: String = """ + override val assembleDependsOn: String = + """ tasks.named("assemble") { dependsOn(tasks.withType(Jar::class.java)) // ShadowJar is a subtype of Jar. } - """.trimIndent() + """ + .trimIndent() } diff --git a/src/documentTest/kotlin/com/github/jengelman/gradle/plugins/shadow/snippet/SnippetExecutable.kt b/src/documentTest/kotlin/com/github/jengelman/gradle/plugins/shadow/snippet/SnippetExecutable.kt index 88a30614d..3d02c49ec 100644 --- a/src/documentTest/kotlin/com/github/jengelman/gradle/plugins/shadow/snippet/SnippetExecutable.kt +++ b/src/documentTest/kotlin/com/github/jengelman/gradle/plugins/shadow/snippet/SnippetExecutable.kt @@ -19,9 +19,7 @@ sealed class SnippetExecutable : Executable { abstract val snippet: String - /** - * Unique name for the test, formatted as `publishing/README.md:10`. - */ + /** Unique name for the test, formatted as `publishing/README.md:10`. */ abstract val displayName: String abstract val exceptionTransformer: (Throwable) -> Throwable @@ -36,8 +34,10 @@ sealed class SnippetExecutable : Executable { } private fun execute(projectRoot: Path, snippet: String) { - projectRoot.resolve("settings.gradle").writeText( - """ + projectRoot + .resolve("settings.gradle") + .writeText( + """ dependencyResolutionManagement { repositories { mavenLocal() @@ -50,8 +50,9 @@ sealed class SnippetExecutable : Executable { include ':api', ':main' rootProject.name = 'snippet' enableFeaturePreview 'TYPESAFE_PROJECT_ACCESSORS' - """.trimIndent(), - ) + """ + .trimIndent() + ) val apiScript = buildString { append(pluginsBlock) @@ -61,23 +62,25 @@ sealed class SnippetExecutable : Executable { projectRoot.addSubProject("api", apiScript) val (imports, withoutImports) = importsExtractor(snippet) - val mainScript = buildString { - append(imports) - append(lineSeparator) - // All buildscript {} blocks must appear before any plugins {} blocks in the script. - if (withoutImports.contains("buildscript {")) { - append(withoutImports) - } else { - if (!withoutImports.contains("plugins {")) { - append(pluginsBlock) + val mainScript = + buildString { + append(imports) + append(lineSeparator) + // All buildscript {} blocks must appear before any plugins {} blocks in the script. + if (withoutImports.contains("buildscript {")) { + append(withoutImports) + } else { + if (!withoutImports.contains("plugins {")) { + append(pluginsBlock) + append(lineSeparator) + } + append(withoutImports) + } + append(lineSeparator) + append(assembleDependsOn) append(lineSeparator) } - append(withoutImports) - } - append(lineSeparator) - append(assembleDependsOn) - append(lineSeparator) - }.trimIndent() + .trimIndent() projectRoot.addSubProject("main", mainScript) projectRoot.resolve("main/foo.jar").createFile().also { // Dummy JAR file to ensure the project can be built. @@ -90,20 +93,19 @@ sealed class SnippetExecutable : Executable { try { gradleRunner( - projectDir = projectRoot, - arguments = listOf("build", "--stacktrace"), - warningsAsErrors = mainScript.toWarningsAsErrors(), - ).build().assertNoDeprecationWarnings() + projectDir = projectRoot, + arguments = listOf("build", "--stacktrace"), + warningsAsErrors = mainScript.toWarningsAsErrors(), + ) + .build() + .assertNoDeprecationWarnings() } catch (t: Throwable) { throw RuntimeException("Failed to execute snippet:\n\n$mainScript", t) } } private fun Path.addSubProject(project: String, buildScriptText: String) { - resolve(project) - .createDirectory() - .resolve(buildScriptName) - .writeText(buildScriptText) + resolve(project).createDirectory().resolve(buildScriptName).writeText(buildScriptText) } private fun importsExtractor(snippet: String): Pair { @@ -129,9 +131,10 @@ sealed class SnippetExecutable : Executable { snippet: String, testName: String, exceptionTransformer: (Throwable) -> Throwable, - ): SnippetExecutable = when (lang) { - DslLang.Groovy -> GroovyBuildExecutable(snippet, testName, exceptionTransformer) - DslLang.Kotlin -> KotlinBuildExecutable(snippet, testName, exceptionTransformer) - } + ): SnippetExecutable = + when (lang) { + DslLang.Groovy -> GroovyBuildExecutable(snippet, testName, exceptionTransformer) + DslLang.Kotlin -> KotlinBuildExecutable(snippet, testName, exceptionTransformer) + } } } diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/ApplicationPluginTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/ApplicationPluginTest.kt index 3534a320e..bfcc48a8e 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/ApplicationPluginTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/ApplicationPluginTest.kt @@ -36,37 +36,45 @@ class ApplicationPluginTest : BasePluginTest() { @DisabledOnOs( OS.WINDOWS, architectures = ["aarch64"], - disabledReason = "Cannot use toolchain on Windows ARM64", // TODO: remove when min Gradle is bumped to 9.2+ + disabledReason = + "Cannot use toolchain on Windows ARM64", // TODO: remove when min Gradle is bumped to 9.2+ ) @Test fun integrationWithApplicationPluginAndJavaToolchains() { prepare( mainClassWithImports = true, dependenciesBlock = "implementation 'junit:junit:3.8.2'", - projectBlock = """ + projectBlock = + """ java { toolchain.languageVersion = JavaLanguageVersion.of(17) } - """.trimIndent(), - settingsBlock = """ + """ + .trimIndent(), + settingsBlock = + """ plugins { id 'org.gradle.toolchains.foojay-resolver-convention' } - """.trimIndent(), - runShadowBlock = $$""" + """ + .trimIndent(), + runShadowBlock = + $$""" doFirst { logger.lifecycle("Running application with JDK ${it.javaLauncher.get().metadata.languageVersion.asInt()}") } - """.trimIndent(), + """ + .trimIndent(), ) val result = runWithSuccess(runShadowPath) - assertThat(result.output).contains( - "Running application with JDK 17", - "Hello, World! (foo) from Main", - "Refs: junit.framework.Test", - ) + assertThat(result.output) + .contains( + "Running application with JDK 17", + "Hello, World! (foo) from Main", + "Refs: junit.framework.Test", + ) } @Test @@ -74,17 +82,19 @@ class ApplicationPluginTest : BasePluginTest() { prepare( mainClassWithImports = true, dependenciesBlock = "implementation 'junit:junit:3.8.2'", - applicationBlock = "applicationDefaultJvmArgs = ['--add-opens=java.base/java.lang=ALL-UNNAMED']", + applicationBlock = + "applicationDefaultJvmArgs = ['--add-opens=java.base/java.lang=ALL-UNNAMED']", ) runWithSuccess(installShadowDistPath) val installPath = path("build/install/") - assertThat(installPath.walkEntries()).containsOnly( - "myapp-shadow/bin/myapp", - "myapp-shadow/bin/myapp.bat", - "myapp-shadow/lib/myapp-1.0-all.jar", - ) + assertThat(installPath.walkEntries()) + .containsOnly( + "myapp-shadow/bin/myapp", + "myapp-shadow/bin/myapp.bat", + "myapp-shadow/lib/myapp-1.0-all.jar", + ) commonAssertions( jarPath("myapp-shadow/lib/myapp-1.0-all.jar", installPath), @@ -94,25 +104,26 @@ class ApplicationPluginTest : BasePluginTest() { val unixScript = path("myapp-shadow/bin/myapp", installPath) val winScript = path("myapp-shadow/bin/myapp.bat", installPath) - assertThat(unixScript.readText()).contains( - $$"CLASSPATH=$APP_HOME/lib/myapp-1.0-all.jar", - $$"exec \"$JAVACMD\" \"$@\"", - "DEFAULT_JVM_OPTS='\"--add-opens=java.base/java.lang=ALL-UNNAMED\"'", - ) - assertThat(winScript.readText()).contains( - "set CLASSPATH=%APP_HOME%\\lib\\myapp-1.0-all.jar", - "set DEFAULT_JVM_OPTS=\"--add-opens=java.base/java.lang=ALL-UNNAMED\"", - ) + assertThat(unixScript.readText()) + .contains( + $$"CLASSPATH=$APP_HOME/lib/myapp-1.0-all.jar", + $$"exec \"$JAVACMD\" \"$@\"", + "DEFAULT_JVM_OPTS='\"--add-opens=java.base/java.lang=ALL-UNNAMED\"'", + ) + assertThat(winScript.readText()) + .contains( + "set CLASSPATH=%APP_HOME%\\lib\\myapp-1.0-all.jar", + "set DEFAULT_JVM_OPTS=\"--add-opens=java.base/java.lang=ALL-UNNAMED\"", + ) - val runningOutput = if (isWindows) { - runProcess(winScript.toString(), "bar") - } else { - runProcess(unixScript.toString(), "bar") - } - assertThat(runningOutput).contains( - "Hello, World! (bar) from Main", - "Refs: junit.framework.Test", - ) + val runningOutput = + if (isWindows) { + runProcess(winScript.toString(), "bar") + } else { + runProcess(unixScript.toString(), "bar") + } + assertThat(runningOutput) + .contains("Hello, World! (bar) from Main", "Refs: junit.framework.Test") } @Test @@ -124,20 +135,20 @@ class ApplicationPluginTest : BasePluginTest() { commonAssertions(jarPath("build/install/myapp-shadow/lib/myapp-1.0-all.jar")) } - @Issue( - "https://github.com/GradleUp/shadow/issues/613", - ) + @Issue("https://github.com/GradleUp/shadow/issues/613") @Test fun overrideMainClassAttrInManifestBlock() { val main2ClassEntry = writeClass(className = "Main2") prepare( - projectBlock = """ + projectBlock = + """ shadowJar { manifest { attributes '$mainClassAttributeKey': 'my.Main2' } } - """.trimIndent(), + """ + .trimIndent() ) var result = runWithSuccess(runShadowPath) @@ -158,10 +169,11 @@ class ApplicationPluginTest : BasePluginTest() { projectScript.appendText( """ - run { - args 'bar' - } - """.trimIndent(), + run { + args 'bar' + } + """ + .trimIndent() ) result = runWithSuccess(":run") @@ -177,7 +189,8 @@ class ApplicationPluginTest : BasePluginTest() { $shadowJarTask { mainClass = 'my.Main2' // Different from application.mainClass. } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(runShadowPath) // Run without errors. @@ -193,9 +206,7 @@ class ApplicationPluginTest : BasePluginTest() { val result = runWithFailure(runShadowPath) - assertThat(result.output).contains( - "no main manifest attribute, in", - ) + assertThat(result.output).contains("no main manifest attribute, in") } @Test @@ -203,18 +214,22 @@ class ApplicationPluginTest : BasePluginTest() { path("extra/echo.sh").writeText("echo 'Hello, World!'") path("some/dir/hello.txt").writeText("'Hello, World!'") prepare( - projectBlock = """ + projectBlock = + """ distributions.named('$DISTRIBUTION_NAME') { contents.from('extra/echo.sh') { into 'extra' } } - """.trimIndent(), - applicationBlock = """ + """ + .trimIndent(), + applicationBlock = + """ applicationDistribution.from('some/dir') { include '*.txt' } - """.trimIndent(), + """ + .trimIndent(), ) runWithSuccess(shadowDistZipPath) @@ -222,17 +237,16 @@ class ApplicationPluginTest : BasePluginTest() { val zipPath = path("build/distributions/myapp-shadow-1.0.zip") ZipFile(zipPath.toFile()).use { zip -> val entries = zip.entries().toList().filter { !it.isDirectory }.map { it.name } - assertThat(entries).containsOnly( - "myapp-shadow-1.0/bin/myapp", - "myapp-shadow-1.0/bin/myapp.bat", - "myapp-shadow-1.0/lib/myapp-1.0-all.jar", - "myapp-shadow-1.0/extra/echo.sh", - "myapp-shadow-1.0/hello.txt", - ) - assertThat(zip.getContent("myapp-shadow-1.0/extra/echo.sh")) - .isEqualTo("echo 'Hello, World!'") - assertThat(zip.getContent("myapp-shadow-1.0/hello.txt")) - .isEqualTo("'Hello, World!'") + assertThat(entries) + .containsOnly( + "myapp-shadow-1.0/bin/myapp", + "myapp-shadow-1.0/bin/myapp.bat", + "myapp-shadow-1.0/lib/myapp-1.0-all.jar", + "myapp-shadow-1.0/extra/echo.sh", + "myapp-shadow-1.0/hello.txt", + ) + assertThat(zip.getContent("myapp-shadow-1.0/extra/echo.sh")).isEqualTo("echo 'Hello, World!'") + assertThat(zip.getContent("myapp-shadow-1.0/hello.txt")).isEqualTo("'Hello, World!'") } } @@ -246,14 +260,14 @@ class ApplicationPluginTest : BasePluginTest() { val zipPath = path("build/distributions/myapp-shadow-1.0.zip") ZipFile(zipPath.toFile()).use { zip -> val entries = zip.entries().toList().filter { !it.isDirectory }.map { it.name } - assertThat(entries).containsOnly( - "myapp-shadow-1.0/bin/myapp", - "myapp-shadow-1.0/bin/myapp.bat", - "myapp-shadow-1.0/lib/myapp-1.0-all.jar", - "myapp-shadow-1.0/echo.sh", - ) - assertThat(zip.getContent("myapp-shadow-1.0/echo.sh")) - .isEqualTo("echo 'Hello, World!'") + assertThat(entries) + .containsOnly( + "myapp-shadow-1.0/bin/myapp", + "myapp-shadow-1.0/bin/myapp.bat", + "myapp-shadow-1.0/lib/myapp-1.0-all.jar", + "myapp-shadow-1.0/echo.sh", + ) + assertThat(zip.getContent("myapp-shadow-1.0/echo.sh")).isEqualTo("echo 'Hello, World!'") } } @@ -263,27 +277,31 @@ class ApplicationPluginTest : BasePluginTest() { val executableDirs = "sbin" to "sbin" prepare( - applicationBlock = """ + applicationBlock = + """ applicationName = '${applicationNames.first}' executableDir = '${executableDirs.first}' - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(installShadowDistPath, shadowDistZipPath) - assertThat(path("build/install/").walkEntries()).containsOnly( - "${applicationNames.second}-shadow/${executableDirs.second}/${applicationNames.second}", - "${applicationNames.second}-shadow/${executableDirs.second}/${applicationNames.second}.bat", - "${applicationNames.second}-shadow/lib/myapp-1.0-all.jar", - ) + assertThat(path("build/install/").walkEntries()) + .containsOnly( + "${applicationNames.second}-shadow/${executableDirs.second}/${applicationNames.second}", + "${applicationNames.second}-shadow/${executableDirs.second}/${applicationNames.second}.bat", + "${applicationNames.second}-shadow/lib/myapp-1.0-all.jar", + ) val zipPath = path("build/distributions/${applicationNames.second}-shadow-1.0.zip") ZipFile(zipPath.toFile()).use { zip -> val entries = zip.entries().toList().filter { !it.isDirectory }.map { it.name } - assertThat(entries).containsOnly( - "${applicationNames.second}-shadow-1.0/${executableDirs.second}/${applicationNames.second}", - "${applicationNames.second}-shadow-1.0/${executableDirs.second}/${applicationNames.second}.bat", - "${applicationNames.second}-shadow-1.0/lib/myapp-1.0-all.jar", - ) + assertThat(entries) + .containsOnly( + "${applicationNames.second}-shadow-1.0/${executableDirs.second}/${applicationNames.second}", + "${applicationNames.second}-shadow-1.0/${executableDirs.second}/${applicationNames.second}.bat", + "${applicationNames.second}-shadow-1.0/lib/myapp-1.0-all.jar", + ) } } @@ -312,13 +330,14 @@ class ApplicationPluginTest : BasePluginTest() { args 'foo' $runShadowBlock } - """.trimIndent() + lineSeparator, + """ + .trimIndent() + lineSeparator ) settingsScript.writeText( getDefaultSettingsBuildScript( startBlock = settingsBlock, endBlock = "rootProject.name = 'myapp'", - ), + ) ) } @@ -337,9 +356,10 @@ class ApplicationPluginTest : BasePluginTest() { private companion object { @OptIn(ExperimentalPathApi::class) - fun Path.walkEntries(includeDirs: Boolean = false): Sequence = walk() - .filter { includeDirs || it.isRegularFile() } - .map { it.relativeTo(this) } - .map { it.invariantSeparatorsPathString } + fun Path.walkEntries(includeDirs: Boolean = false): Sequence = + walk() + .filter { includeDirs || it.isRegularFile() } + .map { it.relativeTo(this) } + .map { it.invariantSeparatorsPathString } } } diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/BasePluginTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/BasePluginTest.kt index 8e8fdebfe..416e97836 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/BasePluginTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/BasePluginTest.kt @@ -48,74 +48,75 @@ abstract class BasePluginTest { @TempDir lateinit var projectRoot: Path private set + lateinit var localRepo: AppendableMavenRepository private set lateinit var artifactAJar: Path private set + lateinit var artifactBJar: Path private set - val projectScript: Path get() = path("build.gradle") - val settingsScript: Path get() = path("settings.gradle") - val outputJar: JarPath get() = jarPath("build/libs/my-1.0.jar") - open val outputShadowedJar: JarPath get() = jarPath("build/libs/my-1.0-all.jar") - val outputServerShadowedJar: JarPath get() = jarPath("server/build/libs/server-1.0-all.jar") + val projectScript: Path + get() = path("build.gradle") + + val settingsScript: Path + get() = path("settings.gradle") + + val outputJar: JarPath + get() = jarPath("build/libs/my-1.0.jar") + + open val outputShadowedJar: JarPath + get() = jarPath("build/libs/my-1.0-all.jar") + + val outputServerShadowedJar: JarPath + get() = jarPath("server/build/libs/server-1.0-all.jar") @BeforeAll fun beforeAll() { - localRepo = AppendableMavenRepository( - root = createTempDirectory().resolve("local-maven-repo").createDirectories(), - ).apply { - jarModule("junit", "junit", "3.8.2") { - useJar(junitJar) - } - val a = jarModule("my", "a", "1.0") { - buildJar { - insert("a.properties", "a") - insert("a2.properties", "a2") - } - } - val b = jarModule("my", "b", "1.0") { - buildJar { - insert("b.properties", "b") - } - } - val c = jarModule("my", "c", "1.0") { - buildJar { - insert("c.properties", "c") - } - } - val d = jarModule("my", "d", "1.0") { - buildJar { - insert("d.properties", "d") - } - // Depends on c but c does not depend on d. - addDependency(c) - } - val e = jarModule("my", "e", "1.0") { - buildJar { - insert("e.properties", "e") - } - // Circular dependency with f. - addDependency("my:f:1.0") - } - val f = jarModule("my", "f", "1.0") { - buildJar { - insert("f.properties", "f") + localRepo = + AppendableMavenRepository( + root = createTempDirectory().resolve("local-maven-repo").createDirectories() + ) + .apply { + jarModule("junit", "junit", "3.8.2") { useJar(junitJar) } + val a = + jarModule("my", "a", "1.0") { + buildJar { + insert("a.properties", "a") + insert("a2.properties", "a2") + } + } + val b = jarModule("my", "b", "1.0") { buildJar { insert("b.properties", "b") } } + val c = jarModule("my", "c", "1.0") { buildJar { insert("c.properties", "c") } } + val d = + jarModule("my", "d", "1.0") { + buildJar { insert("d.properties", "d") } + // Depends on c but c does not depend on d. + addDependency(c) + } + val e = + jarModule("my", "e", "1.0") { + buildJar { insert("e.properties", "e") } + // Circular dependency with f. + addDependency("my:f:1.0") + } + val f = + jarModule("my", "f", "1.0") { + buildJar { insert("f.properties", "f") } + // Circular dependency with e. + addDependency(e) + } + bomModule("my", "bom", "1.0") { + addDependency(a) + addDependency(b) + addDependency(c) + addDependency(d) + addDependency(e) + addDependency(f) + } } - // Circular dependency with e. - addDependency(e) - } - bomModule("my", "bom", "1.0") { - addDependency(a) - addDependency(b) - addDependency(c) - addDependency(d) - addDependency(e) - addDependency(f) - } - } localRepo.publish() artifactAJar = path("my/a/1.0/a-1.0.jar", parent = localRepo.root) @@ -135,8 +136,7 @@ abstract class BasePluginTest { @AfterAll fun afterAll() { - @OptIn(ExperimentalPathApi::class) - localRepo.root.deleteRecursively() + @OptIn(ExperimentalPathApi::class) localRepo.root.deleteRecursively() } fun getDefaultProjectBuildScript( @@ -154,13 +154,16 @@ abstract class BasePluginTest { } $groupInfo $versionInfo - """.trimIndent() + lineSeparator + """ + .trimIndent() + lineSeparator } fun getDefaultSettingsBuildScript( startBlock: String = "", - // Use a test-specific build cache directory. This ensures that we'll only use cached outputs generated during - // this test, and we won't accidentally use cached outputs from a different test or a different build. + // Use a test-specific build cache directory. This ensures that we'll only use cached outputs + // generated during + // this test, and we won't accidentally use cached outputs from a different test or a different + // build. // https://docs.gradle.org/current/userguide/build_cache.html#sec:build_cache_configure_local buildCacheBlock: String = "local { directory = file('build-cache') }", endBlock: String = "rootProject.name = 'my'", @@ -178,7 +181,8 @@ abstract class BasePluginTest { } enableFeaturePreview 'TYPESAFE_PROJECT_ACCESSORS' $endBlock - """.trimIndent() + lineSeparator + """ + .trimIndent() + lineSeparator } fun jarPath(relative: String, parent: Path = projectRoot): JarPath { @@ -202,20 +206,16 @@ abstract class BasePluginTest { return JarBuilder(path("temp/$relative")).apply(builder).write() } - fun runWithSuccess( - vararg arguments: String, - block: GradleRunner.() -> Unit = {}, - ): BuildResult { + fun runWithSuccess(vararg arguments: String, block: GradleRunner.() -> Unit = {}): BuildResult { return runner(arguments = arguments.toList(), block = block) - .build().assertNoDeprecationWarnings() + .build() + .assertNoDeprecationWarnings() } - fun runWithFailure( - vararg arguments: String, - block: GradleRunner.() -> Unit = {}, - ): BuildResult { + fun runWithFailure(vararg arguments: String, block: GradleRunner.() -> Unit = {}): BuildResult { return runner(arguments = arguments.toList(), block = block) - .buildAndFail().assertNoDeprecationWarnings() + .buildAndFail() + .assertNoDeprecationWarnings() } fun writeClass( @@ -240,7 +240,8 @@ abstract class BasePluginTest { System.out.println($classRef); } } - """.trimIndent() + """ + .trimIndent() } JvmLang.Kotlin -> { val imports = if (withImports) "import junit.framework.Test" else "" @@ -255,7 +256,8 @@ abstract class BasePluginTest { println(content) println($classRef) } - """.trimIndent() + """ + .trimIndent() } } }, @@ -265,41 +267,46 @@ abstract class BasePluginTest { return "$basePath.class" } - fun writeClientAndServerModules( - clientShadowed: Boolean = false, - serverShadowBlock: String = "", - ) { + fun writeClientAndServerModules(clientShadowed: Boolean = false, serverShadowBlock: String = "") { settingsScript.appendText( """ - include 'client', 'server' - """.trimIndent(), + include 'client', 'server' + """ + .trimIndent() ) projectScript.writeText("") - path("client/src/main/java/client/Client.java").writeText( - """ + path("client/src/main/java/client/Client.java") + .writeText( + """ package client; public class Client {} - """.trimIndent(), - ) - path("client/build.gradle").writeText( - """ + """ + .trimIndent() + ) + path("client/build.gradle") + .writeText( + """ ${getDefaultProjectBuildScript("java")} dependencies { implementation 'junit:junit:3.8.2' } - """.trimIndent() + lineSeparator, - ) - - path("server/src/main/java/server/Server.java").writeText( """ + .trimIndent() + lineSeparator + ) + + path("server/src/main/java/server/Server.java") + .writeText( + """ package server; import client.Client; public class Server {} - """.trimIndent(), - ) - path("server/build.gradle").writeText( - """ + """ + .trimIndent() + ) + path("server/build.gradle") + .writeText( + """ ${getDefaultProjectBuildScript("java")} dependencies { implementation project(':client') @@ -307,27 +314,34 @@ abstract class BasePluginTest { $shadowJarTask { $serverShadowBlock } - """.trimIndent() + lineSeparator, - ) + """ + .trimIndent() + lineSeparator + ) if (!clientShadowed) return - path("client/build.gradle").appendText( - """ + path("client/build.gradle") + .appendText( + """ $shadowJarTask { relocate 'junit.framework', 'client.junit.framework' } - """.trimIndent() + lineSeparator, - ) - path("server/src/main/java/server/Server.java").writeText( """ + .trimIndent() + lineSeparator + ) + path("server/src/main/java/server/Server.java") + .writeText( + """ package server; import client.Client; import client.junit.framework.Test; public class Server {} - """.trimIndent(), - ) - val replaced = path("server/build.gradle").readText() - .replace("project(':client')", "project(path: ':client', configuration: 'shadow')") + """ + .trimIndent() + ) + val replaced = + path("server/build.gradle") + .readText() + .replace("project(':client')", "project(path: ':client', configuration: 'shadow')") path("server/build.gradle").writeText(replaced) } @@ -343,11 +357,13 @@ abstract class BasePluginTest { } } } - """.trimIndent() + lineSeparator, + """ + .trimIndent() + lineSeparator ) - path("src/main/java/my/plugin/MyPlugin.java").writeText( - """ + path("src/main/java/my/plugin/MyPlugin.java") + .writeText( + """ package my.plugin; import org.gradle.api.Plugin; import org.gradle.api.Project; @@ -356,19 +372,18 @@ abstract class BasePluginTest { System.out.println("MyPlugin: Hello, World!"); } } - """.trimIndent(), - ) + """ + .trimIndent() + ) } - private fun runner( - arguments: Iterable, - block: GradleRunner.() -> Unit, - ): GradleRunner { - val warningsAsErrors = try { - projectScript.readText().toWarningsAsErrors() - } catch (_: UninitializedPropertyAccessException) { - true // Default warning mode if projectScript is not initialized yet. - } + private fun runner(arguments: Iterable, block: GradleRunner.() -> Unit): GradleRunner { + val warningsAsErrors = + try { + projectScript.readText().toWarningsAsErrors() + } catch (_: UninitializedPropertyAccessException) { + true // Default warning mode if projectScript is not initialized yet. + } return gradleRunner( projectDir = projectRoot, arguments = commonGradleArgs + arguments, @@ -392,17 +407,19 @@ abstract class BasePluginTest { val entriesInB = arrayOf("b.properties") val entriesInAB = entriesInA + entriesInB val junitJar: Path = requireResourceAsPath("junit-3.8.2.jar") - val junitRawEntries: List = JarPath(junitJar) - .use { it.entries().toList() } - .filterNot { - // This entry is not present in the jar file. - it.name == "junit3.8.2/" - } + val junitRawEntries: List = + JarPath(junitJar) + .use { it.entries().toList() } + .filterNot { + // This entry is not present in the jar file. + it.name == "junit3.8.2/" + } val junitEntries: Array = junitRawEntries.map { it.name }.toTypedArray() const val manifestEntry = "META-INF/MANIFEST.MF" val manifestEntries = arrayOf("META-INF/", manifestEntry) - val shadowJarTask: String = "tasks.named('$SHADOW_JAR_TASK_NAME', ${ShadowJar::class.java.name})" + val shadowJarTask: String = + "tasks.named('$SHADOW_JAR_TASK_NAME', ${ShadowJar::class.java.name})" const val runShadowTask = "tasks.named('$SHADOW_RUN_TASK_NAME', JavaExec)" const val jarTask = "tasks.named('jar', Jar)" @@ -414,7 +431,9 @@ abstract class BasePluginTest { fun String.toProperties(): Properties = Properties().apply { load(byteInputStream()) } fun implementationFiles(vararg paths: Path): String { - return paths.joinToString(lineSeparator) { "implementation files('${it.invariantSeparatorsPathString}')" } + return paths.joinToString(lineSeparator) { + "implementation files('${it.invariantSeparatorsPathString}')" + } } inline fun transform( @@ -430,7 +449,8 @@ abstract class BasePluginTest { $transformerBlock } } - """.trimIndent() + """ + .trimIndent() } fun Assert.useAll(body: Assert.() -> Unit) = all { diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/CachingTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/CachingTest.kt index eee97ff53..e80cb6010 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/CachingTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/CachingTest.kt @@ -30,63 +30,48 @@ class CachingTest : BasePluginTest() { fun dependenciesChanged() { projectScript.appendText( """ - dependencies { - implementation 'my:a:1.0' - implementation 'my:b:1.0' - } - """.trimIndent(), + dependencies { + implementation 'my:a:1.0' + implementation 'my:b:1.0' + } + """ + .trimIndent() ) - assertCompositeExecutions { - containsOnly( - *entriesInAB, - *manifestEntries, - ) - } + assertCompositeExecutions { containsOnly(*entriesInAB, *manifestEntries) } val replaced = projectScript.readText().replace("implementation 'my:b:1.0'", "") projectScript.writeText(replaced) - assertCompositeExecutions { - containsOnly( - *entriesInA, - *manifestEntries, - ) - } + assertCompositeExecutions { containsOnly(*entriesInA, *manifestEntries) } } @Test fun outputFileChanged() { projectScript.appendText( """ - dependencies { - implementation 'my:a:1.0' - implementation 'my:b:1.0' - } - """.trimIndent() + lineSeparator, + dependencies { + implementation 'my:a:1.0' + implementation 'my:b:1.0' + } + """ + .trimIndent() + lineSeparator ) - assertCompositeExecutions { - containsOnly( - *entriesInAB, - *manifestEntries, - ) - } + assertCompositeExecutions { containsOnly(*entriesInAB, *manifestEntries) } projectScript.appendText( """ $shadowJarTask { archiveBaseName = "foo" } - """.trimIndent(), + """ + .trimIndent() ) assertExecutionsFromCacheAndUpToDate() assertThat(jarPath("build/libs/foo-1.0-all.jar")).useAll { - containsOnly( - *entriesInAB, - *manifestEntries, - ) + containsOnly(*entriesInAB, *manifestEntries) } } @@ -94,19 +79,14 @@ class CachingTest : BasePluginTest() { fun dependencyFilterChanged() { projectScript.appendText( """ - dependencies { - implementation 'my:d:1.0' - } - """.trimIndent() + lineSeparator, + dependencies { + implementation 'my:d:1.0' + } + """ + .trimIndent() + lineSeparator ) val assertions = { - assertCompositeExecutions { - containsOnly( - "c.properties", - "d.properties", - *manifestEntries, - ) - } + assertCompositeExecutions { containsOnly("c.properties", "d.properties", *manifestEntries) } } assertions() @@ -116,7 +96,8 @@ class CachingTest : BasePluginTest() { $shadowJarTask { dependencyFilter = new ${MinimizeDependencyFilter::class.java.name}(project) } - """.trimIndent(), + """ + .trimIndent() ) assertions() @@ -124,22 +105,20 @@ class CachingTest : BasePluginTest() { @Test fun duplicatesStrategyChanged() { - listOf( - DuplicatesStrategy.EXCLUDE, - DuplicatesStrategy.INCLUDE, - DuplicatesStrategy.WARN, - ).forEach { strategy -> - projectScript.writeText( - """ + listOf(DuplicatesStrategy.EXCLUDE, DuplicatesStrategy.INCLUDE, DuplicatesStrategy.WARN) + .forEach { strategy -> + projectScript.writeText( + """ ${getDefaultProjectBuildScript()} $shadowJarTask { duplicatesStrategy = DuplicatesStrategy.$strategy } - """.trimIndent(), - ) + """ + .trimIndent() + ) - assertCompositeExecutions() - } + assertCompositeExecutions() + } } @Test @@ -156,7 +135,8 @@ class CachingTest : BasePluginTest() { attributes 'Bar': 'Bar1' } } - """.trimIndent(), + """ + .trimIndent() ) val assertions = { valueFoo: String, valueBar: String -> @@ -178,9 +158,7 @@ class CachingTest : BasePluginTest() { assertions("Foo2", "Bar2") - replaced = projectScript.readText() - .replace("Foo2", "Foo3") - .replace("Bar2", "Bar3") + replaced = projectScript.readText().replace("Foo2", "Foo3").replace("Bar2", "Bar3") projectScript.writeText(replaced) assertions("Foo3", "Bar3") @@ -199,19 +177,16 @@ class CachingTest : BasePluginTest() { it.mainClass.set('$mainClassName') } } - """.trimIndent(), + """ + .trimIndent() ) - assertCompositeExecutions { - getMainAttr(mainClassAttributeKey).isEqualTo(mainClassName) - } + assertCompositeExecutions { getMainAttr(mainClassAttributeKey).isEqualTo(mainClassName) } val replaced = projectScript.readText().replace(mainClassName, main2ClassName) projectScript.writeText(replaced) - assertCompositeExecutions { - getMainAttr(mainClassAttributeKey).isEqualTo(main2ClassName) - } + assertCompositeExecutions { getMainAttr(mainClassAttributeKey).isEqualTo(main2ClassName) } } @Test @@ -225,45 +200,35 @@ class CachingTest : BasePluginTest() { application { mainClass = '$mainClassName' } - """.trimIndent(), + """ + .trimIndent() ) - assertCompositeExecutions { - getMainAttr(mainClassAttributeKey).isEqualTo(mainClassName) - } + assertCompositeExecutions { getMainAttr(mainClassAttributeKey).isEqualTo(mainClassName) } val replaced = projectScript.readText().replace(mainClassName, main2ClassName) projectScript.writeText(replaced) - assertCompositeExecutions { - getMainAttr(mainClassAttributeKey).isEqualTo(main2ClassName) - } + assertCompositeExecutions { getMainAttr(mainClassAttributeKey).isEqualTo(main2ClassName) } } - @Issue( - "https://github.com/GradleUp/shadow/issues/717", - ) + @Issue("https://github.com/GradleUp/shadow/issues/717") @Test fun jarIncludesExcludesChanged() { val mainClassEntry = writeClass(className = "Main") val main2ClassEntry = writeClass(className = "Main2") projectScript.appendText( """ - dependencies { - implementation 'my:a:1.0' - implementation 'my:b:1.0' - } - """.trimIndent() + lineSeparator, + dependencies { + implementation 'my:a:1.0' + implementation 'my:b:1.0' + } + """ + .trimIndent() + lineSeparator ) assertCompositeExecutions { - containsOnly( - "my/", - mainClassEntry, - main2ClassEntry, - *entriesInAB, - *manifestEntries, - ) + containsOnly("my/", mainClassEntry, main2ClassEntry, *entriesInAB, *manifestEntries) } projectScript.appendText( @@ -271,16 +236,12 @@ class CachingTest : BasePluginTest() { $shadowJarTask { exclude '**.properties' } - """.trimIndent() + lineSeparator, + """ + .trimIndent() + lineSeparator ) assertCompositeExecutions { - containsOnly( - "my/", - mainClassEntry, - main2ClassEntry, - *manifestEntries, - ) + containsOnly("my/", mainClassEntry, main2ClassEntry, *manifestEntries) } projectScript.appendText( @@ -288,32 +249,23 @@ class CachingTest : BasePluginTest() { $shadowJarTask { include '$mainClassEntry' } - """.trimIndent() + lineSeparator, + """ + .trimIndent() + lineSeparator ) - assertCompositeExecutions { - containsOnly( - "my/", - mainClassEntry, - *manifestEntries, - ) - } + assertCompositeExecutions { containsOnly("my/", mainClassEntry, *manifestEntries) } projectScript.appendText( """ $shadowJarTask { include '$main2ClassEntry' } - """.trimIndent() + lineSeparator, + """ + .trimIndent() + lineSeparator ) assertCompositeExecutions { - containsOnly( - "my/", - mainClassEntry, - main2ClassEntry, - *manifestEntries, - ) + containsOnly("my/", mainClassEntry, main2ClassEntry, *manifestEntries) } } @@ -322,19 +274,15 @@ class CachingTest : BasePluginTest() { val mainClassEntry = writeClass(withImports = true) projectScript.appendText( """ - dependencies { - implementation 'junit:junit:3.8.2' - } - """.trimIndent() + lineSeparator, + dependencies { + implementation 'junit:junit:3.8.2' + } + """ + .trimIndent() + lineSeparator ) assertCompositeExecutions { - containsOnly( - "my/", - mainClassEntry, - *junitEntries, - *manifestEntries, - ) + containsOnly("my/", mainClassEntry, *junitEntries, *manifestEntries) } projectScript.appendText( @@ -344,16 +292,11 @@ class CachingTest : BasePluginTest() { exclude(dependency('junit:junit')) } } - """.trimIndent(), + """ + .trimIndent() ) - assertCompositeExecutions { - containsOnly( - "my/", - mainClassEntry, - *manifestEntries, - ) - } + assertCompositeExecutions { containsOnly("my/", mainClassEntry, *manifestEntries) } } @Test @@ -361,16 +304,16 @@ class CachingTest : BasePluginTest() { taskPath = serverShadowJarPath writeClientAndServerModules() - path("server/src/main/java/server/Server.java").writeText( - """ + path("server/src/main/java/server/Server.java") + .writeText( + """ package server; public class Server {} - """.trimIndent(), - ) + """ + .trimIndent() + ) - assertCompositeExecutions( - jarPathProvider = { outputServerShadowedJar }, - ) { + assertCompositeExecutions(jarPathProvider = { outputServerShadowedJar }) { containsOnly( "client/", "server/", @@ -381,25 +324,20 @@ class CachingTest : BasePluginTest() { ) } - path("server/build.gradle").appendText( - """ + path("server/build.gradle") + .appendText( + """ $shadowJarTask { minimize { exclude(dependency('junit:junit:.*')) } } - """.trimIndent(), - ) - - assertCompositeExecutions( - jarPathProvider = { outputServerShadowedJar }, - ) { - containsOnly( - "server/", - "server/Server.class", - *junitEntries, - *manifestEntries, + """ + .trimIndent() ) + + assertCompositeExecutions(jarPathProvider = { outputServerShadowedJar }) { + containsOnly("server/", "server/Server.class", *junitEntries, *manifestEntries) } } @@ -407,20 +345,16 @@ class CachingTest : BasePluginTest() { fun relocatorChanged() { projectScript.appendText( """ - dependencies { - implementation 'junit:junit:3.8.2' - } - """.trimIndent() + lineSeparator, + dependencies { + implementation 'junit:junit:3.8.2' + } + """ + .trimIndent() + lineSeparator ) val mainClassEntry = writeClass(withImports = true) assertCompositeExecutions { - containsOnly( - "my/", - mainClassEntry, - *junitEntries, - *manifestEntries, - ) + containsOnly("my/", mainClassEntry, *junitEntries, *manifestEntries) } projectScript.appendText( @@ -428,20 +362,14 @@ class CachingTest : BasePluginTest() { $shadowJarTask { relocate 'junit.framework', 'foo.junit.framework' } - """.trimIndent(), + """ + .trimIndent() ) - val relocatedEntries = junitEntries - .map { it.replace("junit/framework/", "foo/junit/framework/") }.toTypedArray() + val relocatedEntries = + junitEntries.map { it.replace("junit/framework/", "foo/junit/framework/") }.toTypedArray() assertCompositeExecutions { - containsOnly( - "my/", - "foo/", - "foo/junit/", - mainClassEntry, - *relocatedEntries, - *manifestEntries, - ) + containsOnly("my/", "foo/", "foo/junit/", mainClassEntry, *relocatedEntries, *manifestEntries) } } @@ -449,23 +377,19 @@ class CachingTest : BasePluginTest() { fun serviceFileTransformerPropsChanged() { val mainClassEntry = writeClass() val assertions = { - assertCompositeExecutions { - containsOnly( - "my/", - mainClassEntry, - *manifestEntries, - ) - } + assertCompositeExecutions { containsOnly("my/", mainClassEntry, *manifestEntries) } } assertions() projectScript.appendText( transform( - transformerBlock = """ + transformerBlock = + """ path = 'META-INF/foo' - """.trimIndent(), - ), + """ + .trimIndent() + ) ) assertions() @@ -483,7 +407,8 @@ class CachingTest : BasePluginTest() { $shadowJarTask { mergeServiceFiles() } - """.trimIndent() + lineSeparator, + """ + .trimIndent() + lineSeparator ) assertCompositeExecutions() @@ -493,7 +418,8 @@ class CachingTest : BasePluginTest() { $shadowJarTask { mergeGroovyExtensionModules() } - """.trimIndent() + lineSeparator, + """ + .trimIndent() + lineSeparator ) assertCompositeExecutions() @@ -504,7 +430,8 @@ class CachingTest : BasePluginTest() { // Use Transformer.Companion (no-op) to mock a custom transformer here, it's not cacheable. transform(${ResourceTransformer.Companion::class.java.name}) } - """.trimIndent(), + """ + .trimIndent() ) assertExecutionSuccess() @@ -538,7 +465,8 @@ class CachingTest : BasePluginTest() { } /** - * Combines [assertExecutionSuccess] and [assertExecutionsFromCacheAndUpToDate] for simplifying assertions. + * Combines [assertExecutionSuccess] and [assertExecutionsFromCacheAndUpToDate] for simplifying + * assertions. */ private fun assertCompositeExecutions( jarPathProvider: () -> JarPath = { outputShadowedJar }, diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/FilteringTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/FilteringTest.kt index 612522f68..be80e5e49 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/FilteringTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/FilteringTest.kt @@ -16,11 +16,12 @@ class FilteringTest : BasePluginTest() { super.beforeEach() projectScript.appendText( """ - dependencies { - implementation 'my:a:1.0' - implementation 'my:b:1.0' - } - """.trimIndent() + lineSeparator, + dependencies { + implementation 'my:a:1.0' + implementation 'my:b:1.0' + } + """ + .trimIndent() + lineSeparator ) } @@ -28,12 +29,7 @@ class FilteringTest : BasePluginTest() { fun includeAllDependencies() { runWithSuccess(shadowJarPath) - assertThat(outputShadowedJar).useAll { - containsOnly( - *entriesInAB, - *manifestEntries, - ) - } + assertThat(outputShadowedJar).useAll { containsOnly(*entriesInAB, *manifestEntries) } } @Test @@ -43,17 +39,14 @@ class FilteringTest : BasePluginTest() { $shadowJarTask { exclude 'a2.properties' } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) assertThat(outputShadowedJar).useAll { - containsOnly( - "a.properties", - "b.properties", - *manifestEntries, - ) + containsOnly("a.properties", "b.properties", *manifestEntries) } } @@ -62,12 +55,13 @@ class FilteringTest : BasePluginTest() { fun excludeDependency(useAccessor: Boolean) { settingsScript.appendText( """ - dependencyResolutionManagement { - versionCatalogs.create('libs') { - library('my-d', 'my:d:1.0') - } + dependencyResolutionManagement { + versionCatalogs.create('libs') { + library('my-d', 'my:d:1.0') } - """.trimIndent(), + } + """ + .trimIndent() ) val dependency = if (useAccessor) "libs.my.d" else "'my:d:1.0'" projectScript.appendText( @@ -80,7 +74,8 @@ class FilteringTest : BasePluginTest() { exclude(dependency($dependency)) } } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) @@ -89,16 +84,7 @@ class FilteringTest : BasePluginTest() { } @ParameterizedTest - @ValueSource( - strings = [ - "my:d", - "m.*:d", - "my:d:.*", - "m.*:d:.*", - "m.*:d.*:.*", - ".*:d:.*", - ], - ) + @ValueSource(strings = ["my:d", "m.*:d", "my:d:.*", "m.*:d:.*", "m.*:d.*:.*", ".*:d:.*"]) fun excludeDependencyUsingWildcardSyntax(wildcard: String) { projectScript.appendText( """ @@ -110,7 +96,8 @@ class FilteringTest : BasePluginTest() { exclude(dependency('$wildcard')) } } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) @@ -130,24 +117,22 @@ class FilteringTest : BasePluginTest() { include(dependency('my:d:1.0')) } } - """.trimIndent(), - ) - path("src/main/java/my/Passed.java").writeText( """ + .trimIndent() + ) + path("src/main/java/my/Passed.java") + .writeText( + """ package my; public class Passed {} - """.trimIndent(), - ) + """ + .trimIndent() + ) runWithSuccess(shadowJarPath) assertThat(outputShadowedJar).useAll { - containsOnly( - "d.properties", - "my/", - "my/Passed.class", - *manifestEntries, - ) + containsOnly("d.properties", "my/", "my/Passed.class", *manifestEntries) } } @@ -156,59 +141,53 @@ class FilteringTest : BasePluginTest() { fun filterProjectDependencies(useAccessor: Boolean) { val clientProject = if (useAccessor) "project(projects.client)" else "project(':client')" writeClientAndServerModules( - serverShadowBlock = """ + serverShadowBlock = + """ dependencies { exclude($clientProject) } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(serverShadowJarPath) assertThat(outputServerShadowedJar).useAll { - containsOnly( - "server/", - "server/Server.class", - *junitEntries, - *manifestEntries, - ) + containsOnly("server/", "server/Server.class", *junitEntries, *manifestEntries) } } - @Issue( - "https://github.com/GradleUp/shadow/issues/671", - ) + @Issue("https://github.com/GradleUp/shadow/issues/671") @Test fun filterProjectThatVersionContainsPlus() { writeClientAndServerModules( - serverShadowBlock = """ + serverShadowBlock = + """ dependencies { exclude(project(':client')) } - """.trimIndent(), + """ + .trimIndent() ) path("client/build.gradle").appendText("version = '1.0.0+1'") runWithSuccess(serverShadowJarPath) assertThat(outputServerShadowedJar).useAll { - containsOnly( - "server/", - "server/Server.class", - *junitEntries, - *manifestEntries, - ) + containsOnly("server/", "server/Server.class", *junitEntries, *manifestEntries) } } @Test fun excludeTransitiveProjectDependency() { writeClientAndServerModules( - serverShadowBlock = """ + serverShadowBlock = + """ dependencies { exclude { it.moduleGroup == 'junit' } } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(serverShadowJarPath) @@ -233,17 +212,14 @@ class FilteringTest : BasePluginTest() { include '*.properties' exclude 'a2.properties' } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) assertThat(outputShadowedJar).useAll { - containsOnly( - "a.properties", - "b.properties", - *manifestEntries, - ) + containsOnly("a.properties", "b.properties", *manifestEntries) } } @@ -260,27 +236,20 @@ class FilteringTest : BasePluginTest() { exclude(dependency($dependency)) } } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) assertThat(outputShadowedJar).useAll { - containsOnly( - "f.properties", - *entriesInAB, - *manifestEntries, - ) + containsOnly("f.properties", *entriesInAB, *manifestEntries) } } private fun commonAssertions() { assertThat(outputShadowedJar).useAll { - containsOnly( - "c.properties", - *entriesInAB, - *manifestEntries, - ) + containsOnly("c.properties", *entriesInAB, *manifestEntries) } } } diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/FindResourceInClasspathTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/FindResourceInClasspathTest.kt index 115d940c1..e2c1edffc 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/FindResourceInClasspathTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/FindResourceInClasspathTest.kt @@ -29,16 +29,18 @@ class FindResourceInClasspathTest : BasePluginTest() { classpath = configurations.runtimeClasspath exclude("a.properties") } - """.trimIndent(), + """ + .trimIndent() ) - assertThat(runWithSuccess(":find1").output).contains( - "> Task :find1", - "scanning ", - "/my/a/1.0/a-1.0.jar".variantSeparatorsPathString, - "/a.properties".variantSeparatorsPathString, - "/a2.properties".variantSeparatorsPathString, - ) + assertThat(runWithSuccess(":find1").output) + .contains( + "> Task :find1", + "scanning ", + "/my/a/1.0/a-1.0.jar".variantSeparatorsPathString, + "/a.properties".variantSeparatorsPathString, + "/a2.properties".variantSeparatorsPathString, + ) assertThat(runWithSuccess(":find2").output).all { contains( @@ -47,9 +49,7 @@ class FindResourceInClasspathTest : BasePluginTest() { "/my/a/1.0/a-1.0.jar".variantSeparatorsPathString, "/a.properties".variantSeparatorsPathString, ) - doesNotContain( - "/a2.properties".variantSeparatorsPathString, - ) + doesNotContain("/a2.properties".variantSeparatorsPathString) } assertThat(runWithSuccess(":find3").output).all { @@ -59,9 +59,7 @@ class FindResourceInClasspathTest : BasePluginTest() { "/my/a/1.0/a-1.0.jar".variantSeparatorsPathString, "/a2.properties".variantSeparatorsPathString, ) - doesNotContain( - "/a.properties".variantSeparatorsPathString, - ) + doesNotContain("/a.properties".variantSeparatorsPathString) } } } diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/JavaPluginsTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/JavaPluginsTest.kt index 767325988..b1016fa16 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/JavaPluginsTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/JavaPluginsTest.kt @@ -47,13 +47,11 @@ import org.junit.jupiter.params.provider.MethodSource import org.junit.jupiter.params.provider.ValueSource class JavaPluginsTest : BasePluginTest() { - @Issue( - "https://github.com/GradleUp/shadow/pull/1766", - ) + @Issue("https://github.com/GradleUp/shadow/pull/1766") @Test fun makeAssembleDependOnShadowJarEvenIfAddedLater() { - val kFunction = ShadowJar.Companion::class.declaredFunctions - .single { it.name == "registerShadowJarCommon" } + val kFunction = + ShadowJar.Companion::class.declaredFunctions.single { it.name == "registerShadowJarCommon" } val jvmName = checkNotNull(kFunction.javaMethod).name projectScript.writeText( @@ -77,38 +75,39 @@ class JavaPluginsTest : BasePluginTest() { } } } - """.trimIndent(), + """ + .trimIndent() ) val result = runWithSuccess(ASSEMBLE_TASK_NAME) - assertThat(result.task(":$ASSEMBLE_TASK_NAME")).isNotNull() - .transform { it.outcome }.isEqualTo(SUCCESS) - assertThat(result.task(shadowJarPath)).isNotNull() - .transform { it.outcome }.isEqualTo(SUCCESS) - assertThat(result.output).contains( - "task dependencies: $SHADOW_JAR_TASK_NAME", - ) + assertThat(result.task(":$ASSEMBLE_TASK_NAME")) + .isNotNull() + .transform { it.outcome } + .isEqualTo(SUCCESS) + assertThat(result.task(shadowJarPath)).isNotNull().transform { it.outcome }.isEqualTo(SUCCESS) + assertThat(result.output).contains("task dependencies: $SHADOW_JAR_TASK_NAME") } @Test fun shadowJarCliOptions() { val result = runWithSuccess("help", "--task", shadowJarPath) - assertThat(result.output).contains( - "--add-multi-release-attribute Adds the multi-release attribute to the manifest if any dependencies contain it.", - "--no-add-multi-release-attribute Disables option --add-multi-release-attribute.", - "--enable-auto-relocation Enables auto relocation of packages in the dependencies.", - "--no-enable-auto-relocation Disables option --enable-auto-relocation.", - "--enable-kotlin-module-remapping Enables remapping of Kotlin module metadata files.", - "--no-enable-kotlin-module-remapping Disables option --enable-kotlin-module-remapping.", - "--fail-on-duplicate-entries Fails build if the ZIP entries in the shadowed JAR are duplicate.", - "--no-fail-on-duplicate-entries Disables option --fail-on-duplicate-entries", - "--main-class Main class attribute to add to manifest.", - "--minimize-jar Minimizes the jar by removing unused classes.", - "--no-minimize-jar Disables option --minimize-jar.", - "--relocation-prefix Prefix used for auto relocation of packages in the dependencies.", - ) + assertThat(result.output) + .contains( + "--add-multi-release-attribute Adds the multi-release attribute to the manifest if any dependencies contain it.", + "--no-add-multi-release-attribute Disables option --add-multi-release-attribute.", + "--enable-auto-relocation Enables auto relocation of packages in the dependencies.", + "--no-enable-auto-relocation Disables option --enable-auto-relocation.", + "--enable-kotlin-module-remapping Enables remapping of Kotlin module metadata files.", + "--no-enable-kotlin-module-remapping Disables option --enable-kotlin-module-remapping.", + "--fail-on-duplicate-entries Fails build if the ZIP entries in the shadowed JAR are duplicate.", + "--no-fail-on-duplicate-entries Disables option --fail-on-duplicate-entries", + "--main-class Main class attribute to add to manifest.", + "--minimize-jar Minimizes the jar by removing unused classes.", + "--no-minimize-jar Disables option --minimize-jar.", + "--relocation-prefix Prefix used for auto relocation of packages in the dependencies.", + ) } @Test @@ -136,29 +135,19 @@ class JavaPluginsTest : BasePluginTest() { runWithSuccess(":server:jar") assertThat(jarPath("server/build/libs/server-1.0.jar")).useAll { - containsOnly( - "server/", - "server/Server.class", - *manifestEntries, - ) + containsOnly("server/", "server/Server.class", *manifestEntries) } assertThat(jarPath("client/build/libs/client-1.0-all.jar")).useAll { - containsAtLeast( - "client/", - "client/Client.class", - "client/junit/framework/Test.class", - ) - containsNone( - "server/Server.class", - ) + containsAtLeast("client/", "client/Client.class", "client/junit/framework/Test.class") + containsNone("server/Server.class") } } @Test fun shadowProjectShadowJar() { writeClientAndServerModules(clientShadowed = true) - val relocatedEntries = junitEntries - .map { it.replace("junit/framework/", "client/junit/framework/") }.toTypedArray() + val relocatedEntries = + junitEntries.map { it.replace("junit/framework/", "client/junit/framework/") }.toTypedArray() runWithSuccess(serverShadowJarPath) @@ -174,44 +163,43 @@ class JavaPluginsTest : BasePluginTest() { ) } assertThat(jarPath("client/build/libs/client-1.0-all.jar")).useAll { - containsAtLeast( - "client/Client.class", - "client/junit/framework/Test.class", - ) - containsNone( - "server/Server.class", - ) + containsAtLeast("client/Client.class", "client/junit/framework/Test.class") + containsNone("server/Server.class") } } - @Issue( - "https://github.com/GradleUp/shadow/issues/1606", - ) + @Issue("https://github.com/GradleUp/shadow/issues/1606") @Test fun shadowExposedCustomSourceSetOutput() { writeClientAndServerModules() - path("client/build.gradle").appendText( - """ + path("client/build.gradle") + .appendText( + """ sourceSets { custom } dependencies { implementation sourceSets.custom.output } - """.trimIndent(), - ) - path("client/src/custom/java/client/Custom1.java").writeText( - """ + """ + .trimIndent() + ) + path("client/src/custom/java/client/Custom1.java") + .writeText( + """ package client; public class Custom1 {} - """.trimIndent(), - ) - path("client/src/custom/java/client/Custom2.java").writeText( - """ + """ + .trimIndent() + ) + path("client/src/custom/java/client/Custom2.java") + .writeText( + """ package client; public class Custom2 {} - """.trimIndent(), - ) + """ + .trimIndent() + ) path("client/src/custom/resources/Foo.bar").writeText("Foo=Bar") runWithSuccess(serverShadowJarPath) @@ -231,39 +219,42 @@ class JavaPluginsTest : BasePluginTest() { } } - @Issue( - "https://github.com/GradleUp/shadow/issues/449", - ) + @Issue("https://github.com/GradleUp/shadow/issues/449") @ParameterizedTest @ValueSource(booleans = [false, true]) fun containsMultiReleaseAttrIfAnyDependencyContainsIt(addAttribute: Boolean) { writeClientAndServerModules() - path("client/build.gradle").appendText( - """ + path("client/build.gradle") + .appendText( + """ $jarTask { manifest { attributes '$multiReleaseAttributeKey': 'true' } } - """.trimIndent() + lineSeparator, - ) - path("server/build.gradle").appendText( """ + .trimIndent() + lineSeparator + ) + path("server/build.gradle") + .appendText( + """ $shadowJarTask { addMultiReleaseAttribute = $addAttribute } - """.trimIndent(), - ) + """ + .trimIndent() + ) val result = runWithSuccess(serverShadowJarPath, infoArgument) - assertThat(result.output).contains( - if (addAttribute) { - "Adding Multi-Release attribute to the manifest if any dependencies contain it." - } else { - "Skipping adding Multi-Release attribute to the manifest as it is disabled." - }, - ) + assertThat(result.output) + .contains( + if (addAttribute) { + "Adding Multi-Release attribute to the manifest if any dependencies contain it." + } else { + "Skipping adding Multi-Release attribute to the manifest as it is disabled." + } + ) assertThat(outputServerShadowedJar.use { it.getMainAttr(multiReleaseAttributeKey) }) .isEqualTo(if (addAttribute) "true" else null) } @@ -272,26 +263,29 @@ class JavaPluginsTest : BasePluginTest() { @ValueSource(booleans = [false, true]) fun containsMultiReleaseAttrByCliOption(enable: Boolean) { writeClientAndServerModules() - path("client/build.gradle").appendText( - """ + path("client/build.gradle") + .appendText( + """ $jarTask { manifest { attributes '$multiReleaseAttributeKey': 'true' } } - """.trimIndent() + lineSeparator, - ) + """ + .trimIndent() + lineSeparator + ) val arg = if (enable) "--add-multi-release-attribute" else "--no-add-multi-release-attribute" val result = runWithSuccess(serverShadowJarPath, infoArgument, arg) - assertThat(result.output).contains( - if (enable) { - "Adding Multi-Release attribute to the manifest if any dependencies contain it." - } else { - "Skipping adding Multi-Release attribute to the manifest as it is disabled." - }, - ) + assertThat(result.output) + .contains( + if (enable) { + "Adding Multi-Release attribute to the manifest if any dependencies contain it." + } else { + "Skipping adding Multi-Release attribute to the manifest as it is disabled." + } + ) assertThat(outputServerShadowedJar.use { it.getMainAttr(multiReleaseAttributeKey) }) .isEqualTo(if (enable) "true" else null) } @@ -302,77 +296,64 @@ class JavaPluginsTest : BasePluginTest() { ) @Test fun excludeSomeResourcesByDefault() { - val resJar = buildJar("meta-inf.jar") { - insert("META-INF/INDEX.LIST", "JarIndex-Version: 1.0") - insert("META-INF/a.SF", "Signature File") - insert("META-INF/a.DSA", "DSA Signature Block") - insert("META-INF/a.RSA", "RSA Signature Block") - insert("META-INF/a.properties", "key=value") - insert("META-INF/versions/9/module-info.class", "module myModuleName {}") - insert("META-INF/versions/16/module-info.class", "module myModuleName {}") - insert("module-info.class", "module myModuleName {}") - } + val resJar = + buildJar("meta-inf.jar") { + insert("META-INF/INDEX.LIST", "JarIndex-Version: 1.0") + insert("META-INF/a.SF", "Signature File") + insert("META-INF/a.DSA", "DSA Signature Block") + insert("META-INF/a.RSA", "RSA Signature Block") + insert("META-INF/a.properties", "key=value") + insert("META-INF/versions/9/module-info.class", "module myModuleName {}") + insert("META-INF/versions/16/module-info.class", "module myModuleName {}") + insert("module-info.class", "module myModuleName {}") + } projectScript.appendText( """ dependencies { ${implementationFiles(resJar)} } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) - assertThat(outputShadowedJar).useAll { - containsOnly( - "META-INF/a.properties", - *manifestEntries, - ) - } + assertThat(outputShadowedJar).useAll { containsOnly("META-INF/a.properties", *manifestEntries) } } @Test fun includeRuntimeConfigurationByDefault() { projectScript.appendText( """ - dependencies { - runtimeOnly 'my:a:1.0' - shadow 'my:b:1.0' - compileOnly 'my:b:1.0' - } - """.trimIndent(), + dependencies { + runtimeOnly 'my:a:1.0' + shadow 'my:b:1.0' + compileOnly 'my:b:1.0' + } + """ + .trimIndent() ) runWithSuccess(shadowJarPath) - assertThat(outputShadowedJar).useAll { - containsOnly( - *entriesInA, - *manifestEntries, - ) - } + assertThat(outputShadowedJar).useAll { containsOnly(*entriesInA, *manifestEntries) } } @Test fun includeJavaLibraryConfigurationsByDefault() { - localRepo.apply { - jarModule("my", "api", "1.0") { - buildJar { - insert("api.properties", "api") - } - } - jarModule("my", "implementation", "1.0") { - buildJar { - insert("implementation.properties", "implementation") + localRepo + .apply { + jarModule("my", "api", "1.0") { buildJar { insert("api.properties", "api") } } + jarModule("my", "implementation", "1.0") { + buildJar { insert("implementation.properties", "implementation") } + addDependency("my:b:1.0") } - addDependency("my:b:1.0") - } - jarModule("my", "runtime-only", "1.0") { - buildJar { - insert("runtime-only.properties", "runtime-only") + jarModule("my", "runtime-only", "1.0") { + buildJar { insert("runtime-only.properties", "runtime-only") } } } - }.publish() + .publish() projectScript.writeText( """ @@ -382,7 +363,8 @@ class JavaPluginsTest : BasePluginTest() { implementation 'my:implementation:1.0' runtimeOnly 'my:runtime-only:1.0' } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) @@ -402,10 +384,11 @@ class JavaPluginsTest : BasePluginTest() { fun classPathInManifestNotAddedIfEmpty() { projectScript.appendText( """ - dependencies { - implementation 'junit:junit:3.8.2' - } - """.trimIndent(), + dependencies { + implementation 'junit:junit:3.8.2' + } + """ + .trimIndent() ) runWithSuccess(shadowJarPath) @@ -416,9 +399,7 @@ class JavaPluginsTest : BasePluginTest() { } } - @Issue( - "https://github.com/GradleUp/shadow/issues/65", - ) + @Issue("https://github.com/GradleUp/shadow/issues/65") @ParameterizedTest @ValueSource(strings = [ShadowBasePlugin.CONFIGURATION_NAME, IMPLEMENTATION_CONFIGURATION_NAME]) fun addShadowConfigurationToClassPathInManifest(configuration: String) { @@ -432,30 +413,31 @@ class JavaPluginsTest : BasePluginTest() { attributes '$classPathAttributeKey': '/libs/foo.jar' } } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) val actual = outputShadowedJar.use { it.getMainAttr(classPathAttributeKey) } - val expected = when (configuration) { - ShadowBasePlugin.CONFIGURATION_NAME -> "/libs/foo.jar junit-3.8.2.jar" - else -> "/libs/foo.jar" - } + val expected = + when (configuration) { + ShadowBasePlugin.CONFIGURATION_NAME -> "/libs/foo.jar junit-3.8.2.jar" + else -> "/libs/foo.jar" + } assertThat(actual).isEqualTo(expected) } - @Issue( - "https://github.com/GradleUp/shadow/issues/92", - ) + @Issue("https://github.com/GradleUp/shadow/issues/92") @Test fun doNotIncludeNullValueInClassPathWhenJarFileDoesNotContainClassPath() { projectScript.appendText( """ - dependencies { - shadow 'junit:junit:3.8.2' - } - """.trimIndent(), + dependencies { + shadow 'junit:junit:3.8.2' + } + """ + .trimIndent() ) runWithSuccess(shadowJarPath) @@ -464,9 +446,7 @@ class JavaPluginsTest : BasePluginTest() { assertThat(value).isEqualTo("junit-3.8.2.jar") } - @Issue( - "https://github.com/GradleUp/shadow/issues/203", - ) + @Issue("https://github.com/GradleUp/shadow/issues/203") @ParameterizedTest @EnumSource(ZipEntryCompression::class) fun supportZipCompressions(method: ZipEntryCompression) { @@ -479,17 +459,13 @@ class JavaPluginsTest : BasePluginTest() { zip64 = true entryCompression = ${ZipEntryCompression::class.java.canonicalName}.$method } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) - assertThat(outputShadowedJar).useAll { - containsOnly( - *junitEntries, - *manifestEntries, - ) - } + assertThat(outputShadowedJar).useAll { containsOnly(*junitEntries, *manifestEntries) } } @Issue( @@ -501,18 +477,22 @@ class JavaPluginsTest : BasePluginTest() { writeGradlePluginModule() projectScript.appendText( """ - dependencies { - implementation 'my:a:1.0' - compileOnly 'my:b:1.0' - } - """.trimIndent(), + dependencies { + implementation 'my:a:1.0' + compileOnly 'my:b:1.0' + } + """ + .trimIndent() ) runWithSuccess(shadowJarPath) assertThat(outputShadowedJar).useAll { - transform { actual -> actual.entries().toList().map { it.name }.filter { it.endsWith(".class") } } - .single().isEqualTo("my/plugin/MyPlugin.class") + transform { actual -> + actual.entries().toList().map { it.name }.filter { it.endsWith(".class") } + } + .single() + .isEqualTo("my/plugin/MyPlugin.class") transform { it.mainAttrSize }.isEqualTo(1) // Doesn't contain Gradle classes. getMainAttr(classPathAttributeKey).isNull() @@ -529,9 +509,7 @@ class JavaPluginsTest : BasePluginTest() { } } - @Issue( - "https://github.com/GradleUp/shadow/issues/1422", - ) + @Issue("https://github.com/GradleUp/shadow/issues/1422") @Test fun moveLocalGradleApiToCompileOnly() { projectScript.writeText(getDefaultProjectBuildScript("java-gradle-plugin")) @@ -544,27 +522,24 @@ class JavaPluginsTest : BasePluginTest() { assertThat(outputApi).doesNotContain("unspecified") } - @Issue( - "https://github.com/GradleUp/shadow/issues/1422", - ) + @Issue("https://github.com/GradleUp/shadow/issues/1422") @ParameterizedTest @ValueSource(strings = [COMPILE_ONLY_CONFIGURATION_NAME, API_CONFIGURATION_NAME]) fun doNotReAddSuppressedGradleApi(configuration: String) { projectScript.writeText(getDefaultProjectBuildScript("java-gradle-plugin")) - val output = dependencies( - configuration = configuration, - // Internal flag added in 8.14 to experiment with suppressing local Gradle API. - "-Dorg.gradle.unsafe.suppress-gradle-api=true", - ) + val output = + dependencies( + configuration = configuration, + // Internal flag added in 8.14 to experiment with suppressing local Gradle API. + "-Dorg.gradle.unsafe.suppress-gradle-api=true", + ) // "unspecified" is the local Gradle API. assertThat(output).doesNotContain("unspecified") } - @Issue( - "https://github.com/GradleUp/shadow/issues/1070", - ) + @Issue("https://github.com/GradleUp/shadow/issues/1070") @Test fun registerCustomShadowJarTask() { val mainClassEntry = writeClass(sourceSet = "test", withImports = true) @@ -583,32 +558,24 @@ class JavaPluginsTest : BasePluginTest() { attributes '$mainClassAttributeKey': 'my.Main' } } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(testShadowJarTask) assertThat(jarPath("build/libs/my-1.0-test.jar")).useAll { - containsOnly( - "my/", - mainClassEntry, - *junitEntries, - *manifestEntries, - ) + containsOnly("my/", mainClassEntry, *junitEntries, *manifestEntries) getMainAttr(mainClassAttributeKey).isNotNull() } val pathString = path("build/libs/my-1.0-test.jar").toString() val runningOutput = runProcess("java", "-jar", pathString, "foo") - assertThat(runningOutput).contains( - "Hello, World! (foo) from Main", - "Refs: junit.framework.Test", - ) + assertThat(runningOutput) + .contains("Hello, World! (foo) from Main", "Refs: junit.framework.Test") } - @Issue( - "https://github.com/GradleUp/shadow/issues/1784", - ) + @Issue("https://github.com/GradleUp/shadow/issues/1784") @Test fun registerShadowJarTaskWithoutShadowPluginApplied() { val mainClassEntry = writeClass(sourceSet = "test", withImports = true) @@ -634,37 +601,26 @@ class JavaPluginsTest : BasePluginTest() { logger.lifecycle("Has ShadowPlugin: " + hasShadowPlugin) logger.lifecycle("Has ShadowBasePlugin: " + hasShadowBasePlugin) } - """.trimIndent(), + """ + .trimIndent() ) val result = runWithSuccess(testShadowJarTask) - assertThat(result.output).contains( - "Has ShadowPlugin: false", - "Has ShadowBasePlugin: false", - ) + assertThat(result.output).contains("Has ShadowPlugin: false", "Has ShadowBasePlugin: false") assertThat(jarPath("build/libs/my-1.0-test.jar")).useAll { - containsOnly( - "my/", - mainClassEntry, - *junitEntries, - *manifestEntries, - ) + containsOnly("my/", mainClassEntry, *junitEntries, *manifestEntries) getMainAttr(mainClassAttributeKey).isNotNull() } val pathString = path("build/libs/my-1.0-test.jar").toString() val runningOutput = runProcess("java", "-jar", pathString, "foo") - assertThat(runningOutput).contains( - "Hello, World! (foo) from Main", - "Refs: junit.framework.Test", - ) + assertThat(runningOutput) + .contains("Hello, World! (foo) from Main", "Refs: junit.framework.Test") } - @Issue( - "https://github.com/GradleUp/shadow/issues/443", - ) + @Issue("https://github.com/GradleUp/shadow/issues/443") @Test fun registerCustomShadowJarThatContainsDependenciesOnly() { val mainClassEntry = writeClass() @@ -680,43 +636,34 @@ class JavaPluginsTest : BasePluginTest() { archiveClassifier = 'dep' configurations = project.configurations.named('runtimeClasspath').map { [it] } } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess("jar", dependencyShadowJar) assertThat(jarPath("build/libs/my-1.0.jar")).useAll { - containsOnly( - "my/", - mainClassEntry, - *manifestEntries, - ) + containsOnly("my/", mainClassEntry, *manifestEntries) transform { it.mainAttrSize }.isEqualTo(1) } assertThat(jarPath("build/libs/my-1.0-dep.jar")).useAll { - containsOnly( - *junitEntries, - *manifestEntries, - ) + containsOnly(*junitEntries, *manifestEntries) transform { it.mainAttrSize }.isEqualTo(1) } } - @Issue( - "https://github.com/GradleUp/shadow/issues/915", - ) + @Issue("https://github.com/GradleUp/shadow/issues/915") @Test fun failBuildIfProcessingBadJar() { - val badJarPath = path("bad.jar").apply { - writeText("A bad jar.") - } + val badJarPath = path("bad.jar").apply { writeText("A bad jar.") } projectScript.appendText( """ dependencies { ${implementationFiles(badJarPath)} } - """.trimIndent(), + """ + .trimIndent() ) val result = runWithFailure(shadowJarPath) @@ -733,15 +680,14 @@ class JavaPluginsTest : BasePluginTest() { dependencies { ${implementationFiles(fooAarPath)} } - """.trimIndent(), + """ + .trimIndent() ) val result = runWithFailure(shadowJarPath) - assertThat(result.output).contains( - "Shadowing AAR file is not supported.", - "Please exclude dependency artifact:", - ) + assertThat(result.output) + .contains("Shadowing AAR file is not supported.", "Please exclude dependency artifact:") } @Test @@ -761,7 +707,8 @@ class JavaPluginsTest : BasePluginTest() { into('Bar') } } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) @@ -785,9 +732,7 @@ class JavaPluginsTest : BasePluginTest() { inputStream.copyTo(unzipped.outputStream()) } } - assertThat(jarPath(unzipped.name)).useAll { - containsOnly(*entriesInA) - } + assertThat(jarPath(unzipped.name)).useAll { containsOnly(*entriesInA) } } @Test @@ -802,32 +747,23 @@ class JavaPluginsTest : BasePluginTest() { $shadowJarTask { from(nonJar) } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) assertThat(outputShadowedJar).useAll { - containsOnly( - "a-1.0.jar", - "b-1.0.jar", - *manifestEntries, - ) + containsOnly("a-1.0.jar", "b-1.0.jar", *manifestEntries) } } - @Issue( - "https://github.com/GradleUp/shadow/issues/520", - ) + @Issue("https://github.com/GradleUp/shadow/issues/520") @Test fun onlyKeepFilesFromProjectWhenDuplicatesStrategyIsExclude() { - val fooJar = buildJar("foo.jar") { - insert("module-info.class", "module myModuleName {}") - } + val fooJar = buildJar("foo.jar") { insert("module-info.class", "module myModuleName {}") } val mainClassEntry = writeClass() - writeClass(className = "module-info") { - "module myModuleName {}" - } + writeClass(className = "module-info") { "module myModuleName {}" } projectScript.appendText( """ dependencies { @@ -838,18 +774,14 @@ class JavaPluginsTest : BasePluginTest() { 'module-info.class' ) } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) assertThat(outputShadowedJar).useAll { - containsOnly( - "module-info.class", - "my/", - mainClassEntry, - *manifestEntries, - ) + containsOnly("module-info.class", "my/", mainClassEntry, *manifestEntries) getContent("module-info.class").all { isNotEmpty() // It's the compiled class instead of the original content. @@ -858,9 +790,7 @@ class JavaPluginsTest : BasePluginTest() { } } - @Issue( - "https://github.com/GradleUp/shadow/issues/1441", - ) + @Issue("https://github.com/GradleUp/shadow/issues/1441") @Test fun includeFilesInTaskOutputDirectory() { // Create a build that has a task with jars in the output directory @@ -888,14 +818,13 @@ class JavaPluginsTest : BasePluginTest() { $$shadowJarTask { includedDependencies.from(files(createJars).asFileTree) } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) - assertThat(outputShadowedJar).useAll { - containsOnly(*entriesInAB, *manifestEntries) - } + assertThat(outputShadowedJar).useAll { containsOnly(*entriesInAB, *manifestEntries) } } @Test @@ -903,25 +832,25 @@ class JavaPluginsTest : BasePluginTest() { writeClientAndServerModules() settingsScript.prependText( """ - plugins { - id 'com.gradle.develocity' - } - """.trimIndent() + lineSeparator, + plugins { + id 'com.gradle.develocity' + } + """ + .trimIndent() + lineSeparator ) - val result = runWithSuccess( - serverShadowJarPath, - ipArgument, - infoArgument, - "-P${ENABLE_DEVELOCITY_INTEGRATION_PROPERTY}=true", - "-Dscan.dump", // Using scan.dump avoids actually publishing a Build Scan, writing it to a file instead. - ) + val result = + runWithSuccess( + serverShadowJarPath, + ipArgument, + infoArgument, + "-P${ENABLE_DEVELOCITY_INTEGRATION_PROPERTY}=true", + "-Dscan.dump", // Using scan.dump avoids actually publishing a Build Scan, writing it to a + // file instead. + ) assertThat(result.output).all { - contains( - "Enabling Develocity integration for Shadow plugin.", - "Build scan written", - ) + contains("Enabling Develocity integration for Shadow plugin.", "Build scan written") doesNotContain("Configuration cache problems") } } @@ -939,19 +868,19 @@ class JavaPluginsTest : BasePluginTest() { duplicatesStrategy = DuplicatesStrategy.INCLUDE failOnDuplicateEntries = $enable } - """.trimIndent(), + """ + .trimIndent() ) - val result = if (enable) { - runWithFailure(shadowJarPath) - } else { - runWithSuccess(shadowJarPath, infoArgument) - } + val result = + if (enable) { + runWithFailure(shadowJarPath) + } else { + runWithSuccess(shadowJarPath, infoArgument) + } - assertThat(result.output).contains( - "Duplicate entries found in the shadowed JAR:", - "a.properties (2 times)", - ) + assertThat(result.output) + .contains("Duplicate entries found in the shadowed JAR:", "a.properties (2 times)") } @ParameterizedTest @@ -966,19 +895,19 @@ class JavaPluginsTest : BasePluginTest() { $shadowJarTask { duplicatesStrategy = DuplicatesStrategy.INCLUDE } - """.trimIndent(), + """ + .trimIndent() ) - val result = if (enable) { - runWithFailure(shadowJarPath, "--fail-on-duplicate-entries") - } else { - runWithSuccess(shadowJarPath, infoArgument, "--no-fail-on-duplicate-entries") - } + val result = + if (enable) { + runWithFailure(shadowJarPath, "--fail-on-duplicate-entries") + } else { + runWithSuccess(shadowJarPath, infoArgument, "--no-fail-on-duplicate-entries") + } - assertThat(result.output).contains( - "Duplicate entries found in the shadowed JAR:", - "a.properties (2 times)", - ) + assertThat(result.output) + .contains("Duplicate entries found in the shadowed JAR:", "a.properties (2 times)") } @ParameterizedTest @@ -989,17 +918,14 @@ class JavaPluginsTest : BasePluginTest() { $shadowJarTask { mainClass = '$input' } - """.trimIndent(), + """ + .trimIndent() ) val result = runWithSuccess(shadowJarPath, infoArgument) - assertThat(result.output).contains( - message, - ) - assertThat(outputShadowedJar).useAll { - getMainAttr(mainClassAttributeKey).isEqualTo(expected) - } + assertThat(result.output).contains(message) + assertThat(outputShadowedJar).useAll { getMainAttr(mainClassAttributeKey).isEqualTo(expected) } } @ParameterizedTest @@ -1011,9 +937,7 @@ class JavaPluginsTest : BasePluginTest() { runWithSuccess(shadowJarPath, "--main-class", input) } - assertThat(outputShadowedJar).useAll { - getMainAttr(mainClassAttributeKey).isEqualTo(expected) - } + assertThat(outputShadowedJar).useAll { getMainAttr(mainClassAttributeKey).isEqualTo(expected) } } private fun dependencies(configuration: String, vararg flags: String): String { @@ -1022,9 +946,18 @@ class JavaPluginsTest : BasePluginTest() { private companion object { @JvmStatic - fun fallbackMainClassProvider() = listOf( - Arguments.of("my.Main", "my.Main", "Adding $mainClassAttributeKey attribute to the manifest with value"), - Arguments.of("", null, "Skipping adding $mainClassAttributeKey attribute to the manifest as it is empty."), - ) + fun fallbackMainClassProvider() = + listOf( + Arguments.of( + "my.Main", + "my.Main", + "Adding $mainClassAttributeKey attribute to the manifest with value", + ), + Arguments.of( + "", + null, + "Skipping adding $mainClassAttributeKey attribute to the manifest as it is empty.", + ), + ) } } diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/KotlinPluginsTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/KotlinPluginsTest.kt index 6a13603d1..84b763e4a 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/KotlinPluginsTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/KotlinPluginsTest.kt @@ -21,7 +21,9 @@ class KotlinPluginsTest : BasePluginTest() { @BeforeEach override fun beforeEach() { super.beforeEach() - projectScript.writeText(getDefaultProjectBuildScript(plugin = "org.jetbrains.kotlin.multiplatform")) + projectScript.writeText( + getDefaultProjectBuildScript(plugin = "org.jetbrains.kotlin.multiplatform") + ) } @ParameterizedTest @@ -36,20 +38,16 @@ class KotlinPluginsTest : BasePluginTest() { implementation 'junit:junit:3.8.2' $stdlib } - """.trimIndent(), + """ + .trimIndent() ) val mainClassEntry = writeClass(withImports = true, jvmLang = JvmLang.Kotlin) runWithSuccess(shadowJarPath) assertThat(outputShadowedJar).useAll { - val entries = arrayOf( - "my/", - "META-INF/my.kotlin_module", - mainClassEntry, - *junitEntries, - *manifestEntries, - ) + val entries = + arrayOf("my/", "META-INF/my.kotlin_module", mainClassEntry, *junitEntries, *manifestEntries) if (excludeStdlib) { containsOnly(*entries) } else { @@ -82,19 +80,15 @@ class KotlinPluginsTest : BasePluginTest() { } } } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) assertThat(outputShadowedJar).useAll { - val entries = arrayOf( - "my/", - "META-INF/my.kotlin_module", - mainClassEntry, - *entriesInAB, - *manifestEntries, - ) + val entries = + arrayOf("my/", "META-INF/my.kotlin_module", mainClassEntry, *entriesInAB, *manifestEntries) if (excludeStdlib) { containsOnly(*entries) } else { @@ -103,9 +97,7 @@ class KotlinPluginsTest : BasePluginTest() { } } - @Issue( - "https://github.com/GradleUp/shadow/issues/1377", - ) + @Issue("https://github.com/GradleUp/shadow/issues/1377") @Test fun compatKmpForOtherNamedJvmTarget() { val jvmTargetName = "newJvm" @@ -130,41 +122,37 @@ class KotlinPluginsTest : BasePluginTest() { } } } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) assertThat(outputShadowedJar).useAll { - val entries = arrayOf( - "my/", - "META-INF/my.kotlin_module", - mainClassEntry, - *entriesInAB, - *manifestEntries, - ) + val entries = + arrayOf("my/", "META-INF/my.kotlin_module", mainClassEntry, *entriesInAB, *manifestEntries) containsAtLeast(*entries) } } - @Issue( - "https://github.com/GradleUp/shadow/issues/1377", - ) + @Issue("https://github.com/GradleUp/shadow/issues/1377") @Test fun doNotCreateJvmTargetEagerly() { projectScript.appendText( """ - kotlin { - mingwX64() - } - """.trimIndent(), + kotlin { + mingwX64() + } + """ + .trimIndent() ) val result = runWithFailure(shadowJarPath) - assertThat(result.output).contains( - "Cannot locate tasks that match ':shadowJar' as task 'shadowJar' not found in root project", - ) + assertThat(result.output) + .contains( + "Cannot locate tasks that match ':shadowJar' as task 'shadowJar' not found in root project" + ) } @ParameterizedTest @@ -172,7 +160,8 @@ class KotlinPluginsTest : BasePluginTest() { fun setMainClassAttributeFromMainRun(useShadowAttr: Boolean) { val mainClassName = "my.Main" val main2ClassName = "my.Main2" - val mainAttr = if (useShadowAttr) "attributes '$mainClassAttributeKey': '$main2ClassName'" else "" + val mainAttr = + if (useShadowAttr) "attributes '$mainClassAttributeKey': '$main2ClassName'" else "" projectScript.appendText( """ kotlin { @@ -185,13 +174,15 @@ class KotlinPluginsTest : BasePluginTest() { $mainAttr } } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) assertThat(outputShadowedJar).useAll { - getMainAttr(mainClassAttributeKey).isEqualTo(if (useShadowAttr) main2ClassName else mainClassName) + getMainAttr(mainClassAttributeKey) + .isEqualTo(if (useShadowAttr) main2ClassName else mainClassName) } } @@ -200,7 +191,8 @@ class KotlinPluginsTest : BasePluginTest() { fun setManifestAttrsFromJvmTargetJar(useShadowAttr: Boolean) { val mainClassName = "my.Main" val main2ClassName = "my.Main2" - val mainAttr = if (useShadowAttr) "attributes '$mainClassAttributeKey': '$main2ClassName'" else "" + val mainAttr = + if (useShadowAttr) "attributes '$mainClassAttributeKey': '$main2ClassName'" else "" projectScript.appendText( """ kotlin { @@ -216,13 +208,15 @@ class KotlinPluginsTest : BasePluginTest() { $mainAttr } } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) assertThat(outputShadowedJar).useAll { - getMainAttr(mainClassAttributeKey).isEqualTo(if (useShadowAttr) main2ClassName else mainClassName) + getMainAttr(mainClassAttributeKey) + .isEqualTo(if (useShadowAttr) main2ClassName else mainClassName) } } @@ -252,15 +246,17 @@ class KotlinPluginsTest : BasePluginTest() { } } } - """.trimIndent(), + """ + .trimIndent() ) val result = runWithFailure(shadowJarPath, infoArgument) - assertThat(result.output).contains( - "$SHADOW_JAR_TASK_NAME task already exists, skipping configuration for target: $jvmTargetName", // Logged from Shadow. - "Declaring multiple Kotlin Targets of the same type is not supported.", // Thrown from KGP. - ) + assertThat(result.output) + .contains( + "$SHADOW_JAR_TASK_NAME task already exists, skipping configuration for target: $jvmTargetName", // Logged from Shadow. + "Declaring multiple Kotlin Targets of the same type is not supported.", // Thrown from KGP. + ) } private fun compileOnlyStdlib(exclude: Boolean): String { diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/MinimizeTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/MinimizeTest.kt index 272ee76fd..aa50d6e82 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/MinimizeTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/MinimizeTest.kt @@ -14,12 +14,13 @@ import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.ValueSource class MinimizeTest : BasePluginTest() { - private val outputImplShadowedJar: JarPath get() = jarPath("impl/build/libs/impl-1.0-all.jar") + private val outputImplShadowedJar: JarPath + get() = jarPath("impl/build/libs/impl-1.0-all.jar") /** - * 'api' used as api for 'impl', and depended on 'lib'. 'junit' is independent. - * The minimize step shall remove 'junit', but not 'api'. - * Unused classes of 'api' and theirs dependencies also shouldn't be removed. + * 'api' used as api for 'impl', and depended on 'lib'. 'junit' is independent. The minimize step + * shall remove 'junit', but not 'api'. Unused classes of 'api' and theirs dependencies also + * shouldn't be removed. */ @Test fun useMinimizeWithDependenciesWithApiScope() { @@ -42,22 +43,24 @@ class MinimizeTest : BasePluginTest() { } /** - * 'api' used as api for 'impl', and 'lib' used as api for 'api'. - * Unused classes of 'api' and 'lib' shouldn't be removed. + * 'api' used as api for 'impl', and 'lib' used as api for 'api'. Unused classes of 'api' and + * 'lib' shouldn't be removed. */ @Test fun useMinimizeWithTransitiveDependenciesWithApiScope() { writeApiLibAndImplModules() - path("api/build.gradle").writeText( - """ + path("api/build.gradle") + .writeText( + """ plugins { id 'java-library' } dependencies { api project(':lib') } - """.trimIndent(), - ) + """ + .trimIndent() + ) runWithSuccess(":impl:$SHADOW_JAR_TASK_NAME") @@ -76,84 +79,76 @@ class MinimizeTest : BasePluginTest() { } } - /** - * 'Server' depends on 'Client'. 'junit' is independent. - * The minimize shall remove 'junit'. - */ + /** 'Server' depends on 'Client'. 'junit' is independent. The minimize shall remove 'junit'. */ @Test fun minimizeByKeepingOnlyTransitiveDependencies() { writeClientAndServerModules( - serverShadowBlock = """ + serverShadowBlock = + """ minimize() - """.trimIndent(), + """ + .trimIndent() ) - path("server/src/main/java/server/Server.java").writeText( - """ + path("server/src/main/java/server/Server.java") + .writeText( + """ package server; import client.Client; public class Server { // This is to make sure that 'Client' is not removed. private final String client = Client.class.getName(); } - """.trimIndent(), - ) + """ + .trimIndent() + ) runWithSuccess(serverShadowJarPath) assertThat(outputServerShadowedJar).useAll { - containsAtLeast( - "client/Client.class", - "server/Server.class", - ) - containsNone( - "junit/framework/Test.class", - ) + containsAtLeast("client/Client.class", "server/Server.class") + containsNone("junit/framework/Test.class") } } /** - * 'Client', 'Server' and 'junit' are independent. - * 'junit' is excluded from the minimize step. - * The minimize step shall remove 'Client' but not 'junit'. + * 'Client', 'Server' and 'junit' are independent. 'junit' is excluded from the minimize step. The + * minimize step shall remove 'Client' but not 'junit'. */ @Test fun excludeDependencyFromMinimize() { writeClientAndServerModules( - serverShadowBlock = """ + serverShadowBlock = + """ minimize { exclude(dependency('junit:junit:.*')) } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(serverShadowJarPath) assertThat(outputServerShadowedJar).useAll { - containsAtLeast( - "server/Server.class", - *junitEntries, - ) - containsNone( - "client/Client.class", - ) + containsAtLeast("server/Server.class", *junitEntries) + containsNone("client/Client.class") } } /** - * 'Client', 'Server' and 'junit' are independent. - * Unused classes of 'client' and theirs dependencies shouldn't be removed. + * 'Client', 'Server' and 'junit' are independent. Unused classes of 'client' and theirs + * dependencies shouldn't be removed. */ - @Issue( - "https://github.com/GradleUp/shadow/issues/744", - ) + @Issue("https://github.com/GradleUp/shadow/issues/744") @Test fun excludeProjectFromMinimize() { writeClientAndServerModules( - serverShadowBlock = """ + serverShadowBlock = + """ minimize { exclude(project(':client')) } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(serverShadowJarPath) @@ -171,58 +166,54 @@ class MinimizeTest : BasePluginTest() { } /** - * 'Client', 'Server' and 'junit' are independent. - * Unused classes of 'client' and theirs dependencies shouldn't be removed. + * 'Client', 'Server' and 'junit' are independent. Unused classes of 'client' and theirs + * dependencies shouldn't be removed. */ @Test fun excludeProjectFromMinimizeShallNotExcludeTransitiveDependenciesThatAreUsedInSubproject() { writeClientAndServerModules( - serverShadowBlock = """ + serverShadowBlock = + """ minimize { exclude(project(':client')) } - """.trimIndent(), + """ + .trimIndent() ) - path("client/src/main/java/client/Client.java").writeText( - """ + path("client/src/main/java/client/Client.java") + .writeText( + """ package client; import junit.framework.TestCase; public class Client extends TestCase { public static void main(String[] args) {} } - """.trimIndent(), - ) + """ + .trimIndent() + ) runWithSuccess(serverShadowJarPath) assertThat(outputServerShadowedJar).useAll { - containsAtLeast( - "client/Client.class", - "server/Server.class", - *junitEntries, - ) + containsAtLeast("client/Client.class", "server/Server.class", *junitEntries) } - path("client/src/main/java/client/Client.java").writeText( - """ + path("client/src/main/java/client/Client.java") + .writeText( + """ package client; public class Client {} - """.trimIndent(), - ) + """ + .trimIndent() + ) runWithSuccess(serverShadowJarPath) assertThat(outputServerShadowedJar).useAll { - containsAtLeast( - "client/Client.class", - "server/Server.class", - *junitEntries, - ) + containsAtLeast("client/Client.class", "server/Server.class", *junitEntries) } } - @Issue( - "https://github.com/GradleUp/shadow/issues/1610", - ) + @Issue("https://github.com/GradleUp/shadow/issues/1610") @Test fun excludeCircularDependencies() { val dependency = "'my:e:1.0'" @@ -236,17 +227,14 @@ class MinimizeTest : BasePluginTest() { exclude(dependency($dependency)) } } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) assertThat(outputShadowedJar).useAll { - containsOnly( - "e.properties", - "f.properties", - *manifestEntries, - ) + containsOnly("e.properties", "f.properties", *manifestEntries) } } @@ -263,13 +251,8 @@ class MinimizeTest : BasePluginTest() { assertThat(outputServerShadowedJar).useAll { if (enable) { - containsAtLeast( - "server/Server.class", - *manifestEntries, - ) - containsNone( - "client/Client.class", - ) + containsAtLeast("server/Server.class", *manifestEntries) + containsNone("client/Client.class") } else { containsOnly( "client/", @@ -283,19 +266,19 @@ class MinimizeTest : BasePluginTest() { } } - @Issue( - "https://github.com/GradleUp/shadow/issues/1636", - ) + @Issue("https://github.com/GradleUp/shadow/issues/1636") @Test fun minimizeBomDependency() { writeApiLibAndImplModules() - path("impl/build.gradle").appendText( - """ + path("impl/build.gradle") + .appendText( + """ dependencies { api platform('my:bom:1.0') } - """.trimIndent(), - ) + """ + .trimIndent() + ) runWithSuccess(":impl:$SHADOW_JAR_TASK_NAME") @@ -316,46 +299,58 @@ class MinimizeTest : BasePluginTest() { private fun writeApiLibAndImplModules() { settingsScript.appendText( """ - include 'api', 'lib', 'impl' - """.trimIndent() + lineSeparator, + include 'api', 'lib', 'impl' + """ + .trimIndent() + lineSeparator ) projectScript.writeText("") - path("lib/src/main/java/lib/LibEntity.java").writeText( - """ + path("lib/src/main/java/lib/LibEntity.java") + .writeText( + """ package lib; public interface LibEntity {} - """.trimIndent(), - ) - path("lib/src/main/java/lib/UnusedLibEntity.java").writeText( - """ + """ + .trimIndent() + ) + path("lib/src/main/java/lib/UnusedLibEntity.java") + .writeText( + """ package lib; public class UnusedLibEntity implements LibEntity {} - """.trimIndent(), - ) - path("lib/build.gradle").writeText( - """ + """ + .trimIndent() + ) + path("lib/build.gradle") + .writeText( + """ plugins { id 'java' } - """.trimIndent() + lineSeparator, - ) + """ + .trimIndent() + lineSeparator + ) - path("api/src/main/java/api/Entity.java").writeText( - """ + path("api/src/main/java/api/Entity.java") + .writeText( + """ package api; public interface Entity {} - """.trimIndent(), - ) - path("api/src/main/java/api/UnusedEntity.java").writeText( - """ + """ + .trimIndent() + ) + path("api/src/main/java/api/UnusedEntity.java") + .writeText( + """ package api; import lib.LibEntity; public class UnusedEntity implements LibEntity {} - """.trimIndent(), - ) - path("api/build.gradle").writeText( - """ + """ + .trimIndent() + ) + path("api/build.gradle") + .writeText( + """ plugins { id 'java' } @@ -363,18 +358,22 @@ class MinimizeTest : BasePluginTest() { implementation 'junit:junit:3.8.2' implementation project(':lib') } - """.trimIndent() + lineSeparator, - ) + """ + .trimIndent() + lineSeparator + ) - path("impl/src/main/java/impl/SimpleEntity.java").writeText( - """ + path("impl/src/main/java/impl/SimpleEntity.java") + .writeText( + """ package impl; import api.Entity; public class SimpleEntity implements Entity {} - """.trimIndent(), - ) - path("impl/build.gradle").writeText( - """ + """ + .trimIndent() + ) + path("impl/build.gradle") + .writeText( + """ ${getDefaultProjectBuildScript("java-library")} dependencies { api project(':api') @@ -382,7 +381,8 @@ class MinimizeTest : BasePluginTest() { $shadowJarTask { minimize() } - """.trimIndent() + lineSeparator, - ) + """ + .trimIndent() + lineSeparator + ) } } diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/PublishingTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/PublishingTest.kt index 181bd3711..754ce1caf 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/PublishingTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/PublishingTest.kt @@ -51,8 +51,7 @@ import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.ValueSource class PublishingTest : BasePluginTest() { - @TempDir - lateinit var remoteRepoPath: Path + @TempDir lateinit var remoteRepoPath: Path @BeforeEach override fun beforeEach() { @@ -63,17 +62,20 @@ class PublishingTest : BasePluginTest() { @DisabledOnOs( OS.WINDOWS, architectures = ["aarch64"], - disabledReason = "Cannot use toolchain on Windows ARM64", // TODO: remove when min Gradle is bumped to 9.2+ + disabledReason = + "Cannot use toolchain on Windows ARM64", // TODO: remove when min Gradle is bumped to 9.2+ ) @Test fun publishShadowJarWithCorrectTargetJvm() { projectScript.appendText( publishConfiguration( - shadowBlock = """ + shadowBlock = + """ archiveClassifier = '' archiveBaseName = 'maven-all' - """.trimIndent(), - ) + lineSeparator, + """ + .trimIndent() + ) + lineSeparator ) val assertions = { variantAttrs: Array> -> @@ -85,88 +87,98 @@ class PublishingTest : BasePluginTest() { assertions(shadowVariantAttrs) - val attrsWithoutTargetJvm = shadowVariantAttrs.filterNot { (name, _) -> - name == TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE.name - }.toTypedArray() + val attrsWithoutTargetJvm = + shadowVariantAttrs + .filterNot { (name, _) -> name == TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE.name } + .toTypedArray() val targetJvmAttr17 = TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE.name to "17" val targetJvmAttr11 = TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE.name to "11" val targetJvmAttr8 = TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE.name to "8" settingsScript.prependText( """ - plugins { - id 'org.gradle.toolchains.foojay-resolver-convention' - } - """.trimIndent() + lineSeparator, + plugins { + id 'org.gradle.toolchains.foojay-resolver-convention' + } + """ + .trimIndent() + lineSeparator ) projectScript.appendText( """ - java { - toolchain.languageVersion = JavaLanguageVersion.of(17) - } - """.trimIndent() + lineSeparator, + java { + toolchain.languageVersion = JavaLanguageVersion.of(17) + } + """ + .trimIndent() + lineSeparator ) assertions(attrsWithoutTargetJvm + targetJvmAttr17) projectScript.appendText( """ - java { - targetCompatibility = JavaVersion.VERSION_11 - } - """.trimIndent() + lineSeparator, + java { + targetCompatibility = JavaVersion.VERSION_11 + } + """ + .trimIndent() + lineSeparator ) assertions(attrsWithoutTargetJvm + targetJvmAttr11) projectScript.appendText( """ - java { - sourceCompatibility = JavaVersion.VERSION_1_8 - } - """.trimIndent() + lineSeparator, + java { + sourceCompatibility = JavaVersion.VERSION_1_8 + } + """ + .trimIndent() + lineSeparator ) // sourceCompatibility doesn't affect the target JVM version. assertions(attrsWithoutTargetJvm + targetJvmAttr11) projectScript.appendText( """ - tasks.named('compileJava') { - options.release = 8 - } - """.trimIndent() + lineSeparator, + tasks.named('compileJava') { + options.release = 8 + } + """ + .trimIndent() + lineSeparator ) // options.release flag is honored. assertions(attrsWithoutTargetJvm + targetJvmAttr8) } - @Issue( - "https://github.com/GradleUp/shadow/issues/1665", - ) + @Issue("https://github.com/GradleUp/shadow/issues/1665") @Test fun dontInjectTargetJvmVersionWhenAutoTargetJvmDisabled() { projectScript.appendText( publishConfiguration( - projectBlock = """ + projectBlock = + """ java { disableAutoTargetJvm() } - """.trimIndent(), - shadowBlock = """ + """ + .trimIndent(), + shadowBlock = + """ archiveClassifier = '' archiveBaseName = 'maven-all' - """.trimIndent(), - ), + """ + .trimIndent(), + ) ) val result = publish(infoArgument) - assertThat(result.output).contains( - "Cannot set the target JVM version to Int.MAX_VALUE when `java.autoTargetJvmDisabled` is enabled or in other cases.", - ) + assertThat(result.output) + .contains( + "Cannot set the target JVM version to Int.MAX_VALUE when `java.autoTargetJvmDisabled` is enabled or in other cases." + ) assertShadowVariantCommon( gmm = gmmAdapter.fromJson(repoPath("my/maven-all/1.0/maven-all-1.0.module")), - variantAttrs = shadowVariantAttrs.filterNot { (name, _) -> - name == TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE.name - }.toTypedArray(), + variantAttrs = + shadowVariantAttrs + .filterNot { (name, _) -> name == TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE.name } + .toTypedArray(), ) } @@ -174,28 +186,34 @@ class PublishingTest : BasePluginTest() { fun dontInjectTargetJvmVersionWhenOptingOut() { projectScript.appendText( publishConfiguration( - projectBlock = """ + projectBlock = + """ shadow { addTargetJvmVersionAttribute = false } - """.trimIndent(), - shadowBlock = """ + """ + .trimIndent(), + shadowBlock = + """ archiveClassifier = '' archiveBaseName = 'maven-all' - """.trimIndent(), - ), + """ + .trimIndent(), + ) ) val result = publish(infoArgument) - assertThat(result.output).contains( - "Skipping setting org.gradle.jvm.version attribute for shadowRuntimeElements configuration.", - ) + assertThat(result.output) + .contains( + "Skipping setting org.gradle.jvm.version attribute for shadowRuntimeElements configuration." + ) assertShadowVariantCommon( gmm = gmmAdapter.fromJson(repoPath("my/maven-all/1.0/maven-all-1.0.module")), - variantAttrs = shadowVariantAttrs.filterNot { (name, _) -> - name == TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE.name - }.toTypedArray(), + variantAttrs = + shadowVariantAttrs + .filterNot { (name, _) -> name == TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE.name } + .toTypedArray(), ) } @@ -203,26 +221,32 @@ class PublishingTest : BasePluginTest() { fun overrideBundlingAttrInGradleMetadata() { projectScript.appendText( publishConfiguration( - projectBlock = """ + projectBlock = + """ shadow { bundlingAttribute = Bundling.EMBEDDED } - """.trimIndent(), - shadowBlock = """ + """ + .trimIndent(), + shadowBlock = + """ archiveClassifier = '' archiveBaseName = 'maven-all' - """.trimIndent(), - ), + """ + .trimIndent(), + ) ) publish() assertShadowVariantCommon( gmm = gmmAdapter.fromJson(repoPath("my/maven-all/1.0/maven-all-1.0.module")), - variantAttrs = commonVariantAttrs + arrayOf( - Bundling.BUNDLING_ATTRIBUTE.name to Bundling.EMBEDDED, - Usage.USAGE_ATTRIBUTE.name to Usage.JAVA_RUNTIME, - ), + variantAttrs = + commonVariantAttrs + + arrayOf( + Bundling.BUNDLING_ATTRIBUTE.name to Bundling.EMBEDDED, + Usage.USAGE_ATTRIBUTE.name to Usage.JAVA_RUNTIME, + ), ) } @@ -230,37 +254,42 @@ class PublishingTest : BasePluginTest() { fun publishShadowJarInsteadOfJar() { projectScript.appendText( publishConfiguration( - shadowBlock = """ + shadowBlock = + """ archiveClassifier = '' - """.trimIndent(), - publicationsBlock = """ + """ + .trimIndent(), + publicationsBlock = + """ shadow(MavenPublication) { from components.shadow } - """.trimIndent(), - ), + """ + .trimIndent(), + ) ) publish() val artifactRoot = "my/maven/1.0" - assertThat(repoPath(artifactRoot).entries).containsOnly( - "maven-1.0.jar", - "maven-1.0.module", - "maven-1.0.pom", - "maven-1.0.jar.md5", - "maven-1.0.module.md5", - "maven-1.0.pom.md5", - "maven-1.0.jar.sha1", - "maven-1.0.module.sha1", - "maven-1.0.pom.sha1", - "maven-1.0.jar.sha256", - "maven-1.0.module.sha256", - "maven-1.0.pom.sha256", - "maven-1.0.jar.sha512", - "maven-1.0.module.sha512", - "maven-1.0.pom.sha512", - ) + assertThat(repoPath(artifactRoot).entries) + .containsOnly( + "maven-1.0.jar", + "maven-1.0.module", + "maven-1.0.pom", + "maven-1.0.jar.md5", + "maven-1.0.module.md5", + "maven-1.0.pom.md5", + "maven-1.0.jar.sha1", + "maven-1.0.module.sha1", + "maven-1.0.pom.sha1", + "maven-1.0.jar.sha256", + "maven-1.0.module.sha256", + "maven-1.0.pom.sha256", + "maven-1.0.jar.sha512", + "maven-1.0.module.sha512", + "maven-1.0.pom.sha512", + ) assertShadowJarCommon(repoJarPath("$artifactRoot/maven-1.0.jar")) assertPomCommon(repoPath("$artifactRoot/maven-1.0.pom")) assertShadowVariantCommon(gmmAdapter.fromJson(repoPath("$artifactRoot/maven-1.0.module"))) @@ -270,32 +299,35 @@ class PublishingTest : BasePluginTest() { fun publishCustomShadowJar() { projectScript.appendText( publishConfiguration( - projectBlock = """ + projectBlock = + """ def testShadowJar = tasks.register('testShadowJar', ${ShadowJar::class.java.name}) { description = 'Create a combined JAR of project and test dependencies' archiveClassifier = 'tests' from sourceSets.named('test').map { it.output } configurations = project.configurations.named('testRuntimeClasspath').map { [it] } } - """.trimIndent(), - dependenciesBlock = """ + """ + .trimIndent(), + dependenciesBlock = + """ testImplementation 'junit:junit:3.8.2' - """.trimIndent(), - publicationsBlock = """ + """ + .trimIndent(), + publicationsBlock = + """ shadow(MavenPublication) { artifact testShadowJar } - """.trimIndent(), - ), + """ + .trimIndent(), + ) ) publish() assertThat(repoJarPath("my/maven/1.0/maven-1.0-tests.jar")).useAll { - containsOnly( - *junitEntries, - *manifestEntries, - ) + containsOnly(*junitEntries, *manifestEntries) } } @@ -304,34 +336,43 @@ class PublishingTest : BasePluginTest() { writeGradlePluginModule() projectScript.appendText( publishConfiguration( - projectBlock = """ + projectBlock = + """ apply plugin: 'com.gradle.plugin-publish' group = 'my.plugin' version = '1.0' - """.trimIndent(), - shadowBlock = """ + """ + .trimIndent(), + shadowBlock = + """ archiveClassifier = '' - """.trimIndent(), - publicationsBlock = """ + """ + .trimIndent(), + publicationsBlock = + """ pluginMaven(MavenPublication) { artifactId = 'my-gradle-plugin' } - """.trimIndent(), - ), + """ + .trimIndent(), + ) ) publish() val artifactRoot = "my/plugin/my-gradle-plugin/1.0" - assertThat(repoPath(artifactRoot).entries.filter { it.endsWith(".jar") }).containsOnly( - "my-gradle-plugin-1.0.jar", - "my-gradle-plugin-1.0-javadoc.jar", - "my-gradle-plugin-1.0-sources.jar", - ) + assertThat(repoPath(artifactRoot).entries.filter { it.endsWith(".jar") }) + .containsOnly( + "my-gradle-plugin-1.0.jar", + "my-gradle-plugin-1.0-javadoc.jar", + "my-gradle-plugin-1.0-sources.jar", + ) assertShadowJarCommon(repoJarPath("$artifactRoot/my-gradle-plugin-1.0.jar")) assertPomCommon(repoPath("$artifactRoot/my-gradle-plugin-1.0.pom")) - assertShadowVariantCommon(gmmAdapter.fromJson(repoPath("$artifactRoot/my-gradle-plugin-1.0.module"))) + assertShadowVariantCommon( + gmmAdapter.fromJson(repoPath("$artifactRoot/my-gradle-plugin-1.0.module")) + ) } @Issue( @@ -343,44 +384,51 @@ class PublishingTest : BasePluginTest() { fun publishShadowJarWithCustomArtifactName() { projectScript.appendText( publishConfiguration( - projectBlock = """ + projectBlock = + """ group = 'my-group' version = '2.0' - """.trimIndent(), - shadowBlock = """ + """ + .trimIndent(), + shadowBlock = + """ archiveClassifier = 'my-classifier' archiveExtension = 'my-ext' archiveBaseName = 'maven-all' - """.trimIndent(), - publicationsBlock = """ - shadow(MavenPublication) { - from components.shadow - artifactId = 'my-artifact' - } - """.trimIndent(), - ), + """ + .trimIndent(), + publicationsBlock = + """ + shadow(MavenPublication) { + from components.shadow + artifactId = 'my-artifact' + } + """ + .trimIndent(), + ) ) publish() val artifactRoot = "my-group/my-artifact/2.0" - assertThat(repoPath(artifactRoot).entries).containsOnly( - "my-artifact-2.0-my-classifier.my-ext.sha512", - "my-artifact-2.0-my-classifier.my-ext", - "my-artifact-2.0.pom.sha256", - "my-artifact-2.0.module", - "my-artifact-2.0.pom", - "my-artifact-2.0.module.sha256", - "my-artifact-2.0.module.sha1", - "my-artifact-2.0.module.md5", - "my-artifact-2.0.pom.sha512", - "my-artifact-2.0-my-classifier.my-ext.sha256", - "my-artifact-2.0.module.sha512", - "my-artifact-2.0-my-classifier.my-ext.sha1", - "my-artifact-2.0-my-classifier.my-ext.md5", - "my-artifact-2.0.pom.md5", - "my-artifact-2.0.pom.sha1", - ) + assertThat(repoPath(artifactRoot).entries) + .containsOnly( + "my-artifact-2.0-my-classifier.my-ext.sha512", + "my-artifact-2.0-my-classifier.my-ext", + "my-artifact-2.0.pom.sha256", + "my-artifact-2.0.module", + "my-artifact-2.0.pom", + "my-artifact-2.0.module.sha256", + "my-artifact-2.0.module.sha1", + "my-artifact-2.0.module.md5", + "my-artifact-2.0.pom.sha512", + "my-artifact-2.0-my-classifier.my-ext.sha256", + "my-artifact-2.0.module.sha512", + "my-artifact-2.0-my-classifier.my-ext.sha1", + "my-artifact-2.0-my-classifier.my-ext.md5", + "my-artifact-2.0.pom.md5", + "my-artifact-2.0.pom.sha1", + ) assertShadowJarCommon(repoJarPath("$artifactRoot/my-artifact-2.0-my-classifier.my-ext")) assertPomCommon(repoPath("$artifactRoot/my-artifact-2.0.pom")) @@ -391,12 +439,15 @@ class PublishingTest : BasePluginTest() { fun publishJarAndShadowJarWithGradleMetadata() { projectScript.appendText( publishConfiguration( - dependenciesBlock = """ + dependenciesBlock = + """ implementation 'my:a:1.0' implementation 'my:b:1.0' shadow 'my:b:1.0' - """.trimIndent(), - publicationsBlock = """ + """ + .trimIndent(), + publicationsBlock = + """ java(MavenPublication) { from components.java } @@ -404,112 +455,107 @@ class PublishingTest : BasePluginTest() { from components.shadow artifactId = "maven-all" } - """.trimIndent(), - ), + """ + .trimIndent(), + ) ) publish() - assertThat(repoPath("my/maven/1.0").entries).containsOnly( - // Entries of maven-1.0.jar - "maven-1.0.jar", - "maven-1.0.module", - "maven-1.0.pom", - "maven-1.0.jar.md5", - "maven-1.0.module.md5", - "maven-1.0.pom.md5", - "maven-1.0.jar.sha1", - "maven-1.0.module.sha1", - "maven-1.0.pom.sha1", - "maven-1.0.jar.sha256", - "maven-1.0.module.sha256", - "maven-1.0.pom.sha256", - "maven-1.0.jar.sha512", - "maven-1.0.module.sha512", - "maven-1.0.pom.sha512", - // Entries of maven-1.0-all.jar - "maven-1.0-all.jar", - "maven-1.0-all.jar.md5", - "maven-1.0-all.jar.sha1", - "maven-1.0-all.jar.sha256", - "maven-1.0-all.jar.sha512", - ) - assertThat(repoPath("my/maven-all/1.0").entries).containsOnly( - "maven-all-1.0-all.jar", - "maven-all-1.0.module", - "maven-all-1.0.pom", - "maven-all-1.0-all.jar.md5", - "maven-all-1.0.module.md5", - "maven-all-1.0.pom.md5", - "maven-all-1.0-all.jar.sha1", - "maven-all-1.0.module.sha1", - "maven-all-1.0.pom.sha1", - "maven-all-1.0-all.jar.sha256", - "maven-all-1.0.module.sha256", - "maven-all-1.0.pom.sha256", - "maven-all-1.0-all.jar.sha512", - "maven-all-1.0.module.sha512", - "maven-all-1.0.pom.sha512", - ) + assertThat(repoPath("my/maven/1.0").entries) + .containsOnly( + // Entries of maven-1.0.jar + "maven-1.0.jar", + "maven-1.0.module", + "maven-1.0.pom", + "maven-1.0.jar.md5", + "maven-1.0.module.md5", + "maven-1.0.pom.md5", + "maven-1.0.jar.sha1", + "maven-1.0.module.sha1", + "maven-1.0.pom.sha1", + "maven-1.0.jar.sha256", + "maven-1.0.module.sha256", + "maven-1.0.pom.sha256", + "maven-1.0.jar.sha512", + "maven-1.0.module.sha512", + "maven-1.0.pom.sha512", + // Entries of maven-1.0-all.jar + "maven-1.0-all.jar", + "maven-1.0-all.jar.md5", + "maven-1.0-all.jar.sha1", + "maven-1.0-all.jar.sha256", + "maven-1.0-all.jar.sha512", + ) + assertThat(repoPath("my/maven-all/1.0").entries) + .containsOnly( + "maven-all-1.0-all.jar", + "maven-all-1.0.module", + "maven-all-1.0.pom", + "maven-all-1.0-all.jar.md5", + "maven-all-1.0.module.md5", + "maven-all-1.0.pom.md5", + "maven-all-1.0-all.jar.sha1", + "maven-all-1.0.module.sha1", + "maven-all-1.0.pom.sha1", + "maven-all-1.0-all.jar.sha256", + "maven-all-1.0.module.sha256", + "maven-all-1.0.pom.sha256", + "maven-all-1.0-all.jar.sha512", + "maven-all-1.0.module.sha512", + "maven-all-1.0.pom.sha512", + ) - assertThat(repoJarPath("my/maven/1.0/maven-1.0.jar")).useAll { - containsNone(*entriesInAB) - } + assertThat(repoJarPath("my/maven/1.0/maven-1.0.jar")).useAll { containsNone(*entriesInAB) } assertThat(repoJarPath("my/maven/1.0/maven-1.0-all.jar")).useAll { - containsOnly( - *entriesInAB, - *manifestEntries, - ) + containsOnly(*entriesInAB, *manifestEntries) } assertPomCommon(repoPath("my/maven/1.0/maven-1.0.pom"), arrayOf("my:a:1.0", "my:b:1.0")) gmmAdapter.fromJson(repoPath("my/maven/1.0/maven-1.0.module")).let { gmm -> // apiElements, runtimeElements, shadowRuntimeElements - assertThat(gmm.variantNames).containsOnly( - API_ELEMENTS_CONFIGURATION_NAME, - RUNTIME_ELEMENTS_CONFIGURATION_NAME, - SHADOW_RUNTIME_ELEMENTS_CONFIGURATION_NAME, - ) - assertThat(gmm.apiElementsVariant).all { - transform { it.attributes }.containsOnly( - *commonVariantAttrs, - Bundling.BUNDLING_ATTRIBUTE.name to Bundling.EXTERNAL, - Usage.USAGE_ATTRIBUTE.name to Usage.JAVA_API, + assertThat(gmm.variantNames) + .containsOnly( + API_ELEMENTS_CONFIGURATION_NAME, + RUNTIME_ELEMENTS_CONFIGURATION_NAME, + SHADOW_RUNTIME_ELEMENTS_CONFIGURATION_NAME, ) + assertThat(gmm.apiElementsVariant).all { + transform { it.attributes } + .containsOnly( + *commonVariantAttrs, + Bundling.BUNDLING_ATTRIBUTE.name to Bundling.EXTERNAL, + Usage.USAGE_ATTRIBUTE.name to Usage.JAVA_API, + ) transform { it.coordinates }.isEmpty() } assertThat(gmm.runtimeElementsVariant).all { - transform { it.attributes }.containsOnly( - *commonVariantAttrs, - Bundling.BUNDLING_ATTRIBUTE.name to Bundling.EXTERNAL, - Usage.USAGE_ATTRIBUTE.name to Usage.JAVA_RUNTIME, - ) - transform { it.coordinates }.containsOnly( - "my:a:1.0", - "my:b:1.0", - ) + transform { it.attributes } + .containsOnly( + *commonVariantAttrs, + Bundling.BUNDLING_ATTRIBUTE.name to Bundling.EXTERNAL, + Usage.USAGE_ATTRIBUTE.name to Usage.JAVA_RUNTIME, + ) + transform { it.coordinates }.containsOnly("my:a:1.0", "my:b:1.0") } assertShadowVariantCommon(gmm) } assertPomCommon(repoPath("my/maven-all/1.0/maven-all-1.0.pom")) gmmAdapter.fromJson(repoPath("my/maven-all/1.0/maven-all-1.0.module")).let { gmm -> - assertThat(gmm.variantNames).containsOnly( - SHADOW_RUNTIME_ELEMENTS_CONFIGURATION_NAME, - ) + assertThat(gmm.variantNames).containsOnly(SHADOW_RUNTIME_ELEMENTS_CONFIGURATION_NAME) assertShadowVariantCommon(gmm) } } - @Issue( - "https://github.com/GradleUp/shadow/issues/651", - ) + @Issue("https://github.com/GradleUp/shadow/issues/651") @ParameterizedTest @ValueSource(booleans = [false, true]) fun publishShadowVariantJar(addShadowVariant: Boolean) { projectScript.appendText( publishingBlock( - projectBlock = """ + projectBlock = + """ dependencies { implementation 'my:a:1.0' shadow 'my:b:1.0' @@ -517,103 +563,103 @@ class PublishingTest : BasePluginTest() { shadow { addShadowVariantIntoJavaComponent = $addShadowVariant } - """.trimIndent(), - publicationsBlock = """ + """ + .trimIndent(), + publicationsBlock = + """ shadow(MavenPublication) { from components.java } - """.trimIndent(), - ), + """ + .trimIndent(), + ) ) val result = publish(infoArgument) - assertThat(result.output).contains( - if (addShadowVariant) { - "Adding shadowRuntimeElements variant to Java component." - } else { - "Skipping adding shadowRuntimeElements variant to Java component." - }, - ) + assertThat(result.output) + .contains( + if (addShadowVariant) { + "Adding shadowRuntimeElements variant to Java component." + } else { + "Skipping adding shadowRuntimeElements variant to Java component." + } + ) val assertVariantsCommon = { gmm: GradleModuleMetadata -> assertThat(gmm.apiElementsVariant).all { - transform { it.attributes }.containsOnly( - *commonVariantAttrs, - Bundling.BUNDLING_ATTRIBUTE.name to Bundling.EXTERNAL, - Usage.USAGE_ATTRIBUTE.name to Usage.JAVA_API, - ) + transform { it.attributes } + .containsOnly( + *commonVariantAttrs, + Bundling.BUNDLING_ATTRIBUTE.name to Bundling.EXTERNAL, + Usage.USAGE_ATTRIBUTE.name to Usage.JAVA_API, + ) transform { it.coordinates }.isEmpty() } assertThat(gmm.runtimeElementsVariant).all { - transform { it.attributes }.containsOnly( - *commonVariantAttrs, - Bundling.BUNDLING_ATTRIBUTE.name to Bundling.EXTERNAL, - Usage.USAGE_ATTRIBUTE.name to Usage.JAVA_RUNTIME, - ) - transform { it.coordinates }.containsOnly( - "my:a:1.0", - ) + transform { it.attributes } + .containsOnly( + *commonVariantAttrs, + Bundling.BUNDLING_ATTRIBUTE.name to Bundling.EXTERNAL, + Usage.USAGE_ATTRIBUTE.name to Usage.JAVA_RUNTIME, + ) + transform { it.coordinates }.containsOnly("my:a:1.0") } } - val entriesCommon = arrayOf( - "maven-1.0.jar", - "maven-1.0.jar.md5", - "maven-1.0.jar.sha1", - "maven-1.0.jar.sha256", - "maven-1.0.jar.sha512", - "maven-1.0.module", - "maven-1.0.module.md5", - "maven-1.0.module.sha1", - "maven-1.0.module.sha256", - "maven-1.0.module.sha512", - "maven-1.0.pom", - "maven-1.0.pom.md5", - "maven-1.0.pom.sha1", - "maven-1.0.pom.sha256", - "maven-1.0.pom.sha512", - ) + val entriesCommon = + arrayOf( + "maven-1.0.jar", + "maven-1.0.jar.md5", + "maven-1.0.jar.sha1", + "maven-1.0.jar.sha256", + "maven-1.0.jar.sha512", + "maven-1.0.module", + "maven-1.0.module.md5", + "maven-1.0.module.sha1", + "maven-1.0.module.sha256", + "maven-1.0.module.sha512", + "maven-1.0.pom", + "maven-1.0.pom.md5", + "maven-1.0.pom.sha1", + "maven-1.0.pom.sha256", + "maven-1.0.pom.sha512", + ) val artifactEntries = repoPath("my/maven/1.0/").entries val gmm = gmmAdapter.fromJson(repoPath("my/maven/1.0/maven-1.0.module")) - val pomDependencies = pomReader.read(repoPath("my/maven/1.0/maven-1.0.pom")) - .dependencies.map { it.coordinate to it.scope } + val pomDependencies = + pomReader.read(repoPath("my/maven/1.0/maven-1.0.pom")).dependencies.map { + it.coordinate to it.scope + } if (addShadowVariant) { - assertThat(artifactEntries).containsOnly( - "maven-1.0-all.jar", - "maven-1.0-all.jar.md5", - "maven-1.0-all.jar.sha1", - "maven-1.0-all.jar.sha256", - "maven-1.0-all.jar.sha512", - *entriesCommon, - ) - assertThat(gmm.variantNames).containsOnly( - API_ELEMENTS_CONFIGURATION_NAME, - RUNTIME_ELEMENTS_CONFIGURATION_NAME, - SHADOW_RUNTIME_ELEMENTS_CONFIGURATION_NAME, - ) + assertThat(artifactEntries) + .containsOnly( + "maven-1.0-all.jar", + "maven-1.0-all.jar.md5", + "maven-1.0-all.jar.sha1", + "maven-1.0-all.jar.sha256", + "maven-1.0-all.jar.sha512", + *entriesCommon, + ) + assertThat(gmm.variantNames) + .containsOnly( + API_ELEMENTS_CONFIGURATION_NAME, + RUNTIME_ELEMENTS_CONFIGURATION_NAME, + SHADOW_RUNTIME_ELEMENTS_CONFIGURATION_NAME, + ) assertVariantsCommon(gmm) assertShadowVariantCommon(gmm) - assertThat(pomDependencies).containsOnly( - "my:a:1.0" to "runtime", - "my:b:1.0" to "compile", - ) + assertThat(pomDependencies).containsOnly("my:a:1.0" to "runtime", "my:b:1.0" to "compile") } else { assertThat(artifactEntries).containsOnly(*entriesCommon) - assertThat(gmm.variantNames).containsOnly( - API_ELEMENTS_CONFIGURATION_NAME, - RUNTIME_ELEMENTS_CONFIGURATION_NAME, - ) + assertThat(gmm.variantNames) + .containsOnly(API_ELEMENTS_CONFIGURATION_NAME, RUNTIME_ELEMENTS_CONFIGURATION_NAME) assertVariantsCommon(gmm) - assertThat(pomDependencies).containsOnly( - "my:a:1.0" to "runtime", - ) + assertThat(pomDependencies).containsOnly("my:a:1.0" to "runtime") } } private fun repoPath(relative: String): Path { - return remoteRepoPath.resolve(relative).also { - check(it.exists()) { "Path not found: $it" } - } + return remoteRepoPath.resolve(relative).also { check(it.exists()) { "Path not found: $it" } } } private fun repoJarPath(relative: String): JarPath { @@ -624,17 +670,21 @@ class PublishingTest : BasePluginTest() { private fun publishConfiguration( projectBlock: String = "", - dependenciesBlock: String = """ + dependenciesBlock: String = + """ implementation 'my:a:1.0' shadow 'my:b:1.0' - """.trimIndent(), + """ + .trimIndent(), shadowBlock: String = "", - publicationsBlock: String = """ + publicationsBlock: String = + """ shadow(MavenPublication) { from components.shadow artifactId = 'maven-all' } - """.trimIndent(), + """ + .trimIndent(), ): String { return """ dependencies { @@ -644,13 +694,11 @@ class PublishingTest : BasePluginTest() { $shadowBlock } ${publishingBlock(projectBlock = projectBlock, publicationsBlock = publicationsBlock)} - """.trimIndent() + """ + .trimIndent() } - private fun publishingBlock( - projectBlock: String, - publicationsBlock: String, - ): String { + private fun publishingBlock(projectBlock: String, publicationsBlock: String): String { return """ apply plugin: 'maven-publish' $projectBlock @@ -662,17 +710,17 @@ class PublishingTest : BasePluginTest() { maven { url = '${remoteRepoPath.toUri()}' } } } - """.trimIndent() + """ + .trimIndent() } - private fun assertPomCommon( - pomPath: Path, - coordinates: Array = arrayOf("my:b:1.0"), - ) { + private fun assertPomCommon(pomPath: Path, coordinates: Array = arrayOf("my:b:1.0")) { assertThat(pomReader.read(pomPath)).all { transform { it.dependencies.map(Dependency::coordinate) }.containsOnly(*coordinates) // All scopes should be runtime. - transform { it.dependencies.map(Dependency::getScope).distinct() }.single().isEqualTo("runtime") + transform { it.dependencies.map(Dependency::getScope).distinct() } + .single() + .isEqualTo("runtime") } } @@ -698,25 +746,32 @@ class PublishingTest : BasePluginTest() { } private companion object { - val gmmAdapter: JsonAdapter = Moshi.Builder().add(KotlinJsonAdapterFactory()).build() - .adapter(GradleModuleMetadata::class.java) + val gmmAdapter: JsonAdapter = + Moshi.Builder() + .add(KotlinJsonAdapterFactory()) + .build() + .adapter(GradleModuleMetadata::class.java) val pomReader = MavenXpp3Reader() - val commonVariantAttrs = arrayOf( - Category.CATEGORY_ATTRIBUTE.name to Category.LIBRARY, - LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE.name to LibraryElements.JAR, - TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE.name to JavaVersion.current().majorVersion, - ) + val commonVariantAttrs = + arrayOf( + Category.CATEGORY_ATTRIBUTE.name to Category.LIBRARY, + LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE.name to LibraryElements.JAR, + TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE.name to JavaVersion.current().majorVersion, + ) - val shadowVariantAttrs = commonVariantAttrs + arrayOf( - Bundling.BUNDLING_ATTRIBUTE.name to Bundling.SHADOWED, - Usage.USAGE_ATTRIBUTE.name to Usage.JAVA_RUNTIME, - ) + val shadowVariantAttrs = + commonVariantAttrs + + arrayOf( + Bundling.BUNDLING_ATTRIBUTE.name to Bundling.SHADOWED, + Usage.USAGE_ATTRIBUTE.name to Usage.JAVA_RUNTIME, + ) fun MavenXpp3Reader.read(path: Path): Model = path.inputStream().use { read(it) } fun JsonAdapter.fromJson(path: Path): T = checkNotNull(fromJson(path.readText())) - val Path.entries: List get() = listDirectoryEntries().map { it.name } + val Path.entries: List + get() = listDirectoryEntries().map { it.name } } } diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/RelocationTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/RelocationTest.kt index 9a1244388..852ebcc79 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/RelocationTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/RelocationTest.kt @@ -45,35 +45,32 @@ class RelocationTest : BasePluginTest() { enableAutoRelocation = true relocationPrefix = '$relocationPrefix' } - """.trimIndent(), + """ + .trimIndent() ) val entryPrefix = relocationPrefix.replace('.', '/') - val relocatedEntries = buildSet { - addAll( - junitEntries.map { "$entryPrefix/$it" } - .filterNot { it.startsWith("$entryPrefix/META-INF/") }, - ) - var parent = entryPrefix - while (parent.isNotEmpty()) { - add("$parent/") - parent = parent.substringBeforeLast('/', "") - } - }.toTypedArray() + val relocatedEntries = + buildSet { + addAll( + junitEntries + .map { "$entryPrefix/$it" } + .filterNot { it.startsWith("$entryPrefix/META-INF/") } + ) + var parent = entryPrefix + while (parent.isNotEmpty()) { + add("$parent/") + parent = parent.substringBeforeLast('/', "") + } + } + .toTypedArray() val result = runWithSuccess(shadowJarPath, infoArgument) assertThat(outputShadowedJar).useAll { - containsOnly( - "my/", - mainClassEntry, - *relocatedEntries, - *manifestEntries, - ) + containsOnly("my/", mainClassEntry, *relocatedEntries, *manifestEntries) } // Make sure the relocator count is aligned with the number of unique packages in junit jar. - assertThat(result.output).contains( - "Relocator count: 6.", - ) + assertThat(result.output).contains("Relocator count: 6.") } @ParameterizedTest @@ -82,45 +79,43 @@ class RelocationTest : BasePluginTest() { val mainClassEntry = writeClass() projectScript.appendText( """ - dependencies { - implementation 'junit:junit:3.8.2' - } - """.trimIndent(), + dependencies { + implementation 'junit:junit:3.8.2' + } + """ + .trimIndent() ) - val relocatedEntries = junitEntries.map { "$relocationPrefix/$it" } - .filterNot { it.startsWith("$relocationPrefix/META-INF/") } - .toTypedArray() + val relocatedEntries = + junitEntries + .map { "$relocationPrefix/$it" } + .filterNot { it.startsWith("$relocationPrefix/META-INF/") } + .toTypedArray() if (enable) { - runWithSuccess(shadowJarPath, "--enable-auto-relocation", "--relocation-prefix=$relocationPrefix") + runWithSuccess( + shadowJarPath, + "--enable-auto-relocation", + "--relocation-prefix=$relocationPrefix", + ) } else { - runWithSuccess(shadowJarPath, "--no-enable-auto-relocation", "--relocation-prefix=$relocationPrefix") + runWithSuccess( + shadowJarPath, + "--no-enable-auto-relocation", + "--relocation-prefix=$relocationPrefix", + ) } - val commonEntries = arrayOf( - "my/", - mainClassEntry, - *manifestEntries, - ) + val commonEntries = arrayOf("my/", mainClassEntry, *manifestEntries) assertThat(outputShadowedJar).useAll { if (enable) { - containsOnly( - "$relocationPrefix/", - *relocatedEntries, - *commonEntries, - ) + containsOnly("$relocationPrefix/", *relocatedEntries, *commonEntries) } else { - containsOnly( - *junitEntries, - *commonEntries, - ) + containsOnly(*junitEntries, *commonEntries) } } } - @Issue( - "https://github.com/GradleUp/shadow/issues/58", - ) + @Issue("https://github.com/GradleUp/shadow/issues/58") @Test fun relocateDependencyFiles() { val mainClassEntry = writeClass() @@ -133,17 +128,20 @@ class RelocationTest : BasePluginTest() { relocate 'junit.runner', 'a' relocate 'junit.framework', 'b' } - """.trimIndent(), + """ + .trimIndent() ) val runnerFilter = { it: String -> it.startsWith("junit/runner/") } val frameworkFilter = { it: String -> it.startsWith("junit/framework/") } - val runnerEntries = junitEntries - .filter(runnerFilter) - .map { it.replace("junit/runner/", "a/") }.toTypedArray() - val frameworkEntries = junitEntries - .filter(frameworkFilter) - .map { it.replace("junit/framework/", "b/") }.toTypedArray() - val otherJunitEntries = junitEntries.filterNot { runnerFilter(it) || frameworkFilter(it) }.toTypedArray() + val runnerEntries = + junitEntries.filter(runnerFilter).map { it.replace("junit/runner/", "a/") }.toTypedArray() + val frameworkEntries = + junitEntries + .filter(frameworkFilter) + .map { it.replace("junit/framework/", "b/") } + .toTypedArray() + val otherJunitEntries = + junitEntries.filterNot { runnerFilter(it) || frameworkFilter(it) }.toTypedArray() runWithSuccess(shadowJarPath) @@ -175,17 +173,22 @@ class RelocationTest : BasePluginTest() { include 'junit.framework.Test*' } } - """.trimIndent(), + """ + .trimIndent() ) - val runnerFilter = { it: String -> it.startsWith("junit/runner/") && it != "junit/runner/BaseTestRunner.class" } + val runnerFilter = { it: String -> + it.startsWith("junit/runner/") && it != "junit/runner/BaseTestRunner.class" + } val frameworkFilter = { it: String -> it.startsWith("junit/framework/Test") } - val runnerEntries = junitEntries - .filter(runnerFilter) - .map { it.replace("junit/runner/", "a/") }.toTypedArray() - val frameworkEntries = junitEntries - .filter(frameworkFilter) - .map { it.replace("junit/framework/", "b/") }.toTypedArray() - val otherJunitEntries = junitEntries.filterNot { runnerFilter(it) || frameworkFilter(it) }.toTypedArray() + val runnerEntries = + junitEntries.filter(runnerFilter).map { it.replace("junit/runner/", "a/") }.toTypedArray() + val frameworkEntries = + junitEntries + .filter(frameworkFilter) + .map { it.replace("junit/framework/", "b/") } + .toTypedArray() + val otherJunitEntries = + junitEntries.filterNot { runnerFilter(it) || frameworkFilter(it) }.toTypedArray() runWithSuccess(shadowJarPath) @@ -217,13 +220,15 @@ class RelocationTest : BasePluginTest() { $shadowJarTask { relocate 'junit.framework', 'shadow.junit' } - """.trimIndent(), + """ + .trimIndent() ) - val relocatedEntries = junitEntries - .map { it.replace("junit/framework/", "shadow/junit/") }.toTypedArray() + val relocatedEntries = + junitEntries.map { it.replace("junit/framework/", "shadow/junit/") }.toTypedArray() - path("src/main/java/my/MyTest.java").writeText( - """ + path("src/main/java/my/MyTest.java") + .writeText( + """ package my; import junit.framework.Test; import junit.framework.TestResult; @@ -231,29 +236,27 @@ class RelocationTest : BasePluginTest() { public int countTestCases() { return 0; } public void run(TestResult result) { } } - """.trimIndent(), - ) + """ + .trimIndent() + ) runWithSuccess(shadowJarPath) assertThat(outputShadowedJar).useAll { - containsOnly( - "my/", - "shadow/", - "my/MyTest.class", - *relocatedEntries, - *manifestEntries, - ) + containsOnly("my/", "shadow/", "my/MyTest.class", *relocatedEntries, *manifestEntries) } val url = outputShadowedJar.use { it.toUri().toURL() } URLClassLoader(arrayOf(url), ClassLoader.getSystemClassLoader().parent).use { classLoader -> assertFailure { - // check that the class can be loaded. If the file was not relocated properly, we should get a NoDefClassFound - // Isolated class loader with only the JVM system jars and the output jar from the test project - classLoader.loadClass("my.MyTest") - fail("Should not reach here.") - }.isInstanceOf(AssertionFailedError::class) + // check that the class can be loaded. If the file was not relocated properly, we should + // get a NoDefClassFound + // Isolated class loader with only the JVM system jars and the output jar from the test + // project + classLoader.loadClass("my.MyTest") + fail("Should not reach here.") + } + .isInstanceOf(AssertionFailedError::class) } } @@ -263,9 +266,7 @@ class RelocationTest : BasePluginTest() { ) @Test fun relocateResourceFiles() { - val depJar = buildJar("foo.jar") { - insert("foo/dep.properties", "c") - } + val depJar = buildJar("foo.jar") { insert("foo/dep.properties", "c") } writeClass(packageName = "foo", className = "Foo") path("src/main/resources/foo/foo.properties").writeText("name=foo") @@ -277,7 +278,8 @@ class RelocationTest : BasePluginTest() { $shadowJarTask { relocate 'foo', 'bar' } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) @@ -295,7 +297,10 @@ class RelocationTest : BasePluginTest() { @ParameterizedTest @MethodSource("preserveLastModifiedProvider") - fun preserveLastModifiedCorrectly(enableAutoRelocation: Boolean, preserveFileTimestamps: Boolean) { + fun preserveLastModifiedCorrectly( + enableAutoRelocation: Boolean, + preserveFileTimestamps: Boolean, + ) { // Minus 3 sec to avoid the time difference between the file system and the JVM. val currentTimeMillis = System.currentTimeMillis() - 3.seconds.inWholeMilliseconds val junitEntryTimeRange = junitRawEntries.map { it.time }.let { it.min()..it.max() } @@ -309,15 +314,17 @@ class RelocationTest : BasePluginTest() { enableAutoRelocation = $enableAutoRelocation preserveFileTimestamps = $preserveFileTimestamps } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) if (enableAutoRelocation) { - val (relocatedEntries, otherEntries) = outputShadowedJar.use { - it.entries().toList().partition { entry -> entry.name.startsWith("shadow/") } - } + val (relocatedEntries, otherEntries) = + outputShadowedJar.use { + it.entries().toList().partition { entry -> entry.name.startsWith("shadow/") } + } assertThat(relocatedEntries).isNotEmpty() assertThat(otherEntries).isNotEmpty() val (relocatedDirs, relocatedClasses) = relocatedEntries.partition { it.isDirectory } @@ -332,9 +339,12 @@ class RelocationTest : BasePluginTest() { } } (relocatedDirs + otherEntries).forEach { entry -> - // Relocated directories and other entries are newly created, so they should be in now time. + // Relocated directories and other entries are newly created, so they should be in now + // time. if (entry.time < currentTimeMillis) { - fail("Relocated directory ${entry.name} has an invalid last modified time: ${entry.time}") + fail( + "Relocated directory ${entry.name} has an invalid last modified time: ${entry.time}" + ) } } } else { @@ -346,9 +356,10 @@ class RelocationTest : BasePluginTest() { } } } else { - val (shadowedEntries, otherEntries) = outputShadowedJar.use { - it.entries().toList().partition { entry -> entry.name.startsWith("junit/") } - } + val (shadowedEntries, otherEntries) = + outputShadowedJar.use { + it.entries().toList().partition { entry -> entry.name.startsWith("junit/") } + } assertThat(shadowedEntries).isNotEmpty() assertThat(otherEntries).isNotEmpty() @@ -383,9 +394,10 @@ class RelocationTest : BasePluginTest() { ) @Test fun excludeKotlinBuiltinsFromRelocation() { - val kotlinJar = buildJar("kotlin.jar") { - insert("kotlin/kotlin.kotlin_builtins", "This is a Kotlin builtins file.") - } + val kotlinJar = + buildJar("kotlin.jar") { + insert("kotlin/kotlin.kotlin_builtins", "This is a Kotlin builtins file.") + } projectScript.appendText( """ dependencies { @@ -396,31 +408,30 @@ class RelocationTest : BasePluginTest() { exclude('kotlin/kotlin.kotlin_builtins') } } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) assertThat(outputShadowedJar).useAll { - containsOnly( - "kotlin/", - "kotlin/kotlin.kotlin_builtins", - *manifestEntries, - ) + containsOnly("kotlin/", "kotlin/kotlin.kotlin_builtins", *manifestEntries) } } @ParameterizedTest @ValueSource(booleans = [false, true]) fun relocateAllPackagesButCertainOne(exclude: Boolean) { - val relocateConfig = if (exclude) { - """ + val relocateConfig = + if (exclude) { + """ exclude 'junit/**' exclude 'META-INF/**' - """.trimIndent() - } else { - "" - } + """ + .trimIndent() + } else { + "" + } projectScript.appendText( """ dependencies { @@ -431,23 +442,17 @@ class RelocationTest : BasePluginTest() { $relocateConfig } } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) assertThat(outputShadowedJar).useAll { if (exclude) { - containsOnly( - *junitEntries, - *manifestEntries, - ) + containsOnly(*junitEntries, *manifestEntries) } else { - containsOnly( - "foo/", - "foo/$manifestEntry", - *junitEntries.map { "foo/$it" }.toTypedArray(), - ) + containsOnly("foo/", "foo/$manifestEntry", *junitEntries.map { "foo/$it" }.toTypedArray()) } } } @@ -464,19 +469,14 @@ class RelocationTest : BasePluginTest() { configurations = [] relocate('', 'foo/') } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) assertThat(outputShadowedJar).useAll { - containsOnly( - "foo/", - "foo/my/", - "foo/META-INF/", - "foo/$mainClassEntry", - "foo/$manifestEntry", - ) + containsOnly("foo/", "foo/my/", "foo/META-INF/", "foo/$mainClassEntry", "foo/$manifestEntry") } } @@ -491,16 +491,14 @@ class RelocationTest : BasePluginTest() { } relocate('foo', 'shadow.foo') } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) val result = runProcess("java", "-jar", outputShadowedJar.use { it.toString() }) - assertThat(result).contains( - "shadow.foo.Foo", - "shadow.foo.Bar", - ) + assertThat(result).contains("shadow.foo.Foo", "shadow.foo.Bar") } @Issue( @@ -521,41 +519,35 @@ class RelocationTest : BasePluginTest() { skipStringConstants = $skipStringConstants } } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) val result = runProcess("java", "-jar", outputShadowedJar.use { it.toString() }) if (skipStringConstants) { - assertThat(result).contains( - "foo.Foo", - "foo.Bar", - ) + assertThat(result).contains("foo.Foo", "foo.Bar") } else { - assertThat(result).contains( - "shadow.foo.Foo", - "shadow.foo.Bar", - ) + assertThat(result).contains("shadow.foo.Foo", "shadow.foo.Bar") } } - @Issue( - "https://github.com/GradleUp/shadow/issues/1403", - ) + @Issue("https://github.com/GradleUp/shadow/issues/1403") @Test fun relocateMultiClassSignatureStringConstants() { writeClass { """ - package my; - public class Main { - public static void main(String[] args) { - System.out.println("Lorg/package/ClassA;Lorg/package/ClassB;"); - System.out.println("(Lorg/package/ClassC;Lorg/package/ClassD;)"); - System.out.println("()Lorg/package/ClassE;Lorg/package/ClassF;"); - } + package my; + public class Main { + public static void main(String[] args) { + System.out.println("Lorg/package/ClassA;Lorg/package/ClassB;"); + System.out.println("(Lorg/package/ClassC;Lorg/package/ClassD;)"); + System.out.println("()Lorg/package/ClassE;Lorg/package/ClassF;"); } - """.trimIndent() + } + """ + .trimIndent() } projectScript.appendText( """ @@ -565,18 +557,20 @@ class RelocationTest : BasePluginTest() { } relocate('org.package', 'shadow.org.package') } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) val result = runProcess("java", "-jar", outputShadowedJar.use { it.toString() }) // Just check that the jar can be executed without NoClassDefFoundError. - assertThat(result).contains( - "Lshadow/org/package/ClassA;Lshadow/org/package/ClassB", - "Lshadow/org/package/ClassC;Lshadow/org/package/ClassD", - "Lshadow/org/package/ClassE;Lshadow/org/package/ClassF", - ) + assertThat(result) + .contains( + "Lshadow/org/package/ClassA;Lshadow/org/package/ClassB", + "Lshadow/org/package/ClassC;Lshadow/org/package/ClassD", + "Lshadow/org/package/ClassE;Lshadow/org/package/ClassF", + ) } @Test @@ -590,7 +584,8 @@ class RelocationTest : BasePluginTest() { $shadowJarTask { enableAutoRelocation = true } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(":jar", shadowJarPath) @@ -600,18 +595,15 @@ class RelocationTest : BasePluginTest() { assertThat(relocatedBytes).isEqualTo(originalBytes) } - @Issue( - "https://github.com/GradleUp/shadow/issues/843", - ) + @Issue("https://github.com/GradleUp/shadow/issues/843") @OptIn(UnstableMetadataApi::class) @ParameterizedTest @ValueSource(booleans = [false, true]) fun relocateKotlinModuleFiles(enableKotlinModuleRemapping: Boolean) { val originalModuleFilePath = "META-INF/kotlin-stdlib.kotlin_module" val originalModuleFileBytes = requireResourceAsPath(originalModuleFilePath).readBytes() - val stdlibJar = buildJar("stdlib.jar") { - insert(originalModuleFilePath, originalModuleFileBytes) - } + val stdlibJar = + buildJar("stdlib.jar") { insert(originalModuleFilePath, originalModuleFileBytes) } projectScript.appendText( """ dependencies { @@ -621,7 +613,8 @@ class RelocationTest : BasePluginTest() { relocate('kotlin', 'my.kotlin') enableKotlinModuleRemapping = $enableKotlinModuleRemapping } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) @@ -630,26 +623,21 @@ class RelocationTest : BasePluginTest() { if (enableKotlinModuleRemapping) { assertThat(outputShadowedJar).useAll { - containsOnly( - relocatedModuleFilePath, - *manifestEntries, - ) + containsOnly(relocatedModuleFilePath, *manifestEntries) } } else { assertThat(outputShadowedJar).useAll { - containsOnly( - originalModuleFilePath, - *manifestEntries, - ) + containsOnly(originalModuleFilePath, *manifestEntries) } - assertThat(outputShadowedJar.use { it.getBytes(originalModuleFilePath) }).isEqualTo(originalModuleFileBytes) + assertThat(outputShadowedJar.use { it.getBytes(originalModuleFilePath) }) + .isEqualTo(originalModuleFileBytes) return } - val originalModule = KotlinModuleMetadata.read(requireResourceAsStream(originalModuleFilePath).readBytes()) - val relocatedModule = outputShadowedJar.use { - KotlinModuleMetadata.read(it.getBytes(relocatedModuleFilePath)) - } + val originalModule = + KotlinModuleMetadata.read(requireResourceAsStream(originalModuleFilePath).readBytes()) + val relocatedModule = + outputShadowedJar.use { KotlinModuleMetadata.read(it.getBytes(relocatedModuleFilePath)) } assertThat(relocatedModule.version.toString()).isEqualTo("2.2.0") assertThat(originalModule.version.toString()).isEqualTo("2.2.0") @@ -674,22 +662,23 @@ class RelocationTest : BasePluginTest() { } else { assertThat(relocatedParts.fileFacades).isNotEmpty() assertThat(relocatedParts.fileFacades).isNotEqualTo(originalParts.fileFacades) - assertThat(relocatedParts.fileFacades).isEqualTo( - originalParts.fileFacades.map { it.replace("kotlin/", "my/kotlin/") }, - ) + assertThat(relocatedParts.fileFacades) + .isEqualTo(originalParts.fileFacades.map { it.replace("kotlin/", "my/kotlin/") }) } if (originalParts.multiFileClassParts.isEmpty()) { assertThat(relocatedParts.multiFileClassParts).isEmpty() } else { assertThat(relocatedParts.multiFileClassParts).isNotEmpty() - assertThat(relocatedParts.multiFileClassParts).isNotEqualTo(originalParts.multiFileClassParts) - assertThat(relocatedParts.multiFileClassParts).isEqualTo( - originalParts.multiFileClassParts.entries.associateTo(mutableMapOf()) { (name, facade) -> - name.replace("kotlin/", "my/kotlin/") to - facade.replace("kotlin/", "my/kotlin/") - }, - ) + assertThat(relocatedParts.multiFileClassParts) + .isNotEqualTo(originalParts.multiFileClassParts) + assertThat(relocatedParts.multiFileClassParts) + .isEqualTo( + originalParts.multiFileClassParts.entries.associateTo(mutableMapOf()) { (name, facade) + -> + name.replace("kotlin/", "my/kotlin/") to facade.replace("kotlin/", "my/kotlin/") + } + ) } } } @@ -697,36 +686,39 @@ class RelocationTest : BasePluginTest() { private fun writeClassWithStringRef() { writeClass { """ - package my; - public class Main { - public static void main(String[] args) { - switch (1) { - default: - System.out.println("foo.Foo"); // Test case for string constants used in switch statements. - break; - } - System.out.println("foo.Bar"); + package my; + public class Main { + public static void main(String[] args) { + switch (1) { + default: + System.out.println("foo.Foo"); // Test case for string constants used in switch statements. + break; } + System.out.println("foo.Bar"); } - """.trimIndent() + } + """ + .trimIndent() } } private companion object { @JvmStatic - fun preserveLastModifiedProvider() = listOf( - Arguments.of(false, false), - Arguments.of(true, false), - Arguments.of(false, true), - Arguments.of(true, true), - ) + fun preserveLastModifiedProvider() = + listOf( + Arguments.of(false, false), + Arguments.of(true, false), + Arguments.of(false, true), + Arguments.of(true, true), + ) @JvmStatic - fun relocationCliOptionProvider() = listOf( - Arguments.of(false, "foo"), - Arguments.of(false, "bar"), - Arguments.of(true, "foo"), - Arguments.of(true, "bar"), - ) + fun relocationCliOptionProvider() = + listOf( + Arguments.of(false, "foo"), + Arguments.of(false, "bar"), + Arguments.of(true, "foo"), + Arguments.of(true, "bar"), + ) } } diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/AppendingTransformerTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/AppendingTransformerTest.kt index 8d417f309..05d179e78 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/AppendingTransformerTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/AppendingTransformerTest.kt @@ -11,29 +11,29 @@ class AppendingTransformerTest : BaseTransformerTest() { @ParameterizedTest @ValueSource(booleans = [false, true]) fun appendTestProperties(shortSyntax: Boolean) { - val one = buildJarOne { - insert(ENTRY_TEST_PROPERTIES, CONTENT_ONE) - } - val two = buildJarTwo { - insert(ENTRY_TEST_PROPERTIES, CONTENT_TWO) - } - val config = if (shortSyntax) { - """ + val one = buildJarOne { insert(ENTRY_TEST_PROPERTIES, CONTENT_ONE) } + val two = buildJarTwo { insert(ENTRY_TEST_PROPERTIES, CONTENT_TWO) } + val config = + if (shortSyntax) { + """ dependencies { ${implementationFiles(one, two)} } $shadowJarTask { append('$ENTRY_TEST_PROPERTIES') } - """.trimIndent() - } else { - transform( - dependenciesBlock = implementationFiles(one, two), - transformerBlock = """ + """ + .trimIndent() + } else { + transform( + dependenciesBlock = implementationFiles(one, two), + transformerBlock = + """ resource = '$ENTRY_TEST_PROPERTIES' - """.trimIndent(), - ) - } + """ + .trimIndent(), + ) + } projectScript.appendText(config) runWithSuccess(shadowJarPath) @@ -53,8 +53,9 @@ class AppendingTransformerTest : BaseTransformerTest() { insert("resources/$APPLICATION_YML_FILE", CONTENT_TWO) insert("resources/config/$APPLICATION_YML_FILE", CONTENT_THREE) } - val config = if (shortSyntax) { - """ + val config = + if (shortSyntax) { + """ dependencies { ${implementationFiles(one, two)} } @@ -62,45 +63,56 @@ class AppendingTransformerTest : BaseTransformerTest() { append('resources/$APPLICATION_YML_FILE', '$APPLICATION_YML_SEPARATOR') append('resources/config/$APPLICATION_YML_FILE', '$APPLICATION_YML_SEPARATOR') } - """.trimIndent() - } else { - val block1 = transform( - dependenciesBlock = implementationFiles(one, two), - transformerBlock = """ + """ + .trimIndent() + } else { + val block1 = + transform( + dependenciesBlock = implementationFiles(one, two), + transformerBlock = + """ resource = 'resources/$APPLICATION_YML_FILE' separator = '$APPLICATION_YML_SEPARATOR' - """.trimIndent(), - ) - val block2 = transform( - dependenciesBlock = implementationFiles(one, two), - transformerBlock = """ + """ + .trimIndent(), + ) + val block2 = + transform( + dependenciesBlock = implementationFiles(one, two), + transformerBlock = + """ resource = 'resources/config/$APPLICATION_YML_FILE' separator = '$APPLICATION_YML_SEPARATOR' - """.trimIndent(), - ) - block1 + lineSeparator + block2 - } + """ + .trimIndent(), + ) + block1 + lineSeparator + block2 + } projectScript.appendText(config) runWithSuccess(shadowJarPath) val content1 = outputShadowedJar.use { it.getContent("resources/$APPLICATION_YML_FILE") } - assertThat(content1).isEqualTo( - """ + assertThat(content1) + .isEqualTo( + """ $CONTENT_ONE --- $CONTENT_TWO - """.trimIndent(), - ) - val content2 = outputShadowedJar.use { it.getContent("resources/config/$APPLICATION_YML_FILE") } - assertThat(content2).isEqualTo( """ + .trimIndent() + ) + val content2 = outputShadowedJar.use { it.getContent("resources/config/$APPLICATION_YML_FILE") } + assertThat(content2) + .isEqualTo( + """ $CONTENT_TWO --- $CONTENT_THREE - """.trimIndent(), - ) + """ + .trimIndent() + ) } private companion object { diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/BaseTransformerTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/BaseTransformerTest.kt index 75e6881b1..46d2e8eb8 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/BaseTransformerTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/BaseTransformerTest.kt @@ -16,7 +16,8 @@ abstract class BaseTransformerTest : BasePluginTest() { // Most transformers in tests require this to handle duplicate resources. duplicatesStrategy = DuplicatesStrategy.INCLUDE } - """.trimIndent() + lineSeparator, + """ + .trimIndent() + lineSeparator ) } @@ -24,7 +25,7 @@ abstract class BaseTransformerTest : BasePluginTest() { builder: JarBuilder.() -> Unit = { insert(ENTRY_SERVICES_SHADE, CONTENT_ONE) insert(ENTRY_SERVICES_FOO, "one") - }, + } ): Path { return buildJar("one.jar", builder) } @@ -33,7 +34,7 @@ abstract class BaseTransformerTest : BasePluginTest() { builder: JarBuilder.() -> Unit = { insert(ENTRY_SERVICES_SHADE, CONTENT_TWO) insert(ENTRY_SERVICES_FOO, "two") - }, + } ): Path { return buildJar("two.jar", builder) } diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/GroovyExtensionModuleTransformerTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/GroovyExtensionModuleTransformerTest.kt index 4dbbaf736..ff0c20e6c 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/GroovyExtensionModuleTransformerTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/GroovyExtensionModuleTransformerTest.kt @@ -24,20 +24,22 @@ class GroovyExtensionModuleTransformerTest : BaseTransformerTest() { @ParameterizedTest @ValueSource(booleans = [false, true]) fun groovyExtensionModuleTransformer(shortSyntax: Boolean) { - val config = if (shortSyntax) { - """ + val config = + if (shortSyntax) { + """ dependencies { ${implementationFiles(buildJarFoo(), buildJarBar())} } $shadowJarTask { mergeGroovyExtensionModules() } - """.trimIndent() - } else { - transform( - dependenciesBlock = implementationFiles(buildJarFoo(), buildJarBar()), - ) - } + """ + .trimIndent() + } else { + transform( + dependenciesBlock = implementationFiles(buildJarFoo(), buildJarBar()) + ) + } projectScript.appendText(config) runWithSuccess(shadowJarPath) @@ -53,11 +55,8 @@ class GroovyExtensionModuleTransformerTest : BaseTransformerTest() { ) { projectScript.appendText( transform( - dependenciesBlock = implementationFiles( - buildJarFoo(fooEntry), - buildJarBar(barEntry), - ), - ), + dependenciesBlock = implementationFiles(buildJarFoo(fooEntry), buildJarBar(barEntry)) + ) ) runWithSuccess(shadowJarPath) @@ -76,7 +75,8 @@ class GroovyExtensionModuleTransformerTest : BaseTransformerTest() { relocate('com.acme', 'com.example.shaded.acme') mergeGroovyExtensionModules() } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) @@ -88,39 +88,41 @@ class GroovyExtensionModuleTransformerTest : BaseTransformerTest() { assertThat(properties.getProperty(KEY_EXTENSION_CLASSES)) .isEqualTo( "com.example.shaded.acme.foo.FooExtension,com.example.shaded.acme.foo.BarExtension," + - "com.example.shaded.acme.bar.SomeExtension,com.example.shaded.acme.bar.AnotherExtension", + "com.example.shaded.acme.bar.SomeExtension,com.example.shaded.acme.bar.AnotherExtension" ) assertThat(properties.getProperty(KEY_STATIC_EXTENSION_CLASSES)) - .isEqualTo("com.example.shaded.acme.foo.FooStaticExtension,com.example.shaded.acme.bar.SomeStaticExtension") + .isEqualTo( + "com.example.shaded.acme.foo.FooStaticExtension,com.example.shaded.acme.bar.SomeStaticExtension" + ) } - private fun buildJarFoo( - entry: String = PATH_GROOVY_EXTENSION_MODULE_DESCRIPTOR, - ): Path = buildJar("foo.jar") { - insert( - entry, - """ + private fun buildJarFoo(entry: String = PATH_GROOVY_EXTENSION_MODULE_DESCRIPTOR): Path = + buildJar("foo.jar") { + insert( + entry, + """ $KEY_MODULE_NAME=foo $KEY_MODULE_VERSION=1.0.5 $KEY_EXTENSION_CLASSES=$EXTENSION_CLASSES_FOO $KEY_STATIC_EXTENSION_CLASSES=$STATIC_EXTENSION_CLASSES_FOO - """.trimIndent(), - ) - } - - private fun buildJarBar( - entry: String = PATH_GROOVY_EXTENSION_MODULE_DESCRIPTOR, - ): Path = buildJar("bar.jar") { - insert( - entry, """ + .trimIndent(), + ) + } + + private fun buildJarBar(entry: String = PATH_GROOVY_EXTENSION_MODULE_DESCRIPTOR): Path = + buildJar("bar.jar") { + insert( + entry, + """ $KEY_MODULE_NAME=bar $KEY_MODULE_VERSION=2.3.5 $KEY_EXTENSION_CLASSES=$EXTENSION_CLASSES_BAR $KEY_STATIC_EXTENSION_CLASSES=$STATIC_EXTENSION_CLASSES_BAR - """.trimIndent(), - ) - } + """ + .trimIndent(), + ) + } private fun commonAssertions() { val properties = outputShadowedJar.extensionModuleProperties @@ -139,16 +141,28 @@ class GroovyExtensionModuleTransformerTest : BaseTransformerTest() { const val STATIC_EXTENSION_CLASSES_FOO = "com.acme.foo.FooStaticExtension" const val STATIC_EXTENSION_CLASSES_BAR = "com.acme.bar.SomeStaticExtension" - val JarPath.extensionModuleProperties get() = use { - it.getContent(PATH_GROOVY_EXTENSION_MODULE_DESCRIPTOR).toProperties() - } + val JarPath.extensionModuleProperties + get() = use { it.getContent(PATH_GROOVY_EXTENSION_MODULE_DESCRIPTOR).toProperties() } @JvmStatic - fun resourcePathProvider() = listOf( - Arguments.of(PATH_LEGACY_GROOVY_EXTENSION_MODULE_DESCRIPTOR, PATH_LEGACY_GROOVY_EXTENSION_MODULE_DESCRIPTOR), - Arguments.of(PATH_GROOVY_EXTENSION_MODULE_DESCRIPTOR, PATH_GROOVY_EXTENSION_MODULE_DESCRIPTOR), - Arguments.of(PATH_LEGACY_GROOVY_EXTENSION_MODULE_DESCRIPTOR, PATH_GROOVY_EXTENSION_MODULE_DESCRIPTOR), - Arguments.of(PATH_GROOVY_EXTENSION_MODULE_DESCRIPTOR, PATH_LEGACY_GROOVY_EXTENSION_MODULE_DESCRIPTOR), - ) + fun resourcePathProvider() = + listOf( + Arguments.of( + PATH_LEGACY_GROOVY_EXTENSION_MODULE_DESCRIPTOR, + PATH_LEGACY_GROOVY_EXTENSION_MODULE_DESCRIPTOR, + ), + Arguments.of( + PATH_GROOVY_EXTENSION_MODULE_DESCRIPTOR, + PATH_GROOVY_EXTENSION_MODULE_DESCRIPTOR, + ), + Arguments.of( + PATH_LEGACY_GROOVY_EXTENSION_MODULE_DESCRIPTOR, + PATH_GROOVY_EXTENSION_MODULE_DESCRIPTOR, + ), + Arguments.of( + PATH_GROOVY_EXTENSION_MODULE_DESCRIPTOR, + PATH_LEGACY_GROOVY_EXTENSION_MODULE_DESCRIPTOR, + ), + ) } } diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.kt index 45f3287a3..1df22797d 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.kt @@ -19,61 +19,62 @@ class PropertiesFileTransformerTest : BaseTransformerTest() { @ParameterizedTest @EnumSource(MergeStrategy::class) fun mergePropertiesWithDifferentStrategies(strategy: MergeStrategy) { - val one = buildJarOne { - insert("META-INF/test.properties", "key1=one\nkey2=one") - } - val two = buildJarTwo { - insert("META-INF/test.properties", "key2=two\nkey3=two") - } + val one = buildJarOne { insert("META-INF/test.properties", "key1=one\nkey2=one") } + val two = buildJarTwo { insert("META-INF/test.properties", "key2=two\nkey3=two") } projectScript.appendText( transform( dependenciesBlock = implementationFiles(one, two), - transformerBlock = """ + transformerBlock = + """ mergeStrategy = $mergeStrategyClassName.$strategy mergeSeparator = ";" paths = ["META-INF/test.properties"] - """.trimIndent(), - ), + """ + .trimIndent(), + ) ) if (strategy == MergeStrategy.Fail) { val result = runWithFailure(shadowJarPath) assertThat(result).taskOutcomeEquals(shadowJarPath, FAILED) - assertThat(result.output.invariantEolString).contains( - """ + assertThat(result.output.invariantEolString) + .contains( + """ Caused by: java.lang.IllegalStateException: The following properties files have conflicting property values and cannot be merged: * META-INF/test.properties * Property key2 is duplicated 2 times with different values - """.trimIndent(), - ) + """ + .trimIndent() + ) } else { runWithSuccess(shadowJarPath) - val expected = when (strategy) { - MergeStrategy.First -> - """ - |key1=one - |key2=one - |key3=two - | - """.trimMargin() - MergeStrategy.Latest -> - """ - |key1=one - |key2=two - |key3=two - | - """.trimMargin() - MergeStrategy.Append -> - """ - |key1=one - |key2=one;two - |key3=two - | - """.trimMargin() - else -> fail("Unexpected strategy: $strategy") - } + val expected = + when (strategy) { + MergeStrategy.First -> + """ + |key1=one + |key2=one + |key3=two + |""" + .trimMargin() + MergeStrategy.Latest -> + """ + |key1=one + |key2=two + |key3=two + |""" + .trimMargin() + MergeStrategy.Append -> + """ + |key1=one + |key2=one;two + |key3=two + |""" + .trimMargin() + else -> fail("Unexpected strategy: $strategy") + } val content = outputShadowedJar.use { it.getContent("META-INF/test.properties") } assertThat(content.invariantEolString).isEqualTo(expected) } @@ -81,21 +82,19 @@ class PropertiesFileTransformerTest : BaseTransformerTest() { @Test fun mergePropertiesWithKeyTransformer() { - val one = buildJarOne { - insert("META-INF/test.properties", "foo=bar") - } - val two = buildJarTwo { - insert("META-INF/test.properties", "FOO=baz") - } + val one = buildJarOne { insert("META-INF/test.properties", "foo=bar") } + val two = buildJarTwo { insert("META-INF/test.properties", "FOO=baz") } projectScript.appendText( transform( dependenciesBlock = implementationFiles(one, two), - transformerBlock = """ + transformerBlock = + """ mergeStrategy = $mergeStrategyClassName.Append keyTransformer = { key -> key.toUpperCase() } paths = ["META-INF/test.properties"] - """.trimIndent(), - ), + """ + .trimIndent(), + ) ) runWithSuccess(shadowJarPath) @@ -106,21 +105,19 @@ class PropertiesFileTransformerTest : BaseTransformerTest() { @Test fun mergePropertiesWithSpecifiedCharset() { - val one = buildJarOne { - insert("META-INF/utf8.properties", "foo=第一") - } - val two = buildJarTwo { - insert("META-INF/utf8.properties", "foo=第二") - } + val one = buildJarOne { insert("META-INF/utf8.properties", "foo=第一") } + val two = buildJarTwo { insert("META-INF/utf8.properties", "foo=第二") } projectScript.appendText( transform( dependenciesBlock = implementationFiles(one, two), - transformerBlock = """ + transformerBlock = + """ mergeStrategy = $mergeStrategyClassName.Append charsetName = "utf-8" paths = ["META-INF/utf8.properties"] - """.trimIndent(), - ), + """ + .trimIndent(), + ) ) runWithSuccess(shadowJarPath) @@ -142,13 +139,15 @@ class PropertiesFileTransformerTest : BaseTransformerTest() { projectScript.appendText( transform( dependenciesBlock = implementationFiles(one, two), - transformerBlock = """ + transformerBlock = + """ mappings = [ "META-INF/foo.properties": ["mergeStrategy": "append", "mergeSeparator": ";"], "META-INF/bar.properties": ["mergeStrategy": "latest"] ] - """.trimIndent(), - ), + """ + .trimIndent(), + ) ) runWithSuccess(shadowJarPath) @@ -159,48 +158,51 @@ class PropertiesFileTransformerTest : BaseTransformerTest() { } } - @Issue( - "https://github.com/GradleUp/shadow/issues/856", - ) + @Issue("https://github.com/GradleUp/shadow/issues/856") @Test fun mergedPropertiesWithoutComments() { val one = buildJarOne { insert( "META-INF/test.properties", """ - # A comment from jar one. - foo=one - """.trimIndent(), + # A comment from jar one. + foo=one + """ + .trimIndent(), ) } val two = buildJarTwo { insert( "META-INF/test.properties", """ - # A comment from jar two. - foo=two - """.trimIndent(), + # A comment from jar two. + foo=two + """ + .trimIndent(), ) } projectScript.appendText( transform( dependenciesBlock = implementationFiles(one, two), - transformerBlock = """ + transformerBlock = + """ mergeStrategy = $mergeStrategyClassName.Append paths = ["META-INF/test.properties"] - """.trimIndent(), - ), + """ + .trimIndent(), + ) ) runWithSuccess(shadowJarPath) val content = outputShadowedJar.use { it.getContent("META-INF/test.properties") } - assertThat(content.invariantEolString).isEqualTo( - """ + assertThat(content.invariantEolString) + .isEqualTo( + """ |foo=one,two - | - """.trimMargin(), - ) + |""" + .trimMargin() + ) } private companion object { diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerTest.kt index 6162f3f3d..f1902d590 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerTest.kt @@ -23,8 +23,9 @@ class ServiceFileTransformerTest : BaseTransformerTest() { @ParameterizedTest @ValueSource(booleans = [false, true]) fun serviceResourceTransformer(shortSyntax: Boolean) { - val config = if (shortSyntax) { - """ + val config = + if (shortSyntax) { + """ dependencies { ${implementationFiles(buildJarOne(), buildJarTwo())} } @@ -33,15 +34,18 @@ class ServiceFileTransformerTest : BaseTransformerTest() { exclude 'META-INF/services/com.acme.*' } } - """.trimIndent() - } else { - transform( - dependenciesBlock = implementationFiles(buildJarOne(), buildJarTwo()), - transformerBlock = """ - exclude 'META-INF/services/com.acme.*' - """.trimIndent(), - ) - } + """ + .trimIndent() + } else { + transform( + dependenciesBlock = implementationFiles(buildJarOne(), buildJarTwo()), + transformerBlock = + """ + exclude 'META-INF/services/com.acme.*' + """ + .trimIndent(), + ) + } projectScript.appendText(config) runWithSuccess(shadowJarPath) @@ -55,29 +59,29 @@ class ServiceFileTransformerTest : BaseTransformerTest() { @ParameterizedTest @ValueSource(booleans = [false, true]) fun serviceResourceTransformerAlternatePath(shortSyntax: Boolean) { - val one = buildJarOne { - insert(ENTRY_FOO_SHADE, CONTENT_ONE) - } - val two = buildJarTwo { - insert(ENTRY_FOO_SHADE, CONTENT_TWO) - } - val config = if (shortSyntax) { - """ + val one = buildJarOne { insert(ENTRY_FOO_SHADE, CONTENT_ONE) } + val two = buildJarTwo { insert(ENTRY_FOO_SHADE, CONTENT_TWO) } + val config = + if (shortSyntax) { + """ dependencies { ${implementationFiles(one, two)} } $shadowJarTask { mergeServiceFiles("META-INF/foo") } - """.trimIndent() - } else { - transform( - dependenciesBlock = implementationFiles(one, two), - transformerBlock = """ - path = 'META-INF/foo' - """.trimIndent(), - ) - } + """ + .trimIndent() + } else { + transform( + dependenciesBlock = implementationFiles(one, two), + transformerBlock = + """ + path = 'META-INF/foo' + """ + .trimIndent(), + ) + } projectScript.appendText(config) runWithSuccess(shadowJarPath) @@ -92,9 +96,10 @@ class ServiceFileTransformerTest : BaseTransformerTest() { insert( "META-INF/services/java.sql.Driver", """ - oracle.jdbc.OracleDriver - org.apache.hive.jdbc.HiveDriver - """.trimIndent(), + oracle.jdbc.OracleDriver + org.apache.hive.jdbc.HiveDriver + """ + .trimIndent(), ) insert( "META-INF/services/org.apache.axis.components.compiler.Compiler", @@ -109,18 +114,16 @@ class ServiceFileTransformerTest : BaseTransformerTest() { insert( "META-INF/services/java.sql.Driver", """ - org.apache.derby.jdbc.AutoloadedDriver - com.mysql.jdbc.Driver - """.trimIndent(), + org.apache.derby.jdbc.AutoloadedDriver + com.mysql.jdbc.Driver + """ + .trimIndent(), ) insert( "META-INF/services/org.apache.axis.components.compiler.Compiler", "org.apache.axis.components.compiler.Jikes", ) - insert( - "META-INF/services/org.apache.commons.logging.LogFactory", - "org.mortbay.log.Factory", - ) + insert("META-INF/services/org.apache.commons.logging.LogFactory", "org.mortbay.log.Factory") } projectScript.appendText( @@ -135,32 +138,39 @@ class ServiceFileTransformerTest : BaseTransformerTest() { exclude 'org.apache.commons.logging.LogFactory' } } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) assertThat(outputShadowedJar).useAll { - getContent("META-INF/services/java.sql.Driver").isEqualTo( - """ + getContent("META-INF/services/java.sql.Driver") + .isEqualTo( + """ oracle.jdbc.OracleDriver myapache.hive.jdbc.HiveDriver myapache.derby.jdbc.AutoloadedDriver com.mysql.jdbc.Driver - """.trimIndent(), - ) - getContent("META-INF/services/myapache.axis.components.compiler.Compiler").isEqualTo( - """ + """ + .trimIndent() + ) + getContent("META-INF/services/myapache.axis.components.compiler.Compiler") + .isEqualTo( + """ myapache.axis.components.compiler.Javac org.apache.axis.components.compiler.Jikes - """.trimIndent(), - ) - getContent("META-INF/services/org.apache.commons.logging.LogFactory").isEqualTo( - """ + """ + .trimIndent() + ) + getContent("META-INF/services/org.apache.commons.logging.LogFactory") + .isEqualTo( + """ myapache.commons.logging.impl.LogFactoryImpl org.mortbay.log.Factory - """.trimIndent(), - ) + """ + .trimIndent() + ) } } @@ -171,12 +181,8 @@ class ServiceFileTransformerTest : BaseTransformerTest() { @Test fun transformProjectResources() { val servicesBarEntry = "META-INF/services/foo.Bar" - val one = buildJarOne { - insert(servicesBarEntry, CONTENT_ONE) - } - val two = buildJarTwo { - insert(servicesBarEntry, CONTENT_TWO) - } + val one = buildJarOne { insert(servicesBarEntry, CONTENT_ONE) } + val two = buildJarTwo { insert(servicesBarEntry, CONTENT_TWO) } projectScript.appendText( """ dependencies { @@ -185,7 +191,8 @@ class ServiceFileTransformerTest : BaseTransformerTest() { $shadowJarTask { mergeServiceFiles() } - """.trimIndent(), + """ + .trimIndent() ) path("src/main/resources/$servicesBarEntry").writeText(CONTENT_THREE) @@ -197,10 +204,7 @@ class ServiceFileTransformerTest : BaseTransformerTest() { @ParameterizedTest @MethodSource("withThrowingProvider") - fun honorDuplicatesStrategyWithThrowing( - strategy: DuplicatesStrategy, - outputRegex: String, - ) { + fun honorDuplicatesStrategyWithThrowing(strategy: DuplicatesStrategy, outputRegex: String) { writeDuplicatesStrategy(strategy) val result = runWithFailure(shadowJarPath) @@ -235,7 +239,8 @@ class ServiceFileTransformerTest : BaseTransformerTest() { duplicatesStrategy = DuplicatesStrategy.INCLUDE } } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) @@ -256,7 +261,8 @@ class ServiceFileTransformerTest : BaseTransformerTest() { duplicatesStrategy = DuplicatesStrategy.EXCLUDE } } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) @@ -284,7 +290,8 @@ class ServiceFileTransformerTest : BaseTransformerTest() { } } } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) @@ -305,28 +312,38 @@ class ServiceFileTransformerTest : BaseTransformerTest() { duplicatesStrategy = DuplicatesStrategy.$strategy mergeServiceFiles() } - """.trimIndent() + lineSeparator, + """ + .trimIndent() + lineSeparator ) } private companion object { @JvmStatic - fun withThrowingProvider() = listOf( - Arguments.of(FAIL, "Cannot copy zip entry .* to .* because zip entry .* has already been copied there"), - Arguments.of(INHERIT, "Entry .* is a duplicate but no duplicate handling strategy has been set"), - ) + fun withThrowingProvider() = + listOf( + Arguments.of( + FAIL, + "Cannot copy zip entry .* to .* because zip entry .* has already been copied there", + ), + Arguments.of( + INHERIT, + "Entry .* is a duplicate but no duplicate handling strategy has been set", + ), + ) @JvmStatic - fun withoutThrowingProvider() = listOf( - Arguments.of(EXCLUDE, CONTENT_ONE, "one"), - Arguments.of(INCLUDE, CONTENT_ONE_TWO, "one\ntwo"), - Arguments.of(WARN, CONTENT_ONE_TWO, "one\ntwo"), - ) + fun withoutThrowingProvider() = + listOf( + Arguments.of(EXCLUDE, CONTENT_ONE, "one"), + Arguments.of(INCLUDE, CONTENT_ONE_TWO, "one\ntwo"), + Arguments.of(WARN, CONTENT_ONE_TWO, "one\ntwo"), + ) @JvmStatic - fun eachFileStrategyProvider() = listOf( - Arguments.of(EXCLUDE, INCLUDE, ENTRY_SERVICES_SHADE), - Arguments.of(INCLUDE, EXCLUDE, ENTRY_SERVICES_FOO), - ) + fun eachFileStrategyProvider() = + listOf( + Arguments.of(EXCLUDE, INCLUDE, ENTRY_SERVICES_SHADE), + Arguments.of(INCLUDE, EXCLUDE, ENTRY_SERVICES_FOO), + ) } } diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/TransformersTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/TransformersTest.kt index 90e0db8c5..540a7c2d5 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/TransformersTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/TransformersTest.kt @@ -50,11 +50,13 @@ class TransformersTest : BaseTransformerTest() { projectScript.appendText( transform( dependenciesBlock = implementationFiles(one, two), - transformerBlock = """ + transformerBlock = + """ exclude('multiple-contents') ${if (excludeAll) "exclude('differing-content-2')" else ""} - """.trimIndent(), - ), + """ + .trimIndent(), + ) ) if (excludeAll) { @@ -72,22 +74,25 @@ class TransformersTest : BaseTransformerTest() { "META-INF/", "META-INF/MANIFEST.MF", ) - getContents("multiple-contents").containsExactlyInAnyOrder("content", "content-is-different") + getContents("multiple-contents") + .containsExactlyInAnyOrder("content", "content-is-different") getContent("single-source").isEqualTo("content") getContent("same-content-twice").isEqualTo("content") - getContents("differing-content-2").containsExactlyInAnyOrder("content", "content-is-different") + getContents("differing-content-2") + .containsExactlyInAnyOrder("content", "content-is-different") } } else { val buildResult = runWithFailure(shadowJarPath) assertThat(buildResult).taskOutcomeEquals(shadowJarPath, FAILED) - assertThat(buildResult.output).contains( - // Keep this list approach for Unix/Windows test compatibility. - "Execution failed for task ':shadowJar'.", - "> Found 1 path duplicate(s) with different content in the shadowed JAR:", - " * differing-content-2", - "differing-content-2 (SHA256: ed7002b439e9ac845f22357d822bac1444730fbdb6016d3ec9432297b9ec9f73)", - "differing-content-2 (SHA256: aa845861bbd4578700e10487d85b25ead8723ee98fbf143df7b7e0bf1cb3385d)", - ) + assertThat(buildResult.output) + .contains( + // Keep this list approach for Unix/Windows test compatibility. + "Execution failed for task ':shadowJar'.", + "> Found 1 path duplicate(s) with different content in the shadowed JAR:", + " * differing-content-2", + "differing-content-2 (SHA256: ed7002b439e9ac845f22357d822bac1444730fbdb6016d3ec9432297b9ec9f73)", + "differing-content-2 (SHA256: aa845861bbd4578700e10487d85b25ead8723ee98fbf143df7b7e0bf1cb3385d)", + ) } } @@ -102,7 +107,8 @@ class TransformersTest : BaseTransformerTest() { attributes '$TEST_ENTRY_ATTR_KEY': 'PASSED' } } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) @@ -124,29 +130,22 @@ class TransformersTest : BaseTransformerTest() { commonAssertions() } - @Issue( - "https://github.com/GradleUp/shadow/issues/427", - ) + @Issue("https://github.com/GradleUp/shadow/issues/427") @Test fun mergeLog4j2PluginCacheFiles() { val content = requireResourceAsPath(PLUGIN_CACHE_FILE).readText() - val one = buildJarOne { - insert(PLUGIN_CACHE_FILE, content) - } - val two = buildJarOne { - insert(PLUGIN_CACHE_FILE, content) - } + val one = buildJarOne { insert(PLUGIN_CACHE_FILE, content) } + val two = buildJarOne { insert(PLUGIN_CACHE_FILE, content) } projectScript.appendText( transform( - dependenciesBlock = implementationFiles(one, two), - ), + dependenciesBlock = implementationFiles(one, two) + ) ) runWithSuccess(shadowJarPath) - val actualFileBytes = outputShadowedJar.use { jar -> - jar.getStream(PLUGIN_CACHE_FILE).use { it.readAllBytes() } - } + val actualFileBytes = + outputShadowedJar.use { jar -> jar.getStream(PLUGIN_CACHE_FILE).use { it.readAllBytes() } } assertThat(actualFileBytes.contentHashCode()).all { // Hash of the original plugin cache file. isNotEqualTo(-2114104185) @@ -159,20 +158,19 @@ class TransformersTest : BaseTransformerTest() { val foo = path("foo").apply { writeText("foo") } projectScript.appendText( transform( - transformerBlock = """ + transformerBlock = + """ resource = 'bar' file = file('${foo.invariantSeparatorsPathString}') - """.trimIndent(), - ), + """ + .trimIndent() + ) ) runWithSuccess(shadowJarPath) assertThat(outputShadowedJar).useAll { - containsOnly( - "bar", - *manifestEntries, - ) + containsOnly("bar", *manifestEntries) getContent("bar").isEqualTo("foo") } } @@ -187,16 +185,13 @@ class TransformersTest : BaseTransformerTest() { transform( dependenciesBlock = implementationFiles(one), transformerBlock = "resource = 'foo'", - ), + ) ) runWithSuccess(shadowJarPath) assertThat(outputShadowedJar).useAll { - containsOnly( - "bar", - *manifestEntries, - ) + containsOnly("bar", *manifestEntries) getContent("bar").isEqualTo("foo") } } @@ -217,18 +212,13 @@ class TransformersTest : BaseTransformerTest() { transform( dependenciesBlock = implementationFiles(one, two), transformerBlock = "resources = ['foo/bar']", - ), + ) ) runWithSuccess(shadowJarPath) assertThat(outputShadowedJar).useAll { - containsOnly( - "foo/", - "foo/bar", - "foo/baz", - *manifestEntries, - ) + containsOnly("foo/", "foo/bar", "foo/baz", *manifestEntries) getContent("foo/bar").isEqualTo("bar1") getContent("foo/baz").isEqualTo("baz3") } @@ -246,22 +236,16 @@ class TransformersTest : BaseTransformerTest() { // Use Transformer.Companion (no-op) to mock a custom transformer here. transform(${ResourceTransformer.Companion::class.java.name}) } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) - assertThat(outputShadowedJar).useAll { - containsOnly( - *entriesInAB, - *manifestEntries, - ) - } + assertThat(outputShadowedJar).useAll { containsOnly(*entriesInAB, *manifestEntries) } } - @Issue( - "https://github.com/GradleUp/shadow/issues/1626", - ) + @Issue("https://github.com/GradleUp/shadow/issues/1626") @Test fun useApacheNoticeTransformerWithoutProjectName() { val noticeEntry = "META-INF/NOTICE" @@ -274,7 +258,8 @@ class TransformersTest : BaseTransformerTest() { This product includes software developed at The Apache Software Foundation (https://www.apache.org/). - """.trimIndent(), + """ + .trimIndent(), ) } val two = buildJarTwo { @@ -286,35 +271,35 @@ class TransformersTest : BaseTransformerTest() { This product includes software developed at The Apache Software Foundation (https://www.apache.org/). - """.trimIndent(), + """ + .trimIndent(), ) } projectScript.appendText( transform( dependenciesBlock = implementationFiles(one, two), transformerBlock = "addHeader = false", - ), + ) ) runWithSuccess(shadowJarPath) assertThat(outputShadowedJar).useAll { - containsOnly( - noticeEntry, - *manifestEntries, - ) - getContent(noticeEntry).isEqualTo( - """ - Apache Commons Pool - Copyright 2001-2025 The Apache Software Foundation + containsOnly(noticeEntry, *manifestEntries) + getContent(noticeEntry) + .isEqualTo( + """ + Apache Commons Pool + Copyright 2001-2025 The Apache Software Foundation - This product includes software developed at - The Apache Software Foundation (https://www.apache.org/). + This product includes software developed at + The Apache Software Foundation (https://www.apache.org/). - Apache Commons DBCP - Copyright 2001-2024 The Apache Software Foundation - """.trimIndent(), - ) + Apache Commons DBCP + Copyright 2001-2024 The Apache Software Foundation + """ + .trimIndent() + ) } } @@ -322,28 +307,22 @@ class TransformersTest : BaseTransformerTest() { fun overrideOutputPathOfNoticeFile() { val noticeEntry = "META-INF/NOTICE" val customNoticeEntry = "META-INF/CUSTOM_NOTICE" - val one = buildJarOne { - insert(noticeEntry, "Notice from A") - } - val two = buildJarTwo { - insert(noticeEntry, "Notice from B") - } + val one = buildJarOne { insert(noticeEntry, "Notice from A") } + val two = buildJarTwo { insert(noticeEntry, "Notice from B") } projectScript.appendText( transform( dependenciesBlock = implementationFiles(one, two), transformerBlock = "addHeader = false; outputPath = '$customNoticeEntry'", - ), + ) ) runWithSuccess(shadowJarPath) assertThat(outputShadowedJar).useAll { - containsOnly( - customNoticeEntry, - *manifestEntries, - ) - getContent(customNoticeEntry).isEqualTo( - """ + containsOnly(customNoticeEntry, *manifestEntries) + getContent(customNoticeEntry) + .isEqualTo( + """ Copyright 2006-2026 The Apache Software Foundation This product includes software developed at @@ -352,8 +331,9 @@ class TransformersTest : BaseTransformerTest() { Notice from A Notice from B - """.trimIndent(), - ) + """ + .trimIndent() + ) } } @@ -370,14 +350,13 @@ class TransformersTest : BaseTransformerTest() { $shadowJarTask { transform(${transformer.java.name}) $configuration } - """.trimIndent(), + """ + .trimIndent() ) runWithSuccess(shadowJarPath) - assertThat(outputShadowedJar).useAll { - containsAtLeast(*entriesInAB) - } + assertThat(outputShadowedJar).useAll { containsAtLeast(*entriesInAB) } } private fun commonAssertions( @@ -385,7 +364,7 @@ class TransformersTest : BaseTransformerTest() { assertThat(getValue(TEST_ENTRY_ATTR_KEY)).isEqualTo("PASSED") assertThat(getValue(mainClassAttributeKey)).isEqualTo("my.Main") assertThat(getValue(NEW_ENTRY_ATTR_KEY)).isEqualTo("NEW") - }, + } ) { val mf = outputShadowedJar.use { it.manifest } assertThat(mf).isNotNull() @@ -396,7 +375,8 @@ class TransformersTest : BaseTransformerTest() { const val NEW_ENTRY_ATTR_KEY = "New-Entry" const val TEST_ENTRY_ATTR_KEY = "Test-Entry" - val MANIFEST_ATTRS = """ + val MANIFEST_ATTRS = + """ $jarTask { manifest { attributes '$mainClassAttributeKey': 'my.Main' @@ -409,58 +389,57 @@ class TransformersTest : BaseTransformerTest() { attributes '$TEST_ENTRY_ATTR_KEY': 'PASSED' } } - """.trimIndent() + """ + .trimIndent() @JvmStatic - fun transformerConfigProvider() = listOf( - "" to ApacheLicenseResourceTransformer::class, - "" to ComponentsXmlResourceTransformer::class, - "" to ManifestAppenderTransformer::class, - "" to ManifestResourceTransformer::class, - ) + fun transformerConfigProvider() = + listOf( + "" to ApacheLicenseResourceTransformer::class, + "" to ComponentsXmlResourceTransformer::class, + "" to ManifestAppenderTransformer::class, + "" to ManifestResourceTransformer::class, + ) } @Test fun mergeLicenseResourceTransformer() { - val one = buildJarOne { - insert("META-INF/LICENSE", "license one") - } - val two = buildJarTwo { - insert("META-INF/LICENSE", "license two") - } + val one = buildJarOne { insert("META-INF/LICENSE", "license one") } + val two = buildJarTwo { insert("META-INF/LICENSE", "license two") } val artifactLicense = path("my-license") artifactLicense.writeText("artifact license text") projectScript.appendText( transform( dependenciesBlock = implementationFiles(one, two), - transformerBlock = """ + transformerBlock = + """ outputPath = 'MY_LICENSE' artifactLicense = file('${artifactLicense.invariantSeparatorsPathString}') firstSeparator = '####' separator = '----' - """.trimIndent(), - ), + """ + .trimIndent(), + ) ) runWithSuccess(shadowJarPath) assertThat(outputShadowedJar).useAll { - containsOnly( - "MY_LICENSE", - "META-INF/", - "META-INF/MANIFEST.MF", - ) - getContent("MY_LICENSE").transform { it.invariantEolString }.isEqualTo( - """ + containsOnly("MY_LICENSE", "META-INF/", "META-INF/MANIFEST.MF") + getContent("MY_LICENSE") + .transform { it.invariantEolString } + .isEqualTo( + """ SPDX-License-Identifier: Apache-2.0 artifact license text #### license one ---- license two - """.trimIndent(), - ) + """ + .trimIndent() + ) } } } diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/XmlAppendingTransformerTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/XmlAppendingTransformerTest.kt index 2cc226f20..3721f9a89 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/XmlAppendingTransformerTest.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/XmlAppendingTransformerTest.kt @@ -11,81 +11,83 @@ class XmlAppendingTransformerTest : BaseTransformerTest() { @Test fun appendXmlFiles() { val xmlEntry = "properties.xml" - val xmlContent = """ + val xmlContent = + """ %s - """.trimIndent() - val one = buildJarOne { - insert(xmlEntry, xmlContent.format("key1", "val1")) - } - val two = buildJarTwo { - insert(xmlEntry, xmlContent.format("key2", "val2")) - } + """ + .trimIndent() + val one = buildJarOne { insert(xmlEntry, xmlContent.format("key1", "val1")) } + val two = buildJarTwo { insert(xmlEntry, xmlContent.format("key2", "val2")) } projectScript.appendText( transform( dependenciesBlock = implementationFiles(one, two), - transformerBlock = """ + transformerBlock = + """ resource = '$xmlEntry' - """.trimIndent(), - ), + """ + .trimIndent(), + ) ) runWithSuccess(shadowJarPath) val content = outputShadowedJar.use { it.getContent(xmlEntry) }.trimIndent() - assertThat(content).isEqualTo( - """ + assertThat(content) + .isEqualTo( + """ val1 val2 - """.trimIndent(), - ) + """ + .trimIndent() + ) } - @Issue( - "https://github.com/GradleUp/shadow/issues/168", - ) + @Issue("https://github.com/GradleUp/shadow/issues/168") @Test fun mergeNestedLevels() { val xmlEntry = "META-INF/nested.xml" - val xmlContent = """ + val xmlContent = + """ %s - """.trimIndent() - val one = buildJarOne { - insert(xmlEntry, xmlContent.format("")) - } - val two = buildJarTwo { - insert(xmlEntry, xmlContent.format("")) - } + """ + .trimIndent() + val one = buildJarOne { insert(xmlEntry, xmlContent.format("")) } + val two = buildJarTwo { insert(xmlEntry, xmlContent.format("")) } projectScript.appendText( transform( dependenciesBlock = implementationFiles(one, two), - transformerBlock = """ + transformerBlock = + """ resource = '$xmlEntry' - """.trimIndent(), - ), + """ + .trimIndent(), + ) ) runWithSuccess(shadowJarPath) val content = outputShadowedJar.use { it.getContent(xmlEntry) }.trimIndent() - assertThat(content).isEqualTo( - """ + assertThat(content) + .isEqualTo( + """ - """.trimIndent(), - ) + """ + .trimIndent() + ) } } diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/util/AppendableMavenRepository.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/util/AppendableMavenRepository.kt index cda9c70c0..629aba91c 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/util/AppendableMavenRepository.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/util/AppendableMavenRepository.kt @@ -16,16 +16,16 @@ import org.apache.maven.model.Dependency import org.apache.maven.model.Model import org.gradle.api.logging.Logging -class AppendableMavenRepository( - val root: Path, -) { +class AppendableMavenRepository(val root: Path) { private val modules = mutableListOf() private val jarsDir: Path init { check(root.exists()) { "Maven repository root directory does not exist: $root" } - root.resolve("settings.gradle").createFile() + root + .resolve("settings.gradle") + .createFile() .writeText("rootProject.name = '${root.name}'$lineSeparator") root.resolve("build.gradle").createFile() jarsDir = root.resolve("jars").createDirectory() @@ -54,61 +54,64 @@ class AppendableMavenRepository( } fun publish() { - check(modules.isNotEmpty()) { - "No modules to publish. Please add at least one module." - } - modules.groupBy { it::class }.forEach { (type, group) -> - @Suppress("UNCHECKED_CAST") - when (type) { - JarModule::class -> { - configureJarModules(group as List) - } - BomModule::class -> { - configureBomModules(group as List) + check(modules.isNotEmpty()) { "No modules to publish. Please add at least one module." } + modules + .groupBy { it::class } + .forEach { (type, group) -> + @Suppress("UNCHECKED_CAST") + when (type) { + JarModule::class -> { + configureJarModules(group as List) + } + BomModule::class -> { + configureBomModules(group as List) + } + else -> error("Unsupported module type: $type") } - else -> error("Unsupported module type: $type") } - } - gradleRunner( - projectDir = root, - arguments = commonGradleArgs + "publish", - ).build() + gradleRunner(projectDir = root, arguments = commonGradleArgs + "publish").build() logger.info( """ Publish modules to Maven repository at ${root.toUri()}: ${modules.joinToString(lineSeparator) { it.coordinate }} - """.trimIndent(), + """ + .trimIndent() ) modules.clear() } private fun configureJarModules(jarModules: List) { - val mavenPublications = jarModules.joinToString(lineSeparator) { module -> - var index = -1 - val nodes = module.dependencies.joinToString(lineSeparator) { - index++ - val node = "dependencyNode$index" - """ + val mavenPublications = + jarModules.joinToString(lineSeparator) { module -> + var index = -1 + val nodes = + module.dependencies.joinToString(lineSeparator) { + index++ + val node = "dependencyNode$index" + """ def $node = dependenciesNode.appendNode('dependency') $node.appendNode('groupId', '${it.groupId}') $node.appendNode('artifactId', '${it.artifactId}') $node.appendNode('version', '${it.version}') $node.appendNode('scope', '${it.scope}') - """.trimIndent() - } - module.createMavenPublication( """ + .trimIndent() + } + module.createMavenPublication( + """ artifact '${module.artifactPath}' pom.withXml { xml -> def dependenciesNode = xml.asNode().get('dependencies') ?: xml.asNode().appendNode('dependencies') $nodes } - """.trimIndent(), - ) - } - val scriptContent = """ + """ + .trimIndent() + ) + } + val scriptContent = + """ plugins { id 'maven-publish' } @@ -120,18 +123,18 @@ class AppendableMavenRepository( maven { url = '${root.toUri()}' } } } - """.trimIndent() + """ + .trimIndent() val jarsModule = "jars-module" root.resolve("settings.gradle").appendText("include '$jarsModule'$lineSeparator") - root.resolve("$jarsModule/build.gradle") - .createFileIfNotExists() - .writeText(scriptContent) + root.resolve("$jarsModule/build.gradle").createFileIfNotExists().writeText(scriptContent) } private fun configureBomModules(bomModules: List) { // BOM modules are published one by one. bomModules.forEachIndexed { index, module -> - val scriptContent = """ + val scriptContent = + """ plugins { id 'maven-publish' id 'java-platform' @@ -149,18 +152,15 @@ class AppendableMavenRepository( maven { url = '${root.toUri()}' } } } - """.trimIndent() + """ + .trimIndent() val pomModule = "pom-module-$index" root.resolve("settings.gradle").appendText("include '$pomModule'$lineSeparator") - root.resolve("$pomModule/build.gradle") - .createFileIfNotExists() - .writeText(scriptContent) + root.resolve("$pomModule/build.gradle").createFileIfNotExists().writeText(scriptContent) } } - private fun Module.createMavenPublication( - block: String, - ): String { + private fun Module.createMavenPublication(block: String): String { return """ create('${coordinate.replace(":", "")}', MavenPublication) { artifactId = '$artifactId' @@ -168,14 +168,11 @@ class AppendableMavenRepository( version = '$version' $block } - """.trimIndent() + """ + .trimIndent() } - sealed class Module( - groupId: String, - artifactId: String, - version: String, - ) : Model() { + sealed class Module(groupId: String, artifactId: String, version: String) : Model() { val coordinate = "$groupId:$artifactId:$version" init { @@ -185,29 +182,35 @@ class AppendableMavenRepository( } fun addDependency(coordinate: String, scope: String = "runtime") { - val (groupId, artifactId, version) = coordinate.split(":").takeIf { it.size == 3 } - ?: error("Invalid coordinate format: '$coordinate'. Expected format is 'groupId:artifactId:version'.") - val dependency = Dependency().also { - it.groupId = groupId - it.artifactId = artifactId - it.version = version - it.scope = scope - } + val (groupId, artifactId, version) = + coordinate.split(":").takeIf { it.size == 3 } + ?: error( + "Invalid coordinate format: '$coordinate'. Expected format is 'groupId:artifactId:version'." + ) + val dependency = + Dependency().also { + it.groupId = groupId + it.artifactId = artifactId + it.version = version + it.scope = scope + } addDependency(dependency) } } - inner class JarModule( - groupId: String, - artifactId: String, - version: String, - ) : Module(groupId, artifactId, version) { + inner class JarModule(groupId: String, artifactId: String, version: String) : + Module(groupId, artifactId, version) { private var existingJar: Path? = null val artifactPath: String - get() = existingJar?.also { - check(it.exists() && it.isRegularFile()) { "Jar file does not exist or is not a regular file: $it" } - }?.invariantSeparatorsPathString ?: error("No jar file provided for $coordinate") + get() = + existingJar + ?.also { + check(it.exists() && it.isRegularFile()) { + "Jar file does not exist or is not a regular file: $it" + } + } + ?.invariantSeparatorsPathString ?: error("No jar file provided for $coordinate") fun useJar(existingJar: Path) { this.existingJar = existingJar @@ -219,11 +222,8 @@ class AppendableMavenRepository( } } - class BomModule( - groupId: String, - artifactId: String, - version: String, - ) : Module(groupId, artifactId, version) { + class BomModule(groupId: String, artifactId: String, version: String) : + Module(groupId, artifactId, version) { init { packaging = "pom" } @@ -234,7 +234,8 @@ private val logger = Logging.getLogger(AppendableMavenRepository::class.java) private val lineSeparator = System.lineSeparator() -val Dependency.coordinate: String get() = "$groupId:$artifactId:$version" +val Dependency.coordinate: String + get() = "$groupId:$artifactId:$version" private fun Path.createFileIfNotExists(): Path { if (!exists()) { diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/util/GradleModuleMetadata.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/util/GradleModuleMetadata.kt index 4ae3ebc55..fef15ab37 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/util/GradleModuleMetadata.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/util/GradleModuleMetadata.kt @@ -5,16 +5,21 @@ import org.gradle.api.plugins.JavaPlugin.API_ELEMENTS_CONFIGURATION_NAME import org.gradle.api.plugins.JavaPlugin.RUNTIME_ELEMENTS_CONFIGURATION_NAME /** - * Refs the format from [Gradle Module Metadata](https://github.com/gradle/gradle/blob/master/platforms/documentation/docs/src/docs/design/gradle-module-metadata-latest-specification.md). + * Refs the format from + * [Gradle Module Metadata](https://github.com/gradle/gradle/blob/master/platforms/documentation/docs/src/docs/design/gradle-module-metadata-latest-specification.md). */ -data class GradleModuleMetadata( - private val variants: List, -) { - val apiElementsVariant: Variant get() = variants.single { it.name == API_ELEMENTS_CONFIGURATION_NAME } - val runtimeElementsVariant: Variant get() = variants.single { it.name == RUNTIME_ELEMENTS_CONFIGURATION_NAME } - val shadowRuntimeElementsVariant: Variant get() = variants.single { it.name == SHADOW_RUNTIME_ELEMENTS_CONFIGURATION_NAME } +data class GradleModuleMetadata(private val variants: List) { + val apiElementsVariant: Variant + get() = variants.single { it.name == API_ELEMENTS_CONFIGURATION_NAME } - val variantNames: List get() = variants.map { it.name } + val runtimeElementsVariant: Variant + get() = variants.single { it.name == RUNTIME_ELEMENTS_CONFIGURATION_NAME } + + val shadowRuntimeElementsVariant: Variant + get() = variants.single { it.name == SHADOW_RUNTIME_ELEMENTS_CONFIGURATION_NAME } + + val variantNames: List + get() = variants.map { it.name } data class Variant( val name: String, @@ -22,21 +27,19 @@ data class GradleModuleMetadata( private val dependencies: List = emptyList(), private val files: List = emptyList(), ) { - val coordinates: List get() = dependencies.map { it.coordinate } - val fileNames: List get() = files.map { it.name } + val coordinates: List + get() = dependencies.map { it.coordinate } + + val fileNames: List + get() = files.map { it.name } - data class Dependency( - val group: String, - val module: String, - val version: Version, - ) { - val coordinate: String get() = "$group:$module:${version.requires}" + data class Dependency(val group: String, val module: String, val version: Version) { + val coordinate: String + get() = "$group:$module:${version.requires}" data class Version(val requires: String) } - data class File( - val name: String, - ) + data class File(val name: String) } } diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/util/Issue.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/util/Issue.kt index e7b936358..f0b5c4010 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/util/Issue.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/util/Issue.kt @@ -6,7 +6,9 @@ import org.junit.jupiter.api.extension.ExtensionContext import org.junit.jupiter.api.extension.ExtensionContext.Namespace /** - * This is related to [spock.lang.Issue](https://github.com/spockframework/spock/blob/master/spock-core/src/main/java/spock/lang/Issue.java) but is used for JUnit 5 tests. + * This is related to + * [spock.lang.Issue](https://github.com/spockframework/spock/blob/master/spock-core/src/main/java/spock/lang/Issue.java) + * but is used for JUnit 5 tests. * * @see [Tags] */ @@ -17,15 +19,14 @@ annotation class Issue(vararg val values: String) class IssueExtension : BeforeEachCallback { override fun beforeEach(context: ExtensionContext) { val issueAnnotation = context.requiredTestMethod.getAnnotation(Issue::class.java) ?: return - val store = context.getStore(Namespace.create(IssueExtension::class.java, context.requiredTestClass)) + val store = + context.getStore(Namespace.create(IssueExtension::class.java, context.requiredTestClass)) store.put("tags", issueAnnotation.values.map(::issueLinkToTag)) } } private fun issueLinkToTag(link: String): String { - return issueLinkRegex.replace(link) { matchResult -> - "ISSUE-${matchResult.groupValues[1]}" - } + return issueLinkRegex.replace(link) { matchResult -> "ISSUE-${matchResult.groupValues[1]}" } } private val issueLinkRegex = "https://github\\.com/[^/]+/[^/]+/issues/(\\d+)".toRegex() diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/util/JarBuilder.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/util/JarBuilder.kt index 3fc1eb220..67964a25b 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/util/JarBuilder.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/util/JarBuilder.kt @@ -5,18 +5,14 @@ import java.util.jar.JarEntry import java.util.jar.JarOutputStream import kotlin.io.path.outputStream -class JarBuilder( - private val outputPath: Path, -) { +class JarBuilder(private val outputPath: Path) { private val contents = mutableMapOf() private val entries = mutableSetOf() private val jos = JarOutputStream(outputPath.outputStream()) fun insert(entry: String, content: String): JarBuilder = insert(entry, content.toByteArray()) - fun insert(entry: String, content: ByteArray): JarBuilder = apply { - contents[entry] = content - } + fun insert(entry: String, content: ByteArray): JarBuilder = apply { contents[entry] = content } fun write(): Path { jos.use { diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/util/JvmLang.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/util/JvmLang.kt index 2243ef674..9beeaf8ac 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/util/JvmLang.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/util/JvmLang.kt @@ -1,11 +1,8 @@ package com.github.jengelman.gradle.plugins.shadow.util -enum class JvmLang( - val suffix: String, -) { +enum class JvmLang(val suffix: String) { Java("java"), - Kotlin("kt"), - ; + Kotlin("kt"); override fun toString(): String = name.lowercase() } diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/util/RunProcess.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/util/RunProcess.kt index d9e3f5218..8cbc02816 100644 --- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/util/RunProcess.kt +++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/util/RunProcess.kt @@ -1,17 +1,13 @@ package com.github.jengelman.gradle.plugins.shadow.util -fun runProcess( - vararg commands: String, -): String { +fun runProcess(vararg commands: String): String { val process = ProcessBuilder(commands.toList()).start() val exitCode = process.waitFor() val err = process.errorStream.bufferedReader().use { it.readText() } val out = process.inputStream.bufferedReader().use { it.readText() } - check(exitCode == 0 && err.isEmpty()) { - "Error occurred when running command line: $err" - } + check(exitCode == 0 && err.isEmpty()) { "Error occurred when running command line: $err" } return out } diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowApplicationPlugin.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowApplicationPlugin.kt index 0f1879582..115c7575f 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowApplicationPlugin.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowApplicationPlugin.kt @@ -26,18 +26,20 @@ import org.gradle.api.tasks.bundling.Zip /** * A [Plugin] which packages and runs a project as a Java Application using the shadowed jar. * - * Modified from [org.gradle.api.plugins.ApplicationPlugin.java](https://github.com/gradle/gradle/blob/fdecc3c95828bb9a1c1bb6114483fe5b16f9159d/platforms/jvm/plugins-application/src/main/java/org/gradle/api/plugins/ApplicationPlugin.java). + * Modified from + * [org.gradle.api.plugins.ApplicationPlugin.java](https://github.com/gradle/gradle/blob/fdecc3c95828bb9a1c1bb6114483fe5b16f9159d/platforms/jvm/plugins-application/src/main/java/org/gradle/api/plugins/ApplicationPlugin.java). * * @see [ApplicationPlugin] */ public abstract class ShadowApplicationPlugin : Plugin { - override fun apply(project: Project): Unit = with(project) { - addRunTask() - addCreateScriptsTask() - configureDistribution() - configureShadowJarMainClass() - configureInstallTask() - } + override fun apply(project: Project): Unit = + with(project) { + addRunTask() + addCreateScriptsTask() + configureDistribution() + configureShadowJarMainClass() + configureInstallTask() + } protected open fun Project.addRunTask() { tasks.register(SHADOW_RUN_TASK_NAME, JavaExec::class.java) { task -> @@ -58,7 +60,8 @@ public abstract class ShadowApplicationPlugin : Plugin { protected open fun Project.addCreateScriptsTask() { tasks.register(SHADOW_SCRIPTS_TASK_NAME, CreateStartScripts::class.java) { task -> - task.description = "Creates OS specific scripts to run the project as a JVM application using the shadow jar" + task.description = + "Creates OS specific scripts to run the project as a JVM application using the shadow jar" task.classpath = files(tasks.shadowJar) @@ -67,7 +70,9 @@ public abstract class ShadowApplicationPlugin : Plugin { task.mainModule.convention(mainModule) task.mainClass.convention(mainClass) task.conventionMapping.map("applicationName", ::getApplicationName) - task.conventionMapping.map("outputDir") { layout.buildDirectory.dir("scriptsShadow").get().asFile } + task.conventionMapping.map("outputDir") { + layout.buildDirectory.dir("scriptsShadow").get().asFile + } task.conventionMapping.map("executableDir", ::getExecutableDir) task.conventionMapping.map("defaultJvmOpts", ::getApplicationDefaultJvmArgs) } @@ -82,17 +87,18 @@ public abstract class ShadowApplicationPlugin : Plugin { task.doFirst("Check installation directory") { val destinationDir = task.destinationDir - val children = destinationDir.list() ?: throw IOException("Could not list directory $destinationDir") + val children = + destinationDir.list() ?: throw IOException("Could not list directory $destinationDir") if (children.isEmpty()) return@doFirst if ( !destinationDir.resolve("lib").isDirectory || - !destinationDir.resolve("bin").isDirectory || - !destinationDir.resolve(executableDir.get()).isDirectory + !destinationDir.resolve("bin").isDirectory || + !destinationDir.resolve(executableDir.get()).isDirectory ) { throw GradleException( "The specified installation directory '$destinationDir' is neither empty nor does it contain an installation for '${applicationName.get()}'.\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.", + "Alternatively, choose a different installation directory." ) } } @@ -103,10 +109,12 @@ public abstract class ShadowApplicationPlugin : Plugin { distributions.register(DISTRIBUTION_NAME) { dist -> dist.distributionBaseName.convention( provider { - // distributionBaseName defaults to `$project.name-$distribution.name`, applicationName defaults to project.name - // so we append the suffix to match the default distributionBaseName. Modified from `ApplicationPlugin.configureDistribution()`. + // distributionBaseName defaults to `$project.name-$distribution.name`, applicationName + // defaults to project.name + // so we append the suffix to match the default distributionBaseName. Modified from + // `ApplicationPlugin.configureDistribution()`. "${applicationExtension.applicationName}-$DISTRIBUTION_NAME" - }, + } ) dist.contents { distSpec -> distSpec.from(file("src/dist")) @@ -126,15 +134,11 @@ public abstract class ShadowApplicationPlugin : Plugin { } protected open fun Project.configureShadowJarMainClass() { - tasks.shadowJar.configure { task -> - task.mainClass.convention(applicationExtension.mainClass) - } + tasks.shadowJar.configure { task -> task.mainClass.convention(applicationExtension.mainClass) } } public companion object { - /** - * Reflects the number of 755. - */ + /** Reflects the number of 755. */ private const val UNIX_SCRIPT_PERMISSIONS = "rwxr-xr-x" public const val DISTRIBUTION_NAME: String = SHADOW diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowBasePlugin.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowBasePlugin.kt index c1c4f22a4..862c497c0 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowBasePlugin.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowBasePlugin.kt @@ -14,20 +14,20 @@ import org.gradle.api.plugins.ExtensionContainer public abstract class ShadowBasePlugin : Plugin { - override fun apply(project: Project): Unit = with(project) { - with(extensions.create(EXTENSION_NAME, ShadowExtension::class.java)) { - addShadowVariantIntoJavaComponent.convention(true) - addTargetJvmVersionAttribute.convention(true) - bundlingAttribute.convention(Bundling.SHADOWED) + override fun apply(project: Project): Unit = + with(project) { + with(extensions.create(EXTENSION_NAME, ShadowExtension::class.java)) { + addShadowVariantIntoJavaComponent.convention(true) + addTargetJvmVersionAttribute.convention(true) + bundlingAttribute.convention(Bundling.SHADOWED) + } + @Suppress("EagerGradleConfiguration") // this should be created eagerly. + configurations.create(CONFIGURATION_NAME) } - @Suppress("EagerGradleConfiguration") // this should be created eagerly. - configurations.create(CONFIGURATION_NAME) - } public companion object { /** * Most of the components registered by Shadow plugin will use this name (`shadow`). - * * - [ExtensionContainer.create] * - [ConfigurationContainer.register] * - [SoftwareComponentContainer.register] diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowExtension.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowExtension.kt index b74387e8a..8cf5927c8 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowExtension.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowExtension.kt @@ -6,16 +6,18 @@ import org.gradle.api.provider.Property public interface ShadowExtension { /** - * If `true`, publishes the [ShadowJavaPlugin.SHADOW_RUNTIME_ELEMENTS_CONFIGURATION_NAME] as an optional variant of - * the `java` component. This affects how consumers resolve the published artifact. + * If `true`, publishes the [ShadowJavaPlugin.SHADOW_RUNTIME_ELEMENTS_CONFIGURATION_NAME] as an + * optional variant of the `java` component. This affects how consumers resolve the published + * artifact. * * Defaults to `true`. */ public val addShadowVariantIntoJavaComponent: Property /** - * If `true`, adds a [TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE] attribute to the Gradle Module Metadata of the - * shadowed JAR. This affects how consumers resolve the published artifact based on the target JVM version. + * If `true`, adds a [TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE] attribute to the Gradle + * Module Metadata of the shadowed JAR. This affects how consumers resolve the published artifact + * based on the target JVM version. * * Defaults to `true`. */ @@ -24,7 +26,8 @@ public interface ShadowExtension { /** * The [Bundling] attribute to use for the Gradle Module Metadata. * - * Per description of the attribute, you should set it to either [Bundling.SHADOWED] or [Bundling.EMBEDDED]. + * Per description of the attribute, you should set it to either [Bundling.SHADOWED] or + * [Bundling.EMBEDDED]. * * Defaults to [Bundling.SHADOWED]. */ diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.kt index f58b81e39..55c86d5da 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.kt @@ -26,22 +26,24 @@ import org.gradle.api.plugins.JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME import org.gradle.api.plugins.JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME import org.gradle.api.tasks.bundling.Jar -public abstract class ShadowJavaPlugin @Inject constructor( - private val softwareComponentFactory: SoftwareComponentFactory, -) : Plugin { +public abstract class ShadowJavaPlugin +@Inject +constructor(private val softwareComponentFactory: SoftwareComponentFactory) : Plugin { - override fun apply(project: Project): Unit = with(project) { - configureShadowJar() - configureConfigurations() - configureComponents() - configureJavaGradlePlugin() - } + override fun apply(project: Project): Unit = + with(project) { + configureShadowJar() + configureConfigurations() + configureComponents() + configureJavaGradlePlugin() + } protected open fun Project.configureShadowJar() { - val taskProvider = registerShadowJarCommon(tasks.named("jar", Jar::class.java)) { task -> - task.from(sourceSets.named("main").map { it.output }) - task.configurations.convention(provider { listOf(runtimeConfiguration) }) - } + val taskProvider = + registerShadowJarCommon(tasks.named("jar", Jar::class.java)) { task -> + task.from(sourceSets.named("main").map { it.output }) + task.configurations.convention(provider { listOf(runtimeConfiguration) }) + } artifacts.add(configurations.shadow.name, taskProvider) } @@ -50,42 +52,61 @@ public abstract class ShadowJavaPlugin @Inject constructor( configurations.named(COMPILE_CLASSPATH_CONFIGURATION_NAME) { compileClasspath -> compileClasspath.extendsFrom(shadowConfiguration) } - val shadowRuntimeElements = configurations.register(SHADOW_RUNTIME_ELEMENTS_CONFIGURATION_NAME) { - it.extendsFrom(shadowConfiguration) - it.isCanBeConsumed = true - it.isCanBeResolved = false - it.attributes { attrs -> - attrs.attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage::class.java, Usage.JAVA_RUNTIME)) - attrs.attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category::class.java, Category.LIBRARY)) - attrs.attribute( - LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, - objects.named(LibraryElements::class.java, LibraryElements.JAR), - ) - attrs.attributeProvider( - Bundling.BUNDLING_ATTRIBUTE, - shadow.bundlingAttribute.map { attr -> objects.named(Bundling::class.java, attr) }, - ) + val shadowRuntimeElements = + configurations.register(SHADOW_RUNTIME_ELEMENTS_CONFIGURATION_NAME) { + it.extendsFrom(shadowConfiguration) + it.isCanBeConsumed = true + it.isCanBeResolved = false + it.attributes { attrs -> + attrs.attribute( + Usage.USAGE_ATTRIBUTE, + objects.named(Usage::class.java, Usage.JAVA_RUNTIME), + ) + attrs.attribute( + Category.CATEGORY_ATTRIBUTE, + objects.named(Category::class.java, Category.LIBRARY), + ) + attrs.attribute( + LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, + objects.named(LibraryElements::class.java, LibraryElements.JAR), + ) + attrs.attributeProvider( + Bundling.BUNDLING_ATTRIBUTE, + shadow.bundlingAttribute.map { attr -> objects.named(Bundling::class.java, attr) }, + ) + } + it.outgoing.artifact(tasks.shadowJar) } - it.outgoing.artifact(tasks.shadowJar) - } // Must use afterEvaluate here as we need to track the changes of addTargetJvmVersionAttribute. afterEvaluate { if (shadow.addTargetJvmVersionAttribute.get()) { - logger.info("Setting ${TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE.name} attribute for ${shadowRuntimeElements.name} configuration.") + logger.info( + "Setting ${TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE.name} attribute for ${shadowRuntimeElements.name} configuration." + ) } else { - logger.info("Skipping setting ${TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE.name} attribute for ${shadowRuntimeElements.name} configuration.") + logger.info( + "Skipping setting ${TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE.name} attribute for ${shadowRuntimeElements.name} configuration." + ) return@afterEvaluate } - val targetJvmVersion = configurations.named(COMPILE_CLASSPATH_CONFIGURATION_NAME).map { compileClasspath -> - compileClasspath.attributes.getAttribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE) - }.getOrElse(javaPluginExtension.targetCompatibility.majorVersion.toInt()) + val targetJvmVersion = + configurations + .named(COMPILE_CLASSPATH_CONFIGURATION_NAME) + .map { compileClasspath -> + compileClasspath.attributes.getAttribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE) + } + .getOrElse(javaPluginExtension.targetCompatibility.majorVersion.toInt()) // https://github.com/gradle/gradle/blob/4198ab0670df14af9f77b9098dc892b199ac1f3f/platforms/jvm/plugins-java-base/src/main/java/org/gradle/api/plugins/jvm/internal/DefaultJvmLanguageUtilities.java#L85-L87 if (targetJvmVersion == Int.MAX_VALUE) { - logger.info("Cannot set the target JVM version to Int.MAX_VALUE when `java.autoTargetJvmDisabled` is enabled or in other cases.") + logger.info( + "Cannot set the target JVM version to Int.MAX_VALUE when `java.autoTargetJvmDisabled` is enabled or in other cases." + ) } else { - logger.info("Setting target JVM version to $targetJvmVersion for ${shadowRuntimeElements.name} configuration.") + logger.info( + "Setting target JVM version to $targetJvmVersion for ${shadowRuntimeElements.name} configuration." + ) shadowRuntimeElements.configure { it.attributes { attrs -> attrs.attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, targetJvmVersion) @@ -102,7 +123,8 @@ public abstract class ShadowJavaPlugin @Inject constructor( shadowComponent.addVariantsFromConfigurationCompat(shadowRuntimeElements) { variant -> variant.mapToMavenScope("runtime") } - // Must use afterEvaluate here as we need to track the changes of addShadowVariantIntoJavaComponent. + // Must use afterEvaluate here as we need to track the changes of + // addShadowVariantIntoJavaComponent. afterEvaluate { if (shadow.addShadowVariantIntoJavaComponent.get()) { logger.info("Adding ${shadowRuntimeElements.name} variant to Java component.") @@ -124,13 +146,16 @@ public abstract class ShadowJavaPlugin @Inject constructor( val gradleApi = dependencies.gradleApi() // Remove the gradleApi so it isn't merged into the jar file. // This is required because 'java-gradle-plugin' adds gradleApi() to the 'api' configuration. - // See https://github.com/gradle/gradle/blob/972c3e5c6ef990dd2190769c1ce31998a9402a79/subprojects/plugin-development/src/main/java/org/gradle/plugin/devel/plugins/JavaGradlePluginPlugin.java#L161. + // See + // https://github.com/gradle/gradle/blob/972c3e5c6ef990dd2190769c1ce31998a9402a79/subprojects/plugin-development/src/main/java/org/gradle/plugin/devel/plugins/JavaGradlePluginPlugin.java#L161. configurations.named(API_CONFIGURATION_NAME) { api -> // Only proceed if the removal is successful. if (!api.dependencies.remove(gradleApi)) return@named // Compile only gradleApi() to make sure the plugin can compile against Gradle API. - configurations.getByName(COMPILE_ONLY_CONFIGURATION_NAME) - .dependencies.add(dependencies.gradleApi()) + configurations + .getByName(COMPILE_ONLY_CONFIGURATION_NAME) + .dependencies + .add(dependencies.gradleApi()) } } } @@ -140,7 +165,8 @@ public abstract class ShadowJavaPlugin @Inject constructor( public const val SHADOW_RUNTIME_ELEMENTS_CONFIGURATION_NAME: String = "shadowRuntimeElements" @get:JvmSynthetic - public inline val ConfigurationContainer.shadowRuntimeElements: NamedDomainObjectProvider + public inline val ConfigurationContainer.shadowRuntimeElements: + NamedDomainObjectProvider get() = named(SHADOW_RUNTIME_ELEMENTS_CONFIGURATION_NAME) } } diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowKmpPlugin.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowKmpPlugin.kt index 3467cd562..441ad5b5d 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowKmpPlugin.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowKmpPlugin.kt @@ -12,19 +12,24 @@ import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget public abstract class ShadowKmpPlugin : Plugin { - override fun apply(project: Project): Unit = with(project) { - extensions.getByType(KotlinMultiplatformExtension::class.java).targets.configureEach { target -> - if (target !is KotlinJvmTarget) return@configureEach - @Suppress("EagerGradleConfiguration") - if (tasks.findByName(SHADOW_JAR_TASK_NAME) != null) { - // Declaring multiple Kotlin Targets of the same type is not supported. See https://kotl.in/declaring-multiple-targets for more details. - logger.info("$SHADOW_JAR_TASK_NAME task already exists, skipping configuration for target: ${target.name}") - return@configureEach - } + override fun apply(project: Project): Unit = + with(project) { + extensions.getByType(KotlinMultiplatformExtension::class.java).targets.configureEach { target + -> + if (target !is KotlinJvmTarget) return@configureEach + @Suppress("EagerGradleConfiguration") + if (tasks.findByName(SHADOW_JAR_TASK_NAME) != null) { + // Declaring multiple Kotlin Targets of the same type is not supported. See + // https://kotl.in/declaring-multiple-targets for more details. + logger.info( + "$SHADOW_JAR_TASK_NAME task already exists, skipping configuration for target: ${target.name}" + ) + return@configureEach + } - configureShadowJar(target) + configureShadowJar(target) + } } - } private fun Project.configureShadowJar(target: KotlinJvmTarget) { val kotlinJvmMain = target.compilations.named("main") @@ -33,15 +38,13 @@ public abstract class ShadowKmpPlugin : Plugin { task.configurations.convention( provider { listOf(configurations.getByName(kotlinJvmMain.get().runtimeDependencyConfigurationName)) - }, + } ) if (!isAtLeastKgp("1.9.0")) return@registerShadowJarCommon @OptIn(ExperimentalKotlinGradlePluginApi::class) - target.mainRun { - task.mainClass.convention(mainClass) - } + target.mainRun { task.mainClass.convention(mainClass) } } } } diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowPlugin.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowPlugin.kt index de22b3038..8b5d9d18b 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowPlugin.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowPlugin.kt @@ -9,37 +9,36 @@ import org.gradle.api.Project public abstract class ShadowPlugin : Plugin { - override fun apply(project: Project): Unit = with(project.plugins) { - apply(ShadowBasePlugin::class.java) - // org.gradle.api.plugins.JavaPlugin - withId("org.gradle.java") { - apply(ShadowJavaPlugin::class.java) - } - // org.gradle.api.plugins.ApplicationPlugin - withId("org.gradle.application") { - apply(ShadowApplicationPlugin::class.java) - } - withId(KOTLIN_MULTIPLATFORM_PLUGIN_ID) { - apply(ShadowKmpPlugin::class.java) - } - withId("com.android.base") { - error( - "Shadow does not support using with AGP, you may need Android Fused Library plugin instead. " + - "See https://developer.android.com/build/publish-library/fused-library", - ) - } - project.configureBuildScan() + override fun apply(project: Project): Unit = + with(project.plugins) { + apply(ShadowBasePlugin::class.java) + // org.gradle.api.plugins.JavaPlugin + withId("org.gradle.java") { apply(ShadowJavaPlugin::class.java) } + // org.gradle.api.plugins.ApplicationPlugin + withId("org.gradle.application") { apply(ShadowApplicationPlugin::class.java) } + withId(KOTLIN_MULTIPLATFORM_PLUGIN_ID) { apply(ShadowKmpPlugin::class.java) } + withId("com.android.base") { + error( + "Shadow does not support using with AGP, you may need Android Fused Library plugin instead. " + + "See https://developer.android.com/build/publish-library/fused-library" + ) + } + project.configureBuildScan() - // Apply the legacy plugin last. - // Because we apply the ShadowJavaPlugin/ShadowApplication plugin in a withType callback for the - // respective JavaPlugin/ApplicationPlugin, it may still apply before the shadowJar task is created etc. - // If the user applies shadow before those plugins. However, this is fine, because this was also - // the behavior with the old plugin when applying in that order. - apply(LegacyShadowPlugin::class.java) - } + // Apply the legacy plugin last. + // Because we apply the ShadowJavaPlugin/ShadowApplication plugin in a withType callback for + // the + // respective JavaPlugin/ApplicationPlugin, it may still apply before the shadowJar task is + // created etc. + // If the user applies shadow before those plugins. However, this is fine, because this was + // also + // the behavior with the old plugin when applying in that order. + apply(LegacyShadowPlugin::class.java) + } private fun Project.configureBuildScan() { - val enableDevelocityIntegration = findOptionalProperty(ENABLE_DEVELOCITY_INTEGRATION_PROPERTY)?.toBoolean() ?: false + val enableDevelocityIntegration = + findOptionalProperty(ENABLE_DEVELOCITY_INTEGRATION_PROPERTY)?.toBoolean() ?: false if (enableDevelocityIntegration) { logger.info("Enabling Develocity integration for Shadow plugin.") } else { @@ -50,6 +49,7 @@ public abstract class ShadowPlugin : Plugin { } public companion object { - public const val ENABLE_DEVELOCITY_INTEGRATION_PROPERTY: String = "com.gradleup.shadow.enableDevelocityIntegration" + public const val ENABLE_DEVELOCITY_INTEGRATION_PROPERTY: String = + "com.gradleup.shadow.enableDevelocityIntegration" } } diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/DefaultDependencyFilter.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/DefaultDependencyFilter.kt index 4033738dd..c743b14b8 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/DefaultDependencyFilter.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/DefaultDependencyFilter.kt @@ -4,16 +4,16 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.DependencyFilter import org.gradle.api.Project import org.gradle.api.artifacts.ResolvedDependency -internal class DefaultDependencyFilter( - project: Project, -) : DependencyFilter.AbstractDependencyFilter(project) { +internal class DefaultDependencyFilter(project: Project) : + DependencyFilter.AbstractDependencyFilter(project) { override fun resolve( dependencies: Set, includedDependencies: MutableSet, excludedDependencies: MutableSet, ) { dependencies.forEach { dep -> - val added = if (dep.isIncluded()) includedDependencies.add(dep) else excludedDependencies.add(dep) + val added = + if (dep.isIncluded()) includedDependencies.add(dep) else excludedDependencies.add(dep) if (added) { resolve(dep.children, includedDependencies, excludedDependencies) } diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/DefaultInheritManifest.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/DefaultInheritManifest.kt index 247cafbbf..887a26419 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/DefaultInheritManifest.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/DefaultInheritManifest.kt @@ -16,17 +16,12 @@ internal class DefaultInheritManifest( manifest: Manifest? = null, // `AbstractTask.getServices` is protected, we need to get it via `DefaultProject`. // https://github.com/gradle/gradle/blob/master/subprojects/core/src/main/java/org/gradle/api/internal/AbstractTask.java#L194 - private val fileResolver: FileResolver = (project as DefaultProject).services.get(FileResolver::class.java), + private val fileResolver: FileResolver = + (project as DefaultProject).services.get(FileResolver::class.java), private val internalManifest: Manifest = manifest ?: DefaultManifest(fileResolver), -) : InheritManifest, - Manifest by internalManifest { +) : InheritManifest, Manifest by internalManifest { - override fun inheritFrom( - vararg inheritPaths: Any, - action: Action, - ) { - inheritPaths.forEach { - from(it, action) - } + override fun inheritFrom(vararg inheritPaths: Any, action: Action) { + inheritPaths.forEach { from(it, action) } } } diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/GradleCompat.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/GradleCompat.kt index 03c281209..ae7f649e3 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/GradleCompat.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/GradleCompat.kt @@ -24,12 +24,11 @@ import org.gradle.api.tasks.SourceSetContainer import org.gradle.jvm.toolchain.JavaToolchainService import org.gradle.util.GradleVersion -/** - * Return `runtimeClasspath` or `runtime` configuration. - */ +/** Return `runtimeClasspath` or `runtime` configuration. */ internal inline val Project.runtimeConfiguration: Configuration - get() = configurations.findByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME) - ?: configurations.getByName("runtime") + get() = + configurations.findByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME) + ?: configurations.getByName("runtime") internal inline val Project.sourceSets: SourceSetContainer get() = extensions.getByType(SourceSetContainer::class.java) @@ -46,8 +45,10 @@ internal inline val Project.javaPluginExtension: JavaPluginExtension internal inline val Project.javaToolchainService: JavaToolchainService get() = extensions.getByType(JavaToolchainService::class.java) -// ExtraPropertiesExtension is IP safe and contains properties from both the root `gradle.properties` and the -// subproject's `gradle.properties`. See https://github.com/gradle/gradle/issues/29600#issuecomment-3580868326. +// ExtraPropertiesExtension is IP safe and contains properties from both the root +// `gradle.properties` and the +// subproject's `gradle.properties`. See +// https://github.com/gradle/gradle/issues/29600#issuecomment-3580868326. internal fun Project.findOptionalProperty(propertyName: String): String? { val extras = checkNotNull(extensions.findByType(ExtraPropertiesExtension::class.java)) return if (extras.has(propertyName)) extras.get(propertyName)?.toString() else null @@ -64,9 +65,7 @@ internal fun Project.addBuildScanCustomValues() { } } -/** - * TODO: this could be removed after bumping the min Gradle requirement to 9.2 or above. - */ +/** TODO: this could be removed after bumping the min Gradle requirement to 9.2 or above. */ @Suppress("UnstableApiUsage") internal fun AdhocComponentWithVariants.addVariantsFromConfigurationCompat( outgoingConfiguration: NamedDomainObjectProvider, @@ -81,44 +80,42 @@ internal fun AdhocComponentWithVariants.addVariantsFromConfigurationCompat( } internal inline fun ObjectFactory.property( - defaultValue: Any? = null, -): Property = property(V::class.java).apply { - defaultValue ?: return@apply - if (defaultValue is Provider<*>) { - @Suppress("UNCHECKED_CAST") - convention(defaultValue as Provider) - } else { - convention(defaultValue as V) + defaultValue: Any? = null +): Property = + property(V::class.java).apply { + defaultValue ?: return@apply + if (defaultValue is Provider<*>) { + @Suppress("UNCHECKED_CAST") convention(defaultValue as Provider) + } else { + convention(defaultValue as V) + } } -} @Suppress("UNCHECKED_CAST") internal inline fun ObjectFactory.setProperty( - defaultValue: Any? = null, -): SetProperty = setProperty(V::class.java).apply { - defaultValue ?: return@apply - if (defaultValue is Provider<*>) { - convention(defaultValue as Provider>) - } else { - convention(defaultValue as Iterable) + defaultValue: Any? = null +): SetProperty = + setProperty(V::class.java).apply { + defaultValue ?: return@apply + if (defaultValue is Provider<*>) { + convention(defaultValue as Provider>) + } else { + convention(defaultValue as Iterable) + } } -} @Suppress("UNCHECKED_CAST") internal inline fun ObjectFactory.mapProperty( - defaultValue: Any? = null, -): MapProperty = mapProperty(String::class.java, V::class.java).apply { - defaultValue ?: return@apply - if (defaultValue is Provider<*>) { - convention(defaultValue as Provider>) - } else { - convention(defaultValue as Map) + defaultValue: Any? = null +): MapProperty = + mapProperty(String::class.java, V::class.java).apply { + defaultValue ?: return@apply + if (defaultValue is Provider<*>) { + convention(defaultValue as Provider>) + } else { + convention(defaultValue as Map) + } } -} -internal inline fun ObjectFactory.fileCollection( - path: () -> Any, -): ConfigurableFileCollection = fileCollection().apply { - @Suppress("UnstableApiUsage") - convention(path()) -} +internal inline fun ObjectFactory.fileCollection(path: () -> Any): ConfigurableFileCollection = + fileCollection().apply { @Suppress("UnstableApiUsage") convention(path()) } diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/MinimizeDependencyFilter.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/MinimizeDependencyFilter.kt index 0ee204f86..75fdd5d46 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/MinimizeDependencyFilter.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/MinimizeDependencyFilter.kt @@ -4,20 +4,20 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.DependencyFilter import org.gradle.api.Project import org.gradle.api.artifacts.ResolvedDependency -internal class MinimizeDependencyFilter( - project: Project, -) : DependencyFilter.AbstractDependencyFilter(project) { +internal class MinimizeDependencyFilter(project: Project) : + DependencyFilter.AbstractDependencyFilter(project) { override fun resolve( dependencies: Set, includedDependencies: MutableSet, excludedDependencies: MutableSet, ) { dependencies.forEach { dep -> - val added = if (dep.isIncluded() && !excludedDependencies.any { it in dep.parents }) { - includedDependencies.add(dep) - } else { - excludedDependencies.add(dep) - } + val added = + if (dep.isIncluded() && !excludedDependencies.any { it in dep.parents }) { + includedDependencies.add(dep) + } else { + excludedDependencies.add(dep) + } if (added) { resolve(dep.children, includedDependencies, excludedDependencies) } diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/RelocatorRemapper.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/RelocatorRemapper.kt index ccf2bd659..ac30aeb81 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/RelocatorRemapper.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/RelocatorRemapper.kt @@ -8,8 +8,10 @@ import org.objectweb.asm.Opcodes import org.objectweb.asm.commons.Remapper /** - * Modified from [org.apache.maven.plugins.shade.DefaultShader.RelocatorRemapper](https://github.com/apache/maven-shade-plugin/blob/83c123d1f9c5f6927af2aca12ee322b5168a7c63/src/main/java/org/apache/maven/plugins/shade/DefaultShader.java#L689-L772). - * Modified from [org.apache.maven.plugins.shade.DefaultShader.DefaultPackageMapper](https://github.com/apache/maven-shade-plugin/blob/199ffaecd26a912527173ed4edae366e48a00998/src/main/java/org/apache/maven/plugins/shade/DefaultShader.java#L737-L774). + * Modified from + * [org.apache.maven.plugins.shade.DefaultShader.RelocatorRemapper](https://github.com/apache/maven-shade-plugin/blob/83c123d1f9c5f6927af2aca12ee322b5168a7c63/src/main/java/org/apache/maven/plugins/shade/DefaultShader.java#L689-L772). + * Modified from + * [org.apache.maven.plugins.shade.DefaultShader.DefaultPackageMapper](https://github.com/apache/maven-shade-plugin/blob/199ffaecd26a912527173ed4edae366e48a00998/src/main/java/org/apache/maven/plugins/shade/DefaultShader.java#L737-L774). * * @author John Engelman */ @@ -30,9 +32,7 @@ internal class RelocatorRemapper( private fun mapName(name: String, mapLiterals: Boolean = false): String { // Maybe a list of types. - val newName = name.split(';').joinToString(";") { - mapNameImpl(it, mapLiterals) - } + val newName = name.split(';').joinToString(";") { mapNameImpl(it, mapLiterals) } if (newName != name) { onModified() @@ -66,9 +66,7 @@ internal class RelocatorRemapper( } private companion object { - /** - * https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html - */ + /** https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html */ val classPattern: Pattern = Pattern.compile("([\\[()BCDFIJSZ]*)?L([^;]+);?") } } diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/ReproducibleProperties.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/ReproducibleProperties.kt index 02c3a3097..044becfb8 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/ReproducibleProperties.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/ReproducibleProperties.kt @@ -6,9 +6,7 @@ import java.io.Writer import java.nio.charset.Charset import java.util.Properties -/** - * Provides functionality for reproducible serialization. - */ +/** Provides functionality for reproducible serialization. */ internal class ReproducibleProperties : Properties() { override fun store(writer: Writer, comments: String) { throw UnsupportedOperationException("use writeWithoutComments()") @@ -19,19 +17,21 @@ internal class ReproducibleProperties : Properties() { } fun writeWithoutComments(charset: Charset, os: OutputStream) { - val bufferedReader = StringWriter().apply { - super.store(this, null) - }.toString().reader().buffered() + val bufferedReader = + StringWriter().apply { super.store(this, null) }.toString().reader().buffered() - os.bufferedWriter(charset).apply { - var line: String? = null - while (bufferedReader.readLine().also { line = it } != null && line != null) { - if (!line.startsWith("#")) { - write(line) - newLine() + os + .bufferedWriter(charset) + .apply { + var line: String? = null + while (bufferedReader.readLine().also { line = it } != null && line != null) { + if (!line.startsWith("#")) { + write(line) + newLine() + } } } - }.flush() + .flush() } override val entries: MutableSet> diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/UnusedTracker.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/UnusedTracker.kt index 1c6f9d97a..e9b09ba44 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/UnusedTracker.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/UnusedTracker.kt @@ -22,7 +22,9 @@ internal class UnusedTracker( private val cp = Clazzpath() init { - projectUnits = sourceSetsClassesDirs.map { cp.addClazzpathUnit(it) } + classJars.map { cp.addClazzpathUnit(it) } + projectUnits = + sourceSetsClassesDirs.map { cp.addClazzpathUnit(it) } + + classJars.map { cp.addClazzpathUnit(it) } } fun findUnused(): Set { @@ -42,8 +44,8 @@ internal class UnusedTracker( companion object { fun getApiJarsFromProject(project: Project): FileCollection { - val apiDependencies = project.configurations.findByName("api")?.dependencies - ?: return project.files() + val apiDependencies = + project.configurations.findByName("api")?.dependencies ?: return project.files() val runtimeConfiguration = project.runtimeConfiguration val apiJars = mutableListOf() apiDependencies.forEach { dep -> @@ -59,7 +61,8 @@ internal class UnusedTracker( is ExternalModuleDependency -> Unit else -> { addJar(runtimeConfiguration, dep, apiJars) - val jarFile = runtimeConfiguration.find { it.name.startsWith("${dep.name}-") } ?: return@forEach + val jarFile = + runtimeConfiguration.find { it.name.startsWith("${dep.name}-") } ?: return@forEach apiJars.add(jarFile) } } diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/Utils.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/Utils.kt index 2845bc1ea..a28e06d5b 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/Utils.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/Utils.kt @@ -8,19 +8,13 @@ import java.util.Properties import java.util.jar.Attributes.Name as JarAttributeName import org.apache.tools.zip.ZipEntry -/** - * Known as `Main-Class` in the manifest file. - */ +/** Known as `Main-Class` in the manifest file. */ internal val mainClassAttributeKey = JarAttributeName.MAIN_CLASS.toString() -/** - * Known as `Class-Path` in the manifest file. - */ +/** Known as `Class-Path` in the manifest file. */ internal val classPathAttributeKey = JarAttributeName.CLASS_PATH.toString() -/** - * Known as `Multi-Release` in the manifest file. - */ +/** Known as `Multi-Release` in the manifest file. */ internal val multiReleaseAttributeKey = JarAttributeName.MULTI_RELEASE.toString() /** @@ -30,31 +24,31 @@ internal val multiReleaseAttributeKey = JarAttributeName.MULTI_RELEASE.toString( internal inline fun Any?.cast(): T = this as T @Suppress("NOTHING_TO_INLINE") -internal inline fun unsafeLazy(noinline initializer: () -> T): Lazy = lazy(LazyThreadSafetyMode.NONE, initializer) +internal inline fun unsafeLazy(noinline initializer: () -> T): Lazy = + lazy(LazyThreadSafetyMode.NONE, initializer) internal inline fun zipEntry( name: String, preserveLastModified: Boolean = true, lastModified: Long = -1, block: ZipEntry.() -> Unit = {}, -): ZipEntry = ZipEntry(name).apply { - if (preserveLastModified) { - if (lastModified >= 0) { - time = lastModified +): ZipEntry = + ZipEntry(name).apply { + if (preserveLastModified) { + if (lastModified >= 0) { + time = lastModified + } + } else { + time = ShadowCopyAction.CONSTANT_TIME_FOR_ZIP_ENTRIES } - } else { - time = ShadowCopyAction.CONSTANT_TIME_FOR_ZIP_ENTRIES + block() } - block() -} internal fun Properties.inputStream( charset: Charset = Charsets.ISO_8859_1, comments: String = "", ): ByteArrayInputStream { val os = ByteArrayOutputStream() - os.writer(charset).use { writer -> - store(writer, comments) - } + os.writer(charset).use { writer -> store(writer, comments) } return os.toByteArray().inputStream() } diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/RelocationContext.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/RelocationContext.kt index 00fcc90ac..f7ada4233 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/RelocationContext.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/RelocationContext.kt @@ -1,12 +1,8 @@ package com.github.jengelman.gradle.plugins.shadow.relocation -public data class RelocateClassContext( - public val className: String, -) +public data class RelocateClassContext(public val className: String) -public data class RelocatePathContext( - public val path: String, -) +public data class RelocatePathContext(public val path: String) public fun Relocator.relocateClass(className: String): String { return relocateClass(RelocateClassContext(className)) diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/Relocator.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/Relocator.kt index 424ee4508..774b0bed9 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/Relocator.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/Relocator.kt @@ -4,7 +4,8 @@ import com.github.jengelman.gradle.plugins.shadow.transformers.CacheableTransfor import org.gradle.api.tasks.Input /** - * Modified from [org.apache.maven.plugins.shade.relocation.Relocator.java](https://github.com/apache/maven-shade-plugin/blob/master/src/main/java/org/apache/maven/plugins/shade/relocation/Relocator.java). + * Modified from + * [org.apache.maven.plugins.shade.relocation.Relocator.java](https://github.com/apache/maven-shade-plugin/blob/master/src/main/java/org/apache/maven/plugins/shade/relocation/Relocator.java). * * @author Jason van Zyl * @author John Engelman @@ -26,13 +27,14 @@ public interface Relocator { * Defaults to `false`. */ @get:Input - public val skipStringConstants: Boolean get() = false + public val skipStringConstants: Boolean + get() = false } /** - * Marks that a given instance of [Relocator] is compatible with the Gradle build cache. - * In other words, it has its appropriate inputs annotated so that Gradle can consider them when - * determining the cache key. + * Marks that a given instance of [Relocator] is compatible with the Gradle build cache. In other + * words, it has its appropriate inputs annotated so that Gradle can consider them when determining + * the cache key. * * @see [CacheableTransformer] */ diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/SimpleRelocator.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/SimpleRelocator.kt index b4519f995..26676f766 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/SimpleRelocator.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/SimpleRelocator.kt @@ -7,14 +7,17 @@ import org.codehaus.plexus.util.SelectorUtils import org.gradle.api.tasks.Input /** - * Modified from [org.apache.maven.plugins.shade.relocation.SimpleRelocator.java](https://github.com/apache/maven-shade-plugin/blob/master/src/main/java/org/apache/maven/plugins/shade/relocation/SimpleRelocator.java). + * Modified from + * [org.apache.maven.plugins.shade.relocation.SimpleRelocator.java](https://github.com/apache/maven-shade-plugin/blob/master/src/main/java/org/apache/maven/plugins/shade/relocation/SimpleRelocator.java). * * @author Jason van Zyl * @author Mauro Talevi * @author John Engelman */ @CacheableRelocator -public open class SimpleRelocator @JvmOverloads constructor( +public open class SimpleRelocator +@JvmOverloads +constructor( pattern: String? = null, shadedPattern: String? = null, includes: List? = null, @@ -29,11 +32,9 @@ public open class SimpleRelocator @JvmOverloads constructor( private val sourcePackageExcludes = mutableSetOf() private val sourcePathExcludes = mutableSetOf() - @get:Input - public val includes: MutableSet = mutableSetOf() + @get:Input public val includes: MutableSet = mutableSetOf() - @get:Input - public val excludes: MutableSet = mutableSetOf() + @get:Input public val excludes: MutableSet = mutableSetOf() init { if (rawString) { @@ -74,13 +75,13 @@ public open class SimpleRelocator @JvmOverloads constructor( // Excludes should be subpackages of the global pattern. if (exclude.startsWith(this.pattern)) { sourcePackageExcludes.add( - exclude.substring(this.pattern.length).replaceFirst("[.][*]$".toRegex(), ""), + exclude.substring(this.pattern.length).replaceFirst("[.][*]$".toRegex(), "") ) } // Excludes should be subpackages of the global pattern. if (exclude.startsWith(pathPattern)) { sourcePathExcludes.add( - exclude.substring(pathPattern.length).replaceFirst("/[*]$".toRegex(), ""), + exclude.substring(pathPattern.length).replaceFirst("/[*]$".toRegex(), "") ) } } @@ -105,7 +106,9 @@ public open class SimpleRelocator @JvmOverloads constructor( // Allow for annoying option of an extra / on the front of a path. See MSHADE-119; // comes from getClass().getResource("/a/b/c.properties"). adjustedPath = adjustedPath.removePrefix("/") - return isIncluded(adjustedPath) && !isExcluded(adjustedPath) && adjustedPath.startsWith(pathPattern) + return isIncluded(adjustedPath) && + !isExcluded(adjustedPath) && + adjustedPath.startsWith(pathPattern) } override fun canRelocateClass(className: String): Boolean { @@ -127,11 +130,13 @@ public open class SimpleRelocator @JvmOverloads constructor( } /** - * We don't call this function now, so we don't have to expose [sourcePackageExcludes] and [sourcePathExcludes] as inputs. + * We don't call this function now, so we don't have to expose [sourcePackageExcludes] and + * [sourcePathExcludes] as inputs. */ override fun applyToSourceContent(sourceContent: String): String { if (rawString) return sourceContent - val content = shadeSourceWithExcludes(sourceContent, pattern, shadedPattern, sourcePackageExcludes) + val content = + shadeSourceWithExcludes(sourceContent, pattern, shadedPattern, sourcePackageExcludes) return shadeSourceWithExcludes(content, pathPattern, shadedPathPattern, sourcePathExcludes) } @@ -150,18 +155,19 @@ public open class SimpleRelocator @JvmOverloads constructor( excludes == other.excludes } - override fun hashCode(): Int = Objects.hash( - rawString, - skipStringConstants, - pattern, - pathPattern, - shadedPattern, - shadedPathPattern, - sourcePackageExcludes, - sourcePathExcludes, - includes, - excludes, - ) + override fun hashCode(): Int = + Objects.hash( + rawString, + skipStringConstants, + pattern, + pathPattern, + shadedPattern, + shadedPathPattern, + sourcePackageExcludes, + sourcePathExcludes, + includes, + excludes, + ) override fun toString(): String = buildString { append("SimpleRelocator(") @@ -187,27 +193,26 @@ public open class SimpleRelocator @JvmOverloads constructor( } private companion object { - /** - * Match dot, slash or space at end of string - */ + /** Match dot, slash or space at end of string */ val RX_ENDS_WITH_DOT_SLASH_SPACE: Pattern = Pattern.compile("[./ ]$") /** * Match - * - certain Java keywords + space - * - beginning of Javadoc link + optional line breaks and continuations with '*' - * - (opening curly brace / opening parenthesis / comma / equals / semicolon) + space - * - (closing curly brace / closing multi-line comment) + space + * - certain Java keywords + space + * - beginning of Javadoc link + optional line breaks and continuations with '*' + * - (opening curly brace / opening parenthesis / comma / equals / semicolon) + space + * - (closing curly brace / closing multi-line comment) + space * * at end of string */ - val RX_ENDS_WITH_JAVA_KEYWORD: Pattern = Pattern.compile( - "\\b(import|package|public|protected|private|static|final|synchronized|abstract|volatile|extends|implements|throws) $" + - "|" + - "\\{@link( \\*)* $" + - "|" + - "([{}(=;,]|\\*/) $", - ) + val RX_ENDS_WITH_JAVA_KEYWORD: Pattern = + Pattern.compile( + "\\b(import|package|public|protected|private|static|final|synchronized|abstract|volatile|extends|implements|throws) $" + + "|" + + "\\{@link( \\*)* $" + + "|" + + "([{}(=;,]|\\*/) $" + ) fun normalizePatterns(patterns: Collection?) = buildSet { patterns ?: return@buildSet @@ -220,14 +225,17 @@ public open class SimpleRelocator @JvmOverloads constructor( val fileName = FilenameUtils.getName(pattern) val fileParent = FilenameUtils.getPathNoEndSeparator(pattern) - val filePattern = if (!fileParent.isNullOrEmpty() && fileName.isNotEmpty()) { - // It's a file pattern like `kotlin/kotlin.kotlin_builtins`, so we don't need to normalize it. - pattern - } else { - pattern.replace('.', '/') - } + val filePattern = + if (!fileParent.isNullOrEmpty() && fileName.isNotEmpty()) { + // It's a file pattern like `kotlin/kotlin.kotlin_builtins`, so we don't need to + // normalize it. + pattern + } else { + pattern.replace('.', '/') + } add(filePattern) - // Actually, class patterns should just use 'foo.bar.*' ending with a single asterisk, but some users + // Actually, class patterns should just use 'foo.bar.*' ending with a single asterisk, but + // some users // mistake them for path patterns like 'my/path/**', so let us be a bit more lenient here. if (filePattern.endsWith("/*") || filePattern.endsWith("/**")) { val packagePattern = filePattern.take(filePattern.lastIndexOf('/')) @@ -242,11 +250,15 @@ public open class SimpleRelocator @JvmOverloads constructor( patternTo: String, excludedPatterns: Set, ): String { - // Usually shading makes package names a bit longer, so make buffer 10% bigger than original source. + // Usually shading makes package names a bit longer, so make buffer 10% bigger than original + // source. val shadedSourceContent = StringBuilder(sourceContent.length * 11 / 10) - // Make sure that search pattern starts at word boundary and that we look for literal ".", not regex jokers. - val snippets = sourceContent.split(("\\b" + patternFrom.replace(".", "[.]") + "\\b").toRegex()) - .filter(CharSequence::isNotEmpty) + // Make sure that search pattern starts at word boundary and that we look for literal ".", not + // regex jokers. + val snippets = + sourceContent + .split(("\\b" + patternFrom.replace(".", "[.]") + "\\b").toRegex()) + .filter(CharSequence::isNotEmpty) snippets.forEachIndexed { i, snippet -> val isFirstSnippet = i == 0 val previousSnippet = if (isFirstSnippet) "" else snippets[i - 1] @@ -261,12 +273,11 @@ public open class SimpleRelocator @JvmOverloads constructor( shadedSourceContent.append(snippet) } else { val previousSnippetOneLine = previousSnippet.replace("\\s+".toRegex(), " ") - val afterDotSlashSpace = RX_ENDS_WITH_DOT_SLASH_SPACE.matcher(previousSnippetOneLine).find() + val afterDotSlashSpace = + RX_ENDS_WITH_DOT_SLASH_SPACE.matcher(previousSnippetOneLine).find() val afterJavaKeyWord = RX_ENDS_WITH_JAVA_KEYWORD.matcher(previousSnippetOneLine).find() val shouldExclude = doExclude || afterDotSlashSpace && !afterJavaKeyWord - shadedSourceContent - .append(if (shouldExclude) patternFrom else patternTo) - .append(snippet) + shadedSourceContent.append(if (shouldExclude) patternFrom else patternTo).append(snippet) } } return shadedSourceContent.toString() diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/DependencyFilter.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/DependencyFilter.kt index 8a0d7a683..90d38555b 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/DependencyFilter.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/DependencyFilter.kt @@ -13,34 +13,25 @@ import org.gradle.api.specs.Spec // DependencyFilter is used as Gradle Input in ShadowJar, so it must be Serializable. public interface DependencyFilter : Serializable { - /** - * Resolve a [configuration] against the [include]/[exclude] rules in the filter. - */ + /** Resolve a [configuration] against the [include]/[exclude] rules in the filter. */ public fun resolve(configuration: Configuration): FileCollection /** - * Resolve all [configurations] against the [include]/[exclude] rules in the filter and combine the results. + * Resolve all [configurations] against the [include]/[exclude] rules in the filter and combine + * the results. */ public fun resolve(configurations: Collection): FileCollection - /** - * Exclude dependencies that match the provided [spec]. - */ + /** Exclude dependencies that match the provided [spec]. */ public fun exclude(spec: Spec) - /** - * Include dependencies that match the provided [spec]. - */ + /** Include dependencies that match the provided [spec]. */ public fun include(spec: Spec) - /** - * Create a [Spec] that matches the provided project [notation]. - */ + /** Create a [Spec] that matches the provided project [notation]. */ public fun project(notation: Any): Spec - /** - * Create a [Spec] that matches the provided [dependencyNotation]. - */ + /** Create a [Spec] that matches the provided [dependencyNotation]. */ public fun dependency(dependencyNotation: Any): Spec public abstract class AbstractDependencyFilter( @@ -68,9 +59,9 @@ public interface DependencyFilter : Serializable { } override fun resolve(configurations: Collection): FileCollection { - return configurations.map { resolve(it) } - .reduceOrNull { acc, fileCollection -> acc + fileCollection } - ?: project.files() + return configurations + .map { resolve(it) } + .reduceOrNull { acc, fileCollection -> acc + fileCollection } ?: project.files() } override fun exclude(spec: Spec) { @@ -83,21 +74,24 @@ public interface DependencyFilter : Serializable { override fun project(notation: Any): Spec { @Suppress("UNCHECKED_CAST") - val realNotation = when (notation) { - is ProjectDependency -> return notation.toSpec() - is Provider<*> -> mapOf("path" to notation.get()) - is String -> mapOf("path" to notation) - is Map<*, *> -> notation as Map - else -> throw IllegalArgumentException("Unsupported notation type: ${notation::class.java}") - } + val realNotation = + when (notation) { + is ProjectDependency -> return notation.toSpec() + is Provider<*> -> mapOf("path" to notation.get()) + is String -> mapOf("path" to notation) + is Map<*, *> -> notation as Map + else -> + throw IllegalArgumentException("Unsupported notation type: ${notation::class.java}") + } return project.dependencies.project(realNotation).toSpec() } override fun dependency(dependencyNotation: Any): Spec { - val realNotation = when (dependencyNotation) { - is Provider<*> -> dependencyNotation.get() - else -> dependencyNotation - } + val realNotation = + when (dependencyNotation) { + is Provider<*> -> dependencyNotation.get() + else -> dependencyNotation + } return project.dependencies.create(realNotation).toSpec() } @@ -109,17 +103,24 @@ public interface DependencyFilter : Serializable { private fun Dependency.toSpec(): Spec { return Spec { resolvedDependency -> - val groupMatch = group?.let { - it == resolvedDependency.moduleGroup || resolvedDependency.moduleGroup.matches(it.toRegex()) - } ?: true - val nameMatch = name.let { - it == resolvedDependency.moduleName || resolvedDependency.moduleName.matches(it.toRegex()) - } - val versionMatch = version?.let { - // Version like `1.0.0+1` can't be converted to regex directly because `+` is a special character in regex. - // So we check for exact match first, then fallback to regex match. - it == resolvedDependency.moduleVersion || resolvedDependency.moduleVersion.matches(it.toRegex()) - } ?: true + val groupMatch = + group?.let { + it == resolvedDependency.moduleGroup || + resolvedDependency.moduleGroup.matches(it.toRegex()) + } ?: true + val nameMatch = + name.let { + it == resolvedDependency.moduleName || + resolvedDependency.moduleName.matches(it.toRegex()) + } + val versionMatch = + version?.let { + // Version like `1.0.0+1` can't be converted to regex directly because `+` is a special + // character in regex. + // So we check for exact match first, then fallback to regex match. + it == resolvedDependency.moduleVersion || + resolvedDependency.moduleVersion.matches(it.toRegex()) + } ?: true groupMatch && nameMatch && versionMatch } diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/FindResourceInClasspath.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/FindResourceInClasspath.kt index 3fc2fe0a1..ad34c7ac8 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/FindResourceInClasspath.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/FindResourceInClasspath.kt @@ -14,11 +14,11 @@ import org.gradle.work.DisableCachingByDefault /** * Helper task to temporarily add to your build script to find resources in the classpath that were - * identified as duplicates by [com.github.jengelman.gradle.plugins.shadow.transformers.MergePropertiesResourceTransformer] or + * identified as duplicates by + * [com.github.jengelman.gradle.plugins.shadow.transformers.MergePropertiesResourceTransformer] or * [com.github.jengelman.gradle.plugins.shadow.transformers.DeduplicatingResourceTransformer]. * * First, add the task to your build script: - * * ```kotlin * val findResources by tasks.registering(FindResourceInClasspath::class) { * // add configurations to search for resources in dependency jars @@ -40,14 +40,11 @@ import org.gradle.work.DisableCachingByDefault */ @DisableCachingByDefault(because = "Not worth caching") public abstract class FindResourceInClasspath(private val patternSet: PatternSet) : - DefaultTask(), - PatternFilterable by patternSet { + DefaultTask(), PatternFilterable by patternSet { @Inject public constructor() : this(PatternSet()) - @get:InputFiles - @get:Classpath - public abstract val classpath: ConfigurableFileCollection + @get:InputFiles @get:Classpath public abstract val classpath: ConfigurableFileCollection @Input // Trigger task executions after includes changed. override fun getIncludes(): MutableSet = patternSet.includes @@ -55,8 +52,7 @@ public abstract class FindResourceInClasspath(private val patternSet: PatternSet @Input // Trigger task executions after excludes changed. override fun getExcludes(): MutableSet = patternSet.excludes - @get:Inject - protected abstract val archiveOperations: ArchiveOperations + @get:Inject protected abstract val archiveOperations: ArchiveOperations @TaskAction public fun findResources() { diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowCopyAction.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowCopyAction.kt index 428c77fd2..f76439721 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowCopyAction.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowCopyAction.kt @@ -1,4 +1,6 @@ -@file:Suppress("InternalGradleApiUsage") // We have to use internal Gradle APIs to implement a CopyAction. +@file:Suppress( + "InternalGradleApiUsage" +) // We have to use internal Gradle APIs to implement a CopyAction. package com.github.jengelman.gradle.plugins.shadow.tasks @@ -35,7 +37,8 @@ import org.objectweb.asm.ClassWriter import org.objectweb.asm.commons.ClassRemapper /** - * Modified from [org.gradle.api.internal.file.archive.ZipCopyAction.java](https://github.com/gradle/gradle/blob/b893c2b085046677cf858fb3d5ce00e68e556c3a/platforms/core-configuration/file-operations/src/main/java/org/gradle/api/internal/file/archive/ZipCopyAction.java). + * Modified from + * [org.gradle.api.internal.file.archive.ZipCopyAction.java](https://github.com/gradle/gradle/blob/b893c2b085046677cf858fb3d5ce00e68e556c3a/platforms/core-configuration/file-operations/src/main/java/org/gradle/api/internal/file/archive/ZipCopyAction.java). */ public open class ShadowCopyAction @Deprecated("This should not be used as a public API. Will be made internal in a future release.") @@ -53,17 +56,21 @@ constructor( private val visitedDirs = mutableMapOf() override fun execute(stream: CopyActionProcessingStream): WorkResult { - val zipOutStream = try { - zosProvider(zipFile) - } catch (e: Exception) { - throw GradleException("Could not create ZIP '$zipFile'.", e) - } + val zipOutStream = + try { + zosProvider(zipFile) + } catch (e: Exception) { + throw GradleException("Could not create ZIP '$zipFile'.", e) + } try { zipOutStream.use { zos -> stream.process(StreamAction(zos)) processTransformers(zos) - addDirs(zos) // This must be called after adding all file entries to avoid duplicate directories being added. + addDirs( + zos + ) // This must be called after adding all file entries to avoid duplicate directories being + // added. checkDuplicateEntries(zos) } } catch (e: Exception) { @@ -80,7 +87,8 @@ constructor( } ``` See: https://docs.gradle.org/current/dsl/org.gradle.api.tasks.bundling.Zip.html#org.gradle.api.tasks.bundling.Zip:zip64 for more details. - """.trimIndent(), + """ + .trimIndent() ) } zipFile.delete() @@ -98,8 +106,7 @@ constructor( } private fun addDirs(zos: ZipOutputStream) { - @Suppress("UNCHECKED_CAST") - val entries = zos.entries.map { it.name } + @Suppress("UNCHECKED_CAST") val entries = zos.entries.map { it.name } val added = entries.toMutableSet() val currentTimeMillis = System.currentTimeMillis() @@ -108,32 +115,31 @@ constructor( val entryName = "$parent/" if (parent.isNotEmpty() && added.add(entryName)) { val details = visitedDirs[parent] - val (lastModified, flag) = if (details == null) { - currentTimeMillis to UnixStat.DEFAULT_DIR_PERM - } else { - details.lastModified to details.permissions.toUnixNumeric() - } - val entry = zipEntry(entryName, preserveFileTimestamps, lastModified) { - unixMode = UnixStat.DIR_FLAG or flag - } + val (lastModified, flag) = + if (details == null) { + currentTimeMillis to UnixStat.DEFAULT_DIR_PERM + } else { + details.lastModified to details.permissions.toUnixNumeric() + } + val entry = + zipEntry(entryName, preserveFileTimestamps, lastModified) { + unixMode = UnixStat.DIR_FLAG or flag + } zos.putNextEntry(entry) zos.closeEntry() addParent(parent) } } - entries.forEach { - addParent(it) - } + entries.forEach { addParent(it) } } private fun checkDuplicateEntries(zos: ZipOutputStream) { val entries = zos.entries.map { it.name } val duplicates = entries.groupingBy { it }.eachCount().filter { it.value > 1 } if (duplicates.isNotEmpty()) { - val dupEntries = duplicates.entries.joinToString(separator = "\n") { - "${it.key} (${it.value} times)" - } + val dupEntries = + duplicates.entries.joinToString(separator = "\n") { "${it.key} (${it.value} times)" } val message = "Duplicate entries found in the shadowed JAR: \n$dupEntries" if (failOnDuplicateEntries) { throw GradleException(message) @@ -143,9 +149,8 @@ constructor( } } - private inner class StreamAction( - private val zipOutStr: ZipOutputStream, - ) : CopyActionProcessingStreamAction { + private inner class StreamAction(private val zipOutStr: ZipOutputStream) : + CopyActionProcessingStreamAction { init { logger.info("Relocator count: ${relocators.size}.") if (encoding != null) { @@ -201,110 +206,122 @@ constructor( } /** - * Applies remapping to the given class with the specified relocation path. The remapped class is then written - * to the zip file. + * Applies remapping to the given class with the specified relocation path. The remapped class + * is then written to the zip file. */ - private fun FileCopyDetails.remapClass() = file.readBytes().let { bytes -> - var modified = false - val remapper = RelocatorRemapper(relocators) { modified = true } + private fun FileCopyDetails.remapClass() = + file.readBytes().let { bytes -> + var modified = false + val remapper = RelocatorRemapper(relocators) { modified = true } - // We don't pass the ClassReader here. This forces the ClassWriter to rebuild the constant pool. - // Copying the original constant pool should be avoided because it would keep references - // to the original class names. This is not a problem at runtime (because these entries in the - // constant pool are never used), but confuses some tools such as Felix's maven-bundle-plugin - // that use the constant pool to determine the dependencies of a class. - val cw = ClassWriter(0) - val cr = ClassReader(bytes) - val cv = ClassRemapper(cw, remapper) + // We don't pass the ClassReader here. This forces the ClassWriter to rebuild the constant + // pool. + // Copying the original constant pool should be avoided because it would keep references + // to the original class names. This is not a problem at runtime (because these entries in + // the + // constant pool are never used), but confuses some tools such as Felix's + // maven-bundle-plugin + // that use the constant pool to determine the dependencies of a class. + val cw = ClassWriter(0) + val cr = ClassReader(bytes) + val cv = ClassRemapper(cw, remapper) - try { - cr.accept(cv, ClassReader.EXPAND_FRAMES) - } catch (t: Throwable) { - throw GradleException("Error in ASM processing class $path", t) - } + try { + cr.accept(cv, ClassReader.EXPAND_FRAMES) + } catch (t: Throwable) { + throw GradleException("Error in ASM processing class $path", t) + } - val newBytes = if (modified) { - cw.toByteArray() - } else { - // If we didn't need to change anything, keep the original bytes as-is - bytes - } + val newBytes = + if (modified) { + cw.toByteArray() + } else { + // If we didn't need to change anything, keep the original bytes as-is + bytes + } - // Temporarily remove the multi-release prefix. - val multiReleasePrefix = "^META-INF/versions/\\d+/".toRegex().find(path)?.value.orEmpty() - val newPath = path.replace(multiReleasePrefix, "") - val relocatedPath = multiReleasePrefix + relocators.relocatePath(newPath) - try { - val entry = zipEntry(relocatedPath, preserveFileTimestamps, lastModified) { - unixMode = UnixStat.FILE_FLAG or permissions.toUnixNumeric() + // Temporarily remove the multi-release prefix. + val multiReleasePrefix = "^META-INF/versions/\\d+/".toRegex().find(path)?.value.orEmpty() + val newPath = path.replace(multiReleasePrefix, "") + val relocatedPath = multiReleasePrefix + relocators.relocatePath(newPath) + try { + val entry = + zipEntry(relocatedPath, preserveFileTimestamps, lastModified) { + unixMode = UnixStat.FILE_FLAG or permissions.toUnixNumeric() + } + // Now we put it back on so the class file is written out with the right extension. + zipOutStr.putNextEntry(entry) + zipOutStr.write(newBytes) + zipOutStr.closeEntry() + } catch (_: ZipException) { + logger.warn("We have a duplicate $relocatedPath in source project") } - // Now we put it back on so the class file is written out with the right extension. - zipOutStr.putNextEntry(entry) - zipOutStr.write(newBytes) - zipOutStr.closeEntry() - } catch (_: ZipException) { - logger.warn("We have a duplicate $relocatedPath in source project") } - } /** - * Applies remapping to the given kotlin module with the specified relocation path. - * The remapped module is then written to the zip file. + * Applies remapping to the given kotlin module with the specified relocation path. The remapped + * module is then written to the zip file. */ @OptIn(UnstableMetadataApi::class) - private fun FileCopyDetails.remapKotlinModule() = file.readBytes().let { bytes -> - val kmMetadata = KotlinModuleMetadata.read(bytes) - val newKmModule = KmModule().apply { - // We don't need to relocate the nested properties in `optionalAnnotationClasses`, there is a very special use case for Kotlin Multiplatform. - optionalAnnotationClasses += kmMetadata.kmModule.optionalAnnotationClasses - packageParts += kmMetadata.kmModule.packageParts.map { (pkg, parts) -> - val relocatedPkg = relocators.relocateClass(pkg) - val relocatedParts = KmPackageParts( - parts.fileFacades.mapTo(mutableListOf()) { relocators.relocatePath(it) }, - parts.multiFileClassParts.entries.associateTo(mutableMapOf()) { (name, facade) -> - relocators.relocatePath(name) to relocators.relocatePath(facade) - }, - ) - relocatedPkg to relocatedParts - } - } - val newKmMetadata = KotlinModuleMetadata(newKmModule, kmMetadata.version) + private fun FileCopyDetails.remapKotlinModule() = + file.readBytes().let { bytes -> + val kmMetadata = KotlinModuleMetadata.read(bytes) + val newKmModule = + KmModule().apply { + // We don't need to relocate the nested properties in `optionalAnnotationClasses`, there + // is a very special use case for Kotlin Multiplatform. + optionalAnnotationClasses += kmMetadata.kmModule.optionalAnnotationClasses + packageParts += + kmMetadata.kmModule.packageParts.map { (pkg, parts) -> + val relocatedPkg = relocators.relocateClass(pkg) + val relocatedParts = + KmPackageParts( + parts.fileFacades.mapTo(mutableListOf()) { relocators.relocatePath(it) }, + parts.multiFileClassParts.entries.associateTo(mutableMapOf()) { (name, facade) + -> + relocators.relocatePath(name) to relocators.relocatePath(facade) + }, + ) + relocatedPkg to relocatedParts + } + } + val newKmMetadata = KotlinModuleMetadata(newKmModule, kmMetadata.version) - val newBytes = newKmMetadata.write() - val relocatedPath = relocators.relocatePath(path) - val entryName = when { - relocatedPath != path -> relocatedPath - // Nothing changed, so keep the original path. - newBytes.contentEquals(bytes) -> path - // Content changed but path didn't, so rename to avoid name clash. The filename does not matter to the compiler. - else -> path.replace(".kotlin_module", ".shadow.kotlin_module") - } - val entry = zipEntry(entryName, preserveFileTimestamps, lastModified) { - unixMode = UnixStat.FILE_FLAG or permissions.toUnixNumeric() + val newBytes = newKmMetadata.write() + val relocatedPath = relocators.relocatePath(path) + val entryName = + when { + relocatedPath != path -> relocatedPath + // Nothing changed, so keep the original path. + newBytes.contentEquals(bytes) -> path + // Content changed but path didn't, so rename to avoid name clash. The filename does not + // matter to the compiler. + else -> path.replace(".kotlin_module", ".shadow.kotlin_module") + } + val entry = + zipEntry(entryName, preserveFileTimestamps, lastModified) { + unixMode = UnixStat.FILE_FLAG or permissions.toUnixNumeric() + } + zipOutStr.putNextEntry(entry) + zipOutStr.write(newBytes) + zipOutStr.closeEntry() } - zipOutStr.putNextEntry(entry) - zipOutStr.write(newBytes) - zipOutStr.closeEntry() - } private fun transform(fileDetails: FileCopyDetails, path: String): Boolean { val transformer = transformers.find { it.canTransformResource(fileDetails) } ?: return false fileDetails.file.inputStream().use { inputStream -> transformer.transform( - TransformerContext( - path = path, - inputStream = inputStream, - relocators = relocators, - ), + TransformerContext(path = path, inputStream = inputStream, relocators = relocators) ) } return true } private fun FileCopyDetails.writeToZip(entryName: String) { - val entry = zipEntry(entryName, preserveFileTimestamps, lastModified) { - unixMode = UnixStat.FILE_FLAG or permissions.toUnixNumeric() - } + val entry = + zipEntry(entryName, preserveFileTimestamps, lastModified) { + unixMode = UnixStat.FILE_FLAG or permissions.toUnixNumeric() + } zipOutStr.putNextEntry(entry) copyTo(zipOutStr) zipOutStr.closeEntry() @@ -315,13 +332,16 @@ constructor( private val logger = Logging.getLogger(ShadowCopyAction::class.java) private val ZipOutputStream.entries: List - get() = this::class.java.getDeclaredField("entries").apply { isAccessible = true }.get(this).cast() + get() = + this::class.java.getDeclaredField("entries").apply { isAccessible = true }.get(this).cast() /** - * A copy of [org.gradle.api.internal.file.archive.ZipEntryConstants.CONSTANT_TIME_FOR_ZIP_ENTRIES]. + * A copy of + * [org.gradle.api.internal.file.archive.ZipEntryConstants.CONSTANT_TIME_FOR_ZIP_ENTRIES]. * * 1980-02-01 00:00:00 (318182400000). */ - public val CONSTANT_TIME_FOR_ZIP_ENTRIES: Long = GregorianCalendar(1980, 1, 1, 0, 0, 0).timeInMillis + public val CONSTANT_TIME_FOR_ZIP_ENTRIES: Long = + GregorianCalendar(1980, 1, 1, 0, 0, 0).timeInMillis } } diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar.kt index 4977aa1d4..8ec8ba3c0 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/ShadowJar.kt @@ -62,10 +62,12 @@ import org.gradle.language.base.plugins.LifecycleBasePlugin @CacheableTask public abstract class ShadowJar : Jar() { private val dependencyFilterForMinimize = MinimizeDependencyFilter(project) - private val shadowDependencies = project.provider { - // Find shadow configuration here instead of get, as the ShadowJar tasks could be registered without Shadow plugin applied. - project.configurations.findByName(ShadowBasePlugin.CONFIGURATION_NAME) ?: project.files() - } + private val shadowDependencies = + project.provider { + // Find shadow configuration here instead of get, as the ShadowJar tasks could be registered + // without Shadow plugin applied. + project.configurations.findByName(ShadowBasePlugin.CONFIGURATION_NAME) ?: project.files() + } init { group = LifecycleBasePlugin.BUILD_GROUP @@ -87,46 +89,48 @@ public abstract class ShadowJar : Jar() { * Defaults to `false`. */ @get:Input - @get:Option(option = "minimize-jar", description = "Minimizes the jar by removing unused classes.") + @get:Option( + option = "minimize-jar", + description = "Minimizes the jar by removing unused classes.", + ) public open val minimizeJar: Property = objectFactory.property(false) @get:Classpath - public open val toMinimize: ConfigurableFileCollection = objectFactory.fileCollection { - minimizeJar.map { - if (it) (dependencyFilterForMinimize.resolve(configurations.get()) - apiJars) else emptySet() + public open val toMinimize: ConfigurableFileCollection = + objectFactory.fileCollection { + minimizeJar.map { + if (it) (dependencyFilterForMinimize.resolve(configurations.get()) - apiJars) + else emptySet() + } } - } @get:Classpath - public open val apiJars: ConfigurableFileCollection = objectFactory.fileCollection { - minimizeJar.map { - if (it) UnusedTracker.getApiJarsFromProject(project) else emptySet() + public open val apiJars: ConfigurableFileCollection = + objectFactory.fileCollection { + minimizeJar.map { if (it) UnusedTracker.getApiJarsFromProject(project) else emptySet() } } - } @get:InputFiles @get:PathSensitive(PathSensitivity.RELATIVE) - public open val sourceSetsClassesDirs: ConfigurableFileCollection = objectFactory.fileCollection { - minimizeJar.map { - if (it) { - project.sourceSets.map { sourceSet -> sourceSet.output.classesDirs.filter(File::isDirectory) } - } else { - emptySet() + public open val sourceSetsClassesDirs: ConfigurableFileCollection = + objectFactory.fileCollection { + minimizeJar.map { + if (it) { + project.sourceSets.map { sourceSet -> + sourceSet.output.classesDirs.filter(File::isDirectory) + } + } else { + emptySet() + } } } - } - /** - * [ResourceTransformer]s to be applied in the shadow steps. - */ + /** [ResourceTransformer]s to be applied in the shadow steps. */ @get:Nested public open val transformers: SetProperty = objectFactory.setProperty() - /** - * [Relocator]s to be applied in the shadow steps. - */ - @get:Nested - public open val relocators: SetProperty = objectFactory.setProperty() + /** [Relocator]s to be applied in the shadow steps. */ + @get:Nested public open val relocators: SetProperty = objectFactory.setProperty() /** * The configurations to include dependencies from. @@ -140,13 +144,12 @@ public abstract class ShadowJar : Jar() { public open val dependencyFilter: Property = objectFactory.property(DefaultDependencyFilter(project)) - /** - * Final dependencies to be shadowed. - */ + /** Final dependencies to be shadowed. */ @get:Classpath - public open val includedDependencies: ConfigurableFileCollection = objectFactory.fileCollection { - dependencyFilter.zip(configurations) { df, cs -> df.resolve(cs) } - } + public open val includedDependencies: ConfigurableFileCollection = + objectFactory.fileCollection { + dependencyFilter.zip(configurations) { df, cs -> df.resolve(cs) } + } /** * Enables auto relocation of packages in the dependencies. @@ -165,9 +168,10 @@ public abstract class ShadowJar : Jar() { /** * Enables remapping of Kotlin module metadata (`.kotlin_module`) files. * - * If you enable this option, the Kotlin module metadata file paths and their contents will be relocated if they are - * matched by any of the configured [relocators]. Someone may want to disable this feature and write their own - * [ResourceTransformer]s to handle Kotlin module metadata files in a custom way. + * If you enable this option, the Kotlin module metadata file paths and their contents will be + * relocated if they are matched by any of the configured [relocators]. Someone may want to + * disable this feature and write their own [ResourceTransformer]s to handle Kotlin module + * metadata files in a custom way. * * Defaults to `true`. */ @@ -190,13 +194,14 @@ public abstract class ShadowJar : Jar() { option = "relocation-prefix", description = "Prefix used for auto relocation of packages in the dependencies.", ) - public open val relocationPrefix: Property = objectFactory.property(ShadowBasePlugin.SHADOW) + public open val relocationPrefix: Property = + objectFactory.property(ShadowBasePlugin.SHADOW) /** * Main class attribute to add to manifest. * - * This property will be used as a fallback if there is no explicit `Main-Class` attribute set for the [ShadowJar] - * task or the main [Jar] task. + * This property will be used as a fallback if there is no explicit `Main-Class` attribute set for + * the [ShadowJar] task or the main [Jar] task. * * Defaults to `null`. */ @@ -224,8 +229,8 @@ public abstract class ShadowJar : Jar() { public open val failOnDuplicateEntries: Property = objectFactory.property(false) /** - * Adds the [java.util.jar.Attributes.Name.MULTI_RELEASE] attribute to the manifest of the shadow JAR if any - * dependencies contain the attribute. + * Adds the [java.util.jar.Attributes.Name.MULTI_RELEASE] attribute to the manifest of the shadow + * JAR if any dependencies contain the attribute. * * Defaults to `true`. */ @@ -251,19 +256,24 @@ public abstract class ShadowJar : Jar() { * * This global strategy can be overridden for individual files by using [filesMatching]. * - * The default value is [EXCLUDE]. Different strategies will lead to different results for `foo/bar` files in the JARs to be merged: - * + * The default value is [EXCLUDE]. Different strategies will lead to different results for + * `foo/bar` files in the JARs to be merged: * - [EXCLUDE]: The **first** `foo/bar` file will be included in the final JAR. - * - [FAIL]: **Fail** the build with a `DuplicateFileCopyingException` if there are duplicate `foo/bar` files. + * - [FAIL]: **Fail** the build with a `DuplicateFileCopyingException` if there are duplicate + * `foo/bar` files. * - [INCLUDE]: **Duplicate** `foo/bar` entries will be included in the final JAR. - * - [INHERIT]: **Fail** the build with an exception like `Entry .* is a duplicate but no duplicate handling strategy has been set`. - * - [WARN]: **Warn** about duplicates in the build log, this behaves exactly as [INHERIT] otherwise. - * - * **NOTE:** The strategy takes precedence over transforming and relocating. - * Some [ResourceTransformer]s like [ServiceFileTransformer] will not work as expected with setting the strategy to - * [EXCLUDE] (the default), as the duplicate resource files fed for them are excluded beforehand. - * Want [ResourceTransformer]s and the strategy to work together? See more details in the - * [Handling Duplicates Strategy](https://gradleup.com/shadow/configuration/merging/#handling-duplicates-strategy) section. + * - [INHERIT]: **Fail** the build with an exception like `Entry .* is a duplicate but no + * duplicate handling strategy has been set`. + * - [WARN]: **Warn** about duplicates in the build log, this behaves exactly as [INHERIT] + * otherwise. + * + * **NOTE:** The strategy takes precedence over transforming and relocating. Some + * [ResourceTransformer]s like [ServiceFileTransformer] will not work as expected with setting the + * strategy to [EXCLUDE] (the default), as the duplicate resource files fed for them are excluded + * beforehand. Want [ResourceTransformer]s and the strategy to work together? See more details in + * the + * [Handling Duplicates Strategy](https://gradleup.com/shadow/configuration/merging/#handling-duplicates-strategy) + * section. * * @see [eachFile] * @see [filesMatching] @@ -273,21 +283,16 @@ public abstract class ShadowJar : Jar() { */ override fun getDuplicatesStrategy(): DuplicatesStrategy = super.getDuplicatesStrategy() - @get:Inject - protected abstract val archiveOperations: ArchiveOperations + @get:Inject protected abstract val archiveOperations: ArchiveOperations - /** - * Enable [minimizeJar] and execute the [action] with the [DependencyFilter] for minimize. - */ + /** Enable [minimizeJar] and execute the [action] with the [DependencyFilter] for minimize. */ @JvmOverloads public open fun minimize(action: Action = Action {}) { minimizeJar.set(true) action.execute(dependencyFilterForMinimize) } - /** - * Extra dependency operations to be applied in the shadow steps. - */ + /** Extra dependency operations to be applied in the shadow steps. */ public open fun dependencies(action: Action) { action.execute(dependencyFilter.get()) } @@ -295,9 +300,10 @@ public abstract class ShadowJar : Jar() { /** * Merge Java services files with [rootPath]. * - * *Warning*: In most cases, this should be used with the correct [getDuplicatesStrategy] to ensure duplicate service - * files are handled properly. See more details in the - * [Handling Duplicates Strategy](https://gradleup.com/shadow/configuration/merging/#handling-duplicates-strategy) section. + * *Warning*: In most cases, this should be used with the correct [getDuplicatesStrategy] to + * ensure duplicate service files are handled properly. See more details in the + * [Handling Duplicates Strategy](https://gradleup.com/shadow/configuration/merging/#handling-duplicates-strategy) + * section. * * @see [getDuplicatesStrategy] */ @@ -308,9 +314,10 @@ public abstract class ShadowJar : Jar() { /** * Merge Java services files with [action]. * - * *Warning*: In most cases, this should be used with the correct [getDuplicatesStrategy] to ensure duplicate service - * files are handled properly. See more details in the - * [Handling Duplicates Strategy](https://gradleup.com/shadow/configuration/merging/#handling-duplicates-strategy) section. + * *Warning*: In most cases, this should be used with the correct [getDuplicatesStrategy] to + * ensure duplicate service files are handled properly. See more details in the + * [Handling Duplicates Strategy](https://gradleup.com/shadow/configuration/merging/#handling-duplicates-strategy) + * section. * * @see [getDuplicatesStrategy] */ @@ -322,9 +329,10 @@ public abstract class ShadowJar : Jar() { /** * Merge Groovy extension modules (`META-INF/**/org.codehaus.groovy.runtime.ExtensionModule`). * - * *Warning*: In most cases, this should be used with the correct [getDuplicatesStrategy] to ensure duplicate extension module - * files are handled properly. See more details in the - * [Handling Duplicates Strategy](https://gradleup.com/shadow/configuration/merging/#handling-duplicates-strategy) section. + * *Warning*: In most cases, this should be used with the correct [getDuplicatesStrategy] to + * ensure duplicate extension module files are handled properly. See more details in the + * [Handling Duplicates Strategy](https://gradleup.com/shadow/configuration/merging/#handling-duplicates-strategy) + * section. * * @see [getDuplicatesStrategy] */ @@ -335,22 +343,25 @@ public abstract class ShadowJar : Jar() { /** * Append contents to a resource in the jar. * - * e.g. `append("resources/application.yml", "\n---\n")` for merging `resources/application.yml` files. + * e.g. `append("resources/application.yml", "\n---\n")` for merging `resources/application.yml` + * files. * * @param resourcePath The path to the resource in the jar. - * @param separator The separator to use between the original content and the appended content, defaults to [AppendingTransformer.DEFAULT_SEPARATOR] (`\n`). + * @param separator The separator to use between the original content and the appended content, + * defaults to [AppendingTransformer.DEFAULT_SEPARATOR] (`\n`). */ @JvmOverloads - public open fun append(resourcePath: String, separator: String = AppendingTransformer.DEFAULT_SEPARATOR) { + public open fun append( + resourcePath: String, + separator: String = AppendingTransformer.DEFAULT_SEPARATOR, + ) { transform(AppendingTransformer::class.java) { it.resource.set(resourcePath) it.separator.set(separator) } } - /** - * Relocate classes and resources matching [pattern] to [destination] using [SimpleRelocator]. - */ + /** Relocate classes and resources matching [pattern] to [destination] using [SimpleRelocator]. */ @JvmOverloads public open fun relocate( pattern: String, @@ -361,26 +372,20 @@ public abstract class ShadowJar : Jar() { addRelocator(relocator, action) } - /** - * Relocate classes and resources using a [Relocator]. - */ + /** Relocate classes and resources using a [Relocator]. */ @JvmOverloads public open fun relocate(clazz: Class, action: Action = Action {}) { val relocator = clazz.getDeclaredConstructor().newInstance() addRelocator(relocator, action) } - /** - * Relocate classes and resources using a [Relocator]. - */ + /** Relocate classes and resources using a [Relocator]. */ @JvmOverloads public open fun relocate(relocator: R, action: Action = Action {}) { addRelocator(relocator, action) } - /** - * Relocate classes and resources using a [Relocator]. - */ + /** Relocate classes and resources using a [Relocator]. */ @JvmSynthetic public inline fun relocate(action: Action = Action {}) { relocate(R::class.java, action) @@ -389,37 +394,49 @@ public abstract class ShadowJar : Jar() { /** * Transform resources using a [ResourceTransformer]. * - * *Warning*: Most of the [ResourceTransformer]s should be used with the correct [getDuplicatesStrategy] to ensure - * duplicate resource files are handled properly. See more details in the - * [Handling Duplicates Strategy](https://gradleup.com/shadow/configuration/merging/#handling-duplicates-strategy) section. + * *Warning*: Most of the [ResourceTransformer]s should be used with the correct + * [getDuplicatesStrategy] to ensure duplicate resource files are handled properly. See more + * details in the + * [Handling Duplicates Strategy](https://gradleup.com/shadow/configuration/merging/#handling-duplicates-strategy) + * section. * * @see [getDuplicatesStrategy] */ @JvmOverloads - public open fun transform(clazz: Class, action: Action = Action {}) { + public open fun transform( + clazz: Class, + action: Action = Action {}, + ) { addTransform(clazz.create(objectFactory), action) } /** * Transform resources using a [ResourceTransformer]. * - * *Warning*: Most of the [ResourceTransformer]s should be used with the correct [getDuplicatesStrategy] to ensure - * duplicate resource files are handled properly. See more details in the - * [Handling Duplicates Strategy](https://gradleup.com/shadow/configuration/merging/#handling-duplicates-strategy) section. + * *Warning*: Most of the [ResourceTransformer]s should be used with the correct + * [getDuplicatesStrategy] to ensure duplicate resource files are handled properly. See more + * details in the + * [Handling Duplicates Strategy](https://gradleup.com/shadow/configuration/merging/#handling-duplicates-strategy) + * section. * * @see [getDuplicatesStrategy] */ @JvmOverloads - public open fun transform(transformer: T, action: Action = Action {}) { + public open fun transform( + transformer: T, + action: Action = Action {}, + ) { addTransform(transformer, action) } /** * Transform resources using a [ResourceTransformer]. * - * *Warning*: Most of the [ResourceTransformer]s should be used with the correct [getDuplicatesStrategy] to ensure - * duplicate resource files are handled properly. See more details in the - * [Handling Duplicates Strategy](https://gradleup.com/shadow/configuration/merging/#handling-duplicates-strategy) section. + * *Warning*: Most of the [ResourceTransformer]s should be used with the correct + * [getDuplicatesStrategy] to ensure duplicate resource files are handled properly. See more + * details in the + * [Handling Duplicates Strategy](https://gradleup.com/shadow/configuration/merging/#handling-duplicates-strategy) + * section. * * @see [getDuplicatesStrategy] */ @@ -436,11 +453,13 @@ public abstract class ShadowJar : Jar() { from(file) } file.extension.equals("aar", ignoreCase = true) -> { - val message = """ + val message = + """ Shadowing AAR file is not supported. Please exclude dependency artifact: $file or use Android Fused Library plugin instead. See https://developer.android.com/build/publish-library/fused-library. - """.trimIndent() + """ + .trimIndent() error(message) } else -> { @@ -456,17 +475,20 @@ public abstract class ShadowJar : Jar() { override fun createCopyAction(): org.gradle.api.internal.file.copy.CopyAction { val zosProvider = { destination: File -> try { - val entryCompressionMethod = when (entryCompression) { - ZipEntryCompression.DEFLATED -> ZipOutputStream.DEFLATED - ZipEntryCompression.STORED -> ZipOutputStream.STORED - } - val stream = if (entryCompressionMethod == ZipOutputStream.STORED) { - ZipOutputStream(destination) - } else { - // Improve performance by avoiding lots of small writes to the file system. - // It is not possible to do this with STORED entries as the implementation requires a RandomAccessFile to update the CRC after write. - ZipOutputStream(destination.outputStream().buffered()) - } + val entryCompressionMethod = + when (entryCompression) { + ZipEntryCompression.DEFLATED -> ZipOutputStream.DEFLATED + ZipEntryCompression.STORED -> ZipOutputStream.STORED + } + val stream = + if (entryCompressionMethod == ZipOutputStream.STORED) { + ZipOutputStream(destination) + } else { + // Improve performance by avoiding lots of small writes to the file system. + // It is not possible to do this with STORED entries as the implementation requires a + // RandomAccessFile to update the CRC after write. + ZipOutputStream(destination.outputStream().buffered()) + } stream.apply { setUseZip64(if (isZip64) Zip64Mode.AsNeeded else Zip64Mode.Never) setMethod(entryCompressionMethod) @@ -475,19 +497,19 @@ public abstract class ShadowJar : Jar() { throw IOException("Unable to create ZIP output stream for file $destination.", e) } } - val unusedClasses = if (minimizeJar.get()) { - val unusedTracker = UnusedTracker( - sourceSetsClassesDirs = sourceSetsClassesDirs.files, - classJars = apiJars, - toMinimize = toMinimize, - ) - includedDependencies.files.forEach { - unusedTracker.addDependency(it) + val unusedClasses = + if (minimizeJar.get()) { + val unusedTracker = + UnusedTracker( + sourceSetsClassesDirs = sourceSetsClassesDirs.files, + classJars = apiJars, + toMinimize = toMinimize, + ) + includedDependencies.files.forEach { unusedTracker.addDependency(it) } + unusedTracker.findUnused() + } else { + emptySet() } - unusedTracker.findUnused() - } else { - emptySet() - } @Suppress("DEPRECATION") return ShadowCopyAction( zipFile = archiveFile.get().asFile, @@ -515,7 +537,9 @@ public abstract class ShadowJar : Jar() { private val packageRelocators: List get() { if (enableAutoRelocation.get()) { - logger.info("Adding auto relocation packages in the dependencies with prefix '${relocationPrefix.get()}'.") + logger.info( + "Adding auto relocation packages in the dependencies with prefix '${relocationPrefix.get()}'." + ) } else { logger.info("Skipping package relocators as auto relocation is disabled.") return emptyList() @@ -523,7 +547,9 @@ public abstract class ShadowJar : Jar() { val prefix = relocationPrefix.get() return includedDependencies.files.flatMap { file -> JarFile(file).use { jarFile -> - jarFile.entries().toList() + jarFile + .entries() + .toList() .filter { it.name.endsWith(".class") && it.name != "module-info.class" } .map { it.name.substringBeforeLast('/').replace('/', '.') } .toSet() @@ -536,14 +562,20 @@ public abstract class ShadowJar : Jar() { val mainClassValue = mainClass.orNull when { manifest.attributes.contains(mainClassAttributeKey) -> { - logger.info("Skipping adding $mainClassAttributeKey attribute to the manifest as it is already set.") + logger.info( + "Skipping adding $mainClassAttributeKey attribute to the manifest as it is already set." + ) } mainClassValue.isNullOrEmpty() -> { - logger.info("Skipping adding $mainClassAttributeKey attribute to the manifest as it is empty.") + logger.info( + "Skipping adding $mainClassAttributeKey attribute to the manifest as it is empty." + ) } else -> { manifest.attributes[mainClassAttributeKey] = mainClassValue - logger.info("Adding $mainClassAttributeKey attribute to the manifest with value '$mainClassValue'.") + logger.info( + "Adding $mainClassAttributeKey attribute to the manifest with value '$mainClassValue'." + ) } } @@ -555,22 +587,28 @@ public abstract class ShadowJar : Jar() { } if (addMultiReleaseAttribute.get()) { - logger.info("Adding $multiReleaseAttributeKey attribute to the manifest if any dependencies contain it.") + logger.info( + "Adding $multiReleaseAttributeKey attribute to the manifest if any dependencies contain it." + ) } else { - logger.info("Skipping adding $multiReleaseAttributeKey attribute to the manifest as it is disabled.") + logger.info( + "Skipping adding $multiReleaseAttributeKey attribute to the manifest as it is disabled." + ) return } - val includeMultiReleaseAttr = includedDependencies.files.any { - try { - JarFile(it).use { jarFile -> - // Manifest might be null or the attribute name is invalid, or any other case. - runCatching { jarFile.manifest.mainAttributes.getValue(multiReleaseAttributeKey) }.getOrNull() - } == "true" - } catch (_: IOException) { - // If the jar file is not valid, ignore it. - false + val includeMultiReleaseAttr = + includedDependencies.files.any { + try { + JarFile(it).use { jarFile -> + // Manifest might be null or the attribute name is invalid, or any other case. + runCatching { jarFile.manifest.mainAttributes.getValue(multiReleaseAttributeKey) } + .getOrNull() + } == "true" + } catch (_: IOException) { + // If the jar file is not valid, ignore it. + false + } } - } if (includeMultiReleaseAttr) { manifest.attributes[multiReleaseAttributeKey] = true } @@ -587,32 +625,36 @@ public abstract class ShadowJar : Jar() { jarTask: TaskProvider, action: Action, ): TaskProvider { - return tasks.register(SHADOW_JAR_TASK_NAME, ShadowJar::class.java) { task -> - task.archiveClassifier.set("all") - task.exclude( - "META-INF/INDEX.LIST", - "META-INF/*.SF", - "META-INF/*.DSA", - "META-INF/*.RSA", - // module-info.class in Multi-Release folders. - "META-INF/versions/**/module-info.class", - "module-info.class", - ) - - task.manifest = DefaultInheritManifest( - project, - @Suppress("EagerGradleConfiguration") // The ctor doesn't support Provider. - jarTask.get().manifest, - ) - - action.execute(task) - }.also { task -> - // Can't use `named` directly as the task is optional or may not exist when the plugin is applied. - // Using Spec applies the action to the task if it is added later. - tasks.named(LifecycleBasePlugin.ASSEMBLE_TASK_NAME::equals).configureEach { - it.dependsOn(task) + return tasks + .register(SHADOW_JAR_TASK_NAME, ShadowJar::class.java) { task -> + task.archiveClassifier.set("all") + task.exclude( + "META-INF/INDEX.LIST", + "META-INF/*.SF", + "META-INF/*.DSA", + "META-INF/*.RSA", + // module-info.class in Multi-Release folders. + "META-INF/versions/**/module-info.class", + "module-info.class", + ) + + task.manifest = + DefaultInheritManifest( + project, + @Suppress("EagerGradleConfiguration") // The ctor doesn't support Provider. + jarTask.get().manifest, + ) + + action.execute(task) + } + .also { task -> + // Can't use `named` directly as the task is optional or may not exist when the plugin is + // applied. + // Using Spec applies the action to the task if it is added later. + tasks.named(LifecycleBasePlugin.ASSEMBLE_TASK_NAME::equals).configureEach { + it.dependsOn(task) + } } - } } } } diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheLicenseResourceTransformer.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheLicenseResourceTransformer.kt index f28ec92b3..3a9826114 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheLicenseResourceTransformer.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheLicenseResourceTransformer.kt @@ -5,19 +5,19 @@ import org.gradle.api.tasks.util.PatternSet /** * Prevents duplicate copies of the license. * - * Modified from [org.apache.maven.plugins.shade.resource.ApacheLicenseResourceTransformer.java](https://github.com/apache/maven-shade-plugin/blob/master/src/main/java/org/apache/maven/plugins/shade/resource/ApacheLicenseResourceTransformer.java). + * Modified from + * [org.apache.maven.plugins.shade.resource.ApacheLicenseResourceTransformer.java](https://github.com/apache/maven-shade-plugin/blob/master/src/main/java/org/apache/maven/plugins/shade/resource/ApacheLicenseResourceTransformer.java). * * @author John Engelman */ @CacheableTransformer -public open class ApacheLicenseResourceTransformer @JvmOverloads constructor( - patternSet: PatternSet = PatternSet() - .apply { isCaseSensitive = false } - .include( - LICENSE_PATH, - LICENSE_TXT_PATH, - LICENSE_MD_PATH, - ), +public open class ApacheLicenseResourceTransformer +@JvmOverloads +constructor( + patternSet: PatternSet = + PatternSet() + .apply { isCaseSensitive = false } + .include(LICENSE_PATH, LICENSE_TXT_PATH, LICENSE_MD_PATH) ) : PatternFilterableResourceTransformer(patternSet = patternSet) { private companion object { private const val LICENSE_PATH = "META-INF/LICENSE" diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheNoticeResourceTransformer.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheNoticeResourceTransformer.kt index 95e04b0e0..2276eff33 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheNoticeResourceTransformer.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheNoticeResourceTransformer.kt @@ -17,7 +17,8 @@ import org.gradle.api.tasks.util.PatternSet /** * Merges `META-INF/NOTICE.TXT` files. * - * Modified from [org.apache.maven.plugins.shade.resource.ApacheNoticeResourceTransformer.java](https://github.com/apache/maven-shade-plugin/blob/master/src/main/java/org/apache/maven/plugins/shade/resource/ApacheNoticeResourceTransformer.java). + * Modified from + * [org.apache.maven.plugins.shade.resource.ApacheNoticeResourceTransformer.java](https://github.com/apache/maven-shade-plugin/blob/master/src/main/java/org/apache/maven/plugins/shade/resource/ApacheNoticeResourceTransformer.java). * * @author John Engelman */ @@ -28,51 +29,50 @@ public open class ApacheNoticeResourceTransformer( ) : PatternFilterableResourceTransformer(patternSet) { private val entries = mutableSetOf() private val organizationEntries = mutableMapOf>() - private inline val charset get() = Charset.forName(charsetName.get()) + private inline val charset + get() = Charset.forName(charsetName.get()) - /** - * Fallback [copyright] as the [Property] value can't be changed in execution phase. - */ + /** Fallback [copyright] as the [Property] value can't be changed in execution phase. */ private var fallbackCopyright: String? = null - @get:Input - public open val projectName: Property = objectFactory.property("") + @get:Input public open val projectName: Property = objectFactory.property("") - @get:Input - public open val addHeader: Property = objectFactory.property(true) + @get:Input public open val addHeader: Property = objectFactory.property(true) @get:Input - public open val preamble1: Property = objectFactory.property( - """ + public open val preamble1: Property = + objectFactory.property( + """ // ------------------------------------------------------------------ // NOTICE file corresponding to the section 4d of The Apache License, // Version 2.0, in this case for - """.trimIndent() + " ", // The space is important for formatting. - ) + """ + .trimIndent() + " " // The space is important for formatting. + ) @get:Input - public open val preamble2: Property = objectFactory.property( - "\n// ------------------------------------------------------------------\n", - ) + public open val preamble2: Property = + objectFactory.property( + "\n// ------------------------------------------------------------------\n" + ) @get:Input - public open val preamble3: Property = objectFactory.property("This product includes software developed at\n") + public open val preamble3: Property = + objectFactory.property("This product includes software developed at\n") @get:Input - public open val organizationName: Property = objectFactory.property("The Apache Software Foundation") + public open val organizationName: Property = + objectFactory.property("The Apache Software Foundation") @get:Input - public open val organizationURL: Property = objectFactory.property("https://www.apache.org/") + public open val organizationURL: Property = + objectFactory.property("https://www.apache.org/") - @get:Input - public open val inceptionYear: Property = objectFactory.property("2006") + @get:Input public open val inceptionYear: Property = objectFactory.property("2006") - @get:Input - public open val copyright: Property = objectFactory.property("") + @get:Input public open val copyright: Property = objectFactory.property("") - /** - * The file encoding of the `NOTICE` file. - */ + /** The file encoding of the `NOTICE` file. */ @get:Input public open val charsetName: Property = objectFactory.property(Charsets.UTF_8.name()) @@ -81,19 +81,17 @@ public open class ApacheNoticeResourceTransformer( * * Defaults to `META-INF/NOTICE`. */ - @get:Input - public open val outputPath: Property = objectFactory.property(NOTICE_PATH) + @get:Input public open val outputPath: Property = objectFactory.property(NOTICE_PATH) @Inject - public constructor(objectFactory: ObjectFactory) : this( + public constructor( + objectFactory: ObjectFactory + ) : this( objectFactory, - patternSet = PatternSet() - .apply { isCaseSensitive = false } - .include( - NOTICE_PATH, - NOTICE_TXT_PATH, - NOTICE_MD_PATH, - ), + patternSet = + PatternSet() + .apply { isCaseSensitive = false } + .include(NOTICE_PATH, NOTICE_TXT_PATH, NOTICE_MD_PATH), ) override fun transform(context: TransformerContext) { @@ -107,9 +105,10 @@ public open class ApacheNoticeResourceTransformer( val inceptionYear = inceptionYear.get() if (entries.isEmpty()) { - val year = SimpleDateFormat("yyyy", Locale.US).format(Date()).let { - if (inceptionYear != it) "$inceptionYear-$it" else it - } + val year = + SimpleDateFormat("yyyy", Locale.US).format(Date()).let { + if (inceptionYear != it) "$inceptionYear-$it" else it + } // Add headers. if (addHeader) { entries.add("$preamble1$projectName$preamble2") @@ -132,7 +131,10 @@ public open class ApacheNoticeResourceTransformer( if (trimmedLine.isNotEmpty()) { if (trimmedLine.startsWith("- ")) { // resource-bundle 1.3 mode. - if (lineCount == 1 && sb.toString().contains("This product includes/uses software(s) developed by")) { + if ( + lineCount == 1 && + sb.toString().contains("This product includes/uses software(s) developed by") + ) { currentOrg = organizationEntries.getOrPut(sb.toString().trim()) { TreeSet() } sb.setLength(0) } else if (sb.isNotEmpty() && currentOrg != null) { diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/AppendingTransformer.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/AppendingTransformer.kt index b65ebd2fd..7e29c4ceb 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/AppendingTransformer.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/AppendingTransformer.kt @@ -13,23 +13,23 @@ import org.gradle.api.tasks.Input /** * A resource processor that appends content for a resource, separated by a newline. * - * Modified from [org.apache.maven.plugins.shade.resource.AppendingTransformer.java](https://github.com/apache/maven-shade-plugin/blob/master/src/main/java/org/apache/maven/plugins/shade/resource/AppendingTransformer.java). + * Modified from + * [org.apache.maven.plugins.shade.resource.AppendingTransformer.java](https://github.com/apache/maven-shade-plugin/blob/master/src/main/java/org/apache/maven/plugins/shade/resource/AppendingTransformer.java). * * @author John Engelman */ @CacheableTransformer -public open class AppendingTransformer @Inject constructor( - final override val objectFactory: ObjectFactory, -) : ResourceTransformer { - @Suppress("ktlint:standard:backing-property-naming") - private var _data: ByteArrayOutputStream? = null // It's nullable to allow lazy initialization to support CC. - private inline val data get() = _data ?: ByteArrayOutputStream().also { _data = it } +public open class AppendingTransformer +@Inject +constructor(final override val objectFactory: ObjectFactory) : ResourceTransformer { + private var _data: ByteArrayOutputStream? = + null // It's nullable to allow lazy initialization to support CC. + private inline val data + get() = _data ?: ByteArrayOutputStream().also { _data = it } - @get:Input - public open val resource: Property = objectFactory.property("") + @get:Input public open val resource: Property = objectFactory.property("") - @get:Input - public open val separator: Property = objectFactory.property(DEFAULT_SEPARATOR) + @get:Input public open val separator: Property = objectFactory.property(DEFAULT_SEPARATOR) override fun canTransformResource(element: FileTreeElement): Boolean { return resource.get().equals(element.path, ignoreCase = true) @@ -38,7 +38,8 @@ public open class AppendingTransformer @Inject constructor( override fun transform(context: TransformerContext) { data.let { if (it.size() > 0) { - // Append the separator before the new content to ensure the separator is not at the end of the file. + // Append the separator before the new content to ensure the separator is not at the end of + // the file. it.write(separator.get().toByteArray()) } context.inputStream.copyTo(it) diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ComponentsXmlResourceTransformer.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ComponentsXmlResourceTransformer.kt index a28e0e68e..b36860de0 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ComponentsXmlResourceTransformer.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ComponentsXmlResourceTransformer.kt @@ -17,7 +17,8 @@ import org.gradle.api.tasks.Internal /** * A resource processor that aggregates plexus `components.xml` files. * - * Modified from [org.apache.maven.plugins.shade.resource.ComponentsXmlResourceTransformer.java](https://github.com/apache/maven-shade-plugin/blob/master/src/main/java/org/apache/maven/plugins/shade/resource/ComponentsXmlResourceTransformer.java). + * Modified from + * [org.apache.maven.plugins.shade.resource.ComponentsXmlResourceTransformer.java](https://github.com/apache/maven-shade-plugin/blob/master/src/main/java/org/apache/maven/plugins/shade/resource/ComponentsXmlResourceTransformer.java). * * @author John Engelman */ @@ -46,49 +47,45 @@ public open class ComponentsXmlResourceTransformer : ResourceTransformer { } override fun transform(context: TransformerContext) { - val newDom = try { - val bis = object : BufferedInputStream(context.inputStream) { - @Throws(IOException::class) - override fun close() { - // Leave ZIP open. - } + val newDom = + try { + val bis = + object : BufferedInputStream(context.inputStream) { + @Throws(IOException::class) + override fun close() { + // Leave ZIP open. + } + } + Xpp3DomBuilder.build(XmlStreamReader(bis)) + } catch (e: Exception) { + throw IOException("Error parsing components.xml in ${context.inputStream}", e) } - Xpp3DomBuilder.build(XmlStreamReader(bis)) - } catch (e: Exception) { - throw IOException("Error parsing components.xml in ${context.inputStream}", e) - } // Only try to merge in components if there are some elements in the component-set. if (newDom.getChild("components") == null) return val children = newDom.getChild("components").getChildren("component") for (component in children) { - val role = getValue(component, "role").let { - context.relocators.relocateClass(it) - } + val role = getValue(component, "role").let { context.relocators.relocateClass(it) } setValue(component, "role", role) val roleHint = getValue(component, "role-hint") - val impl = getValue(component, "implementation").let { - context.relocators.relocateClass(it) - } + val impl = getValue(component, "implementation").let { context.relocators.relocateClass(it) } setValue(component, "implementation", impl) val key = "$role:$roleHint" - // TODO: use the tools in Plexus to merge these properly. For now, I just need an all-or-nothing. + // TODO: use the tools in Plexus to merge these properly. For now, I just need an + // all-or-nothing. // Configuration carry over. - components[key]?.getChild("configuration")?.let { - component.addChild(it) - } + components[key]?.getChild("configuration")?.let { component.addChild(it) } val requirements = component.getChild("requirements") if (requirements != null && requirements.childCount > 0) { for (r in requirements.childCount - 1 downTo 0) { val requirement = requirements.getChild(r) - val requiredRole = getValue(requirement, "role").let { - context.relocators.relocateClass(it) - } + val requiredRole = + getValue(requirement, "role").let { context.relocators.relocateClass(it) } setValue(requirement, "role", requiredRole) } } diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/DeduplicatingResourceTransformer.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/DeduplicatingResourceTransformer.kt index 3c5498a84..61d95e66d 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/DeduplicatingResourceTransformer.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/DeduplicatingResourceTransformer.kt @@ -17,28 +17,25 @@ import org.gradle.api.tasks.util.PatternSet * Multiple files with the same path but different content lead to an error. * * Some scenarios for duplicate resources in a shadow jar: + * - Duplicate `.class` files Having duplicate `.class` files with different content is a situation + * indicating that the resulting jar is built with _incompatible_ classes, likely leading to + * issues during runtime. This situation can happen when one dependency is (also) included in an + * uber jar. + * - Duplicate `META-INF///pom.properties`/`xml` files. Some dependencies + * contain shaded variants of other dependencies. Tools that inspect jar files to extract the + * included dependencies, for example, for license auditing use cases or tools that collect + * information of all included dependencies, may rely on these files. Hence, it is desirable to + * retain the duplicate resource `pom.properties`/`xml` resources. * - * - Duplicate `.class` files - * Having duplicate `.class` files with different content is a situation indicating that the resulting jar is - * built with _incompatible_ classes, likely leading to issues during runtime. - * This situation can happen when one dependency is (also) included in an uber jar. - * - * - Duplicate `META-INF///pom.properties`/`xml` files. - * Some dependencies contain shaded variants of other dependencies. - * Tools that inspect jar files to extract the included dependencies, for example, for license auditing - * use cases or tools that collect information of all included dependencies, may rely on these files. - * Hence, it is desirable to retain the duplicate resource `pom.properties`/`xml` resources. - * - * [DeduplicatingResourceTransformer] checks all entries in the resulting jar. - * It is generally not recommended to use any of the [include] configuration functions. + * [DeduplicatingResourceTransformer] checks all entries in the resulting jar. It is generally not + * recommended to use any of the [include] configuration functions. * * There are reasons to retain duplicate resources with different contents in the resulting jar. * This can be achieved with the [exclude] configuration functions. * * To exclude a path or pattern from being deduplicated, for example, legit - * `META-INF///pom.properties`/`xml`, configure the transformer with an exclusion - * like the following: - * + * `META-INF///pom.properties`/`xml`, configure the transformer with an + * exclusion like the following: * ```kotlin * tasks.shadowJar { * transform(DeduplicatingResourceTransformer::class.java) { @@ -52,27 +49,25 @@ import org.gradle.api.tasks.util.PatternSet * *Tip*: the [FindResourceInClasspath] convenience task can be used to find resources in a Gradle * classpath/configuration. * - * *Warning* Do **not** combine [PreserveFirstFoundResourceTransformer] with this transformer, - * as they handle duplicates differently and combining them would lead to redundant or unexpected behavior. + * *Warning* Do **not** combine [PreserveFirstFoundResourceTransformer] with this transformer, as + * they handle duplicates differently and combining them would lead to redundant or unexpected + * behavior. */ @CacheableTransformer public open class DeduplicatingResourceTransformer( final override val objectFactory: ObjectFactory, patternSet: PatternSet, ) : PatternFilterableResourceTransformer(patternSet) { - @get:Internal - internal val sources: MutableMap = mutableMapOf() + @get:Internal internal val sources: MutableMap = mutableMapOf() - @Inject - public constructor(objectFactory: ObjectFactory) : this(objectFactory, PatternSet()) + @Inject public constructor(objectFactory: ObjectFactory) : this(objectFactory, PatternSet()) override fun canTransformResource(element: FileTreeElement): Boolean { val file = element.file val hash = file.sha256Hex() - val pathInfos = sources.computeIfAbsent(element.path) { - PathInfos(patternSpec.isSatisfiedBy(element)) - } + val pathInfos = + sources.computeIfAbsent(element.path) { PathInfos(patternSpec.isSatisfiedBy(element)) } val retainInOutput = pathInfos.addFile(hash, file) return !retainInOutput @@ -85,13 +80,13 @@ public open class DeduplicatingResourceTransformer( if (duplicatePaths.isNotEmpty()) { val message = buildString { - append("Found ${duplicatePaths.size} path duplicate(s) with different content in the shadowed JAR:\n") + append( + "Found ${duplicatePaths.size} path duplicate(s) with different content in the shadowed JAR:\n" + ) duplicatePaths.forEach { (path, infos) -> append(" * $path\n") infos.filesPerHash.forEach { (hash, files) -> - files.forEach { file -> - append(" * ${file.path} (SHA256: $hash)\n") - } + files.forEach { file -> append(" * ${file.path} (SHA256: $hash)\n") } } } } @@ -99,9 +94,10 @@ public open class DeduplicatingResourceTransformer( } } - internal fun duplicateContentViolations(): Map = sources.filter { (_, pathInfos) -> - pathInfos.failOnDuplicateContent && pathInfos.uniqueContentCount() > 1 - } + internal fun duplicateContentViolations(): Map = + sources.filter { (_, pathInfos) -> + pathInfos.failOnDuplicateContent && pathInfos.uniqueContentCount() > 1 + } internal data class PathInfos(val failOnDuplicateContent: Boolean) { val filesPerHash: MutableMap> = mutableMapOf() @@ -118,9 +114,7 @@ public open class DeduplicatingResourceTransformer( internal companion object { fun File.sha256Hex(): String { try { - return inputStream().use { - DigestUtils.sha256Hex(it) - } + return inputStream().use { DigestUtils.sha256Hex(it) } } catch (e: Exception) { throw RuntimeException("Failed to read data or calculate hash for $this", e) } diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/DontIncludeResourceTransformer.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/DontIncludeResourceTransformer.kt index 308913552..c7e459edb 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/DontIncludeResourceTransformer.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/DontIncludeResourceTransformer.kt @@ -13,16 +13,17 @@ import org.gradle.api.tasks.Input * * You can also use [ShadowJar.exclude] instead. * - * Modified from [org.apache.maven.plugins.shade.resource.DontIncludeResourceTransformer.java](https://github.com/apache/maven-shade-plugin/blob/master/src/main/java/org/apache/maven/plugins/shade/resource/DontIncludeResourceTransformer.java). + * Modified from + * [org.apache.maven.plugins.shade.resource.DontIncludeResourceTransformer.java](https://github.com/apache/maven-shade-plugin/blob/master/src/main/java/org/apache/maven/plugins/shade/resource/DontIncludeResourceTransformer.java). * * @author John Engelman */ @CacheableTransformer -public open class DontIncludeResourceTransformer @Inject constructor( - final override val objectFactory: ObjectFactory, -) : ResourceTransformer by ResourceTransformer.Companion { - @get:Input - public open val resource: Property = objectFactory.property("") +public open class DontIncludeResourceTransformer +@Inject +constructor(final override val objectFactory: ObjectFactory) : + ResourceTransformer by ResourceTransformer.Companion { + @get:Input public open val resource: Property = objectFactory.property("") override fun canTransformResource(element: FileTreeElement): Boolean { return resource.get().isNotEmpty() && element.path.endsWith(resource.get()) diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/GroovyExtensionModuleTransformer.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/GroovyExtensionModuleTransformer.kt index ea7ef9b6c..bce9df28e 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/GroovyExtensionModuleTransformer.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/GroovyExtensionModuleTransformer.kt @@ -11,18 +11,20 @@ import org.gradle.api.file.FileTreeElement * Aggregate Apache Groovy extension modules descriptors. * * Resource transformer that merges Groovy extension module descriptor files into a single file. - * Groovy extension module descriptor files have the name org.codehaus.groovy.runtime.ExtensionModule - * and live in the META-INF/services (Groovy up to 2.4) or META-INF/groovy (Groovy 2.5+) directory. - * See [GROOVY-8480](https://issues.apache.org/jira/browse/GROOVY-8480) for more details of the change. + * Groovy extension module descriptor files have the name + * org.codehaus.groovy.runtime.ExtensionModule and live in the META-INF/services (Groovy up to 2.4) + * or META-INF/groovy (Groovy 2.5+) directory. See + * [GROOVY-8480](https://issues.apache.org/jira/browse/GROOVY-8480) for more details of the change. * - * If there are several descriptor files spread across many JARs the individual - * entries will be merged into a single descriptor file which will be - * packaged into the resultant JAR produced by the shadowing process. - * It will live in the legacy directory (META-INF/services) if all the processed descriptor - * files came from the legacy location, otherwise it will be written into the now standard location (META-INF/groovy). - * Note that certain JDK9+ tooling will break when using the legacy location. + * If there are several descriptor files spread across many JARs the individual entries will be + * merged into a single descriptor file which will be packaged into the resultant JAR produced by + * the shadowing process. It will live in the legacy directory (META-INF/services) if all the + * processed descriptor files came from the legacy location, otherwise it will be written into the + * now standard location (META-INF/groovy). Note that certain JDK9+ tooling will break when using + * the legacy location. * - * Related to [org.apache.maven.plugins.shade.resource.GroovyResourceTransformer.java](https://github.com/apache/maven-shade-plugin/blob/master/src/main/java/org/apache/maven/plugins/shade/resource/GroovyResourceTransformer.java). + * Related to + * [org.apache.maven.plugins.shade.resource.GroovyResourceTransformer.java](https://github.com/apache/maven-shade-plugin/blob/master/src/main/java/org/apache/maven/plugins/shade/resource/GroovyResourceTransformer.java). */ @CacheableTransformer public open class GroovyExtensionModuleTransformer : ResourceTransformer { @@ -30,7 +32,8 @@ public open class GroovyExtensionModuleTransformer : ResourceTransformer { override fun canTransformResource(element: FileTreeElement): Boolean { val path = element.path - return path == PATH_LEGACY_GROOVY_EXTENSION_MODULE_DESCRIPTOR || path == PATH_GROOVY_EXTENSION_MODULE_DESCRIPTOR + return path == PATH_LEGACY_GROOVY_EXTENSION_MODULE_DESCRIPTOR || + path == PATH_GROOVY_EXTENSION_MODULE_DESCRIPTOR } override fun transform(context: TransformerContext) { @@ -38,18 +41,16 @@ public open class GroovyExtensionModuleTransformer : ResourceTransformer { props.load(context.inputStream) props.forEach { (key, value) -> when (key as String) { - KEY_MODULE_NAME -> handle(key, value as String) { - module.setProperty(key, MERGED_MODULE_NAME) - } - KEY_MODULE_VERSION -> handle(key, value as String) { - module.setProperty(key, MERGED_MODULE_VERSION) - } + KEY_MODULE_NAME -> + handle(key, value as String) { module.setProperty(key, MERGED_MODULE_NAME) } + KEY_MODULE_VERSION -> + handle(key, value as String) { module.setProperty(key, MERGED_MODULE_VERSION) } KEY_EXTENSION_CLASSES, - KEY_STATIC_EXTENSION_CLASSES, - -> { - val relocatedClasses = (value as String).split(',').joinToString(",") { className -> - context.relocators.relocateClass(className) - } + KEY_STATIC_EXTENSION_CLASSES -> { + val relocatedClasses = + (value as String).split(',').joinToString(",") { className -> + context.relocators.relocateClass(className) + } handle(key, relocatedClasses) { existingValue -> module.setProperty(key, "$existingValue,$relocatedClasses") } @@ -62,9 +63,7 @@ public open class GroovyExtensionModuleTransformer : ResourceTransformer { override fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean) { os.putNextEntry(zipEntry(PATH_GROOVY_EXTENSION_MODULE_DESCRIPTOR, preserveFileTimestamps)) - module.inputStream().use { - it.copyTo(os) - } + module.inputStream().use { it.copyTo(os) } os.closeEntry() } diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/IncludeResourceTransformer.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/IncludeResourceTransformer.kt index bfaf753bf..efb96be76 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/IncludeResourceTransformer.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/IncludeResourceTransformer.kt @@ -18,29 +18,28 @@ import org.gradle.api.tasks.PathSensitivity * * You can also use [ShadowJar.from] instead. * - * Modified from [org.apache.maven.plugins.shade.resource.IncludeResourceTransformer.java](https://github.com/apache/maven-shade-plugin/blob/master/src/main/java/org/apache/maven/plugins/shade/resource/IncludeResourceTransformer.java). + * Modified from + * [org.apache.maven.plugins.shade.resource.IncludeResourceTransformer.java](https://github.com/apache/maven-shade-plugin/blob/master/src/main/java/org/apache/maven/plugins/shade/resource/IncludeResourceTransformer.java). * * @author John Engelman */ @CacheableTransformer -public open class IncludeResourceTransformer @Inject constructor( - final override val objectFactory: ObjectFactory, -) : ResourceTransformer by ResourceTransformer.Companion { +public open class IncludeResourceTransformer +@Inject +constructor(final override val objectFactory: ObjectFactory) : + ResourceTransformer by ResourceTransformer.Companion { @get:InputFile @get:PathSensitive(PathSensitivity.NONE) public open val file: RegularFileProperty = objectFactory.fileProperty() - @get:Input - public open val resource: Property = objectFactory.property() + @get:Input public open val resource: Property = objectFactory.property() override fun hasTransformedResource(): Boolean = file.get().asFile.exists() override fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean) { os.putNextEntry(zipEntry(resource.get(), preserveFileTimestamps)) - file.get().asFile.inputStream().use { inputStream -> - inputStream.copyTo(os) - } + file.get().asFile.inputStream().use { inputStream -> inputStream.copyTo(os) } os.closeEntry() } diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/Log4j2PluginsCacheFileTransformer.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/Log4j2PluginsCacheFileTransformer.kt index e3ec52983..3408a25f3 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/Log4j2PluginsCacheFileTransformer.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/Log4j2PluginsCacheFileTransformer.kt @@ -17,21 +17,18 @@ import org.apache.tools.zip.ZipOutputStream import org.gradle.api.file.FileTreeElement /** - * Modified from [org.apache.logging.log4j.maven.plugins.shade.transformer.Log4j2PluginCacheFileTransformer.java](https://github.com/apache/logging-log4j-transform/blob/main/log4j-transform-maven-shade-plugin-extensions/src/main/java/org/apache/logging/log4j/maven/plugins/shade/transformer/Log4j2PluginCacheFileTransformer.java). + * Modified from + * [org.apache.logging.log4j.maven.plugins.shade.transformer.Log4j2PluginCacheFileTransformer.java](https://github.com/apache/logging-log4j-transform/blob/main/log4j-transform-maven-shade-plugin-extensions/src/main/java/org/apache/logging/log4j/maven/plugins/shade/transformer/Log4j2PluginCacheFileTransformer.java). * * @author Paul Nelson Baker * @author John Engelman */ @CacheableTransformer public open class Log4j2PluginsCacheFileTransformer : ResourceTransformer { - /** - * Log4j config files to share across the transformation stages. - */ + /** Log4j config files to share across the transformation stages. */ private val tempFiles = mutableListOf() - /** - * [Relocator] instances to share across the transformation stages. - */ + /** [Relocator] instances to share across the transformation stages. */ private val tempRelocators = mutableListOf() override fun canTransformResource(element: FileTreeElement): Boolean { @@ -45,9 +42,7 @@ public open class Log4j2PluginsCacheFileTransformer : ResourceTransformer { tempRelocators.addAll(context.relocators) } - /** - * @return `true` if any dat file collected. - */ + /** @return `true` if any dat file collected. */ override fun hasTransformedResource(): Boolean = tempFiles.isNotEmpty() override fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean) { diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ManifestAppenderTransformer.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ManifestAppenderTransformer.kt index 2b3d13dd9..ab8c2d70f 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ManifestAppenderTransformer.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ManifestAppenderTransformer.kt @@ -14,17 +14,18 @@ import org.gradle.api.provider.SetProperty import org.gradle.api.tasks.Input /** - * A resource processor that can append arbitrary attributes to the first MANIFEST.MF - * that is found in the set of JARs being processed. The attributes are appended in - * the specified order, and duplicates are allowed. + * A resource processor that can append arbitrary attributes to the first MANIFEST.MF that is found + * in the set of JARs being processed. The attributes are appended in the specified order, and + * duplicates are allowed. * * Modified from [ManifestResourceTransformer]. + * * @author Chris Rankin */ @CacheableTransformer -public open class ManifestAppenderTransformer @Inject constructor( - final override val objectFactory: ObjectFactory, -) : ResourceTransformer { +public open class ManifestAppenderTransformer +@Inject +constructor(final override val objectFactory: ObjectFactory) : ResourceTransformer { private var manifestContents = ByteArray(0) @get:Input diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ManifestResourceTransformer.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ManifestResourceTransformer.kt index 1dc654593..21f2ff859 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ManifestResourceTransformer.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ManifestResourceTransformer.kt @@ -18,24 +18,24 @@ import org.gradle.api.provider.Property import org.gradle.api.tasks.Input /** - * A resource processor that allows the arbitrary addition of attributes to - * the first MANIFEST.MF that is found in the set of JARs being processed, or - * to a newly created manifest for the shaded JAR. + * A resource processor that allows the arbitrary addition of attributes to the first MANIFEST.MF + * that is found in the set of JARs being processed, or to a newly created manifest for the shaded + * JAR. * - * Modified from [org.apache.maven.plugins.shade.resource.ManifestResourceTransformer.java](https://github.com/apache/maven-shade-plugin/blob/master/src/main/java/org/apache/maven/plugins/shade/resource/ManifestResourceTransformer.java). + * Modified from + * [org.apache.maven.plugins.shade.resource.ManifestResourceTransformer.java](https://github.com/apache/maven-shade-plugin/blob/master/src/main/java/org/apache/maven/plugins/shade/resource/ManifestResourceTransformer.java). * * @author Jason van Zyl * @author John Engelman */ @CacheableTransformer -public open class ManifestResourceTransformer @Inject constructor( - final override val objectFactory: ObjectFactory, -) : ResourceTransformer { +public open class ManifestResourceTransformer +@Inject +constructor(final override val objectFactory: ObjectFactory) : ResourceTransformer { private var manifestDiscovered = false private var manifest: Manifest? = null - @get:Input - public open val mainClass: Property = objectFactory.property("") + @get:Input public open val mainClass: Property = objectFactory.property("") @get:Input public open val manifestEntries: MapProperty = objectFactory.mapProperty() @@ -45,8 +45,10 @@ public open class ManifestResourceTransformer @Inject constructor( } override fun transform(context: TransformerContext) { - // We just want to take the first manifest we come across as that's our project's manifest. This is the behavior - // now which is situational at best. Right now there is no context passed in with the processing so we cannot + // We just want to take the first manifest we come across as that's our project's manifest. This + // is the behavior + // now which is situational at best. Right now there is no context passed in with the processing + // so we cannot // tell what artifact is being processed. if (!manifestDiscovered) { try { @@ -67,12 +69,8 @@ public open class ManifestResourceTransformer @Inject constructor( } val attributes = manifest!!.mainAttributes - mainClass.get().takeIf(CharSequence::isNotEmpty)?.let { - attributes[mainClassAttributeKey] = it - } - manifestEntries.get().forEach { (key, value) -> - attributes[JarAttribute.Name(key)] = value - } + mainClass.get().takeIf(CharSequence::isNotEmpty)?.let { attributes[mainClassAttributeKey] = it } + manifestEntries.get().forEach { (key, value) -> attributes[JarAttribute.Name(key)] = value } os.putNextEntry(zipEntry(JarFile.MANIFEST_NAME, preserveFileTimestamps)) manifest!!.write(os) diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/MergeLicenseResourceTransformer.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/MergeLicenseResourceTransformer.kt index 0f895c5e4..7abd3af79 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/MergeLicenseResourceTransformer.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/MergeLicenseResourceTransformer.kt @@ -19,11 +19,10 @@ import org.gradle.api.tasks.util.PatternSet /** * Generates a license file using the configured license text source. * - * An optional `SPDX-License-Identifier` can be placed in front of the license text to avoid ambiguous - * license detection by license-detection-tools. + * An optional `SPDX-License-Identifier` can be placed in front of the license text to avoid + * ambiguous license detection by license-detection-tools. * * License texts found in the file names: - * * - `META-INF/LICENSE` * - `META-INF/LICENSE.txt` * - `META-INF/LICENSE.md` @@ -35,16 +34,15 @@ import org.gradle.api.tasks.util.PatternSet * * To exclude these defaults, add [exclude]s to the transformer configuration. * - * Use the [org.gradle.api.tasks.util.PatternFilterable] functions to specify a different set of files to include, - * the paths mentioned above are then not considered unless explicitly included. + * Use the [org.gradle.api.tasks.util.PatternFilterable] functions to specify a different set of + * files to include, the paths mentioned above are then not considered unless explicitly included. */ @CacheableTransformer public open class MergeLicenseResourceTransformer( final override val objectFactory: ObjectFactory, patternSet: PatternSet, ) : PatternFilterableResourceTransformer(patternSet) { - @get:Internal - internal val elements: MutableSet = LinkedHashSet() + @get:Internal internal val elements: MutableSet = LinkedHashSet() /** Path to write the aggregated license file to. Defaults to `META-INF/LICENSE`. */ @get:Input @@ -68,36 +66,38 @@ public open class MergeLicenseResourceTransformer( * Separator between the project's license text and license texts from the included dependencies. */ @get:Input - public open val firstSeparator: Property = objectFactory.property( - """ + public open val firstSeparator: Property = + objectFactory.property( + """ | |${"-".repeat(120)} | |This artifact includes dependencies with the following licenses: |---------------------------------------------------------------- - | - """.trimMargin(), - ) + |""" + .trimMargin() + ) - /** - * Separator between included dependency license texts. - */ + /** Separator between included dependency license texts. */ @get:Input public open val separator: Property = objectFactory.property("\n${"-".repeat(120)}\n") @Inject - public constructor(objectFactory: ObjectFactory) : this( + public constructor( + objectFactory: ObjectFactory + ) : this( objectFactory, - patternSet = PatternSet().apply { - include( - "META-INF/LICENSE", - "META-INF/LICENSE.txt", - "META-INF/LICENSE.md", - "LICENSE", - "LICENSE.txt", - "LICENSE.md", - ) - }, + patternSet = + PatternSet().apply { + include( + "META-INF/LICENSE", + "META-INF/LICENSE.txt", + "META-INF/LICENSE.md", + "LICENSE", + "LICENSE.txt", + "LICENSE.md", + ) + }, ) override fun transform(context: TransformerContext) { diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PatternFilterableResourceTransformer.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PatternFilterableResourceTransformer.kt index 17945fd8c..5c943d62e 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PatternFilterableResourceTransformer.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PatternFilterableResourceTransformer.kt @@ -14,9 +14,8 @@ import org.gradle.api.tasks.util.PatternSet * @param patternSet The [PatternSet] used for filtering resources. */ public abstract class PatternFilterableResourceTransformer( - @Internal public val patternSet: PatternSet, -) : ResourceTransformer by ResourceTransformer.Companion, - PatternFilterable by patternSet { + @Internal public val patternSet: PatternSet +) : ResourceTransformer by ResourceTransformer.Companion, PatternFilterable by patternSet { @get:Internal protected val patternSpec: Spec by unsafeLazy { diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PreserveFirstFoundResourceTransformer.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PreserveFirstFoundResourceTransformer.kt index a8b6527f8..915f2f360 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PreserveFirstFoundResourceTransformer.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PreserveFirstFoundResourceTransformer.kt @@ -15,16 +15,17 @@ import org.gradle.api.tasks.util.PatternSet /** * A resource processor that preserves the first resource matched and excludes all others. * - * This is useful when you set `shadowJar.duplicatesStrategy = DuplicatesStrategy.INCLUDE` (the default behavior) and - * want to ensure that only the first found resource is included in the final JAR. If there are multiple resources with - * the same path in a project and its dependencies, the first one found should be the project's. + * This is useful when you set `shadowJar.duplicatesStrategy = DuplicatesStrategy.INCLUDE` (the + * default behavior) and want to ensure that only the first found resource is included in the final + * JAR. If there are multiple resources with the same path in a project and its dependencies, the + * first one found should be the project's. * - * This transformer deduplicates included resources based on the path name. - * See [DeduplicatingResourceTransformer] for a transformer that deduplicates based on the paths and contents of - * the resources. + * This transformer deduplicates included resources based on the path name. See + * [DeduplicatingResourceTransformer] for a transformer that deduplicates based on the paths and + * contents of the resources. * - * *Warning* Do **not** combine [DeduplicatingResourceTransformer] with this transformer, - * as they handle duplicates differently and combining them would lead to redundant or unexpected behavior. + * *Warning* Do **not** combine [DeduplicatingResourceTransformer] with this transformer, as they + * handle duplicates differently and combining them would lead to redundant or unexpected behavior. * * @see [DuplicatesStrategy] * @see [ShadowJar.getDuplicatesStrategy] @@ -34,20 +35,15 @@ public open class PreserveFirstFoundResourceTransformer( final override val objectFactory: ObjectFactory, patternSet: PatternSet, ) : PatternFilterableResourceTransformer(patternSet) { - private val includeResources by unsafeLazy { - @Suppress("DEPRECATION") - include(resources.get()) - } + private val includeResources by unsafeLazy { @Suppress("DEPRECATION") include(resources.get()) } - @get:Internal - protected val found: MutableSet = mutableSetOf() + @get:Internal protected val found: MutableSet = mutableSetOf() @get:Deprecated("Use `include(..)` instead") @get:Input public open val resources: SetProperty = objectFactory.setProperty() - @Inject - public constructor(objectFactory: ObjectFactory) : this(objectFactory, PatternSet()) + @Inject public constructor(objectFactory: ObjectFactory) : this(objectFactory, PatternSet()) override fun canTransformResource(element: FileTreeElement): Boolean { // Init once before patternSpec is accessed. diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformer.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformer.kt index 92aeadc21..9b1885a5c 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformer.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformer.kt @@ -21,16 +21,15 @@ import org.gradle.api.tasks.Internal /** * Resources transformer that merges Properties files. * - * The default merge strategy discards duplicate values coming from additional - * resources. This behavior can be changed by setting a value for the [mergeStrategy] property, - * such as [MergeStrategy.First] (default), [MergeStrategy.Latest] or [MergeStrategy.Append]. If the merge strategy is - * [MergeStrategy.Latest] then the last value of a matching property entry will be used. If the - * merge strategy is [MergeStrategy.Append] then the property values will be combined, using a - * merge separator (default value is ','). The merge separator can be changed by - * setting a value for the [mergeSeparator] property. + * The default merge strategy discards duplicate values coming from additional resources. This + * behavior can be changed by setting a value for the [mergeStrategy] property, such as + * [MergeStrategy.First] (default), [MergeStrategy.Latest] or [MergeStrategy.Append]. If the merge + * strategy is [MergeStrategy.Latest] then the last value of a matching property entry will be used. + * If the merge strategy is [MergeStrategy.Append] then the property values will be combined, using + * a merge separator (default value is ','). The merge separator can be changed by setting a value + * for the [mergeSeparator] property. * - * Say there are two properties files A and B with the - * following entries: + * Say there are two properties files A and B with the following entries: * * **A** * - key1 = value1 @@ -61,22 +60,20 @@ import org.gradle.api.tasks.Internal * - key2 = value2;balue2 * - key3 = value3 * - * With `mergeStrategy = MergeStrategy.Fail` the transformation will fail if there are conflicting values. + * With `mergeStrategy = MergeStrategy.Fail` the transformation will fail if there are conflicting + * values. * - * There are three additional properties that can be set: [paths], [mappings], - * and [keyTransformer]. - * The first contains a list of strings or regexes that will be used to determine if - * a path should be transformed or not. The merge strategy and merge separator are - * taken from the global settings. + * There are three additional properties that can be set: [paths], [mappings], and [keyTransformer]. + * The first contains a list of strings or regexes that will be used to determine if a path should + * be transformed or not. The merge strategy and merge separator are taken from the global settings. * - * The [mappings] property allows you to define merge strategy and separator per - * path. If either [paths] or [mappings] is defined then no other path - * entries will be merged. [mappings] has precedence over [paths] if both - * are defined. + * The [mappings] property allows you to define merge strategy and separator per path. If either + * [paths] or [mappings] is defined then no other path entries will be merged. [mappings] has + * precedence over [paths] if both are defined. * - * If you need to transform keys in properties files, e.g. because they contain class - * names about to be relocated, you can set the [keyTransformer] property to a - * closure that receives the original key and returns the key name to be used. + * If you need to transform keys in properties files, e.g. because they contain class names about to + * be relocated, you can set the [keyTransformer] property to a closure that receives the original + * key and returns the key name to be used. * * Example: * ```groovy @@ -93,43 +90,40 @@ import org.gradle.api.tasks.Internal * } * ``` * - * Related to [org.apache.maven.plugins.shade.resource.properties.PropertiesTransformer.java](https://github.com/apache/maven-shade-plugin/blob/master/src/main/java/org/apache/maven/plugins/shade/resource/properties/PropertiesTransformer.java). + * Related to + * [org.apache.maven.plugins.shade.resource.properties.PropertiesTransformer.java](https://github.com/apache/maven-shade-plugin/blob/master/src/main/java/org/apache/maven/plugins/shade/resource/properties/PropertiesTransformer.java). * * @author Andres Almiray * @author Marc Philipp */ @CacheableTransformer -public open class PropertiesFileTransformer @Inject constructor( - final override val objectFactory: ObjectFactory, -) : ResourceTransformer { - private inline val charset get() = Charset.forName(charsetName.get()) +public open class PropertiesFileTransformer +@Inject +constructor(final override val objectFactory: ObjectFactory) : ResourceTransformer { + private inline val charset + get() = Charset.forName(charsetName.get()) - @get:Internal - internal val conflicts: MutableMap> = mutableMapOf() + @get:Internal internal val conflicts: MutableMap> = mutableMapOf() - @get:Internal - internal val propertiesEntries = mutableMapOf() + @get:Internal internal val propertiesEntries = mutableMapOf() - @get:Input - public open val paths: SetProperty = objectFactory.setProperty() + @get:Input public open val paths: SetProperty = objectFactory.setProperty() @get:Input public open val mappings: MapProperty> = objectFactory.mapProperty() @get:Input - public open val mergeStrategy: Property = objectFactory.property(MergeStrategy.First) + public open val mergeStrategy: Property = + objectFactory.property(MergeStrategy.First) - @get:Input - public open val mergeSeparator: Property = objectFactory.property(",") + @get:Input public open val mergeSeparator: Property = objectFactory.property(",") - /** - * The character set to use when reading and writing property files. - * Defaults to `ISO-8859-1`. - */ + /** The character set to use when reading and writing property files. Defaults to `ISO-8859-1`. */ @get:Input public open val charsetName: Property = objectFactory.property(Charsets.ISO_8859_1.name()) - @get:Internal // TODO: should be @Input, but it can't be serialized, see https://github.com/GradleUp/shadow/pull/1208. + @get:Internal // TODO: should be @Input, but it can't be serialized, see + // https://github.com/GradleUp/shadow/pull/1208. public open var keyTransformer: (String) -> String = IDENTITY override fun canTransformResource(element: FileTreeElement): Boolean { @@ -171,7 +165,10 @@ public open class PropertiesFileTransformer @Inject constructor( } } - private fun loadAndTransformKeys(inputStream: InputStream, action: (key: String, value: String) -> Unit) { + private fun loadAndTransformKeys( + inputStream: InputStream, + action: (key: String, value: String) -> Unit, + ) { val props = Properties().apply { load(inputStream.bufferedReader(charset)) } props.forEach { action(keyTransformer(it.key as String), it.value as String) } } @@ -210,11 +207,18 @@ public open class PropertiesFileTransformer @Inject constructor( override fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean) { if (conflicts.isNotEmpty()) { - val message = "The following properties files have conflicting property values and cannot be merged:" + - conflicts.map { (path, props) -> - path + props.map { "Property ${it.key} is duplicated ${it.value} times with different values" } - .joinToString(separator = "\n * ", prefix = "\n * ") - }.joinToString(separator = "\n * ", prefix = "\n * ") + val message = + "The following properties files have conflicting property values and cannot be merged:" + + conflicts + .map { (path, props) -> + path + + props + .map { + "Property ${it.key} is duplicated ${it.value} times with different values" + } + .joinToString(separator = "\n * ", prefix = "\n * ") + } + .joinToString(separator = "\n * ", prefix = "\n * ") error(message) } @@ -229,8 +233,7 @@ public open class PropertiesFileTransformer @Inject constructor( First, Latest, Append, - Fail, - ; + Fail; public companion object { @JvmStatic diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ResourceTransformer.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ResourceTransformer.kt index bb3d523ac..53e72a671 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ResourceTransformer.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ResourceTransformer.kt @@ -9,7 +9,8 @@ import org.gradle.api.model.ObjectFactory import org.gradle.api.tasks.Internal /** - * Modified from [org.apache.maven.plugins.shade.resource.ResourceTransformer.java](https://github.com/apache/maven-shade-plugin/blob/master/src/main/java/org/apache/maven/plugins/shade/resource/ResourceTransformer.java). + * Modified from + * [org.apache.maven.plugins.shade.resource.ResourceTransformer.java](https://github.com/apache/maven-shade-plugin/blob/master/src/main/java/org/apache/maven/plugins/shade/resource/ResourceTransformer.java). * * @author Jason van Zyl * @author Charlie Knudsen @@ -18,37 +19,38 @@ import org.gradle.api.tasks.Internal public interface ResourceTransformer : Named { public fun canTransformResource(element: FileTreeElement): Boolean - @Throws(IOException::class) - public fun transform(context: TransformerContext) + @Throws(IOException::class) public fun transform(context: TransformerContext) public fun hasTransformedResource(): Boolean @Throws(IOException::class) public fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean) - @Suppress("unused") // Used by Gradle side, see https://github.com/GradleUp/shadow/pull/1289#issuecomment-2915738983. + @Suppress("unused") // Used by Gradle side, see + // https://github.com/GradleUp/shadow/pull/1289#issuecomment-2915738983. @Internal override fun getName(): String = this::class.java.simpleName /** - * This is used for creating Gradle's lazy properties in the subclass, Shadow's build-in transformers that depend on - * this have been injected via [ObjectFactory.newInstance]. Custom transformers should implement or inject - * this property if they need to access it. + * This is used for creating Gradle's lazy properties in the subclass, Shadow's build-in + * transformers that depend on this have been injected via [ObjectFactory.newInstance]. Custom + * transformers should implement or inject this property if they need to access it. */ @get:Internal public val objectFactory: ObjectFactory - get() = throw NotImplementedError("You have to make sure this has been implemented or injected.") + get() = + throw NotImplementedError("You have to make sure this has been implemented or injected.") /** - * This also implements [ResourceTransformer] but no-op, which means it could be used by Kotlin delegations. + * This also implements [ResourceTransformer] but no-op, which means it could be used by Kotlin + * delegations. */ public companion object : ResourceTransformer { @JvmStatic public fun Class.create(objectFactory: ObjectFactory): T { // If the constructor takes a single ObjectFactory, inject it in. - val constructor = constructors.find { - it.parameterTypes.singleOrNull() == ObjectFactory::class.java - } + val constructor = + constructors.find { it.parameterTypes.singleOrNull() == ObjectFactory::class.java } return if (constructor != null) { objectFactory.newInstance(this@create) } else { @@ -57,8 +59,14 @@ public interface ResourceTransformer : Named { } public override fun canTransformResource(element: FileTreeElement): Boolean = false + public override fun transform(context: TransformerContext): Unit = Unit - public override fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean): Unit = Unit + + public override fun modifyOutputStream( + os: ZipOutputStream, + preserveFileTimestamps: Boolean, + ): Unit = Unit + public override fun hasTransformedResource(): Boolean = false } } diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformer.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformer.kt index 616603e2b..bcb95ab21 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformer.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformer.kt @@ -8,26 +8,28 @@ import org.gradle.api.tasks.Internal import org.gradle.api.tasks.util.PatternSet /** - * Resources transformer that appends entries in `META-INF/services` resources into - * a single resource. For example, if there are several `META-INF/services/org.apache.maven.project.ProjectBuilder` - * resources spread across many JARs the individual entries will all be concatenated into a single - * `META-INF/services/org.apache.maven.project.ProjectBuilder` resource packaged into the resultant JAR produced - * by the shading process. + * Resources transformer that appends entries in `META-INF/services` resources into a single + * resource. For example, if there are several + * `META-INF/services/org.apache.maven.project.ProjectBuilder` resources spread across many JARs the + * individual entries will all be concatenated into a single + * `META-INF/services/org.apache.maven.project.ProjectBuilder` resource packaged into the resultant + * JAR produced by the shading process. * - * Modified from [org.apache.maven.plugins.shade.resource.ServicesResourceTransformer.java](https://github.com/apache/maven-shade-plugin/blob/master/src/main/java/org/apache/maven/plugins/shade/resource/ServicesResourceTransformer.java). + * Modified from + * [org.apache.maven.plugins.shade.resource.ServicesResourceTransformer.java](https://github.com/apache/maven-shade-plugin/blob/master/src/main/java/org/apache/maven/plugins/shade/resource/ServicesResourceTransformer.java). * * @author jvanzyl * @author Charlie Knudsen * @author John Engelman */ @CacheableTransformer -public open class ServiceFileTransformer @JvmOverloads constructor( - patternSet: PatternSet = PatternSet() - .include(SERVICES_PATTERN) - .exclude(PATH_LEGACY_GROOVY_EXTENSION_MODULE_DESCRIPTOR), +public open class ServiceFileTransformer +@JvmOverloads +constructor( + patternSet: PatternSet = + PatternSet().include(SERVICES_PATTERN).exclude(PATH_LEGACY_GROOVY_EXTENSION_MODULE_DESCRIPTOR) ) : PatternFilterableResourceTransformer(patternSet = patternSet) { - @get:Internal - internal val serviceEntries = mutableMapOf>() + @get:Internal internal val serviceEntries = mutableMapOf>() @get:Internal // No need to mark this as an input as `getIncludes` is already marked as `@Input`. public open var path: String = SERVICES_PATH @@ -38,12 +40,13 @@ public open class ServiceFileTransformer @JvmOverloads constructor( } override fun transform(context: TransformerContext) { - val resource = path + "/" + - context.relocators.relocateClass(context.path.substringAfter("$path/")) + val resource = + path + "/" + context.relocators.relocateClass(context.path.substringAfter("$path/")) val out = serviceEntries.getOrPut(resource) { mutableSetOf() } - context.inputStream.bufferedReader().use { it.readLines() }.forEach { line -> - out.add(context.relocators.relocateClass(line)) - } + context.inputStream + .bufferedReader() + .use { it.readLines() } + .forEach { line -> out.add(context.relocators.relocateClass(line)) } } override fun hasTransformedResource(): Boolean = serviceEntries.isNotEmpty() diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/TransformerContext.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/TransformerContext.kt index 71e3f5cfa..ad91106c1 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/TransformerContext.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/TransformerContext.kt @@ -3,7 +3,9 @@ package com.github.jengelman.gradle.plugins.shadow.transformers import com.github.jengelman.gradle.plugins.shadow.relocation.Relocator import java.io.InputStream -public data class TransformerContext @JvmOverloads constructor( +public data class TransformerContext +@JvmOverloads +constructor( val path: String, val inputStream: InputStream, val relocators: Set = emptySet(), @@ -14,17 +16,24 @@ public data class TransformerContext @JvmOverloads constructor( private var relocators = emptySet() public fun path(path: String): Builder = apply { this.path = path } - public fun inputStream(inputStream: InputStream): Builder = apply { this.inputStream = inputStream } - public fun relocators(relocators: Set): Builder = apply { this.relocators = relocators } - public fun build(): TransformerContext = TransformerContext( - path = path, - inputStream = requireNotNull(inputStream) { "inputStream is required" }, - relocators = relocators, - ) + + public fun inputStream(inputStream: InputStream): Builder = apply { + this.inputStream = inputStream + } + + public fun relocators(relocators: Set): Builder = apply { + this.relocators = relocators + } + + public fun build(): TransformerContext = + TransformerContext( + path = path, + inputStream = requireNotNull(inputStream) { "inputStream is required" }, + relocators = relocators, + ) } public companion object { - @JvmStatic - public fun builder(): Builder = Builder() + @JvmStatic public fun builder(): Builder = Builder() } } diff --git a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/XmlAppendingTransformer.kt b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/XmlAppendingTransformer.kt index 2e02fd805..990bb90f2 100644 --- a/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/XmlAppendingTransformer.kt +++ b/src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/XmlAppendingTransformer.kt @@ -22,37 +22,39 @@ import org.xml.sax.InputSource /** * Appends multiple occurrences of some XML file. * - * Modified from [org.apache.maven.plugins.shade.resource.XmlAppendingTransformer.java](https://github.com/apache/maven-shade-plugin/blob/master/src/main/java/org/apache/maven/plugins/shade/resource/XmlAppendingTransformer.java). + * Modified from + * [org.apache.maven.plugins.shade.resource.XmlAppendingTransformer.java](https://github.com/apache/maven-shade-plugin/blob/master/src/main/java/org/apache/maven/plugins/shade/resource/XmlAppendingTransformer.java). * * @author John Engelman */ @CacheableTransformer -public open class XmlAppendingTransformer @Inject constructor( - final override val objectFactory: ObjectFactory, -) : ResourceTransformer { +public open class XmlAppendingTransformer +@Inject +constructor(final override val objectFactory: ObjectFactory) : ResourceTransformer { private var doc: Document? = null - @get:Input - public open val ignoreDtd: Property = objectFactory.property(true) + @get:Input public open val ignoreDtd: Property = objectFactory.property(true) - @get:Input - public open val resource: Property = objectFactory.property("") + @get:Input public open val resource: Property = objectFactory.property("") override fun canTransformResource(element: FileTreeElement): Boolean { return resource.get().equals(element.path, ignoreCase = true) } override fun transform(context: TransformerContext) { - val r = try { - SAXBuilder(XMLReaders.NONVALIDATING).apply { - expandEntities = false - if (ignoreDtd.get()) { - entityResolver = EntityResolver { _, _ -> InputSource(StringReader("")) } - } - }.build(context.inputStream) - } catch (e: JDOMException) { - throw IOException("Error processing resource ${resource.get()}: ${e.message}", e) - } + val r = + try { + SAXBuilder(XMLReaders.NONVALIDATING) + .apply { + expandEntities = false + if (ignoreDtd.get()) { + entityResolver = EntityResolver { _, _ -> InputSource(StringReader("")) } + } + } + .build(context.inputStream) + } catch (e: JDOMException) { + throw IOException("Error processing resource ${resource.get()}: ${e.message}", e) + } if (doc == null) { doc = r @@ -65,9 +67,7 @@ public open class XmlAppendingTransformer @Inject constructor( mergedEl.setAttribute(a) } } - root.children.forEach { n -> - doc!!.rootElement.addContent(n.clone()) - } + root.children.forEach { n -> doc!!.rootElement.addContent(n.clone()) } } } diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowPropertiesTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowPropertiesTest.kt index 2fdaadf7e..803ca4ba4 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowPropertiesTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/ShadowPropertiesTest.kt @@ -48,212 +48,225 @@ class ShadowPropertiesTest { @BeforeEach fun beforeEach() { - project = ProjectBuilder.builder().withName(PROJECT_NAME).build().also { - it.version = VERSION - it.plugins.apply(ShadowPlugin::class.java) - } + project = + ProjectBuilder.builder().withName(PROJECT_NAME).build().also { + it.version = VERSION + it.plugins.apply(ShadowPlugin::class.java) + } } @Test - fun misc() = with(project) { - assertThat(plugins.hasPlugin(ShadowPlugin::class.java)).isTrue() - assertThat(plugins.hasPlugin(LegacyShadowPlugin::class.java)).isTrue() - assertThat(tasks.findByName(SHADOW_JAR_TASK_NAME)).isNull() + fun misc() = + with(project) { + assertThat(plugins.hasPlugin(ShadowPlugin::class.java)).isTrue() + assertThat(plugins.hasPlugin(LegacyShadowPlugin::class.java)).isTrue() + assertThat(tasks.findByName(SHADOW_JAR_TASK_NAME)).isNull() - with(extensions.getByType(ShadowExtension::class.java)) { - assertThat(addShadowVariantIntoJavaComponent.get()).isTrue() - assertThat(addTargetJvmVersionAttribute.get()).isTrue() - assertThat(bundlingAttribute.get()).isEqualTo(Bundling.SHADOWED) + with(extensions.getByType(ShadowExtension::class.java)) { + assertThat(addShadowVariantIntoJavaComponent.get()).isTrue() + assertThat(addTargetJvmVersionAttribute.get()).isTrue() + assertThat(bundlingAttribute.get()).isEqualTo(Bundling.SHADOWED) + } } - } @Test - fun inheritManifestAttrsFromJars() = with(project) { - plugins.apply(JavaPlugin::class.java) - tasks.jar.configure { - it.manifest.attributes["jar"] = "fromJar" - } - val jar1 = tasks.register("jar1", Jar::class.java) { - it.manifest.attributes["jar1"] = "fromJar1" - } - val jar2 = tasks.register("jar2", Jar::class.java) { - it.manifest.attributes["jar2"] = "fromJar2" - } - tasks.shadowJar.configure { - it.manifest.attributes["shadowJar"] = "fromShadowJar" - it.manifest.from(jar1.get().manifest) - @Suppress("DEPRECATION") // TODO: remove this once InheritManifest is removed. - it.manifest.inheritFrom(jar2.get().manifest) + fun inheritManifestAttrsFromJars() = + with(project) { + plugins.apply(JavaPlugin::class.java) + tasks.jar.configure { it.manifest.attributes["jar"] = "fromJar" } + val jar1 = + tasks.register("jar1", Jar::class.java) { it.manifest.attributes["jar1"] = "fromJar1" } + val jar2 = + tasks.register("jar2", Jar::class.java) { it.manifest.attributes["jar2"] = "fromJar2" } + tasks.shadowJar.configure { + it.manifest.attributes["shadowJar"] = "fromShadowJar" + it.manifest.from(jar1.get().manifest) + @Suppress("DEPRECATION") // TODO: remove this once InheritManifest is removed. + it.manifest.inheritFrom(jar2.get().manifest) + } + // Call effectiveManifest as a way to force merging to happen like writing the jar would. + assertThat(tasks.shadowJar.get().manifest.effectiveManifest.attributes) + .containsOnly( + "Manifest-Version" to "1.0", + "jar" to "fromJar", + "jar1" to "fromJar1", + "jar2" to "fromJar2", + "shadowJar" to "fromShadowJar", + ) } - // Call effectiveManifest as a way to force merging to happen like writing the jar would. - assertThat(tasks.shadowJar.get().manifest.effectiveManifest.attributes).containsOnly( - "Manifest-Version" to "1.0", - "jar" to "fromJar", - "jar1" to "fromJar1", - "jar2" to "fromJar2", - "shadowJar" to "fromShadowJar", - ) - } @Test - fun inheritManifestMainClassFromJar() = with(project) { - plugins.apply(JavaPlugin::class.java) - tasks.jar.configure { - it.manifest.attributes[mainClassAttributeKey] = "Main" - } - tasks.shadowJar.configure { - it.mainClass.set("Main2") // This should not override the inherited one from jar. + fun inheritManifestMainClassFromJar() = + with(project) { + plugins.apply(JavaPlugin::class.java) + tasks.jar.configure { it.manifest.attributes[mainClassAttributeKey] = "Main" } + tasks.shadowJar.configure { + it.mainClass.set("Main2") // This should not override the inherited one from jar. + } + assertThat(tasks.shadowJar.get().manifest.attributes) + .containsOnly("Manifest-Version" to "1.0", mainClassAttributeKey to "Main") } - assertThat(tasks.shadowJar.get().manifest.attributes).containsOnly( - "Manifest-Version" to "1.0", - mainClassAttributeKey to "Main", - ) - } @Test - fun applyJavaPlugin() = with(project) { - plugins.apply(JavaPlugin::class.java) - val shadowJarTask = tasks.shadowJar.get() - val shadowConfig = configurations.shadow.get() - val assembleTask = tasks.getByName(ASSEMBLE_TASK_NAME) + fun applyJavaPlugin() = + with(project) { + plugins.apply(JavaPlugin::class.java) + val shadowJarTask = tasks.shadowJar.get() + val shadowConfig = configurations.shadow.get() + val assembleTask = tasks.getByName(ASSEMBLE_TASK_NAME) - assertThat(shadowConfig.artifacts.files).containsOnly(shadowJarTask.archiveFile.get().asFile) - assertThat(assembleTask.dependsOnTaskNames).containsOnly(shadowJarTask.name) + assertThat(shadowConfig.artifacts.files).containsOnly(shadowJarTask.archiveFile.get().asFile) + assertThat(assembleTask.dependsOnTaskNames).containsOnly(shadowJarTask.name) - // Check inherited properties. - with(shadowJarTask as Jar) { - assertThat(group).isEqualTo(LifecycleBasePlugin.BUILD_GROUP) - assertThat(description).isEqualTo("Create a combined JAR of project and runtime dependencies") + // Check inherited properties. + with(shadowJarTask as Jar) { + assertThat(group).isEqualTo(LifecycleBasePlugin.BUILD_GROUP) + assertThat(description) + .isEqualTo("Create a combined JAR of project and runtime dependencies") - assertThat(archiveAppendix.orNull).isNull() - assertThat(archiveBaseName.get()).isEqualTo(PROJECT_NAME) - assertThat(archiveClassifier.get()).isEqualTo("all") - assertThat(archiveExtension.get()).isEqualTo("jar") - assertThat(archiveFileName.get()).isEqualTo("my-project-1.0.0-all.jar") - assertThat(archiveVersion.get()).isEqualTo(version) - assertThat(archiveFile.get().asFile).all { - isEqualTo(destinationDirectory.file(archiveFileName).get().asFile) - isEqualTo(projectDir.resolve("build/libs/my-project-1.0.0-all.jar")) - } - assertThat(destinationDirectory.get().asFile).all { - isEqualTo(layout.buildDirectory.dir("libs").get().asFile) - isEqualTo(projectDir.resolve("build/libs")) - } + assertThat(archiveAppendix.orNull).isNull() + assertThat(archiveBaseName.get()).isEqualTo(PROJECT_NAME) + assertThat(archiveClassifier.get()).isEqualTo("all") + assertThat(archiveExtension.get()).isEqualTo("jar") + assertThat(archiveFileName.get()).isEqualTo("my-project-1.0.0-all.jar") + assertThat(archiveVersion.get()).isEqualTo(version) + assertThat(archiveFile.get().asFile).all { + isEqualTo(destinationDirectory.file(archiveFileName).get().asFile) + isEqualTo(projectDir.resolve("build/libs/my-project-1.0.0-all.jar")) + } + assertThat(destinationDirectory.get().asFile).all { + isEqualTo(layout.buildDirectory.dir("libs").get().asFile) + isEqualTo(projectDir.resolve("build/libs")) + } - assertThat(duplicatesStrategy).isEqualTo(DuplicatesStrategy.EXCLUDE) - } + assertThat(duplicatesStrategy).isEqualTo(DuplicatesStrategy.EXCLUDE) + } - // Check self properties. - with(shadowJarTask) { - assertThat(addMultiReleaseAttribute.get()).isTrue() - assertThat(enableAutoRelocation.get()).isFalse() - assertThat(enableKotlinModuleRemapping.get()).isTrue() - assertThat(failOnDuplicateEntries.get()).isFalse() - assertThat(minimizeJar.get()).isFalse() - assertThat(mainClass.orNull).isNull() + // Check self properties. + with(shadowJarTask) { + assertThat(addMultiReleaseAttribute.get()).isTrue() + assertThat(enableAutoRelocation.get()).isFalse() + assertThat(enableKotlinModuleRemapping.get()).isTrue() + assertThat(failOnDuplicateEntries.get()).isFalse() + assertThat(minimizeJar.get()).isFalse() + assertThat(mainClass.orNull).isNull() - assertThat(relocationPrefix.get()).isEqualTo(ShadowBasePlugin.SHADOW) - assertThat(configurations.get()).containsOnly(runtimeConfiguration) + assertThat(relocationPrefix.get()).isEqualTo(ShadowBasePlugin.SHADOW) + assertThat(configurations.get()).containsOnly(runtimeConfiguration) + } } - } @Test - fun applyApplicationPlugin() = with(project) { - plugins.apply(ApplicationPlugin::class.java) - val shadowJarTask = tasks.shadowJar.get() - val runShadowTask = tasks.runShadow.get() - val startShadowScripts = tasks.startShadowScripts.get() - val installShadowDist = tasks.installShadowDist.get() - val shadowDistZip = tasks.shadowDistZip.get() - val shadowDistTar = tasks.shadowDistTar.get() + fun applyApplicationPlugin() = + with(project) { + plugins.apply(ApplicationPlugin::class.java) + val shadowJarTask = tasks.shadowJar.get() + val runShadowTask = tasks.runShadow.get() + val startShadowScripts = tasks.startShadowScripts.get() + val installShadowDist = tasks.installShadowDist.get() + val shadowDistZip = tasks.shadowDistZip.get() + val shadowDistTar = tasks.shadowDistTar.get() - with(runShadowTask) { - assertThat(description).isEqualTo("Runs this project as a JVM application using the shadow jar") - assertThat(group).isEqualTo(ApplicationPlugin.APPLICATION_GROUP) - assertThat(classpath.files).containsOnly(shadowJarTask.archiveFile.get().asFile) - assertThat(mainModule.orNull).isEqualTo(applicationExtension.mainModule.orNull) - assertThat(mainClass.orNull).isEqualTo(applicationExtension.mainClass.orNull) - assertThat(jvmArguments.get()).isEqualTo(applicationExtension.applicationDefaultJvmArgs) - assertThat(modularity.inferModulePath.orNull) - .isEqualTo(javaPluginExtension.modularity.inferModulePath.orNull) - assertThat(javaLauncher.get().metadata.jvmVersion) - .isEqualTo(javaToolchainService.launcherFor(javaPluginExtension.toolchain).get().metadata.jvmVersion) - } - - with(startShadowScripts) { - assertThat(description).isEqualTo("Creates OS specific scripts to run the project as a JVM application using the shadow jar") - assertThat(classpath?.files).isNotNull().containsOnly(shadowJarTask.archiveFile.get().asFile) - assertThat(mainModule.orNull).isEqualTo(applicationExtension.mainModule.orNull) - assertThat(mainClass.orNull).isEqualTo(applicationExtension.mainClass.orNull) - assertThat(applicationName).isEqualTo(applicationExtension.applicationName) - assertThat(outputDir).isNotNull().all { - isEqualTo(layout.buildDirectory.dir("scriptsShadow").get().asFile) - isEqualTo(projectDir.resolve("build/scriptsShadow")) + with(runShadowTask) { + assertThat(description) + .isEqualTo("Runs this project as a JVM application using the shadow jar") + assertThat(group).isEqualTo(ApplicationPlugin.APPLICATION_GROUP) + assertThat(classpath.files).containsOnly(shadowJarTask.archiveFile.get().asFile) + assertThat(mainModule.orNull).isEqualTo(applicationExtension.mainModule.orNull) + assertThat(mainClass.orNull).isEqualTo(applicationExtension.mainClass.orNull) + assertThat(jvmArguments.get()).isEqualTo(applicationExtension.applicationDefaultJvmArgs) + assertThat(modularity.inferModulePath.orNull) + .isEqualTo(javaPluginExtension.modularity.inferModulePath.orNull) + assertThat(javaLauncher.get().metadata.jvmVersion) + .isEqualTo( + javaToolchainService + .launcherFor(javaPluginExtension.toolchain) + .get() + .metadata + .jvmVersion + ) } - assertThat(executableDir).isEqualTo(applicationExtension.executableDir) - assertThat(defaultJvmOpts).isEqualTo(applicationExtension.applicationDefaultJvmArgs) - assertThat(modularity.inferModulePath.orNull) - .isEqualTo(javaPluginExtension.modularity.inferModulePath.orNull) - } - with(installShadowDist) { - assertThat(description).isEqualTo("Installs the project as a distribution as-is.") - assertThat(group).isEqualTo("distribution") - assertThat(destinationDir).isNotNull() - .isEqualTo(projectDir.resolve("build/install/my-project-shadow")) - } + with(startShadowScripts) { + assertThat(description) + .isEqualTo( + "Creates OS specific scripts to run the project as a JVM application using the shadow jar" + ) + assertThat(classpath?.files) + .isNotNull() + .containsOnly(shadowJarTask.archiveFile.get().asFile) + assertThat(mainModule.orNull).isEqualTo(applicationExtension.mainModule.orNull) + assertThat(mainClass.orNull).isEqualTo(applicationExtension.mainClass.orNull) + assertThat(applicationName).isEqualTo(applicationExtension.applicationName) + assertThat(outputDir).isNotNull().all { + isEqualTo(layout.buildDirectory.dir("scriptsShadow").get().asFile) + isEqualTo(projectDir.resolve("build/scriptsShadow")) + } + assertThat(executableDir).isEqualTo(applicationExtension.executableDir) + assertThat(defaultJvmOpts).isEqualTo(applicationExtension.applicationDefaultJvmArgs) + assertThat(modularity.inferModulePath.orNull) + .isEqualTo(javaPluginExtension.modularity.inferModulePath.orNull) + } - listOf( - shadowDistZip, - shadowDistTar, - ).forEach { - with(it as AbstractArchiveTask) { - assertThat(description).isEqualTo("Bundles the project as a distribution.") + with(installShadowDist) { + assertThat(description).isEqualTo("Installs the project as a distribution as-is.") assertThat(group).isEqualTo("distribution") - assertThat(archiveAppendix.orNull).isNull() - assertThat(archiveBaseName.get()).isEqualTo("my-project-shadow") - assertThat(archiveClassifier.orNull).isNull() - assertThat(archiveVersion.get()).isEqualTo(version) - assertThat(destinationDirectory.get().asFile).all { - isEqualTo(layout.buildDirectory.dir("distributions").get().asFile) - isEqualTo(projectDir.resolve("build/distributions")) + assertThat(destinationDir) + .isNotNull() + .isEqualTo(projectDir.resolve("build/install/my-project-shadow")) + } + + listOf(shadowDistZip, shadowDistTar).forEach { + with(it as AbstractArchiveTask) { + assertThat(description).isEqualTo("Bundles the project as a distribution.") + assertThat(group).isEqualTo("distribution") + assertThat(archiveAppendix.orNull).isNull() + assertThat(archiveBaseName.get()).isEqualTo("my-project-shadow") + assertThat(archiveClassifier.orNull).isNull() + assertThat(archiveVersion.get()).isEqualTo(version) + assertThat(destinationDirectory.get().asFile).all { + isEqualTo(layout.buildDirectory.dir("distributions").get().asFile) + isEqualTo(projectDir.resolve("build/distributions")) + } } } - } - with(shadowDistZip) { - assertThat(archiveExtension.get()).isEqualTo("zip") - assertThat(archiveFileName.get()).isEqualTo("my-project-shadow-1.0.0.zip") - assertThat(archiveFile.get().asFile).all { - isEqualTo(destinationDirectory.file(archiveFileName).get().asFile) - isEqualTo(projectDir.resolve("build/distributions/my-project-shadow-1.0.0.zip")) + with(shadowDistZip) { + assertThat(archiveExtension.get()).isEqualTo("zip") + assertThat(archiveFileName.get()).isEqualTo("my-project-shadow-1.0.0.zip") + assertThat(archiveFile.get().asFile).all { + isEqualTo(destinationDirectory.file(archiveFileName).get().asFile) + isEqualTo(projectDir.resolve("build/distributions/my-project-shadow-1.0.0.zip")) + } } - } - with(shadowDistTar) { - assertThat(archiveExtension.get()).isEqualTo("tar") - assertThat(archiveFileName.get()).isEqualTo("my-project-shadow-1.0.0.tar") - assertThat(archiveFile.get().asFile).all { - isEqualTo(destinationDirectory.file(archiveFileName).get().asFile) - isEqualTo(projectDir.resolve("build/distributions/my-project-shadow-1.0.0.tar")) + with(shadowDistTar) { + assertThat(archiveExtension.get()).isEqualTo("tar") + assertThat(archiveFileName.get()).isEqualTo("my-project-shadow-1.0.0.tar") + assertThat(archiveFile.get().asFile).all { + isEqualTo(destinationDirectory.file(archiveFileName).get().asFile) + isEqualTo(projectDir.resolve("build/distributions/my-project-shadow-1.0.0.tar")) + } } } - } @Test - fun applyJavaGradlePlugin() = with(project) { - plugins.apply(JavaGradlePluginPlugin::class.java) - val api = configurations.named(API_CONFIGURATION_NAME).get() - val compileOnly = configurations.named(COMPILE_ONLY_CONFIGURATION_NAME).get() - val gradleApi = dependencies.gradleApi() - assertThat(api.dependencies).containsNone(gradleApi) - assertThat(compileOnly.dependencies).containsOnly(gradleApi) - } + fun applyJavaGradlePlugin() = + with(project) { + plugins.apply(JavaGradlePluginPlugin::class.java) + val api = configurations.named(API_CONFIGURATION_NAME).get() + val compileOnly = configurations.named(COMPILE_ONLY_CONFIGURATION_NAME).get() + val gradleApi = dependencies.gradleApi() + assertThat(api.dependencies).containsNone(gradleApi) + assertThat(compileOnly.dependencies).containsOnly(gradleApi) + } private companion object { const val PROJECT_NAME = "my-project" const val VERSION = "1.0.0" - val Task.dependsOnTaskNames: List get() = dependsOn.filterIsInstance().map(Named::getName) + val Task.dependsOnTaskNames: List + get() = dependsOn.filterIsInstance().map(Named::getName) - val TaskContainer.jar: TaskProvider get() = named("jar", Jar::class.java) + val TaskContainer.jar: TaskProvider + get() = named("jar", Jar::class.java) } } diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/ReproduciblePropertiesTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/ReproduciblePropertiesTest.kt index e0775596a..42b6b08eb 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/ReproduciblePropertiesTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/ReproduciblePropertiesTest.kt @@ -21,69 +21,73 @@ class ReproduciblePropertiesTest { @ParameterizedTest @MethodSource("generalCharsetsProvider") fun asciiProps(charset: Charset) { - val output = ReproducibleProperties().also { props -> - props["key"] = "value" - props["key2"] = "value2" - props["a"] = "b" - props["d"] = "e" - props["0"] = "1" - props["b"] = "c" - props["c"] = "d" - props["e"] = "f" - }.writeToString(charset) + val output = + ReproducibleProperties() + .also { props -> + props["key"] = "value" + props["key2"] = "value2" + props["a"] = "b" + props["d"] = "e" + props["0"] = "1" + props["b"] = "c" + props["c"] = "d" + props["e"] = "f" + } + .writeToString(charset) - assertThat(output).isEqualTo( - """ - |0=1 - |a=b - |b=c - |c=d - |d=e - |e=f - |key=value - |key2=value2 - | - """.trimMargin(), - ) + assertThat(output) + .isEqualTo( + """ + |0=1 + |a=b + |b=c + |c=d + |d=e + |e=f + |key=value + |key2=value2 + |""" + .trimMargin() + ) } @ParameterizedTest @MethodSource("utfCharsetsProvider") fun utfProps(charset: Charset) { - val output = ReproducibleProperties().also { props -> - props["äöüß"] = "aouss" - props["áèô"] = "aeo" - props["€²³"] = "x" - props["传傳磨宿说説"] = "b" - }.writeToString(charset) + val output = + ReproducibleProperties() + .also { props -> + props["äöüß"] = "aouss" + props["áèô"] = "aeo" + props["€²³"] = "x" + props["传傳磨宿说説"] = "b" + } + .writeToString(charset) - assertThat(output).isEqualTo( - """ - |áèô=aeo - |äöüß=aouss - |€²³=x - |传傳磨宿说説=b - | - """.trimMargin(), - ) + assertThat(output) + .isEqualTo( + """ + |áèô=aeo + |äöüß=aouss + |€²³=x + |传傳磨宿说説=b + |""" + .trimMargin() + ) } private companion object Companion { @JvmStatic - fun generalCharsetsProvider() = listOf( - StandardCharsets.ISO_8859_1, - StandardCharsets.US_ASCII, - ) + utfCharsetsProvider() + fun generalCharsetsProvider() = + listOf(StandardCharsets.ISO_8859_1, StandardCharsets.US_ASCII) + utfCharsetsProvider() - @JvmStatic - fun utfCharsetsProvider() = listOf( - StandardCharsets.UTF_8, - StandardCharsets.UTF_16, - ) + @JvmStatic fun utfCharsetsProvider() = listOf(StandardCharsets.UTF_8, StandardCharsets.UTF_16) fun ReproducibleProperties.writeToString(charset: Charset): String { - return ByteArrayOutputStream().also { writeWithoutComments(charset, it) } - .toString(charset.name()).invariantEolString + return ByteArrayOutputStream() + .also { writeWithoutComments(charset, it) } + .toString(charset.name()) + .invariantEolString } } } diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/RelocatorRemapperTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/RelocatorRemapperTest.kt index 6ce670cce..5cc83d4ea 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/RelocatorRemapperTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/RelocatorRemapperTest.kt @@ -11,40 +11,51 @@ class RelocatorRemapperTest { @ParameterizedTest @MethodSource("signaturePatternsProvider") fun relocateSignaturePatterns(input: String, expected: String) { - val relocator = RelocatorRemapper( - relocators = setOf( - SimpleRelocator("org.package", "shadow.org.package"), - ), - ) + val relocator = + RelocatorRemapper(relocators = setOf(SimpleRelocator("org.package", "shadow.org.package"))) assertThat(relocator.map(input)).isEqualTo(expected) } private companion object { val primitiveTypes = setOf('B', 'C', 'D', 'F', 'I', 'J', 'S', 'Z') - val primitiveTypePatterns = primitiveTypes.map { - // Methods like `void method(boolean arg1, org.package.ClassA arg2)` - Arguments.of("(${it}Lorg/package/ClassA;)V", "(${it}Lshadow/org/package/ClassA;)V") - } + val primitiveTypePatterns = + primitiveTypes.map { + // Methods like `void method(boolean arg1, org.package.ClassA arg2)` + Arguments.of("(${it}Lorg/package/ClassA;)V", "(${it}Lshadow/org/package/ClassA;)V") + } @JvmStatic - fun signaturePatternsProvider() = listOf( - // Normal class: `org.package.ClassA` - Arguments.of("Lorg/package/ClassA;", "Lshadow/org/package/ClassA;"), - // Array class: `org.package.ClassA[]` - Arguments.of("[Lorg/package/ClassA;", "[Lshadow/org/package/ClassA;"), - // Multidimensional array of class: `org.package.ClassA[][]` - Arguments.of("[[Lorg/package/ClassA;", "[[Lshadow/org/package/ClassA;"), - // Multiple classes: `org.package.ClassA org.package.ClassB` - Arguments.of("Lorg/package/ClassA;Lorg/package/ClassB;", "Lshadow/org/package/ClassA;Lshadow/org/package/ClassB;"), - // Multiple classes: `java.lang.Object org.package.ClassB` - Arguments.of("Ljava/lang/Object;Lorg/package/ClassB;", "Ljava/lang/Object;Lshadow/org/package/ClassB;"), - // Single method argument: `void method(org.package.ClassA arg);` - Arguments.of("(Lorg/package/ClassA;)", "(Lshadow/org/package/ClassA;)"), - // Method arguments: `void method(org.package.ClassA arg1, org.package.ClassB arg2);` - Arguments.of("(Lorg/package/ClassA;Lorg/package/ClassB;)", "(Lshadow/org/package/ClassA;Lshadow/org/package/ClassB;)"), - // Example from issue 1403. - Arguments.of("()Lorg/package/ClassA;Lorg/package/ClassB;", "()Lshadow/org/package/ClassA;Lshadow/org/package/ClassB;"), - ) + primitiveTypePatterns + fun signaturePatternsProvider() = + listOf( + // Normal class: `org.package.ClassA` + Arguments.of("Lorg/package/ClassA;", "Lshadow/org/package/ClassA;"), + // Array class: `org.package.ClassA[]` + Arguments.of("[Lorg/package/ClassA;", "[Lshadow/org/package/ClassA;"), + // Multidimensional array of class: `org.package.ClassA[][]` + Arguments.of("[[Lorg/package/ClassA;", "[[Lshadow/org/package/ClassA;"), + // Multiple classes: `org.package.ClassA org.package.ClassB` + Arguments.of( + "Lorg/package/ClassA;Lorg/package/ClassB;", + "Lshadow/org/package/ClassA;Lshadow/org/package/ClassB;", + ), + // Multiple classes: `java.lang.Object org.package.ClassB` + Arguments.of( + "Ljava/lang/Object;Lorg/package/ClassB;", + "Ljava/lang/Object;Lshadow/org/package/ClassB;", + ), + // Single method argument: `void method(org.package.ClassA arg);` + Arguments.of("(Lorg/package/ClassA;)", "(Lshadow/org/package/ClassA;)"), + // Method arguments: `void method(org.package.ClassA arg1, org.package.ClassB arg2);` + Arguments.of( + "(Lorg/package/ClassA;Lorg/package/ClassB;)", + "(Lshadow/org/package/ClassA;Lshadow/org/package/ClassB;)", + ), + // Example from issue 1403. + Arguments.of( + "()Lorg/package/ClassA;Lorg/package/ClassB;", + "()Lshadow/org/package/ClassA;Lshadow/org/package/ClassB;", + ), + ) + primitiveTypePatterns } } diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/SimpleRelocatorTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/SimpleRelocatorTest.kt index 743c6ff84..6141b1d7e 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/SimpleRelocatorTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/relocation/SimpleRelocatorTest.kt @@ -7,7 +7,8 @@ import assertk.assertions.isTrue import org.junit.jupiter.api.Test /** - * Modified from [org.apache.maven.plugins.shade.relocation.SimpleRelocatorTest.java](https://github.com/apache/maven-shade-plugin/blob/master/src/test/java/org/apache/maven/plugins/shade/relocation/SimpleRelocatorTest.java). + * Modified from + * [org.apache.maven.plugins.shade.relocation.SimpleRelocatorTest.java](https://github.com/apache/maven-shade-plugin/blob/master/src/test/java/org/apache/maven/plugins/shade/relocation/SimpleRelocatorTest.java). */ class SimpleRelocatorTest { @@ -27,10 +28,17 @@ class SimpleRelocatorTest { assertThat(relocator.canRelocatePath("/org/Foo/Class")).isFalse() assertThat(relocator.canRelocatePath("/org/Foo/Class.class")).isFalse() - relocator = SimpleRelocator( - "org.foo", - excludes = listOf("org.foo.Excluded", "org.foo.public.*", "org.foo.recurse.**", "org.foo.Public*Stuff"), - ) + relocator = + SimpleRelocator( + "org.foo", + excludes = + listOf( + "org.foo.Excluded", + "org.foo.public.*", + "org.foo.recurse.**", + "org.foo.Public*Stuff", + ), + ) assertThat(relocator.canRelocatePath("org/foo/Class")).isTrue() assertThat(relocator.canRelocatePath("org/foo/Class.class")).isTrue() assertThat(relocator.canRelocatePath("org/foo/excluded")).isTrue() @@ -67,7 +75,8 @@ class SimpleRelocatorTest { relocator = SimpleRelocator("foo.") assertThat(relocator.canRelocatePath("foo/foo.bar")).isTrue() relocator.exclude("foo/foo.bar") - assertThat(relocator.canRelocatePath("foo/foo.bar")).isFalse() // Don't handle file path pattern. + assertThat(relocator.canRelocatePath("foo/foo.bar")) + .isFalse() // Don't handle file path pattern. assertThat(relocator.canRelocatePath("foo/foobar")).isTrue() relocator.exclude("foo/foobar") assertThat(relocator.canRelocatePath("foo/foobar")).isFalse() // File without extension. @@ -76,10 +85,7 @@ class SimpleRelocatorTest { @Test fun canRelocatePathWithRegex() { // Include with Regex - var relocator = SimpleRelocator( - "org.foo", - includes = listOf("%regex[org/foo/R(\\$.*)?$]"), - ) + var relocator = SimpleRelocator("org.foo", includes = listOf("%regex[org/foo/R(\\$.*)?$]")) assertThat(relocator.canRelocatePath("org/foo/R.class")).isTrue() assertThat(relocator.canRelocatePath($$"org/foo/R$string.class")).isTrue() assertThat(relocator.canRelocatePath($$"org/foo/R$layout.class")).isTrue() @@ -90,10 +96,7 @@ class SimpleRelocatorTest { assertThat(relocator.canRelocatePath($$"org/R$string.class")).isFalse() // Exclude with Regex - relocator = SimpleRelocator( - "org.foo", - excludes = listOf("%regex[org/foo/.*Factory[0-9].*]"), - ) + relocator = SimpleRelocator("org.foo", excludes = listOf("%regex[org/foo/.*Factory[0-9].*]")) assertThat(relocator.canRelocatePath("org/foo/Factory.class")).isTrue() assertThat(relocator.canRelocatePath("org/foo/FooFactoryMain.class")).isTrue() assertThat(relocator.canRelocatePath("org/foo/BarFactory.class")).isTrue() @@ -102,10 +105,11 @@ class SimpleRelocatorTest { assertThat(relocator.canRelocatePath("org/foo/BarFactory2.class")).isFalse() // Include with Regex and normal pattern - relocator = SimpleRelocator( - "org.foo", - includes = listOf("%regex[org/foo/.*Factory[0-9].*]", "org.foo.public.*"), - ) + relocator = + SimpleRelocator( + "org.foo", + includes = listOf("%regex[org/foo/.*Factory[0-9].*]", "org.foo.public.*"), + ) assertThat(relocator.canRelocatePath("org/foo/Factory1.class")).isTrue() assertThat(relocator.canRelocatePath("org/foo/public/Bar.class")).isTrue() assertThat(relocator.canRelocatePath("org/foo/Factory.class")).isFalse() @@ -120,10 +124,17 @@ class SimpleRelocatorTest { assertThat(relocator.canRelocateClass("com.foo.bar.Class")).isFalse() assertThat(relocator.canRelocateClass("org.Foo.Class")).isFalse() - relocator = SimpleRelocator( - "org.foo", - excludes = listOf("org.foo.Excluded", "org.foo.public.*", "org.foo.recurse.**", "org.foo.Public*Stuff"), - ) + relocator = + SimpleRelocator( + "org.foo", + excludes = + listOf( + "org.foo.Excluded", + "org.foo.public.*", + "org.foo.recurse.**", + "org.foo.Public*Stuff", + ), + ) assertThat(relocator.canRelocateClass("org.foo.Class")).isTrue() assertThat(relocator.canRelocateClass("org.foo.excluded")).isTrue() assertThat(relocator.canRelocateClass("org.foo.Excluded")).isFalse() @@ -159,11 +170,12 @@ class SimpleRelocatorTest { @Test fun canRelocateAbsClassPathWithExcludes() { - val relocator = SimpleRelocator( - "org/apache/velocity", - "org/apache/momentum", - excludes = listOf("org/apache/velocity/excluded/*"), - ) + val relocator = + SimpleRelocator( + "org/apache/velocity", + "org/apache/momentum", + excludes = listOf("org/apache/velocity/excluded/*"), + ) assertThat(relocator.canRelocatePath("/org/apache/velocity/mass.properties")).isTrue() assertThat(relocator.canRelocatePath("org/apache/velocity/mass.properties")).isTrue() assertThat(relocator.canRelocatePath("/org/apache/velocity/excluded/mass.properties")).isFalse() @@ -172,11 +184,12 @@ class SimpleRelocatorTest { @Test fun canRelocateAbsClassPathWithIncludes() { - val relocator = SimpleRelocator( - "org/apache/velocity", - "org/apache/momentum", - includes = listOf("org/apache/velocity/included/*"), - ) + val relocator = + SimpleRelocator( + "org/apache/velocity", + "org/apache/momentum", + includes = listOf("org/apache/velocity/included/*"), + ) assertThat(relocator.canRelocatePath("/org/apache/velocity/mass.properties")).isFalse() assertThat(relocator.canRelocatePath("org/apache/velocity/mass.properties")).isFalse() assertThat(relocator.canRelocatePath("/org/apache/velocity/included/mass.properties")).isTrue() @@ -200,12 +213,10 @@ class SimpleRelocatorTest { @Test fun relocateClass() { var relocator = SimpleRelocator("org.foo") - assertThat(relocator.relocateClass("org.foo.bar.Class")) - .isEqualTo("hidden.org.foo.bar.Class") + assertThat(relocator.relocateClass("org.foo.bar.Class")).isEqualTo("hidden.org.foo.bar.Class") relocator = SimpleRelocator("org.foo", "private.stuff") - assertThat(relocator.relocateClass("org.foo.bar.Class")) - .isEqualTo("private.stuff.bar.Class") + assertThat(relocator.relocateClass("org.foo.bar.Class")).isEqualTo("private.stuff.bar.Class") } @Test @@ -214,114 +225,167 @@ class SimpleRelocatorTest { assertThat(relocator.relocatePath("(I)Lorg/foo/bar/Class;")) .isEqualTo("(I)Lhidden/org/foo/bar/Class;") - relocator = SimpleRelocator("^META-INF/org.foo.xml$", "META-INF/hidden.org.foo.xml", rawString = true) + relocator = + SimpleRelocator("^META-INF/org.foo.xml$", "META-INF/hidden.org.foo.xml", rawString = true) assertThat(relocator.relocatePath("META-INF/org.foo.xml")) .isEqualTo("META-INF/hidden.org.foo.xml") } @Test fun relocateMavenFiles() { - val relocator = SimpleRelocator( - "META-INF/maven", - "META-INF/shade/maven", - excludes = listOf("META-INF/maven/com.foo.bar/artifactId/pom.*"), - ) - assertThat(relocator.canRelocatePath("META-INF/maven/com.foo.bar/artifactId/pom.properties")).isFalse() + val relocator = + SimpleRelocator( + "META-INF/maven", + "META-INF/shade/maven", + excludes = listOf("META-INF/maven/com.foo.bar/artifactId/pom.*"), + ) + assertThat(relocator.canRelocatePath("META-INF/maven/com.foo.bar/artifactId/pom.properties")) + .isFalse() assertThat(relocator.canRelocatePath("META-INF/maven/com.foo.bar/artifactId/pom.xml")).isFalse() - assertThat(relocator.canRelocatePath("META-INF/maven/com/foo/bar/artifactId/pom.properties")).isTrue() + assertThat(relocator.canRelocatePath("META-INF/maven/com/foo/bar/artifactId/pom.properties")) + .isTrue() assertThat(relocator.canRelocatePath("META-INF/maven/com/foo/bar/artifactId/pom.xml")).isTrue() - assertThat(relocator.canRelocatePath("META-INF/maven/com-foo-bar/artifactId/pom.properties")).isTrue() + assertThat(relocator.canRelocatePath("META-INF/maven/com-foo-bar/artifactId/pom.properties")) + .isTrue() assertThat(relocator.canRelocatePath("META-INF/maven/com-foo-bar/artifactId/pom.xml")).isTrue() } @Test fun canRelocateExcludedSourceFile() { - val relocator = SimpleRelocator( - "org.foo", - excludes = listOf("org/apache/iceberg/spark/parquet/**", "org/apache/spark/sql/execution/datasources/parquet/**"), - ) - assertThat(relocator.canRelocatePath("org/apache/iceberg/spark/parquet/SparkNativeParquet.class")).isFalse() - assertThat(relocator.canRelocatePath("org/apache/iceberg/spark/parquet/SparkNativeParquet$.class")).isFalse() - assertThat(relocator.canRelocatePath("org/apache/spark/sql/execution/datasources/parquet/v1.class")).isFalse() + val relocator = + SimpleRelocator( + "org.foo", + excludes = + listOf( + "org/apache/iceberg/spark/parquet/**", + "org/apache/spark/sql/execution/datasources/parquet/**", + ), + ) + assertThat( + relocator.canRelocatePath("org/apache/iceberg/spark/parquet/SparkNativeParquet.class") + ) + .isFalse() + assertThat( + relocator.canRelocatePath("org/apache/iceberg/spark/parquet/SparkNativeParquet$.class") + ) + .isFalse() + assertThat( + relocator.canRelocatePath("org/apache/spark/sql/execution/datasources/parquet/v1.class") + ) + .isFalse() assertThat(relocator.canRelocatePath("org/foo/Class.class")).isTrue() } @Test fun canRelocateExcludedSourceFileWithRegex() { - val relocator = SimpleRelocator( - "org.foo", - excludes = listOf("%regex[org/apache/iceberg/.*]", "%regex[org/apache/spark/.*]"), - ) - assertThat(relocator.canRelocatePath("org/apache/iceberg/spark/parquet/SparkNativeParquet.class")).isFalse() - assertThat(relocator.canRelocatePath("org/apache/iceberg/spark/parquet/SparkNativeParquet$.class")).isFalse() - assertThat(relocator.canRelocatePath("org/apache/spark/sql/execution/datasources/parquet/v1.class")).isFalse() + val relocator = + SimpleRelocator( + "org.foo", + excludes = listOf("%regex[org/apache/iceberg/.*]", "%regex[org/apache/spark/.*]"), + ) + assertThat( + relocator.canRelocatePath("org/apache/iceberg/spark/parquet/SparkNativeParquet.class") + ) + .isFalse() + assertThat( + relocator.canRelocatePath("org/apache/iceberg/spark/parquet/SparkNativeParquet$.class") + ) + .isFalse() + assertThat( + relocator.canRelocatePath("org/apache/spark/sql/execution/datasources/parquet/v1.class") + ) + .isFalse() assertThat(relocator.canRelocatePath("org/foo/Class.class")).isTrue() } @Test fun canRelocateIncludedSourceFile() { - val relocator = SimpleRelocator( - includes = listOf("org/apache/iceberg/spark/parquet/**", "org/apache/spark/sql/execution/datasources/parquet/**"), - ) - assertThat(relocator.canRelocatePath("org/apache/iceberg/spark/parquet/SparkNativeParquet.class")).isTrue() - assertThat(relocator.canRelocatePath("org/apache/iceberg/spark/parquet/SparkNativeParquet$.class")).isTrue() - assertThat(relocator.canRelocatePath("org/apache/spark/sql/execution/datasources/parquet/v1.class")).isTrue() + val relocator = + SimpleRelocator( + includes = + listOf( + "org/apache/iceberg/spark/parquet/**", + "org/apache/spark/sql/execution/datasources/parquet/**", + ) + ) + assertThat( + relocator.canRelocatePath("org/apache/iceberg/spark/parquet/SparkNativeParquet.class") + ) + .isTrue() + assertThat( + relocator.canRelocatePath("org/apache/iceberg/spark/parquet/SparkNativeParquet$.class") + ) + .isTrue() + assertThat( + relocator.canRelocatePath("org/apache/spark/sql/execution/datasources/parquet/v1.class") + ) + .isTrue() assertThat(relocator.canRelocatePath("org/foo/Class.class")).isFalse() } @Test fun canRelocateIncludedSourceFileWithRegex() { - val relocator = SimpleRelocator( - includes = listOf("%regex[org/apache/iceberg/.*]", "%regex[org/apache/spark/.*]"), - ) - assertThat(relocator.canRelocatePath("org/apache/iceberg/spark/parquet/SparkNativeParquet.class")).isTrue() - assertThat(relocator.canRelocatePath("org/apache/iceberg/spark/parquet/SparkNativeParquet$.class")).isTrue() - assertThat(relocator.canRelocatePath("org/apache/spark/sql/execution/datasources/parquet/v1.class")).isTrue() + val relocator = + SimpleRelocator( + includes = listOf("%regex[org/apache/iceberg/.*]", "%regex[org/apache/spark/.*]") + ) + assertThat( + relocator.canRelocatePath("org/apache/iceberg/spark/parquet/SparkNativeParquet.class") + ) + .isTrue() + assertThat( + relocator.canRelocatePath("org/apache/iceberg/spark/parquet/SparkNativeParquet$.class") + ) + .isTrue() + assertThat( + relocator.canRelocatePath("org/apache/spark/sql/execution/datasources/parquet/v1.class") + ) + .isTrue() assertThat(relocator.canRelocatePath("org/foo/Class.class")).isFalse() } @Test fun relocateSourceWithExcludesRaw() { - val relocator = SimpleRelocator( - "org.apache.maven", - "com.acme.maven", - listOf("foo.bar", "zot.baz"), - listOf("irrelevant.exclude", "org.apache.maven.exclude1", "org.apache.maven.sub.exclude2"), - true, - ) + val relocator = + SimpleRelocator( + "org.apache.maven", + "com.acme.maven", + listOf("foo.bar", "zot.baz"), + listOf("irrelevant.exclude", "org.apache.maven.exclude1", "org.apache.maven.sub.exclude2"), + true, + ) assertThat(relocator.applyToSourceContent(sourceFile)).isEqualTo(sourceFile) } @Test fun relocateSourceWithExcludes() { // Main relocator with in-/excludes - val relocator = SimpleRelocator( - "org.apache.maven", - "com.acme.maven", - listOf("foo.bar", "zot.baz"), - listOf("irrelevant.exclude", "org.apache.maven.exclude1", "org.apache.maven.sub.exclude2"), - ) + val relocator = + SimpleRelocator( + "org.apache.maven", + "com.acme.maven", + listOf("foo.bar", "zot.baz"), + listOf("irrelevant.exclude", "org.apache.maven.exclude1", "org.apache.maven.sub.exclude2"), + ) // Make sure not to replace variables 'io' and 'ioInput', package 'java.io' val ioRelocator = SimpleRelocator("io", "shaded.io") // Check corner case which was not working in PR #100 val asmRelocator = SimpleRelocator("org.objectweb.asm", "aj.org.objectweb.asm") // Make sure not to replace 'foo' package by path-like 'shaded/foo' - val fooRelocator = SimpleRelocator( - "foo", - "shaded.foo", - excludes = listOf("foo.bar"), - ) + val fooRelocator = SimpleRelocator("foo", "shaded.foo", excludes = listOf("foo.bar")) assertThat( - fooRelocator.applyToSourceContent( - asmRelocator.applyToSourceContent( - ioRelocator.applyToSourceContent(relocator.applyToSourceContent(sourceFile)), - ), - ), - ).isEqualTo(relocatedFile) + fooRelocator.applyToSourceContent( + asmRelocator.applyToSourceContent( + ioRelocator.applyToSourceContent(relocator.applyToSourceContent(sourceFile)) + ) + ) + ) + .isEqualTo(relocatedFile) } private companion object { - val sourceFile = """ + val sourceFile = + """ package org.apache.maven.hello; package org.objectweb.asm; @@ -355,9 +419,11 @@ class SimpleRelocatorTest { String relocationPath = "org/apache/maven/In"; } } - """.trimIndent() + """ + .trimIndent() - val relocatedFile = """ + val relocatedFile = + """ package com.acme.maven.hello; package aj.org.objectweb.asm; @@ -391,6 +457,7 @@ class SimpleRelocatorTest { String relocationPath = "com/acme/maven/In"; } } - """.trimIndent() + """ + .trimIndent() } } diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheLicenseResourceTransformerTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheLicenseResourceTransformerTest.kt index d3b292e30..887c479df 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheLicenseResourceTransformerTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheLicenseResourceTransformerTest.kt @@ -6,9 +6,11 @@ import assertk.assertions.isTrue import org.junit.jupiter.api.Test /** - * Modified from [org.apache.maven.plugins.shade.resource.ApacheLicenseResourceTransformerTest.java](https://github.com/apache/maven-shade-plugin/blob/master/src/test/java/org/apache/maven/plugins/shade/resource/ApacheLicenseResourceTransformerTest.java). + * Modified from + * [org.apache.maven.plugins.shade.resource.ApacheLicenseResourceTransformerTest.java](https://github.com/apache/maven-shade-plugin/blob/master/src/test/java/org/apache/maven/plugins/shade/resource/ApacheLicenseResourceTransformerTest.java). */ -class ApacheLicenseResourceTransformerTest : BaseTransformerTest() { +class ApacheLicenseResourceTransformerTest : + BaseTransformerTest() { init { setupTurkishLocale() diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheNoticeResourceTransformerTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheNoticeResourceTransformerTest.kt index 7f28e2582..f525b6f34 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheNoticeResourceTransformerTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ApacheNoticeResourceTransformerTest.kt @@ -11,7 +11,8 @@ import org.apache.tools.zip.ZipOutputStream import org.junit.jupiter.api.Test /** - * Modified from [org.apache.maven.plugins.shade.resource.ApacheNoticeResourceTransformerTest.java](https://github.com/apache/maven-shade-plugin/blob/master/src/test/java/org/apache/maven/plugins/shade/resource/ApacheNoticeResourceTransformerTest.java). + * Modified from + * [org.apache.maven.plugins.shade.resource.ApacheNoticeResourceTransformerTest.java](https://github.com/apache/maven-shade-plugin/blob/master/src/test/java/org/apache/maven/plugins/shade/resource/ApacheNoticeResourceTransformerTest.java). */ class ApacheNoticeResourceTransformerTest : BaseTransformerTest() { diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/AppendingTransformerTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/AppendingTransformerTest.kt index 514425372..7565aa624 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/AppendingTransformerTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/AppendingTransformerTest.kt @@ -6,7 +6,8 @@ import assertk.assertions.isTrue import org.junit.jupiter.api.Test /** - * Modified from [org.apache.maven.plugins.shade.resource.AppendingTransformerTest.java](https://github.com/apache/maven-shade-plugin/blob/master/src/test/java/org/apache/maven/plugins/shade/resource/AppendingTransformerTest.java). + * Modified from + * [org.apache.maven.plugins.shade.resource.AppendingTransformerTest.java](https://github.com/apache/maven-shade-plugin/blob/master/src/test/java/org/apache/maven/plugins/shade/resource/AppendingTransformerTest.java). */ class AppendingTransformerTest : BaseTransformerTest() { diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/BaseTransformerTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/BaseTransformerTest.kt index 2880784e9..5540141f2 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/BaseTransformerTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/BaseTransformerTest.kt @@ -27,32 +27,48 @@ abstract class BaseTransformerTest { @BeforeEach open fun beforeEach() { @Suppress("UNCHECKED_CAST") - val clazz = (this::class.java.genericSuperclass as ParameterizedType).actualTypeArguments.single() as Class + val clazz = + (this::class.java.genericSuperclass as ParameterizedType).actualTypeArguments.single() + as Class transformer = clazz.create(testObjectFactory) } companion object { fun ResourceTransformer.canTransformResource(path: String, file: File? = null): Boolean { - val element = object : FileTreeElement by noOpDelegate() { - private val _relativePath = RelativePath.parse(true, path) - override fun getPath(): String = _relativePath.pathString - override fun getRelativePath(): RelativePath = _relativePath - override fun getFile(): File = requireNotNull(file) { "File must be provided." } - } + val element = + object : FileTreeElement by noOpDelegate() { + private val _relativePath = RelativePath.parse(true, path) + + override fun getPath(): String = _relativePath.pathString + + override fun getRelativePath(): RelativePath = _relativePath + + override fun getFile(): File = requireNotNull(file) { "File must be provided." } + } return canTransformResource(element) } fun resourceContext(path: String, vararg relocators: Relocator): TransformerContext { - return TransformerContext(path = path, inputStream = requireResourceAsStream(path), relocators = relocators.toSet()) + return TransformerContext( + path = path, + inputStream = requireResourceAsStream(path), + relocators = relocators.toSet(), + ) } - fun textContext(path: String, text: String = "", vararg relocators: Relocator): TransformerContext { - return TransformerContext(path = path, inputStream = text.byteInputStream(), relocators = relocators.toSet()) + fun textContext( + path: String, + text: String = "", + vararg relocators: Relocator, + ): TransformerContext { + return TransformerContext( + path = path, + inputStream = text.byteInputStream(), + relocators = relocators.toSet(), + ) } - fun ResourceTransformer.transformToJar( - preserveFileTimestamps: Boolean = true, - ): JarPath { + fun ResourceTransformer.transformToJar(preserveFileTimestamps: Boolean = true): JarPath { val testableZipPath = createTempFile("testable-zip-file-", ".jar") ZipOutputStream(testableZipPath.outputStream()).use { zipOutputStream -> modifyOutputStream(zipOutputStream, preserveFileTimestamps) @@ -61,12 +77,11 @@ abstract class BaseTransformerTest { } /** - * NOTE: The Turkish locale has a usual case transformation for the letters "I" and "i", making it a prime - * choice to test for improper case-less string comparisons. + * NOTE: The Turkish locale has a usual case transformation for the letters "I" and "i", making + * it a prime choice to test for improper case-less string comparisons. */ fun setupTurkishLocale() { - @Suppress("DEPRECATION") - Locale.setDefault(Locale("tr")) + @Suppress("DEPRECATION") Locale.setDefault(Locale("tr")) } } } diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ComponentsXmlResourceTransformerTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ComponentsXmlResourceTransformerTest.kt index b503223b4..838cf710c 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ComponentsXmlResourceTransformerTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ComponentsXmlResourceTransformerTest.kt @@ -8,19 +8,22 @@ import org.custommonkey.xmlunit.XMLUnit import org.junit.jupiter.api.Test /** - * Modified from [org.apache.maven.plugins.shade.resource.ComponentsXmlResourceTransformerTest.java](https://github.com/apache/maven-shade-plugin/blob/master/src/test/java/org/apache/maven/plugins/shade/resource/ComponentsXmlResourceTransformerTest.java). + * Modified from + * [org.apache.maven.plugins.shade.resource.ComponentsXmlResourceTransformerTest.java](https://github.com/apache/maven-shade-plugin/blob/master/src/test/java/org/apache/maven/plugins/shade/resource/ComponentsXmlResourceTransformerTest.java). */ -class ComponentsXmlResourceTransformerTest : BaseTransformerTest() { +class ComponentsXmlResourceTransformerTest : + BaseTransformerTest() { @Test fun configurationMerging() { XMLUnit.setNormalizeWhitespace(true) transformer.transform(resourceContext("components-1.xml")) transformer.transform(resourceContext("components-2.xml")) - val diff = XMLUnit.compareXML( - requireResourceAsPath("components-expected.xml").readText(), - transformer.transformedResource.decodeToString(), - ) + val diff = + XMLUnit.compareXML( + requireResourceAsPath("components-expected.xml").readText(), + transformer.transformedResource.decodeToString(), + ) assertThat(diff.identical()).isTrue() } } diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/DeduplicatingResourceTransformerTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/DeduplicatingResourceTransformerTest.kt index eba93f87b..3b8e7b4cc 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/DeduplicatingResourceTransformerTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/DeduplicatingResourceTransformerTest.kt @@ -14,10 +14,10 @@ import org.junit.jupiter.api.io.TempDir import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.ValueSource -class DeduplicatingResourceTransformerTest : BaseTransformerTest() { +class DeduplicatingResourceTransformerTest : + BaseTransformerTest() { - @TempDir - lateinit var tempDir: Path + @TempDir lateinit var tempDir: Path private lateinit var file1: File private lateinit var file2: File @@ -31,15 +31,9 @@ class DeduplicatingResourceTransformerTest : BaseTransformerTest retain resource + assertThat(canTransformResource("multiple-contents", file1)).isFalse() + // same path, same file content --> skip resource + assertThat(canTransformResource("multiple-contents", file2)).isTrue() + // same path, different file content --> retain resource (even if it's a duplicate) + assertThat(canTransformResource("multiple-contents", file3)).isFalse() + + assertThat(canTransformResource("single-source", file1)).isFalse() + + assertThat(canTransformResource("same-content-twice", file1)).isFalse() + assertThat(canTransformResource("same-content-twice", file2)).isTrue() + + assertThat(canTransformResource("differing-content-2", file1)).isFalse() + assertThat(canTransformResource("differing-content-2", file3)).isFalse() + + assertThat(sources.keys) + .containsExactlyInAnyOrder( + "multiple-contents", + "single-source", + "same-content-twice", + "differing-content-2", + ) + + val pathInfosMultipleContents = sources.getValue("multiple-contents") + assertThat(pathInfosMultipleContents.failOnDuplicateContent).isEqualTo(exclusionCheck) + assertThat(pathInfosMultipleContents.uniqueContentCount()).isEqualTo(2) + assertThat(pathInfosMultipleContents.filesPerHash) + .containsOnly(hash1 to listOf(file1, file2), hash3 to listOf(file3)) + + val pathInfosSingleSource = sources.getValue("single-source") + assertThat(pathInfosSingleSource.failOnDuplicateContent).isTrue() + assertThat(pathInfosSingleSource.uniqueContentCount()).isEqualTo(1) + assertThat(pathInfosSingleSource.filesPerHash).containsOnly(hash1 to listOf(file1)) + + val pathInfosSameContentTwice = sources.getValue("same-content-twice") + assertThat(pathInfosSameContentTwice.failOnDuplicateContent).isTrue() + assertThat(pathInfosSameContentTwice.uniqueContentCount()).isEqualTo(1) + assertThat(pathInfosSameContentTwice.filesPerHash).containsOnly(hash1 to listOf(file1, file2)) + + val pathInfosDifferingContent2 = sources.getValue("differing-content-2") + assertThat(pathInfosDifferingContent2.failOnDuplicateContent).isTrue() + assertThat(pathInfosDifferingContent2.uniqueContentCount()).isEqualTo(2) + assertThat(pathInfosDifferingContent2.filesPerHash) + .containsOnly(hash1 to listOf(file1), hash3 to listOf(file3)) + + if (exclusionCheck) { + assertThat(duplicateContentViolations()) + .containsOnly( + "multiple-contents" to pathInfosMultipleContents, + "differing-content-2" to pathInfosDifferingContent2, + ) + } else { + assertThat(duplicateContentViolations()) + .containsOnly("differing-content-2" to pathInfosDifferingContent2) + } } - - // new path, new file content --> retain resource - assertThat(canTransformResource("multiple-contents", file1)).isFalse() - // same path, same file content --> skip resource - assertThat(canTransformResource("multiple-contents", file2)).isTrue() - // same path, different file content --> retain resource (even if it's a duplicate) - assertThat(canTransformResource("multiple-contents", file3)).isFalse() - - assertThat(canTransformResource("single-source", file1)).isFalse() - - assertThat(canTransformResource("same-content-twice", file1)).isFalse() - assertThat(canTransformResource("same-content-twice", file2)).isTrue() - - assertThat(canTransformResource("differing-content-2", file1)).isFalse() - assertThat(canTransformResource("differing-content-2", file3)).isFalse() - - assertThat(sources.keys).containsExactlyInAnyOrder( - "multiple-contents", - "single-source", - "same-content-twice", - "differing-content-2", - ) - - val pathInfosMultipleContents = sources.getValue("multiple-contents") - assertThat(pathInfosMultipleContents.failOnDuplicateContent).isEqualTo(exclusionCheck) - assertThat(pathInfosMultipleContents.uniqueContentCount()).isEqualTo(2) - assertThat(pathInfosMultipleContents.filesPerHash).containsOnly( - hash1 to listOf(file1, file2), - hash3 to listOf(file3), - ) - - val pathInfosSingleSource = sources.getValue("single-source") - assertThat(pathInfosSingleSource.failOnDuplicateContent).isTrue() - assertThat(pathInfosSingleSource.uniqueContentCount()).isEqualTo(1) - assertThat(pathInfosSingleSource.filesPerHash).containsOnly(hash1 to listOf(file1)) - - val pathInfosSameContentTwice = sources.getValue("same-content-twice") - assertThat(pathInfosSameContentTwice.failOnDuplicateContent).isTrue() - assertThat(pathInfosSameContentTwice.uniqueContentCount()).isEqualTo(1) - assertThat(pathInfosSameContentTwice.filesPerHash).containsOnly(hash1 to listOf(file1, file2)) - - val pathInfosDifferingContent2 = sources.getValue("differing-content-2") - assertThat(pathInfosDifferingContent2.failOnDuplicateContent).isTrue() - assertThat(pathInfosDifferingContent2.uniqueContentCount()).isEqualTo(2) - assertThat(pathInfosDifferingContent2.filesPerHash).containsOnly(hash1 to listOf(file1), hash3 to listOf(file3)) - - if (exclusionCheck) { - assertThat(duplicateContentViolations()).containsOnly( - "multiple-contents" to pathInfosMultipleContents, - "differing-content-2" to pathInfosDifferingContent2, - ) - } else { - assertThat(duplicateContentViolations()).containsOnly("differing-content-2" to pathInfosDifferingContent2) - } - } } diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/Log4j2PluginsCacheFileTransformerTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/Log4j2PluginsCacheFileTransformerTest.kt index 1c7305588..a6fecafd2 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/Log4j2PluginsCacheFileTransformerTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/Log4j2PluginsCacheFileTransformerTest.kt @@ -28,9 +28,11 @@ import org.junit.jupiter.params.provider.Arguments import org.junit.jupiter.params.provider.MethodSource /** - * Modified from [org.apache.logging.log4j.maven.plugins.shade.transformer.Log4j2PluginCacheFileTransformerTest.java](https://github.com/apache/logging-log4j-transform/blob/main/log4j-transform-maven-shade-plugin-extensions/src/test/java/org/apache/logging/log4j/maven/plugins/shade/transformer/Log4j2PluginCacheFileTransformerTest.java). + * Modified from + * [org.apache.logging.log4j.maven.plugins.shade.transformer.Log4j2PluginCacheFileTransformerTest.java](https://github.com/apache/logging-log4j-transform/blob/main/log4j-transform-maven-shade-plugin-extensions/src/test/java/org/apache/logging/log4j/maven/plugins/shade/transformer/Log4j2PluginCacheFileTransformerTest.java). */ -class Log4j2PluginsCacheFileTransformerTest : BaseTransformerTest() { +class Log4j2PluginsCacheFileTransformerTest : + BaseTransformerTest() { @Test fun canTransformResource() { assertThat(transformer.canTransformResource("")).isFalse() @@ -71,9 +73,7 @@ class Log4j2PluginsCacheFileTransformerTest : BaseTransformerTest while (true) { val jarEntry = inputStream.nextJarEntry @@ -94,9 +94,8 @@ class Log4j2PluginsCacheFileTransformerTest : BaseTransformerTest() { @Test - fun canTransformResource() = with(transformer) { - append("Name", "org/foo/bar/") - append("Sealed", true) + fun canTransformResource() = + with(transformer) { + append("Name", "org/foo/bar/") + append("Sealed", true) - assertThat(canTransformResource(MANIFEST_NAME)).isTrue() - assertThat(canTransformResource(MANIFEST_NAME.lowercase())).isTrue() - } + assertThat(canTransformResource(MANIFEST_NAME)).isTrue() + assertThat(canTransformResource(MANIFEST_NAME.lowercase())).isTrue() + } @Test fun hasTransformedResource() { @@ -34,31 +35,29 @@ class ManifestAppenderTransformerTest : BaseTransformerTest() { @Test - fun defaultIncludes() = with(transformer) { - assertThat(canTransformResource("META-INF/LICENSE")).isTrue() - assertThat(canTransformResource("META-INF/LICENSE.txt")).isTrue() - assertThat(canTransformResource("META-INF/LICENSE.md")).isTrue() - assertThat(canTransformResource("LICENSE")).isTrue() - assertThat(canTransformResource("LICENSE.txt")).isTrue() - assertThat(canTransformResource("LICENSE.md")).isTrue() - assertThat(canTransformResource("something else")).isFalse() - } + fun defaultIncludes() = + with(transformer) { + assertThat(canTransformResource("META-INF/LICENSE")).isTrue() + assertThat(canTransformResource("META-INF/LICENSE.txt")).isTrue() + assertThat(canTransformResource("META-INF/LICENSE.md")).isTrue() + assertThat(canTransformResource("LICENSE")).isTrue() + assertThat(canTransformResource("LICENSE.txt")).isTrue() + assertThat(canTransformResource("LICENSE.md")).isTrue() + assertThat(canTransformResource("something else")).isFalse() + } @Test - fun customIncludes() = with(transformer) { - include("META-INF/FOO") - exclude("META-INF/LICENSE*") - exclude("LICENSE*") - assertThat(canTransformResource("META-INF/FOO")).isTrue() - assertThat(canTransformResource("META-INF/LICENSE")).isFalse() - assertThat(canTransformResource("META-INF/LICENSE.txt")).isFalse() - assertThat(canTransformResource("META-INF/LICENSE.md")).isFalse() - assertThat(canTransformResource("LICENSE")).isFalse() - assertThat(canTransformResource("LICENSE.txt")).isFalse() - assertThat(canTransformResource("LICENSE.md")).isFalse() - assertThat(canTransformResource("something else")).isFalse() - } + fun customIncludes() = + with(transformer) { + include("META-INF/FOO") + exclude("META-INF/LICENSE*") + exclude("LICENSE*") + assertThat(canTransformResource("META-INF/FOO")).isTrue() + assertThat(canTransformResource("META-INF/LICENSE")).isFalse() + assertThat(canTransformResource("META-INF/LICENSE.txt")).isFalse() + assertThat(canTransformResource("META-INF/LICENSE.md")).isFalse() + assertThat(canTransformResource("LICENSE")).isFalse() + assertThat(canTransformResource("LICENSE.txt")).isFalse() + assertThat(canTransformResource("LICENSE.md")).isFalse() + assertThat(canTransformResource("something else")).isFalse() + } @Test - fun deduplicateLicenseTexts(@TempDir tempDir: Path) = with(transformer) { - transformInternal("license one".toByteArray()) - transformInternal("\r\nlicense one\r\n".toByteArray()) - transformInternal("\nlicense one\n".toByteArray()) - transformInternal(" license two".toByteArray()) - transformInternal("\r\n\n\r\n\n license two".toByteArray()) - transformInternal(" license two\r\n\n\r\n\n".toByteArray()) - transformInternal("license three".toByteArray()) + fun deduplicateLicenseTexts(@TempDir tempDir: Path) = + with(transformer) { + transformInternal("license one".toByteArray()) + transformInternal("\r\nlicense one\r\n".toByteArray()) + transformInternal("\nlicense one\n".toByteArray()) + transformInternal(" license two".toByteArray()) + transformInternal("\r\n\n\r\n\n license two".toByteArray()) + transformInternal(" license two\r\n\n\r\n\n".toByteArray()) + transformInternal("license three".toByteArray()) - val artifactLicenseFile = tempDir.resolve("artifact-license").toFile() - artifactLicenseFile.writeText("artifact license file content") - artifactLicense.set(artifactLicenseFile) + val artifactLicenseFile = tempDir.resolve("artifact-license").toFile() + artifactLicenseFile.writeText("artifact license file content") + artifactLicense.set(artifactLicenseFile) - assertThat(elements).containsExactlyInAnyOrder("license one", " license two", "license three") + assertThat(elements) + .containsExactlyInAnyOrder("license one", " license two", "license three") - assertThat(buildLicense()).isEqualTo( - """ - SPDX-License-Identifier: Apache-2.0 - artifact license file content + assertThat(buildLicense()) + .isEqualTo( + """ + SPDX-License-Identifier: Apache-2.0 + artifact license file content - ------------------------------------------------------------------------------------------------------------------------ + ------------------------------------------------------------------------------------------------------------------------ - This artifact includes dependencies with the following licenses: - ---------------------------------------------------------------- + This artifact includes dependencies with the following licenses: + ---------------------------------------------------------------- - license one + license one - ------------------------------------------------------------------------------------------------------------------------ + ------------------------------------------------------------------------------------------------------------------------ - license two + license two - ------------------------------------------------------------------------------------------------------------------------ + ------------------------------------------------------------------------------------------------------------------------ - license three - """.trimIndent(), - ) - } + license three + """ + .trimIndent() + ) + } @Test - fun singleAdditionalLicense(@TempDir tempDir: Path) = with(transformer) { - transformInternal("license one".toByteArray()) + fun singleAdditionalLicense(@TempDir tempDir: Path) = + with(transformer) { + transformInternal("license one".toByteArray()) - val artifactLicenseFile = tempDir.resolve("artifact-license").toFile() - artifactLicenseFile.writeText("artifact license file content") - artifactLicense.set(artifactLicenseFile) + val artifactLicenseFile = tempDir.resolve("artifact-license").toFile() + artifactLicenseFile.writeText("artifact license file content") + artifactLicense.set(artifactLicenseFile) - assertThat(elements).containsExactlyInAnyOrder("license one") + assertThat(elements).containsExactlyInAnyOrder("license one") - assertThat(buildLicense()).isEqualTo( - """ - SPDX-License-Identifier: Apache-2.0 - artifact license file content + assertThat(buildLicense()) + .isEqualTo( + """ + SPDX-License-Identifier: Apache-2.0 + artifact license file content - ------------------------------------------------------------------------------------------------------------------------ + ------------------------------------------------------------------------------------------------------------------------ - This artifact includes dependencies with the following licenses: - ---------------------------------------------------------------- + This artifact includes dependencies with the following licenses: + ---------------------------------------------------------------- - license one - """.trimIndent(), - ) - } + license one + """ + .trimIndent() + ) + } @Test - fun noAdditionalLicenses(@TempDir tempDir: Path) = with(transformer) { - val artifactLicenseFile = tempDir.resolve("artifact-license").toFile() - artifactLicenseFile.writeText("artifact license file content") - artifactLicense.set(artifactLicenseFile) - - assertThat(elements).isEmpty() - - assertThat(buildLicense()).isEqualTo( - """ - SPDX-License-Identifier: Apache-2.0 - artifact license file content - """.trimIndent(), - ) - } + fun noAdditionalLicenses(@TempDir tempDir: Path) = + with(transformer) { + val artifactLicenseFile = tempDir.resolve("artifact-license").toFile() + artifactLicenseFile.writeText("artifact license file content") + artifactLicense.set(artifactLicenseFile) + + assertThat(elements).isEmpty() + + assertThat(buildLicense()) + .isEqualTo( + """ + SPDX-License-Identifier: Apache-2.0 + artifact license file content + """ + .trimIndent() + ) + } @Test - fun noSpdxId(@TempDir tempDir: Path) = with(transformer) { - artifactLicenseSpdxId.unsetConvention() + fun noSpdxId(@TempDir tempDir: Path) = + with(transformer) { + artifactLicenseSpdxId.unsetConvention() - val artifactLicenseFile = tempDir.resolve("artifact-license").toFile() - artifactLicenseFile.writeText("artifact license file content") - artifactLicense.set(artifactLicenseFile) + val artifactLicenseFile = tempDir.resolve("artifact-license").toFile() + artifactLicenseFile.writeText("artifact license file content") + artifactLicense.set(artifactLicenseFile) - assertThat(elements).isEmpty() + assertThat(elements).isEmpty() - assertThat(buildLicense()).isEqualTo( - "artifact license file content", - ) - } + assertThat(buildLicense()).isEqualTo("artifact license file content") + } } diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.kt index f6e65b7b0..bd93a42ca 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/PropertiesFileTransformerTest.kt @@ -44,9 +44,11 @@ class PropertiesFileTransformerTest : BaseTransformerTest, charset: Charset = Charsets.ISO_8859_1): TransformerContext { + fun context( + path: String, + input: Map, + charset: Charset = Charsets.ISO_8859_1, + ): TransformerContext { val properties = Properties().apply { putAll(input) } return TransformerContext(path, properties.inputStream(charset)) } @JvmStatic - fun pathProvider() = listOf( - Arguments.of("foo.properties", true), - Arguments.of("foo/bar.properties", true), - Arguments.of("foo.props", false), - ) + fun pathProvider() = + listOf( + Arguments.of("foo.properties", true), + Arguments.of("foo/bar.properties", true), + Arguments.of("foo.props", false), + ) @JvmStatic - fun charsetProvider() = listOf( - Arguments.of( - "utf8.properties", - "utf-8", - mapOf("foo" to "传傳磨宿说説"), - mapOf("foo" to "传傳磨宿说説"), - ), - ) + fun charsetProvider() = + listOf( + Arguments.of("utf8.properties", "utf-8", mapOf("foo" to "传傳磨宿说説"), mapOf("foo" to "传傳磨宿说説")) + ) @JvmStatic - fun transformConfigWithPathsProvider() = listOf( - Arguments.of( - "f.properties", - listOf("f.properties"), - mapOf("foo" to "foo"), - mapOf("foo" to "bar"), - mapOf("foo" to "foo"), - ), - Arguments.of( - "foo.properties", - listOf(".*.properties"), - mapOf("foo" to "foo"), - mapOf("foo" to "bar"), - mapOf("foo" to "foo"), - ), - Arguments.of( - "foo.properties", - listOf(".*bar"), - mapOf("foo" to "foo"), - mapOf("foo" to "bar"), - emptyMap(), - ), - Arguments.of( - "foo.properties", - emptyList(), - mapOf("foo" to "foo"), - mapOf("foo" to "bar"), - mapOf("foo" to "foo"), - ), - ) + fun transformConfigWithPathsProvider() = + listOf( + Arguments.of( + "f.properties", + listOf("f.properties"), + mapOf("foo" to "foo"), + mapOf("foo" to "bar"), + mapOf("foo" to "foo"), + ), + Arguments.of( + "foo.properties", + listOf(".*.properties"), + mapOf("foo" to "foo"), + mapOf("foo" to "bar"), + mapOf("foo" to "foo"), + ), + Arguments.of( + "foo.properties", + listOf(".*bar"), + mapOf("foo" to "foo"), + mapOf("foo" to "bar"), + emptyMap(), + ), + Arguments.of( + "foo.properties", + emptyList(), + mapOf("foo" to "foo"), + mapOf("foo" to "bar"), + mapOf("foo" to "foo"), + ), + ) @JvmStatic - fun transformConfigWithMappingsProvider() = listOf( - Arguments.of( - "f.properties", - mapOf("f.properties" to mapOf("mergeStrategy" to "first")), - mapOf("foo" to "foo"), - mapOf("foo" to "bar"), - mapOf("foo" to "foo"), - ), - Arguments.of( - "f.properties", - mapOf("f.properties" to mapOf("mergeStrategy" to "latest")), - mapOf("foo" to "foo"), - mapOf("foo" to "bar"), - mapOf("foo" to "bar"), - ), - Arguments.of( - "f.properties", - mapOf("f.properties" to mapOf("mergeStrategy" to "append")), - mapOf("foo" to "foo"), - mapOf("foo" to "bar"), - mapOf("foo" to "foo,bar"), - ), - Arguments.of( - "f.properties", - mapOf("f.properties" to mapOf("mergeStrategy" to "append", "mergeSeparator" to ";")), - mapOf("foo" to "foo"), - mapOf("foo" to "bar"), - mapOf("foo" to "foo;bar"), - ), - Arguments.of( - "foo.properties", - mapOf(".*.properties" to mapOf("mergeStrategy" to "first")), - mapOf("foo" to "foo"), - mapOf("foo" to "bar"), - mapOf("foo" to "foo"), - ), - Arguments.of( - "foo.properties", - mapOf(".*bar" to mapOf("mergeStrategy" to "first")), - mapOf("foo" to "foo"), - mapOf("foo" to "bar"), - emptyMap(), - ), - ) + fun transformConfigWithMappingsProvider() = + listOf( + Arguments.of( + "f.properties", + mapOf("f.properties" to mapOf("mergeStrategy" to "first")), + mapOf("foo" to "foo"), + mapOf("foo" to "bar"), + mapOf("foo" to "foo"), + ), + Arguments.of( + "f.properties", + mapOf("f.properties" to mapOf("mergeStrategy" to "latest")), + mapOf("foo" to "foo"), + mapOf("foo" to "bar"), + mapOf("foo" to "bar"), + ), + Arguments.of( + "f.properties", + mapOf("f.properties" to mapOf("mergeStrategy" to "append")), + mapOf("foo" to "foo"), + mapOf("foo" to "bar"), + mapOf("foo" to "foo,bar"), + ), + Arguments.of( + "f.properties", + mapOf("f.properties" to mapOf("mergeStrategy" to "append", "mergeSeparator" to ";")), + mapOf("foo" to "foo"), + mapOf("foo" to "bar"), + mapOf("foo" to "foo;bar"), + ), + Arguments.of( + "foo.properties", + mapOf(".*.properties" to mapOf("mergeStrategy" to "first")), + mapOf("foo" to "foo"), + mapOf("foo" to "bar"), + mapOf("foo" to "foo"), + ), + Arguments.of( + "foo.properties", + mapOf(".*bar" to mapOf("mergeStrategy" to "first")), + mapOf("foo" to "foo"), + mapOf("foo" to "bar"), + emptyMap(), + ), + ) @JvmStatic - fun transformConfigProvider() = listOf( - Arguments.of( - "f.properties", - "first", - "", - mapOf("foo" to "foo"), - mapOf("foo" to "bar"), - mapOf("foo" to "foo"), - mapOf>(), - ), - Arguments.of( - "f.properties", - "latest", - "", - mapOf("foo" to "foo"), - mapOf("foo" to "bar"), - mapOf("foo" to "bar"), - mapOf>(), - ), - Arguments.of( - "f.properties", - "append", - ",", - mapOf("foo" to "foo"), - mapOf("foo" to "bar"), - mapOf("foo" to "foo,bar"), - mapOf>(), - ), - Arguments.of( - "f.properties", - "append", - ";", - mapOf("foo" to "foo"), - mapOf("foo" to "bar"), - mapOf("foo" to "foo;bar"), - mapOf>(), - ), - Arguments.of( - "f.properties", - "fail", - ";", - mapOf("foo" to "foo"), - mapOf("foo" to "bar"), - mapOf("foo" to "foo"), - mapOf("f.properties" to mapOf("foo" to 2)), - ), - ) + fun transformConfigProvider() = + listOf( + Arguments.of( + "f.properties", + "first", + "", + mapOf("foo" to "foo"), + mapOf("foo" to "bar"), + mapOf("foo" to "foo"), + mapOf>(), + ), + Arguments.of( + "f.properties", + "latest", + "", + mapOf("foo" to "foo"), + mapOf("foo" to "bar"), + mapOf("foo" to "bar"), + mapOf>(), + ), + Arguments.of( + "f.properties", + "append", + ",", + mapOf("foo" to "foo"), + mapOf("foo" to "bar"), + mapOf("foo" to "foo,bar"), + mapOf>(), + ), + Arguments.of( + "f.properties", + "append", + ";", + mapOf("foo" to "foo"), + mapOf("foo" to "bar"), + mapOf("foo" to "foo;bar"), + mapOf>(), + ), + Arguments.of( + "f.properties", + "fail", + ";", + mapOf("foo" to "foo"), + mapOf("foo" to "bar"), + mapOf("foo" to "foo"), + mapOf("f.properties" to mapOf("foo" to 2)), + ), + ) @JvmStatic - fun keyTransformerProvider() = listOf( - Arguments.of( - "foo.properties", - { key: String -> key }, - mapOf("foo" to "bar"), - mapOf("FOO" to "baz"), - mapOf("foo" to "bar", "FOO" to "baz"), - ), - Arguments.of( - "foo.properties", - { key: String -> key.uppercase() }, - mapOf("foo" to "bar"), - mapOf("FOO" to "baz"), - mapOf("FOO" to "bar,baz"), - ), - Arguments.of( - "foo.properties", - { key: String -> "bar.${key.lowercase()}" }, - mapOf("foo" to "bar"), - mapOf("FOO" to "baz"), - mapOf("bar.foo" to "bar,baz"), - ), - Arguments.of( - "foo.properties", - { key: String -> key.replaceFirst(Regex("^(foo)"), "bar.$1") }, - mapOf("foo" to "bar"), - mapOf("FOO" to "baz"), - mapOf("bar.foo" to "bar", "FOO" to "baz"), - ), - ) + fun keyTransformerProvider() = + listOf( + Arguments.of( + "foo.properties", + { key: String -> key }, + mapOf("foo" to "bar"), + mapOf("FOO" to "baz"), + mapOf("foo" to "bar", "FOO" to "baz"), + ), + Arguments.of( + "foo.properties", + { key: String -> key.uppercase() }, + mapOf("foo" to "bar"), + mapOf("FOO" to "baz"), + mapOf("FOO" to "bar,baz"), + ), + Arguments.of( + "foo.properties", + { key: String -> "bar.${key.lowercase()}" }, + mapOf("foo" to "bar"), + mapOf("FOO" to "baz"), + mapOf("bar.foo" to "bar,baz"), + ), + Arguments.of( + "foo.properties", + { key: String -> key.replaceFirst(Regex("^(foo)"), "bar.$1") }, + mapOf("foo" to "bar"), + mapOf("FOO" to "baz"), + mapOf("bar.foo" to "bar", "FOO" to "baz"), + ), + ) } } diff --git a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerTest.kt b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerTest.kt index dfd37491e..f41f3fa4c 100644 --- a/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerTest.kt +++ b/src/test/kotlin/com/github/jengelman/gradle/plugins/shadow/transformers/ServiceFileTransformerTest.kt @@ -20,7 +20,8 @@ import org.junit.jupiter.params.provider.Arguments import org.junit.jupiter.params.provider.MethodSource /** - * Modified from [org.apache.maven.plugins.shade.resource.ServiceResourceTransformerTest.java](https://github.com/apache/maven-shade-plugin/blob/master/src/test/java/org/apache/maven/plugins/shade/resource/ServiceResourceTransformerTest.java). + * Modified from + * [org.apache.maven.plugins.shade.resource.ServiceResourceTransformerTest.java](https://github.com/apache/maven-shade-plugin/blob/master/src/test/java/org/apache/maven/plugins/shade/resource/ServiceResourceTransformerTest.java). */ class ServiceFileTransformerTest : BaseTransformerTest() { private lateinit var tempJar: Path @@ -149,21 +150,23 @@ class ServiceFileTransformerTest : BaseTransformerTest() private companion object { @JvmStatic - fun resourceProvider() = listOf( - // path, exclude, expected - Arguments.of("META-INF/services/java.sql.Driver", false, true), - Arguments.of("META-INF/services/io.dropwizard.logging.AppenderFactory", false, true), - Arguments.of("META-INF/services/org.apache.maven.Shade", true, false), - Arguments.of("META-INF/services/foo/bar/moo.goo.Zoo", false, true), - Arguments.of("foo/bar.properties", false, false), - Arguments.of("foo.props", false, false), - ) + fun resourceProvider() = + listOf( + // path, exclude, expected + Arguments.of("META-INF/services/java.sql.Driver", false, true), + Arguments.of("META-INF/services/io.dropwizard.logging.AppenderFactory", false, true), + Arguments.of("META-INF/services/org.apache.maven.Shade", true, false), + Arguments.of("META-INF/services/foo/bar/moo.goo.Zoo", false, true), + Arguments.of("foo/bar.properties", false, false), + Arguments.of("foo.props", false, false), + ) @JvmStatic - fun serviceFileProvider() = listOf( - // path, input1, input2, output - Arguments.of("META-INF/services/com.acme.Foo", "foo", "bar", "foo\nbar"), - Arguments.of("META-INF/services/com.acme.Bar", "foo\nbar", "zoo", "foo\nbar\nzoo"), - ) + fun serviceFileProvider() = + listOf( + // path, input1, input2, output + Arguments.of("META-INF/services/com.acme.Foo", "foo", "bar", "foo\nbar"), + Arguments.of("META-INF/services/com.acme.Bar", "foo\nbar", "zoo", "foo\nbar\nzoo"), + ) } } diff --git a/src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/GradleRunner.kt b/src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/GradleRunner.kt index 761f4522d..749af3cb9 100644 --- a/src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/GradleRunner.kt +++ b/src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/GradleRunner.kt @@ -9,51 +9,56 @@ import org.gradle.testkit.runner.BuildResult import org.gradle.testkit.runner.GradleRunner private val testKitDir by lazy { - val gradleUserHome = System.getenv("GRADLE_USER_HOME") - ?: Path(System.getProperty("user.home"), ".gradle").absolutePathString() + val gradleUserHome = + System.getenv("GRADLE_USER_HOME") + ?: Path(System.getProperty("user.home"), ".gradle").absolutePathString() Path(gradleUserHome, "testkit") } private val testGradleVersion by lazy { - System.getProperty("TEST_GRADLE_VERSION") ?: error("TEST_GRADLE_VERSION system property is not set.") + System.getProperty("TEST_GRADLE_VERSION") + ?: error("TEST_GRADLE_VERSION system property is not set.") } -val commonGradleArgs = setOf( - "--configuration-cache", - "--build-cache", - "--parallel", - "--stacktrace", - // https://docs.gradle.org/current/userguide/configuration_cache.html#config_cache:usage:parallel - "-Dorg.gradle.configuration-cache.parallel=true", -) +val commonGradleArgs = + setOf( + "--configuration-cache", + "--build-cache", + "--parallel", + "--stacktrace", + // https://docs.gradle.org/current/userguide/configuration_cache.html#config_cache:usage:parallel + "-Dorg.gradle.configuration-cache.parallel=true", + ) fun gradleRunner( projectDir: Path, arguments: Iterable, warningsAsErrors: Boolean = true, block: GradleRunner.() -> Unit = {}, -): GradleRunner = GradleRunner.create() - .withGradleVersion(testGradleVersion) - .forwardOutput() - .withPluginClasspath() - .withTestKitDir(testKitDir.toFile()) - .withArguments( - buildList { - addAll(arguments) - if (warningsAsErrors) { - add("--warning-mode=fail") +): GradleRunner = + GradleRunner.create() + .withGradleVersion(testGradleVersion) + .forwardOutput() + .withPluginClasspath() + .withTestKitDir(testKitDir.toFile()) + .withArguments( + buildList { + addAll(arguments) + if (warningsAsErrors) { + add("--warning-mode=fail") + } } - }, - ) - .withProjectDir(projectDir.toFile()) - .apply(block) + ) + .withProjectDir(projectDir.toFile()) + .apply(block) fun BuildResult.assertNoDeprecationWarnings() = apply { - assertThat(output).doesNotContain( - "has been deprecated and is scheduled to be removed in Gradle", - "has been deprecated. This is scheduled to be removed in Gradle", - "will fail with an error in Gradle", - ) + assertThat(output) + .doesNotContain( + "has been deprecated and is scheduled to be removed in Gradle", + "has been deprecated. This is scheduled to be removed in Gradle", + "will fail with an error in Gradle", + ) } // TODO: https://youtrack.jetbrains.com/issue/KT-78620 diff --git a/src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/JarPath.kt b/src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/JarPath.kt index 41426f009..60302fc1e 100644 --- a/src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/JarPath.kt +++ b/src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/JarPath.kt @@ -20,11 +20,10 @@ import kotlin.io.path.inputStream * be delegated to [JarPath] type. */ @Suppress("JavaDefaultMethodsNotOverriddenByDelegation") -class JarPath(val path: Path) : - JarFile(path.toFile()), - Path by path { +class JarPath(val path: Path) : JarFile(path.toFile()), Path by path { - val mainAttrSize: Int get() = manifest.mainAttributes.size + val mainAttrSize: Int + get() = manifest.mainAttributes.size fun getMainAttr(name: String): String? { return manifest.mainAttributes.getValue(name) @@ -42,16 +41,19 @@ fun ZipFile.getContent(entryName: String): String { } fun ZipFile.getStream(entryName: String): InputStream { - val entry = checkNotNull(getEntry(entryName)) { "Entry $entryName not found in all entries: ${entries().toList()}" } + val entry = + checkNotNull(getEntry(entryName)) { + "Entry $entryName not found in all entries: ${entries().toList()}" + } return getInputStream(entry) } fun Assert.getContent(entryName: String) = transform { it.getContent(entryName) } /** - * Scans the jar file for all entries that match the specified [entryName]. - * Unlike [getContent] or [getStream], which return only one of the matching entries - * (which one is undefined), this function returns all matching entries. + * Scans the jar file for all entries that match the specified [entryName]. Unlike [getContent] or + * [getStream], which return only one of the matching entries (which one is undefined), this + * function returns all matching entries. */ fun Assert.getContents(entryName: String) = transform { actual -> JarInputStream(actual.path.inputStream()).use { jarInput -> @@ -70,38 +72,40 @@ fun Assert.getContents(entryName: String) = transform { actual -> fun Assert.getMainAttr(name: String) = transform { it.getMainAttr(name) } /** - * Ensures the JAR contains at least the specified entries. - * Commonly used with [containsNone] to verify additional constraints. + * Ensures the JAR contains at least the specified entries. Commonly used with [containsNone] to + * verify additional constraints. */ fun Assert.containsAtLeast(vararg entries: String) = toEntries().containsAtLeast(*entries) /** - * Ensures the JAR does not contain any of the specified entries. - * Commonly used with [containsAtLeast] for stricter checks. + * Ensures the JAR does not contain any of the specified entries. Commonly used with + * [containsAtLeast] for stricter checks. */ fun Assert.containsNone(vararg entries: String) = toEntries().containsNone(*entries) /** - * Ensures the JAR contains only the specified entries. - * Used alone, without [containsAtLeast] or [containsNone]. + * Ensures the JAR contains only the specified entries. Used alone, without [containsAtLeast] or + * [containsNone]. */ fun Assert.containsOnly(vararg entries: String) = toEntries().containsOnly(*entries) /** - * Ensures the JAR contains exactly the specified entries, including duplicates, in any order. - * Used alone, without [containsAtLeast] or [containsNone]. + * Ensures the JAR contains exactly the specified entries, including duplicates, in any order. Used + * alone, without [containsAtLeast] or [containsNone]. */ -fun Assert.containsExactlyInAnyOrder(vararg entries: String) = transform { actual -> - ZipInputStream(actual.path.inputStream()).use { jarInput -> - val allEntries = mutableListOf() - while (true) { - val entry = jarInput.nextEntry ?: break - allEntries.add(entry.name) - jarInput.closeEntry() +fun Assert.containsExactlyInAnyOrder(vararg entries: String) = + transform { actual -> + ZipInputStream(actual.path.inputStream()).use { jarInput -> + val allEntries = mutableListOf() + while (true) { + val entry = jarInput.nextEntry ?: break + allEntries.add(entry.name) + jarInput.closeEntry() + } + allEntries + } } - allEntries - } -}.containsExactlyInAnyOrder(*entries) + .containsExactlyInAnyOrder(*entries) private fun Assert.toEntries() = transform { actual -> actual.entries().toList().map { it.name } diff --git a/src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/Resource.kt b/src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/Resource.kt index 0f20ebee3..88a5fbad3 100644 --- a/src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/Resource.kt +++ b/src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/Resource.kt @@ -11,8 +11,9 @@ fun requireResourceAsStream(name: String): InputStream { } fun requireResourceAsPath(name: String): Path { - val resource = Utils::class.java.classLoader.getResource(name) - ?: throw NoSuchFileException("Resource $name not found.") + val resource = + Utils::class.java.classLoader.getResource(name) + ?: throw NoSuchFileException("Resource $name not found.") return resource.toURI().toPath() } diff --git a/src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/Strings.kt b/src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/Strings.kt index 8dac7b1dd..0444763ab 100644 --- a/src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/Strings.kt +++ b/src/testKit/kotlin/com/github/jengelman/gradle/plugins/shadow/testkit/Strings.kt @@ -2,8 +2,10 @@ package com.github.jengelman.gradle.plugins.shadow.testkit import java.nio.file.FileSystems -val String.invariantEolString: String get() = replace(System.lineSeparator(), "\n") +val String.invariantEolString: String + get() = replace(System.lineSeparator(), "\n") -val String.variantSeparatorsPathString: String get() = replace("/", fileSystem.separator) +val String.variantSeparatorsPathString: String + get() = replace("/", fileSystem.separator) private val fileSystem = FileSystems.getDefault()