Repository: GradleUp/shadow
Pull request #1189 (2025-01-25 02:50:02)

Declare manifest attributes in sample task
Refs #516.



Patch:
diff --git a/src/docs/custom-tasks/README.md b/src/docs/custom-tasks/README.md
index 23559d03..bbb7a0eb 100644
--- a/src/docs/custom-tasks/README.md
+++ b/src/docs/custom-tasks/README.md
@@ -14,9 +14,15 @@ def testShadowJar = tasks.register('testShadowJar', com.github.jengelman.gradle.
   archiveClassifier = "tests"
   from sourceSets.test.output
   configurations = [project.configurations.testRuntimeClasspath]
+
+  manifest {
+    // Optionally, set the main class for the JAR.
+    attributes 'Main-Class': 'test.Main'
+    // You can also set other attributes here.
+  }
 }
 
-// Optionally, make the `assemble` task depend on the new task
+// Optionally, make the `assemble` task depend on the new task.
 tasks.named('assemble') {
   dependsOn testShadowJar
 }


Test patch:
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 a7c139d1..795187f6 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
@@ -159,19 +159,22 @@ abstract class BasePluginTest {
   }
 
   fun writeMainClass(
+    sourceSet: String = "main",
     withImports: Boolean = false,
     className: String = "Main",
   ) {
     val imports = if (withImports) "import junit.framework.Test;" else ""
     val classRef = if (withImports) "\"Refs: \" + Test.class.getName()" else "\"Refs: null\""
-
-    path("src/main/java/shadow/$className.java").writeText(
+    path("src/$sourceSet/java/shadow/$className.java").writeText(
       """
         package shadow;
         $imports
         public class $className {
           public static void main(String[] args) {
-            String content = String.format("Hello, World! (%s) from $className", args);
+            if (args.length == 0) {
+              throw new IllegalArgumentException("No arguments provided.");
+            }
+            String content = String.format("Hello, World! (%s) from $className", (Object[]) args);
             System.out.println(content);
             System.out.println($classRef);
           }
diff --git a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/JavaPluginTest.kt b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/JavaPluginTest.kt
index 001ff582..64eab5d7 100644
--- a/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/JavaPluginTest.kt
+++ b/src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/JavaPluginTest.kt
@@ -18,6 +18,7 @@ import com.github.jengelman.gradle.plugins.shadow.util.containsEntries
 import com.github.jengelman.gradle.plugins.shadow.util.doesNotContainEntries
 import com.github.jengelman.gradle.plugins.shadow.util.getMainAttr
 import com.github.jengelman.gradle.plugins.shadow.util.isRegular
+import com.github.jengelman.gradle.plugins.shadow.util.runProcess
 import kotlin.io.path.appendText
 import kotlin.io.path.readText
 import kotlin.io.path.writeText
@@ -491,6 +492,7 @@ class JavaPluginTest : BasePluginTest() {
   )
   @Test
   fun canRegisterCustomShadowJarTask() {
+    writeMainClass(sourceSet = "test", withImports = true)
     val testShadowJarTask = "testShadowJar"
     projectScriptPath.appendText(
       """
@@ -503,6 +505,9 @@ class JavaPluginTest : BasePluginTest() {
           archiveClassifier = "tests"
           from sourceSets.test.output
           configurations = [project.configurations.testRuntimeClasspath]
+          manifest {
+            attributes 'Main-Class': 'shadow.Main'
+          }
         }
       """.trimIndent(),
     )
@@ -510,8 +515,20 @@ class JavaPluginTest : BasePluginTest() {
     val result = run(testShadowJarTask)
 
     assertThat(result).taskOutcomeEquals(":$testShadowJarTask", SUCCESS)
-    val junitEntry = jarPath("build/libs/shadow-1.0-tests.jar").use { it.getEntry("junit") }
-    assertThat(junitEntry).isNotNull()
+    assertThat(jarPath("build/libs/shadow-1.0-tests.jar")).useAll {
+      containsEntries(
+        "junit/framework/Test.class",
+        "shadow/Main.class",
+      )
+      getMainAttr("Main-Class").isNotNull()
+    }
+
+    val pathString = path("build/libs/shadow-1.0-tests.jar").toString()
+    val runningOutput = runProcess("java", "-jar", pathString, "foo")
+    assertThat(runningOutput).contains(
+      "Hello, World! (foo) from Main",
+      "Refs: junit.framework.Test",
+    )
   }
 
   @Test