[Git][java-team/gradle-debian-helper][master] 7 commits: Don't fail on a project applying the java plugin without building a jar or a javadoc

Emmanuel Bourg (@ebourg) gitlab at salsa.debian.org
Wed Sep 30 14:12:07 BST 2026



Emmanuel Bourg pushed to branch master at Debian Java Maintainers / gradle-debian-helper


Commits:
eebdba93 by Emmanuel Bourg at 2026-09-30T14:44:47+02:00
Don't fail on a project applying the java plugin without building a jar or a javadoc

- - - - -
8c8eae4c by Emmanuel Bourg at 2026-09-30T14:44:57+02:00
dh_auto_build now detects the build.gradle.kts and settings.gradle[.kts] scripts

- - - - -
31f0f870 by Emmanuel Bourg at 2026-09-30T15:02:45+02:00
New parser for the debian/gradle.ignoreRules file

- - - - -
59c3c4e7 by Emmanuel Bourg at 2026-09-30T15:02:45+02:00
Ignore the configuration blocks listed in debian/gradle.ignoreRules

- - - - -
25e00d2b by Emmanuel Bourg at 2026-09-30T15:02:45+02:00
New example of an ignored configuration block in the test project

- - - - -
8aa87bad by Emmanuel Bourg at 2026-09-30T15:02:45+02:00
Require the Gradle and Kotlin DSL versions implementing the ignore rules

- - - - -
7695dd78 by Emmanuel Bourg at 2026-09-30T15:06:56+02:00
Upload to unstable

- - - - -


14 changed files:

- README.txt
- debian/changelog
- debian/control
- + debian/maven.rules
- gradle-helper-hook/pom.xml
- + gradle-helper-hook/src/main/java/org/debian/gradle/plugin/IgnoreRules.java
- + gradle-helper-hook/src/test/java/org/debian/gradle/plugin/IgnoreRulesTest.java
- gradle-helper-plugin/pom.xml
- gradle-helper-plugin/src/main/java/org/debian/gradle/DebianHelperPlugin.java
- + gradle-helper-plugin/src/main/java/org/debian/gradle/IgnoredExtension.java
- gradle-helper-plugin/src/main/perl/gradle.pm
- test-project/build.gradle
- + test-project/debian/gradle.ignoreRules
- test-project/init.gradle


Changes:

=====================================
README.txt
=====================================
@@ -8,6 +8,7 @@ It consists in:
        (/usr/share/maven-repo). The resolver uses the same Maven rule files that
        maven-debian-helper and maven-repo-helper employ (debian/maven.rules,
        debian/maven.ignoreRules).
+     * Ignore the plugins and blocks declared in debian/gradle.ignoreRules
      * Generate Maven POMs for being read by maven-repo-helper
      * Let javadoc link to the local Javadoc of default-jdk
  * a build listener displaying a message periodically to prevent the builders from killing Gradle on slow architectures.
@@ -26,13 +27,15 @@ Usage
 
 3. Create debian/maven.rules and/or debian.maven.ignoreRules with the dependency rules
 
-4. For building only some subprojects and ignoring the others,
+4. Create debian/gradle.ignoreRules and declare the ignored plugins
+
+5. For building only some subprojects and ignoring the others,
    pass Gradle parameters to dh_auto_build:
 
     override_dh_auto_build:
             dh_auto_build -- :project1:jar :project2:jar
 
-5. For running tests, override dh_auto_test and call dh_auto_build:
+6. For running tests, override dh_auto_test and call dh_auto_build:
 
     override_dh_auto_test:
             dh_auto_build -- check


=====================================
debian/changelog
=====================================
@@ -1,3 +1,14 @@
+gradle-debian-helper (3.0) unstable; urgency=medium
+
+  * Ignore the configuration blocks listed in debian/gradle.ignoreRules
+  * Require the Gradle and Kotlin DSL versions implementing the ignore rules
+  * Don't fail on a project applying the java plugin without building a jar
+    or a javadoc
+  * dh_auto_build now detects the build.gradle.kts and settings.gradle[.kts]
+    scripts
+
+ -- Emmanuel Bourg <ebourg at apache.org>  Wed, 30 Sep 2026 15:02:54 +0200
+
 gradle-debian-helper (2.5) unstable; urgency=medium
 
   * New dependency on libgradle-kotlin-dsl-java to build Kotlin DSL projects


=====================================
debian/control
=====================================
@@ -8,6 +8,7 @@ Build-Depends:
  debhelper-compat (= 13),
  default-jdk-headless | default-jdk,
  gradle (>= 4.5),
+ junit4,
  maven-debian-helper
 Standards-Version: 4.7.4
 Vcs-Git: https://salsa.debian.org/java-team/gradle-debian-helper.git
@@ -17,8 +18,8 @@ Package: gradle-debian-helper
 Architecture: all
 Depends:
  default-jre-headless | java7-runtime-headless,
- gradle (>= 4.5),
- libgradle-kotlin-dsl-java (>= 0.14.2-2~),
+ gradle (>= 4.6-2~),
+ libgradle-kotlin-dsl-java (>= 0.15.6-2~),
  maven-repo-helper,
  ${misc:Depends}
 Description: Helper tools for building Debian packages with Gradle


=====================================
debian/maven.rules
=====================================
@@ -0,0 +1,2 @@
+
+junit junit jar s/.*/4.x/


=====================================
gradle-helper-hook/pom.xml
=====================================
@@ -15,6 +15,12 @@
       <artifactId>maven-repo-helper</artifactId>
       <version>1.8.10</version>
     </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.13.2</version>
+      <scope>test</scope>
+    </dependency>
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>


=====================================
gradle-helper-hook/src/main/java/org/debian/gradle/plugin/IgnoreRules.java
=====================================
@@ -0,0 +1,278 @@
+/**
+ * Copyright 2026 Emmanuel Bourg
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.debian.gradle.plugin;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * What the build ignores, as declared in <tt>debian/gradle.ignoreRules</tt>.
+ *
+ * <p>The file has a two-column layout. The first column is one of:</p>
+ * <ul>
+ *   <li>a plugin identifier, as the build script writes it</li>
+ *   <li>the name of a plugin class, when the script applies it that way</li>
+ *   <li>the path of a script plugin, the one applied with
+ *       <tt>apply from:</tt>, recognized by its <tt>.gradle</tt> or
+ *       <tt>.gradle.kts</tt> extension</li>
+ *   <li>the path of a project, recognized by its leading colon, which the
+ *       settings file then doesn't include</li>
+ *   <li>a dash, for the blocks no plugin of the script declares</li>
+ * </ul>
+ *
+ * <p>The second column is optional and lists the names ignored with the plugin,
+ * separated by commas or whitespace: its configuration blocks and the class
+ * name of its tasks.</p>
+ *
+ * <pre>
+ * me.champeau.gradle.jmh       jmh
+ * com.gradle.build-scan        buildScan
+ * com.gradle.plugin-publish    pluginBundle,gradlePlugin
+ * org.gradle.kotlin.ktlint-convention
+ * com.example.gradle.SomePlugin
+ * gradle/jmh.gradle            jmh
+ * com.github.spotbugs          spotbugs, com.github.spotbugs.SpotBugsTask
+ * :osgi-test
+ * -                            jmh
+ * </pre>
+ */
+public class IgnoreRules {
+
+    /** The location of the rules */
+    public static final String FILE = "debian/gradle.ignoreRules";
+
+    private final List<Rule> rules = new ArrayList<Rule>();
+
+    /**
+     * An ignored plugin and the configuration blocks it injects.
+     */
+    public static class Rule {
+
+        private final String plugin;
+        private final List<String> extensions;
+
+        Rule(String plugin, List<String> extensions) {
+            this.plugin = plugin;
+            this.extensions = extensions;
+        }
+
+        /** The plugin, the script or the project of the entry, null if it has none */
+        public String getPlugin() {
+            return plugin;
+        }
+
+        /** The names of the configuration blocks injected by the plugin */
+        public List<String> getExtensions() {
+            List<String> blocks = new ArrayList<String>();
+            for (String extension : extensions) {
+                if (!isClassName(extension)) {
+                    blocks.add(extension);
+                }
+            }
+            return Collections.unmodifiableList(blocks);
+        }
+
+        /** The names of the classes brought by the plugin and named by the build script */
+        public List<String> getClasses() {
+            List<String> classes = new ArrayList<String>();
+            for (String extension : extensions) {
+                if (isClassName(extension)) {
+                    classes.add(extension);
+                }
+            }
+            return Collections.unmodifiableList(classes);
+        }
+
+        /** Tells a class from a configuration block: only a class name is qualified */
+        private static boolean isClassName(String name) {
+            return name.indexOf('.') >= 0;
+        }
+
+        /** Tells if the entry designates a project of the build rather than a plugin */
+        public boolean isProject() {
+            return plugin != null && plugin.startsWith(":");
+        }
+
+        /** Tells if the entry designates a script plugin, applied with <tt>apply from:</tt> */
+        public boolean isScript() {
+            return plugin != null && (plugin.endsWith(".gradle") || plugin.endsWith(".gradle.kts"));
+        }
+    }
+
+    /**
+     * Reads the rules of the package from {@link #FILE}.
+     */
+    public static IgnoreRules read() {
+        return new IgnoreRules(new File(FILE));
+    }
+
+    /**
+     * Reads the rules from the specified file.
+     *
+     * @throws IllegalArgumentException if the file cannot be read or holds a malformed entry
+     */
+    public IgnoreRules(File file) {
+        if (!file.exists()) {
+            return;
+        }
+
+        List<String> lines;
+        try {
+            lines = Files.readAllLines(file.toPath(), Charset.forName("UTF-8"));
+        } catch (IOException e) {
+            throw new IllegalArgumentException(file + " could not be read: " + e.getMessage(), e);
+        }
+
+        for (int i = 0; i < lines.size(); i++) {
+            Rule rule = parse(lines.get(i), file + ":" + (i + 1));
+            if (rule != null) {
+                rules.add(rule);
+            }
+        }
+    }
+
+    /**
+     * Parses one line of the file, and returns null if it holds no entry.
+     *
+     * @param location the file and the line number, for the error messages
+     */
+    private Rule parse(String line, String location) {
+        int comment = line.indexOf('#');
+        if (comment >= 0) {
+            line = line.substring(0, comment);
+        }
+        line = line.trim();
+        if (line.isEmpty()) {
+            return null;
+        }
+
+        String[] fields = line.split("\\s+", 2);
+
+        String plugin = "-".equals(fields[0]) ? null : fields[0];
+
+        List<String> extensions = new ArrayList<String>();
+        if (fields.length == 2) {
+            for (String extension : fields[1].split("[,\\s]+")) {
+                extension = extension.trim();
+                if (!extension.isEmpty()) {
+                    extensions.add(extension);
+                }
+            }
+        }
+
+        if (plugin == null && extensions.isEmpty()) {
+            throw new IllegalArgumentException(location + ": an entry with no plugin must name the blocks to ignore");
+        }
+
+        return new Rule(plugin, extensions);
+    }
+
+    /**
+     * Tells if the plugin with the specified identifier is ignored.
+     *
+     * @param id the identifier used in the build script, such as com.gradle.build-scan
+     */
+    public boolean isPluginIgnored(String id) {
+        for (Rule rule : rules) {
+            if (!rule.isScript() && !rule.isProject()
+                    && rule.getPlugin() != null && rule.getPlugin().equals(id)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Tells if the class with the specified name is ignored.
+     *
+     * @param name the fully qualified name of the class
+     */
+    public boolean isClassIgnored(String name) {
+        if (isPluginIgnored(name)) {
+            return true;
+        }
+        for (Rule rule : rules) {
+            if (rule.getClasses().contains(name)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Tells if the script at the specified path is ignored. The rules hold a
+     * path relative to the root of the package, the scripts are applied with an
+     * absolute one, so the end of the path is compared.
+     *
+     * @param path the path of the script plugin applied with <tt>apply from:</tt>
+     */
+    public boolean isScriptIgnored(String path) {
+        for (Rule rule : rules) {
+            if (rule.isScript() && (path.equals(rule.getPlugin()) || path.endsWith("/" + rule.getPlugin()))) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Tells if the project at the specified path is ignored.
+     *
+     * @param path the path of the project, as passed to include()
+     */
+    public boolean isProjectIgnored(String path) {
+        String normalized = path.startsWith(":") ? path : ":" + path;
+        for (Rule rule : rules) {
+            if (rule.isProject() && rule.getPlugin().equals(normalized)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns the names of the configuration blocks to ignore.
+     */
+    public Set<String> getIgnoredExtensions() {
+        Set<String> extensions = new LinkedHashSet<String>();
+        for (Rule rule : rules) {
+            extensions.addAll(rule.getExtensions());
+        }
+        return extensions;
+    }
+
+    /**
+     * Returns the entries read from the file.
+     */
+    public List<Rule> getRules() {
+        return Collections.unmodifiableList(rules);
+    }
+
+    /**
+     * Tells if no rule was declared, and the mechanism therefore does nothing.
+     */
+    public boolean isEmpty() {
+        return rules.isEmpty();
+    }
+}


=====================================
gradle-helper-hook/src/test/java/org/debian/gradle/plugin/IgnoreRulesTest.java
=====================================
@@ -0,0 +1,225 @@
+/**
+ * Copyright 2026 Emmanuel Bourg
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.debian.gradle.plugin;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Arrays;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import static org.junit.Assert.*;
+
+public class IgnoreRulesTest {
+
+    @Rule
+    public TemporaryFolder folder = new TemporaryFolder();
+
+    private IgnoreRules rules2(String... lines) throws IOException {
+        return rules("rules2", lines);
+    }
+
+    private IgnoreRules rules3(String... lines) throws IOException {
+        return rules("rules3", lines);
+    }
+
+    private IgnoreRules rules(String... lines) throws IOException {
+        return rules("rules", lines);
+    }
+
+    private IgnoreRules rules(String name, String[] lines) throws IOException {
+        File file = folder.newFile(name);
+        PrintWriter writer = new PrintWriter(file, "UTF-8");
+        for (String line : lines) {
+            writer.println(line);
+        }
+        writer.close();
+
+        return new IgnoreRules(file);
+    }
+
+    @Test
+    public void testMissingFile() {
+        IgnoreRules rules = new IgnoreRules(new File("does/not/exist"));
+
+        assertTrue("rules", rules.isEmpty());
+        assertTrue("extensions", rules.getIgnoredExtensions().isEmpty());
+        assertFalse("plugin ignored", rules.isPluginIgnored("com.gradle.build-scan"));
+    }
+
+    @Test
+    public void testEmptyFile() throws Exception {
+        IgnoreRules rules = rules("# nothing but a comment", "", "   ");
+
+        assertTrue("rules", rules.isEmpty());
+    }
+
+    @Test
+    public void testPluginWithOneExtension() throws Exception {
+        IgnoreRules rules = rules("me.champeau.gradle.jmh    jmh");
+
+        assertEquals("rules", 1, rules.getRules().size());
+        assertTrue("plugin ignored", rules.isPluginIgnored("me.champeau.gradle.jmh"));
+        assertFalse("other plugin ignored", rules.isPluginIgnored("me.champeau.gradle.other"));
+        assertEquals("extensions", Arrays.asList("jmh"), rules.getRules().get(0).getExtensions());
+    }
+
+    @Test
+    public void testPluginWithoutExtension() throws Exception {
+        IgnoreRules rules = rules("org.gradle.kotlin.ktlint-convention");
+
+        assertTrue("plugin ignored", rules.isPluginIgnored("org.gradle.kotlin.ktlint-convention"));
+        assertTrue("extensions", rules.getIgnoredExtensions().isEmpty());
+    }
+
+    @Test
+    public void testSeveralExtensions() throws Exception {
+        IgnoreRules rules = rules("com.gradle.plugin-publish    pluginBundle,gradlePlugin");
+
+        assertEquals("extensions", Arrays.asList("pluginBundle", "gradlePlugin"),
+                     Arrays.asList(rules.getIgnoredExtensions().toArray()));
+    }
+
+    @Test
+    public void testClassOfAnIgnoredPlugin() throws Exception {
+        IgnoreRules rules = rules("com.github.spotbugs    spotbugs, com.github.spotbugs.SpotBugsTask");
+
+        assertEquals("extensions", Arrays.asList("spotbugs"), rules.getRules().get(0).getExtensions());
+        assertEquals("classes", Arrays.asList("com.github.spotbugs.SpotBugsTask"), rules.getRules().get(0).getClasses());
+        assertTrue("class ignored", rules.isClassIgnored("com.github.spotbugs.SpotBugsTask"));
+        assertFalse("other class ignored", rules.isClassIgnored("com.github.spotbugs.OtherTask"));
+        assertFalse("block registered as a class", rules.isClassIgnored("spotbugs"));
+    }
+
+    @Test
+    public void testPluginAppliedByItsClass() throws Exception {
+        IgnoreRules rules = rules("com.example.gradle.SomePlugin");
+
+        assertTrue("class ignored", rules.isClassIgnored("com.example.gradle.SomePlugin"));
+        assertTrue("extensions", rules.getIgnoredExtensions().isEmpty());
+    }
+
+    @Test
+    public void testExtensionWithoutPlugin() throws Exception {
+        IgnoreRules rules = rules("-    jmh");
+
+        assertNull("plugin", rules.getRules().get(0).getPlugin());
+        assertFalse("plugin ignored", rules.isPluginIgnored("-"));
+        assertEquals("extensions", Arrays.asList("jmh"), rules.getRules().get(0).getExtensions());
+    }
+
+    @Test
+    public void testScript() throws Exception {
+        IgnoreRules rules = rules("gradle/binaryCompatibility.gradle");
+
+        assertTrue("script", rules.getRules().get(0).isScript());
+        assertTrue("absolute path", rules.isScriptIgnored("/build/pkg-1.0/gradle/binaryCompatibility.gradle"));
+        assertTrue("relative path", rules.isScriptIgnored("gradle/binaryCompatibility.gradle"));
+        assertFalse("other script", rules.isScriptIgnored("/build/pkg-1.0/gradle/jmh.gradle"));
+        assertFalse("ignored as a plugin id", rules.isPluginIgnored("gradle/binaryCompatibility.gradle"));
+    }
+
+    @Test
+    public void testKotlinScript() throws Exception {
+        IgnoreRules rules = rules("gradle/jmh.gradle.kts    jmh");
+
+        assertTrue("script", rules.getRules().get(0).isScript());
+        assertTrue("path", rules.isScriptIgnored("/build/pkg/gradle/jmh.gradle.kts"));
+        assertEquals("extensions", Arrays.asList("jmh"), rules.getRules().get(0).getExtensions());
+    }
+
+    @Test
+    public void testPluginIsNotAScript() throws Exception {
+        IgnoreRules rules = rules("me.champeau.gradle.jmh    jmh");
+
+        assertFalse("script", rules.getRules().get(0).isScript());
+        assertFalse("ignored as a script", rules.isScriptIgnored("/build/pkg/me.champeau.gradle.jmh"));
+    }
+
+    @Test
+    public void testProject() throws Exception {
+        IgnoreRules rules = rules(":osgi-test", ":android");
+
+        assertTrue("project", rules.getRules().get(0).isProject());
+        assertTrue("with the colon", rules.isProjectIgnored(":osgi-test"));
+        assertTrue("without the colon", rules.isProjectIgnored("osgi-test"));
+        assertTrue("second entry", rules.isProjectIgnored("android"));
+        assertFalse("other module", rules.isProjectIgnored(":inline"));
+        assertFalse("ignored as a plugin id", rules.isPluginIgnored(":osgi-test"));
+    }
+
+    @Test
+    public void testComments() throws Exception {
+        IgnoreRules rules = rules("# the plugins ignored by this package",
+                                  "",
+                                  "com.gradle.build-scan    buildScan    # applied by --scan",
+                                  "#me.champeau.gradle.jmh    jmh");
+
+        assertEquals("rules", 1, rules.getRules().size());
+        assertTrue("plugin ignored", rules.isPluginIgnored("com.gradle.build-scan"));
+        assertFalse("commented out plugin ignored", rules.isPluginIgnored("me.champeau.gradle.jmh"));
+    }
+
+    @Test
+    public void testDuplicatedExtension() throws Exception {
+        IgnoreRules rules = rules("me.champeau.gradle.jmh    jmh", "-    jmh");
+
+        assertEquals("rules", 2, rules.getRules().size());
+        assertEquals("extensions", 1, rules.getIgnoredExtensions().size());
+    }
+
+    @Test
+    public void testRulesAreNotCached() throws Exception {
+        File file = folder.newFile("gradle.ignoreRules");
+
+        PrintWriter writer = new PrintWriter(file, "UTF-8");
+        writer.println("me.champeau.gradle.jmh    jmh");
+        writer.close();
+        assertTrue("first read", new IgnoreRules(file).isPluginIgnored("me.champeau.gradle.jmh"));
+
+        writer = new PrintWriter(file, "UTF-8");
+        writer.println("com.gradle.build-scan    buildScan");
+        writer.close();
+        assertFalse("second read", new IgnoreRules(file).isPluginIgnored("me.champeau.gradle.jmh"));
+        assertTrue("second read", new IgnoreRules(file).isPluginIgnored("com.gradle.build-scan"));
+    }
+
+    @Test
+    public void testExtensionSeparators() throws Exception {
+        IgnoreRules commas  = rules("com.example.plugin    blockA,blockB");
+        IgnoreRules spaced  = rules2("com.example.plugin    blockA, blockB");
+        IgnoreRules spaces  = rules3("com.example.plugin    blockA blockB");
+
+        for (IgnoreRules rules : Arrays.asList(commas, spaced, spaces)) {
+            assertEquals("extensions", Arrays.asList("blockA", "blockB"),
+                         Arrays.asList(rules.getIgnoredExtensions().toArray()));
+        }
+    }
+
+    @Test
+    public void testExtensionWithoutPluginNorBlock() throws Exception {
+        try {
+            rules("# the line below names nothing", "-");
+            fail("no exception thrown");
+        } catch (IllegalArgumentException e) {
+            assertTrue("message: " + e.getMessage(), e.getMessage().contains(":2: "));
+        }
+    }
+}


=====================================
gradle-helper-plugin/pom.xml
=====================================
@@ -15,6 +15,12 @@
   </properties>
 
   <dependencies>
+    <dependency>
+      <groupId>org.debian.gradle</groupId>
+      <artifactId>gradle-helper-hook</artifactId>
+      <version>1.5</version>
+      <scope>provided</scope>
+    </dependency>
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
@@ -90,6 +96,13 @@
       <scope>system</scope>
       <systemPath>${gradle.libs}/gradle-plugins.jar</systemPath>
     </dependency>
+    <dependency>
+      <groupId>org.gradle</groupId>
+      <artifactId>gradle-model-core</artifactId>
+      <version>${gradle.version}</version>
+      <scope>system</scope>
+      <systemPath>${gradle.libs}/gradle-model-core.jar</systemPath>
+    </dependency>
     <dependency>
       <groupId>org.gradle</groupId>
       <artifactId>gradle-logging</artifactId>


=====================================
gradle-helper-plugin/src/main/java/org/debian/gradle/DebianHelperPlugin.java
=====================================
@@ -18,7 +18,9 @@ package org.debian.gradle;
 
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Set;
 
+import org.debian.gradle.plugin.IgnoreRules;
 import org.debian.gradle.tasks.MavenPom;
 import org.gradle.api.Action;
 import org.gradle.api.Plugin;
@@ -56,6 +58,33 @@ public class DebianHelperPlugin implements Plugin<Gradle> {
             }
         });
 
+        // ignore the configuration blocks listed in debian/gradle.ignoreRules
+        final Set<String> ignoredExtensions = IgnoreRules.read().getIgnoredExtensions();
+        gradle.allprojects(new Action<Project>() {
+            @Override
+            public void execute(final Project project) {
+                for (String name : ignoredExtensions) {
+                    if (project.getExtensions().findByName(name) == null) {
+                        log.info("\tIgnoring the '" + name + "' block of project '" + project.getName() + "'");
+                        project.getExtensions().add(name, new IgnoredExtension());
+                    }
+                }
+
+                // create the stub tasks after the evaluation, before it they
+                // would take the name of a task a plugin is about to create
+                project.afterEvaluate(new Action<Project>() {
+                    @Override
+                    public void execute(Project project) {
+                        for (String name : ignoredExtensions) {
+                            if (project.getTasks().findByName(name) == null) {
+                                project.getTasks().create(name);
+                            }
+                        }
+                    }
+                });
+            }
+        });
+
         // generate the Maven pom after building a project
         gradle.allprojects(new Action<Project>() {
             @Override
@@ -63,13 +92,16 @@ public class DebianHelperPlugin implements Plugin<Gradle> {
                 project.afterEvaluate(new Action<Project>() {
                     @Override
                     public void execute(Project project) {
-                      if (project.getPluginManager().hasPlugin("java")) {
+                      // a project applying the java plugin doesn't necessarily
+                      // build a jar, and there is no pom to generate without one
+                      Task jar = project.getTasks().findByName("jar");
+                      if (project.getPluginManager().hasPlugin("java") && jar != null) {
                           log.info("\tAdding Maven pom generation to project '" + project.getName() + "'");
                           project.getPluginManager().apply("maven");
                           Map<String, Class> debianMavenPomTaskOptions = new HashMap<String, Class>();
                           debianMavenPomTaskOptions.put("type", MavenPom.class);
                           project.task(debianMavenPomTaskOptions, "debianMavenPom");
-                          ((Task) project.getTasksByName("jar", false).toArray()[0]).dependsOn("debianMavenPom");
+                          jar.dependsOn("debianMavenPom");
                       }
                     }
                 });
@@ -83,8 +115,8 @@ public class DebianHelperPlugin implements Plugin<Gradle> {
                 project.afterEvaluate(new Action<Project>() {
                     @Override
                     public void execute(Project project) {
-                        if (project.getPluginManager().hasPlugin("java")) {
-                            Javadoc javadocTask = ((Javadoc) (project.getTasksByName("javadoc", false).toArray()[0]));
+                        Javadoc javadocTask = (Javadoc) project.getTasks().findByName("javadoc");
+                        if (project.getPluginManager().hasPlugin("java") && javadocTask != null) {
                             if (javadocTask.getOptions() instanceof StandardJavadocDocletOptions) {
                                 log.info("\tLinking the generated javadoc to the system JDK API documentation");
                                 ((StandardJavadocDocletOptions) javadocTask.getOptions()).getLinks().add(0, "file:///usr/share/doc/default-jdk/api");


=====================================
gradle-helper-plugin/src/main/java/org/debian/gradle/IgnoredExtension.java
=====================================
@@ -0,0 +1,95 @@
+/**
+ * Copyright 2026 Emmanuel Bourg
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.debian.gradle;
+
+import groovy.lang.Closure;
+import groovy.lang.GroovyObjectSupport;
+
+/**
+ * A stub standing for the configuration block of an ignored plugin. It is
+ * registered under the name of the block and swallows whatever the build script
+ * puts in it.
+ *
+ * <p>This works in a Groovy script, where Gradle accepts any registered name as
+ * a configuration block, without checking the type of the extension, and
+ * delegates the closure to it. The assignments of the block therefore reach
+ * {@link #setProperty}, its method calls {@link #invokeMethod}, and the nested
+ * blocks are swallowed whole since the closure they carry is never called.</p>
+ *
+ * <p>A Kotlin script is compiled before it runs, and no stub can absorb a
+ * member the compiler doesn't know; there the ignored blocks are removed from
+ * the source of the script by libgradle-kotlin-dsl-java.</p>
+ */
+public class IgnoredExtension extends Closure<Object> {
+
+    /**
+     * The owner of the closure. Groovy hands it the methods it doesn't find on
+     * the closure itself, so it has to swallow them as well, and it has to
+     * exist: with a null owner any unknown method call ends in a
+     * NullPointerException before {@link #invokeMethod} is reached.
+     */
+    private static class StubOwner extends GroovyObjectSupport {
+
+        @Override
+        public Object invokeMethod(String name, Object args) {
+            return this;
+        }
+
+        @Override
+        public Object getProperty(String property) {
+            return this;
+        }
+
+        @Override
+        public void setProperty(String property, Object value) {
+        }
+
+        @Override
+        public String toString() {
+            return "ignored";
+        }
+    }
+
+    public IgnoredExtension() {
+        super(new StubOwner());
+    }
+
+    /** Swallows the calls of the blocks the plugin declares as methods, jsign(file: 'x') */
+    @Override
+    public Object call(Object... args) {
+        return this;
+    }
+
+    @Override
+    public Object invokeMethod(String name, Object args) {
+        return this;
+    }
+
+    @Override
+    public Object getProperty(String property) {
+        return this;
+    }
+
+    @Override
+    public void setProperty(String property, Object value) {
+    }
+
+    @Override
+    public String toString() {
+        return "ignored";
+    }
+}


=====================================
gradle-helper-plugin/src/main/perl/gradle.pm
=====================================
@@ -11,12 +11,15 @@ use Dpkg::Control;
 use base 'Debian::Debhelper::Buildsystem';
 
 sub DESCRIPTION {
-	"Gradle (build.gradle)"
+	"Gradle (build.gradle[.kts])"
 }
 
 sub check_auto_buildable {
 	my $this=shift;
-	return (-e $this->get_sourcepath("build.gradle")) ? 1 : 0;
+	foreach my $script ("build.gradle", "build.gradle.kts", "settings.gradle", "settings.gradle.kts") {
+		return 1 if -e $this->get_sourcepath($script);
+	}
+	return 0;
 }
 
 sub new {


=====================================
test-project/build.gradle
=====================================
@@ -2,6 +2,14 @@ allprojects {
     apply plugin: 'java'
 }
 
+jmh {
+    fork = 1
+    resultFormat = 'CSV'
+    profiles {
+        gc = true
+    }
+}
+
 dependencies {
     compile group: 'commons-collections', name: 'commons-collections', version: 'debian'
     compile group: 'commons-lang', name: 'commons-lang', version: '2.6'


=====================================
test-project/debian/gradle.ignoreRules
=====================================
@@ -0,0 +1,2 @@
+# The jmh plugin is ignored, with the configuration block it injects.
+me.champeau.gradle.jmh    jmh


=====================================
test-project/init.gradle
=====================================
@@ -2,6 +2,7 @@ initscript {
     def home = System.properties['user.home']
     dependencies {
         classpath fileTree(dir: '../../../gradle-helper-plugin/target/', include: '*.jar')
+        classpath fileTree(dir: '../../../gradle-helper-hook/target/', include: '*.jar')
         classpath fileTree(dir: home + '/.m2/repository/org/debian/maven/maven-repo-helper/1.8.10/', include: '*.jar')
     }
 }



View it on GitLab: https://salsa.debian.org/java-team/gradle-debian-helper/-/compare/bb9480757e908117bcb782b6a6308036feb6869b...7695dd78520b8c5e52b0cd8605ec2f762c8cd784

-- 
View it on GitLab: https://salsa.debian.org/java-team/gradle-debian-helper/-/compare/bb9480757e908117bcb782b6a6308036feb6869b...7695dd78520b8c5e52b0cd8605ec2f762c8cd784
You're receiving this email because of your account on salsa.debian.org. Manage all notifications: https://salsa.debian.org/-/profile/notifications | Help: https://salsa.debian.org/help


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-java-commits/attachments/20260930/b6710157/attachment.htm>


More information about the pkg-java-commits mailing list