This is an automated email from the ASF dual-hosted git repository.

asf-gitbox-commits pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ant.git

commit 7a444a2f4e24674e0ffc7756c7ff04eaccc91547
Author: Stefan Bodewig <[email protected]>
AuthorDate: Tue Jul 21 18:40:32 2026 +0200

    allow timestamp in generated properties file to be controlled
    
    see https://bz.apache.org/bugzilla/show_bug.cgi?id=61269
---
 WHATSNEW                                           |  7 ++++
 .../tools/ant/taskdefs/optional/PropertyFile.java  |  9 ++++-
 src/main/org/apache/tools/ant/util/DateUtils.java  | 23 +++++++++--
 .../tools/ant/util/LayoutPreservingProperties.java | 45 +++++++++++++++++++++-
 4 files changed, 77 insertions(+), 7 deletions(-)

diff --git a/WHATSNEW b/WHATSNEW
index b8f530a71..4b03f5aca 100644
--- a/WHATSNEW
+++ b/WHATSNEW
@@ -15,6 +15,13 @@ Other changes:
  * Upgraded the jakarta.mail dependency to 2.0.2 because of
    CVE-2025-7962.
 
+ * the SOURCE_DATE_EPOCH environment variable as well as the magic
+   ant.tstamp.now and ant.tstamp.now.iso properties now also affect
+   the timestamp added to a properties file written by <propertyfile>
+   - but only if jdkproperties is false.
+   Based on a patch used by the Debian Ant package maintainers.
+   Part of Bugzilla Report 61269
+
 Fixed bugs:
 -----------
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/PropertyFile.java 
b/src/main/org/apache/tools/ant/taskdefs/optional/PropertyFile.java
index 7c24c94ca..d911ff341 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/PropertyFile.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/PropertyFile.java
@@ -34,11 +34,13 @@ import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Properties;
+import java.util.TimeZone;
 import java.util.Vector;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Task;
 import org.apache.tools.ant.types.EnumeratedAttribute;
+import org.apache.tools.ant.util.DateUtils;
 import org.apache.tools.ant.util.FileUtils;
 import org.apache.tools.ant.util.LayoutPreservingProperties;
 
@@ -190,7 +192,12 @@ public class PropertyFile extends Task {
             // comments and layout
             properties = new Properties();
         } else {
-            properties = new LayoutPreservingProperties();
+            Map.Entry<Date, Boolean> now = DateUtils.getNow(getProject());
+            Calendar c = Calendar.getInstance();
+            c.setTime(now.getKey());
+            TimeZone tz = Boolean.TRUE.equals(now.getValue())
+                ? TimeZone.getTimeZone("UTC") : null;
+            properties = new LayoutPreservingProperties(c, tz);
         }
         try {
             if (propertyfile.exists()) {
diff --git a/src/main/org/apache/tools/ant/util/DateUtils.java 
b/src/main/org/apache/tools/ant/util/DateUtils.java
index 31f87a9e8..1edaecaee 100644
--- a/src/main/org/apache/tools/ant/util/DateUtils.java
+++ b/src/main/org/apache/tools/ant/util/DateUtils.java
@@ -81,9 +81,12 @@ public final class DateUtils {
     public static final DateFormat DATE_HEADER_FORMAT
         = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss ", Locale.US);
 
-    private static final DateFormat DATE_HEADER_FORMAT_INT =
+    private static final SimpleDateFormat READONLY_DATE_HEADER_FORMAT_INT =
         new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss ", Locale.US);
 
+    private static final DateFormat DATE_HEADER_FORMAT_INT =
+        new SimpleDateFormat(READONLY_DATE_HEADER_FORMAT_INT.toPattern(), 
Locale.US);
+
 // code from Magesh moved from DefaultLogger and slightly modified
     private static final MessageFormat MINUTE_SECONDS
             = new MessageFormat("{0}{1}");
@@ -236,7 +239,18 @@ public final class DateUtils {
      */
     public static String getDateForHeader() {
         Calendar cal = Calendar.getInstance();
-        TimeZone tz = cal.getTimeZone();
+        return getDateForHeader(cal, cal.getTimeZone());
+    }
+
+    /**
+     * Returns the given Date in a format suitable for a SMTP date
+     * header.
+     * @return the given date.
+     * @since Ant 1.10.18
+     * @param cal the date to fomat
+     * @param tz timezone to assume
+     */
+    public static String getDateForHeader(Calendar cal, TimeZone tz) {
         int offset = tz.getOffset(cal.get(Calendar.ERA),
                                   cal.get(Calendar.YEAR),
                                   cal.get(Calendar.MONTH),
@@ -256,6 +270,7 @@ public final class DateUtils {
         }
         tzMarker.append(minutes);
         synchronized (DATE_HEADER_FORMAT_INT) {
+            DATE_HEADER_FORMAT_INT.setTimeZone(tz);
             return DATE_HEADER_FORMAT_INT.format(cal.getTime()) + 
tzMarker.toString();
         }
     }
@@ -271,8 +286,8 @@ public final class DateUtils {
      * @since Ant 1.8.0
      */
     public static Date parseDateFromHeader(String datestr) throws 
ParseException {
-        synchronized (DATE_HEADER_FORMAT_INT) {
-            return DATE_HEADER_FORMAT_INT.parse(datestr);
+        synchronized (READONLY_DATE_HEADER_FORMAT_INT) {
+            return READONLY_DATE_HEADER_FORMAT_INT.parse(datestr);
         }
     }
 
diff --git a/src/main/org/apache/tools/ant/util/LayoutPreservingProperties.java 
b/src/main/org/apache/tools/ant/util/LayoutPreservingProperties.java
index fbdb6b930..95f1aaeb1 100644
--- a/src/main/org/apache/tools/ant/util/LayoutPreservingProperties.java
+++ b/src/main/org/apache/tools/ant/util/LayoutPreservingProperties.java
@@ -31,10 +31,12 @@ import java.io.Serializable;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.util.ArrayList;
+import java.util.Calendar;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
+import java.util.TimeZone;
 
 /**
  * <p>A Properties collection which preserves comments and whitespace
@@ -103,11 +105,30 @@ public class LayoutPreservingProperties extends 
Properties {
      */
     private boolean removeComments;
 
+    private final Calendar calendar;
+    private final TimeZone tz;
+
     /**
      * Create a new, empty, Properties collection, with no defaults.
      */
     public LayoutPreservingProperties() {
+        this(null, null);
+    }
+
+    /**
+     * Create a new, empty, Properties collection, with no defaults.
+     *
+     * @param calendar date to use for the date comment - defaults to now if 
not set
+     * @param tz timezone to use for the date comment - defaults to
+     * date's timezone if not set and the system's current timezone if
+     * date isn't set either
+     *
+     * @since Ant 1.10.18
+     */
+    public LayoutPreservingProperties(Calendar calendar, TimeZone tz) {
         super();
+        this.calendar = calendar;
+        this.tz = tz;
     }
 
     /**
@@ -115,9 +136,26 @@ public class LayoutPreservingProperties extends Properties 
{
      * @param defaults the default property values
      */
     public LayoutPreservingProperties(final Properties defaults) {
-        super(defaults);
+        this(defaults, null, null);
     }
 
+    /**
+     * Create a new, empty, Properties collection, with the specified defaults.
+     *
+     * @param defaults the default property values
+     * @param calendar date to use for the date comment - defaults to now if 
not set
+     * @param tz timezone to use for the date comment - defaults to
+     * date's timezone if not set and the system's current timezone if
+     * date isn't set either
+     *
+     * @since Ant 1.10.18
+     */
+    public LayoutPreservingProperties(final Properties defaults, Calendar 
calendar, TimeZone tz) {
+        super(defaults);
+        this.calendar = calendar;
+        this.tz = tz;
+   }
+
     /**
      * Returns <code>true</code> if comments are removed along with
      * properties, or <code>false</code> otherwise. If
@@ -289,7 +327,10 @@ public class LayoutPreservingProperties extends Properties 
{
                 // not an existing date comment
             }
         }
-        osw.write("#" + DateUtils.getDateForHeader() + eol);
+
+        Calendar c = calendar != null ? calendar : Calendar.getInstance();
+        TimeZone t = tz != null ? tz : c.getTimeZone();
+        osw.write("#" + DateUtils.getDateForHeader(c, t) + eol);
 
         boolean writtenSep = false;
         for (LogicalLine line : logicalLines.subList(skipLines, totalLines)) {

Reply via email to