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

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


The following commit(s) were added to refs/heads/master by this push:
     new dc3d7ed34 make xslt use similar out-of-dateness check as other tasks
dc3d7ed34 is described below

commit dc3d7ed34cd506a5b853af5f6dee25ec9ff8a094
Author: Stefan Bodewig <bode...@apache.org>
AuthorDate: Thu Jun 5 20:57:04 2025 +0200

    make xslt use similar out-of-dateness check as other tasks
    
    https://bz.apache.org/bugzilla/show_bug.cgi?id=65756
---
 WHATSNEW                                           | 17 +++++++++
 manual/Tasks/style.html                            |  9 +++++
 src/etc/testcases/taskdefs/style/build.xml         |  2 +-
 .../org/apache/tools/ant/taskdefs/XSLTProcess.java | 41 ++++++++++++++++------
 .../tools/ant/types/selectors/SelectorUtils.java   | 21 ++++++++++-
 5 files changed, 78 insertions(+), 12 deletions(-)

diff --git a/WHATSNEW b/WHATSNEW
index 5095303da..a512e2f62 100644
--- a/WHATSNEW
+++ b/WHATSNEW
@@ -1,6 +1,23 @@
 Changes from Ant 1.10.15 TO Ant 1.10.16
 =======================================
 
+Changes that could break older environments:
+-------------------------------------------
+
+ * <xslt> now uses the same logic to compare file timestamps when
+   determining whether a target file is out-of-date with respect to
+   the source file or stylesheet that most other tasks use. This means
+   it will assume a default timestamp granularity that depends on the
+   current operating system.
+   A new granularity attribute allows you to override the assumed
+   granularity.
+   Under certain edge cases this means xslt will now not process files
+   it would have processed before (when the timestamps of source or
+   stylesheet are very close or even equal to the timestamp of the
+   target). In this case you can set granularity to 0 to get back to
+   the behavior of 1.10.15.
+   Bugzilla Report 65756
+
 Fixed bugs:
 -----------
 
diff --git a/manual/Tasks/style.html b/manual/Tasks/style.html
index 9f0a16c68..6ce33f8c9 100644
--- a/manual/Tasks/style.html
+++ b/manual/Tasks/style.html
@@ -231,6 +231,15 @@ <h3>Parameters</h3>
       1.8.0</em>.</td>
     <td>No; default is <q>true</q></td>
   </tr>
+  <tr>
+    <td>granularity</td>
+    <td>The number of milliseconds leeway to give before deciding a
+      file is out of date with respect of the source file or stylesheet. This 
is
+      needed because not every file system supports tracking the last modified 
time to the
+      millisecond level. This can also be useful if source and target files 
live on separate
+      machines with clocks being out of sync. <em>since Ant 1.10.16</em>.</td>
+    <td>No; default is 1 second, or 2 seconds on DOS systems</td>
+  </tr>
 </table>
 <h3>Parameters specified as nested elements</h3>
 
diff --git a/src/etc/testcases/taskdefs/style/build.xml 
b/src/etc/testcases/taskdefs/style/build.xml
index 42ad93d92..959e61646 100644
--- a/src/etc/testcases/taskdefs/style/build.xml
+++ b/src/etc/testcases/taskdefs/style/build.xml
@@ -96,7 +96,7 @@
       <antcall target="copyXsl">
         <param name="xsl.value" value="new-value"/>
       </antcall>
-      <xslt in="data.xml" out="${output}/out.xml" style="tmp.xsl"/>
+      <xslt in="data.xml" out="${output}/out.xml" style="tmp.xsl" 
granularity="0"/>
       <delete file="tmp.xsl"/>
   </target>
 
diff --git a/src/main/org/apache/tools/ant/taskdefs/XSLTProcess.java 
b/src/main/org/apache/tools/ant/taskdefs/XSLTProcess.java
index 829ab0006..bdb6bb08d 100644
--- a/src/main/org/apache/tools/ant/taskdefs/XSLTProcess.java
+++ b/src/main/org/apache/tools/ant/taskdefs/XSLTProcess.java
@@ -55,6 +55,7 @@ import org.apache.tools.ant.types.resources.FileProvider;
 import org.apache.tools.ant.types.resources.FileResource;
 import org.apache.tools.ant.types.resources.Resources;
 import org.apache.tools.ant.types.resources.Union;
+import org.apache.tools.ant.types.selectors.SelectorUtils;
 import org.apache.tools.ant.util.ClasspathUtils;
 import org.apache.tools.ant.util.FileNameMapper;
 import org.apache.tools.ant.util.FileUtils;
@@ -243,6 +244,13 @@ public class XSLTProcess extends MatchingTask implements 
XSLTLogger {
      */
     private TraceConfiguration traceConfiguration;
 
+    /**
+     * Filesystem timestamp granularity in milliseconds.
+     *
+     * @since Ant 1.10.16
+     */
+    private long granularity = FILE_UTILS.getFileTimestampGranularity();
+
     /**
      * Whether to style all files in the included directories as well;
      * optional, default is true.
@@ -390,9 +398,7 @@ public class XSLTProcess extends MatchingTask implements 
XSLTLogger {
                         stylesheet = alternative;
                     }
                 }
-                final FileResource fr = new FileResource();
-                fr.setProject(getProject());
-                fr.setFile(stylesheet);
+                final FileResource fr = new FileResource(getProject(), 
stylesheet);
                 styleResource = fr;
             } else {
                 styleResource = xslResource;
@@ -692,6 +698,19 @@ public class XSLTProcess extends MatchingTask implements 
XSLTLogger {
         return traceConfiguration;
     }
 
+    /**
+     * Set the number of milliseconds leeway to give before deciding a
+     * target is out of date.
+     *
+     * <p>Default is 1 second, or 2 seconds on DOS systems.</p>
+     * @param granularity the granularity used to decide if a target is out of
+     *                    date.
+     * @since Ant 1.10.16
+     */
+    public void setGranularity(final long granularity) {
+        this.granularity = granularity;
+    }
+
     /**
      * Load processor here instead of in setProcessor - this will be
      * called from within execute, so we have access to the latest
@@ -830,9 +849,11 @@ public class XSLTProcess extends MatchingTask implements 
XSLTLogger {
                 return;
             }
             outF = new File(destDir, outFileName[0]);
+            Resource outR = new FileResource(getProject(), outF);
 
-            if (force || inF.lastModified() > outF.lastModified()
-                    || styleSheetLastModified > outF.lastModified()) {
+            if (force
+                || SelectorUtils.isOutOfDate(inF, outF, granularity)
+                || SelectorUtils.isOutOfDate(stylesheet, outR, granularity)) {
                 ensureDirectoryFor(outF);
                 log("Processing " + inF + " to " + outF);
                 configureLiaison(stylesheet);
@@ -862,11 +883,13 @@ public class XSLTProcess extends MatchingTask implements 
XSLTLogger {
     private void process(final File inFile, final File outFile, final Resource 
stylesheet) throws BuildException {
         try {
             final long styleSheetLastModified = stylesheet.getLastModified();
+            final Resource outResource = new FileResource(getProject(), 
outFile);
             log("In file " + inFile + " time: " + inFile.lastModified(), 
Project.MSG_DEBUG);
             log("Out file " + outFile + " time: " + outFile.lastModified(), 
Project.MSG_DEBUG);
             log("Style file " + xslFile + " time: " + styleSheetLastModified, 
Project.MSG_DEBUG);
-            if (force || inFile.lastModified() >= outFile.lastModified()
-                    || styleSheetLastModified >= outFile.lastModified()) {
+            if (force
+                || SelectorUtils.isOutOfDate(inFile, outFile, granularity)
+                || SelectorUtils.isOutOfDate(stylesheet, outResource, 
granularity)) {
                 ensureDirectoryFor(outFile);
                 log("Processing " + inFile + " to " + outFile, 
Project.MSG_INFO);
                 configureLiaison(stylesheet);
@@ -1242,9 +1265,7 @@ public class XSLTProcess extends MatchingTask implements 
XSLTLogger {
      */
     @Deprecated
     protected void configureLiaison(final File stylesheet) throws 
BuildException {
-        final FileResource fr = new FileResource();
-        fr.setProject(getProject());
-        fr.setFile(stylesheet);
+        final FileResource fr = new FileResource(getProject(), stylesheet);
         configureLiaison(fr);
     }
 
diff --git a/src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java 
b/src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java
index a6af9bcd8..af0f4afcc 100644
--- a/src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java
+++ b/src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java
@@ -573,11 +573,30 @@ public final class SelectorUtils {
      *
      * @param src the original file
      * @param target the file being compared against
-     * @param granularity the amount in milliseconds of slack we will give in
+     * @param granularity the int amount in milliseconds of slack we will give 
in
      *        determining out of dateness
      * @return whether the target is out of date
      */
     public static boolean isOutOfDate(File src, File target, int granularity) {
+        return isOutOfDate(src, target, (long) granularity);
+    }
+
+    /**
+     * Returns dependency information on these two files. If src has been
+     * modified later than target, it returns true. If target doesn't exist,
+     * it likewise returns true. Otherwise, target is newer than src and
+     * is not out of date, thus the method returns false. It also returns
+     * false if the src file doesn't even exist, since how could the
+     * target then be out of date.
+     *
+     * @param src the original file
+     * @param target the file being compared against
+     * @param granularity the amount in milliseconds of slack we will give in
+     *        determining out of dateness
+     * @return whether the target is out of date
+     * @since Ant 1.10.16
+     */
+    public static boolean isOutOfDate(File src, File target, long granularity) 
{
         return src.exists() && (!target.exists()
                 || (src.lastModified() - granularity) > target.lastModified());
     }

Reply via email to