[Git][java-team/groovy][master] 10 commits: Generate the Groovydoc without a timestamp to make the build reproducible

Emmanuel Bourg (@ebourg) gitlab at salsa.debian.org
Fri Oct 16 09:49:23 BST 2026



Emmanuel Bourg pushed to branch master at Debian Java Maintainers / groovy


Commits:
7aeadf7b by Emmanuel Bourg at 2026-10-16T08:14:38+02:00
Generate the Groovydoc without a timestamp to make the build reproducible

- - - - -
ef33bc39 by Emmanuel Bourg at 2026-10-16T08:48:25+02:00
Generate the @Delegate methods in a reproducible order

- - - - -
71ab1285 by Emmanuel Bourg at 2026-10-16T09:01:49+02:00
Generate the trait methods in a reproducible order

- - - - -
fae8d2df by Emmanuel Bourg at 2026-10-16T10:17:11+02:00
Converted debian/watch to the version 5 format

- - - - -
3858e080 by Emmanuel Bourg at 2026-10-16T10:17:11+02:00
Removed the Priority field

- - - - -
95a670eb by Emmanuel Bourg at 2026-10-16T10:17:11+02:00
Removed the Rules-Requires-Root field

- - - - -
6c02d379 by Emmanuel Bourg at 2026-10-16T10:17:11+02:00
Updated the Homepage field

- - - - -
9da721df by Emmanuel Bourg at 2026-10-16T10:17:11+02:00
Standards-Version updated to 4.7.4

- - - - -
07899d71 by Emmanuel Bourg at 2026-10-16T10:17:11+02:00
Tightened the dependency on libjline2-java (Closes: #1022154)

- - - - -
b922b484 by Emmanuel Bourg at 2026-10-16T10:26:22+02:00
Upload to unstable

- - - - -


7 changed files:

- debian/changelog
- debian/control
- + debian/patches/18_reproducible_groovydoc.patch
- + debian/patches/19_reproducible_delegate.patch
- + debian/patches/20_reproducible_traits.patch
- debian/patches/series
- debian/watch


Changes:

=====================================
debian/changelog
=====================================
@@ -1,3 +1,19 @@
+groovy (2.4.21-11) unstable; urgency=medium
+
+  * Team upload.
+  * Generate the Groovydoc without a timestamp to make the build reproducible
+  * Generate the @Delegate methods in a reproducible order
+  * Generate the trait methods in a reproducible order
+  * Converted debian/watch to the version 5 format
+  * Removed the Priority field
+  * Removed the Rules-Requires-Root field
+  * Updated the Homepage field
+  * Standards-Version updated to 4.7.4
+  * Tightened the dependency on libjline2-java, groovysh needs its jansi
+    1.x runtime dependency (Closes: #1022154)
+
+ -- Emmanuel Bourg <ebourg at apache.org>  Fri, 16 Oct 2026 10:26:17 +0200
+
 groovy (2.4.21-10) unstable; urgency=medium
 
   * Team upload.


=====================================
debian/control
=====================================
@@ -1,6 +1,5 @@
 Source: groovy
 Section: java
-Priority: optional
 Maintainer: Debian Java Maintainers <pkg-java-maintainers at lists.alioth.debian.org>
 Uploaders: Felix Natter <fnatter at gmx.net>
 Build-Depends:
@@ -32,11 +31,10 @@ Build-Depends:
  maven-repo-helper,
  testng,
  unzip
-Standards-Version: 4.6.2
+Standards-Version: 4.7.4
 Vcs-Git: https://salsa.debian.org/java-team/groovy.git
 Vcs-Browser: https://salsa.debian.org/java-team/groovy
-Homepage: http://www.groovy-lang.org
-Rules-Requires-Root: no
+Homepage: https://www.groovy-lang.org
 
 Package: groovy
 Architecture: all
@@ -50,7 +48,7 @@ Depends:
  libcommons-cli-java,
  libcommons-logging-java,
  libjansi-java,
- libjline2-java,
+ libjline2-java (>= 2.14.6-6~),
  libjsp-api-java,
  libqdox-java,
  libservlet-api-java,


=====================================
debian/patches/18_reproducible_groovydoc.patch
=====================================
@@ -0,0 +1,28 @@
+Description: Generate the documentation without a timestamp on reproducible builds
+ Groovydoc writes the current date in an HTML comment and in the date meta tag
+ of every page. The timestamp property driving both is now turned off when
+ SOURCE_DATE_EPOCH is set.
+Author: Emmanuel Bourg <ebourg at apache.org>
+Forwarded: no
+--- a/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovydoc.java
++++ b/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovydoc.java
+@@ -450,7 +450,7 @@
+         properties.setProperty("overviewFile", overviewFile != null ? overviewFile.getAbsolutePath() : "");
+         properties.setProperty("charset", charset != null ? charset : "");
+         properties.setProperty("fileEncoding", fileEncoding != null ? fileEncoding : "");
+-        properties.setProperty("timestamp", Boolean.valueOf(!noTimestamp).toString());
++        properties.setProperty("timestamp", Boolean.valueOf(!noTimestamp && System.getenv("SOURCE_DATE_EPOCH") == null).toString());
+         properties.setProperty("versionStamp", Boolean.valueOf(!noVersionStamp).toString());
+ 
+         if (sourcePath != null) {
+--- a/subprojects/groovy-groovydoc/src/main/groovy/org/codehaus/groovy/tools/groovydoc/Main.groovy
++++ b/subprojects/groovy-groovydoc/src/main/groovy/org/codehaus/groovy/tools/groovydoc/Main.groovy
+@@ -195,7 +195,7 @@
+         properties.put("author", author.toString())
+         properties.put("processScripts", (!noScripts).toString())
+         properties.put("includeMainForScripts", (!noMainForScripts).toString())
+-        properties.put("timestamp", (!noTimestamp).toString())
++        properties.put("timestamp", (!noTimestamp && System.getenv("SOURCE_DATE_EPOCH") == null).toString())
+         properties.put("versionStamp", (!noVersionStamp).toString())
+         properties.put("overviewFile", overviewFile?.absolutePath ?: "")
+ 


=====================================
debian/patches/19_reproducible_delegate.patch
=====================================
@@ -0,0 +1,58 @@
+Description: Generate the @Delegate methods in a reproducible order
+ The delegate methods are generated in the order returned by
+ Class.getDeclaredMethods(), which is unspecified and varies from one JVM run
+ to the next. Upstream sorts them on the descriptor without the return type;
+ the version 2.4 keys its own lookups on the full descriptor, so that is what
+ is sorted on here.
+Author: Emmanuel Bourg <ebourg at apache.org>
+Origin: backport, https://github.com/apache/groovy/commit/0d22fbdd3c21
+Bug: https://issues.apache.org/jira/browse/GROOVY-11689
+Applied-Upstream: 4.0.28
+--- a/src/main/org/codehaus/groovy/transform/DelegateASTTransformation.java
++++ b/src/main/org/codehaus/groovy/transform/DelegateASTTransformation.java
+@@ -41,6 +41,8 @@
+ 
+ import java.lang.reflect.Modifier;
+ import java.util.ArrayList;
++import java.util.Collections;
++import java.util.Comparator;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.Set;
+@@ -89,6 +91,16 @@
+     private static final String MEMBER_PARAMETER_ANNOTATIONS = "parameterAnnotations";
+     private static final String MEMBER_METHOD_ANNOTATIONS = "methodAnnotations";
+ 
++    /**
++     * Class.getDeclaredMethods() returns the methods in an unspecified order,
++     * sorting them keeps the generated delegates reproducible.
++     */
++    private static final Comparator<MethodNode> METHOD_DESCRIPTOR_COMPARATOR = new Comparator<MethodNode>() {
++        public int compare(MethodNode m1, MethodNode m2) {
++            return m1.getTypeDescriptor().compareTo(m2.getTypeDescriptor());
++        }
++    };
++
+     public void visit(ASTNode[] nodes, SourceUnit source) {
+         init(nodes, source);
+ 
+@@ -113,6 +125,9 @@
+             for (ClassNode next : type.getAllInterfaces()) {
+                 fieldMethods.addAll(getAllMethods(next));
+             }
++            if (fieldMethods.size() > 1) {
++                Collections.sort(fieldMethods, METHOD_DESCRIPTOR_COMPARATOR);
++            }
+ 
+             final boolean skipInterfaces = memberHasValue(node, MEMBER_INTERFACES, false);
+             final boolean includeDeprecated = memberHasValue(node, MEMBER_DEPRECATED, true) || (type.isInterface() && !skipInterfaces);
+@@ -123,6 +138,9 @@
+             checkIncludeExclude(node, excludes, includes, excludeTypes, includeTypes, MY_TYPE_NAME);
+ 
+             final List<MethodNode> ownerMethods = getAllMethods(owner);
++            if (ownerMethods.size() > 1) {
++                Collections.sort(ownerMethods, METHOD_DESCRIPTOR_COMPARATOR);
++            }
+             for (MethodNode mn : fieldMethods) {
+                 addDelegateMethod(node, fieldNode, owner, ownerMethods, mn, includeDeprecated, includes, excludes, includeTypes, excludeTypes);
+             }


=====================================
debian/patches/20_reproducible_traits.patch
=====================================
@@ -0,0 +1,62 @@
+Description: Generate the trait methods in a reproducible order
+ The methods inherited from a precompiled trait are generated in the order
+ returned by Class.getDeclaredMethods(), which is unspecified and varies from
+ one JVM run to the next.
+Author: Emmanuel Bourg <ebourg at apache.org>
+Origin: backport, https://github.com/apache/groovy/commit/213c3ab7d638
+Bug: https://issues.apache.org/jira/browse/GROOVY-11674
+Applied-Upstream: 4.0.27
+--- a/src/main/org/codehaus/groovy/transform/trait/TraitComposer.java
++++ b/src/main/org/codehaus/groovy/transform/trait/TraitComposer.java
+@@ -62,6 +62,7 @@
+ import java.util.ArrayList;
+ import java.util.Arrays;
+ import java.util.Collections;
++import java.util.Comparator;
+ import java.util.HashMap;
+ import java.util.Iterator;
+ import java.util.LinkedHashMap;
+@@ -91,6 +92,17 @@
+     public static final ClassNode COMPILESTATIC_CLASSNODE = ClassHelper.make(CompileStatic.class);
+ 
+     /**
++     * Class.getDeclaredMethods() returns the methods in an unspecified order,
++     * sorting them keeps the methods generated from a precompiled trait
++     * reproducible.
++     */
++    private static final Comparator<MethodNode> METHOD_DESCRIPTOR_COMPARATOR = new Comparator<MethodNode>() {
++        public int compare(MethodNode m1, MethodNode m2) {
++            return m1.getTypeDescriptor().compareTo(m2.getTypeDescriptor());
++        }
++    };
++
++    /**
+      * Given a class node, if this class node implements a trait, then generate all the appropriate
+      * code which delegates calls to the trait. It is safe to call this method on a class node which
+      * does not implement a trait.
+@@ -145,7 +157,11 @@
+         Map<String,ClassNode> genericsSpec = GenericsUtils.createGenericsSpec(cNode);
+         genericsSpec = GenericsUtils.createGenericsSpec(trait, genericsSpec);
+ 
+-        for (MethodNode methodNode : helperClassNode.getAllDeclaredMethods()) {
++        List<MethodNode> helperMethods = helperClassNode.getAllDeclaredMethods();
++        if (helperMethods.size() > 1) {
++            Collections.sort(helperMethods, METHOD_DESCRIPTOR_COMPARATOR);
++        }
++        for (MethodNode methodNode : helperMethods) {
+             String name = methodNode.getName();
+             Parameter[] helperMethodParams = methodNode.getParameters();
+             boolean isAbstract = methodNode.isAbstract();
+@@ -200,7 +216,11 @@
+             cNode.addInterface(fieldHelperClassNode);
+             // implementation of methods
+             List<MethodNode> declaredMethods = new LinkedList<MethodNode>();
+-            for (MethodNode declaredMethod : fieldHelperClassNode.getAllDeclaredMethods()) {
++            List<MethodNode> fieldHelperMethods = fieldHelperClassNode.getAllDeclaredMethods();
++            if (fieldHelperMethods.size() > 1) {
++                Collections.sort(fieldHelperMethods, METHOD_DESCRIPTOR_COMPARATOR);
++            }
++            for (MethodNode declaredMethod : fieldHelperMethods) {
+                 if (declaredMethod.getName().endsWith(Traits.DIRECT_GETTER_SUFFIX)) {
+                     declaredMethods.add(0, declaredMethod);
+                 } else {


=====================================
debian/patches/series
=====================================
@@ -18,3 +18,6 @@ remove-GroovyDoc-JANSI-dependency.patch
 update-to-JLine2-2.13.patch
 16_fix_type_inference.patch
 17_javadoc_with_java21.patch
+18_reproducible_groovydoc.patch
+19_reproducible_delegate.patch
+20_reproducible_traits.patch


=====================================
debian/watch
=====================================
@@ -1,5 +1,7 @@
-# Track only the supported 2.4.x versions until we can upgrade
-
-version=4
-opts=uversionmangle=s/(\d)[_\.\-\+]?((RC|rc|pre|dev|beta|alpha|b|a)[\-\.]?\d*)$/$1~$2/,dversionmangle=s/\+dfsg//,downloadurlmangle=s|http://www.apache.org/dyn/closer.cgi/|http://dist.apache.org/repos/dist/release/| \
-https://groovy.apache.org/download.html .*/(?:apache-)?groovy-src-([2]{1}\.[4]{1}.*)(?:-incubating)?\.(?:zip|tgz|tbz|txz|(?:tar\.(?:gz|bz2|xz)))
+Version: 5
+Mode: git
+Source: https://github.com/apache/groovy.git
+Matching-Pattern: refs/tags/GROOVY_(2_[\d_]+)
+Uversion-Mangle: s/_/./g
+Repack: yes
+Compression: xz



View it on GitLab: https://salsa.debian.org/java-team/groovy/-/compare/4db6aa2b2dbefb251b80c7ec91776ec0db85c4a0...b922b484e694a7299cec1ab4793bb8708171b819

-- 
View it on GitLab: https://salsa.debian.org/java-team/groovy/-/compare/4db6aa2b2dbefb251b80c7ec91776ec0db85c4a0...b922b484e694a7299cec1ab4793bb8708171b819
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/20261016/838b819e/attachment.htm>


More information about the pkg-java-commits mailing list