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)) {
