Bug 59562 - Regexp mapper + Zip task on Windows
Summary: Regexp mapper + Zip task on Windows
Status: RESOLVED FIXED
Alias: None
Product: Ant
Classification: Unclassified
Component: Core tasks (show other bugs)
Version: 1.9.7
Hardware: PC All
: P2 normal (vote)
Target Milestone: 1.9.8
Assignee: Ant Notifications List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-05-17 14:45 UTC by Gilles QUERRET
Modified: 2016-05-19 04:40 UTC (History)
1 user (show)



Attachments
JUnit test case (690 bytes, patch)
2016-05-17 14:45 UTC, Gilles QUERRET
Details | Diff
JUnit test case (xml file) (1014 bytes, patch)
2016-05-17 14:45 UTC, Gilles QUERRET
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Gilles QUERRET 2016-05-17 14:45:04 UTC
Using this test case, I see a different behavior on Windows and Linux ; I'm
creating two files, then generating a ZIP file (with regexpmapper to rename
files), wait a few seconds (just in case there's  FS timestamp problem) and
re-execute the same Zip task.
On Linux, the second Zip task doesn't do anything (as expected) as the
files are not modified.
On Windows, the Zip file is always updated. With -v, I'm getting :
      [zip] us/xx/xxtest.r added as us/xx/xxtest.r is outdated.
      [zip] us/zz/zztest.r added as us/zz/zztest.r is outdated.
Using Ant 1.9.7, JDK 1.8 on both systems.

Am I doing something wrong, or is there a bug ?

<?xml version="1.0" encoding="utf-8"?>
<project name="test">
 <mkdir dir="src" />
 <touch file="src/xxtest.r" />
 <touch file="src/zztest.r" />
 <zip destFile="foo.zip">
   <mappedresources>
    <fileset dir="src" includes="*.r" />
    <regexpmapper from="^(([a-z][a-z]).*)\.r" to="us/\2/\1.r" />
   </mappedresources>
 </zip>
 <sleep seconds="5" />
 <zip destFile="foo.zip">
   <mappedresources>
    <fileset dir="src" includes="*.r" />
    <regexpmapper from="^(([a-z][a-z]).*)\.r" to="us/\2/\1.r" />
   </mappedresources>
 </zip>
</project>
Comment 1 Gilles QUERRET 2016-05-17 14:45:31 UTC
Created attachment 33846 [details]
JUnit test case
Comment 2 Gilles QUERRET 2016-05-17 14:45:55 UTC
Created attachment 33847 [details]
JUnit test case (xml file)
Comment 3 Gilles QUERRET 2016-05-17 20:25:06 UTC
I think I've found the issue, but would like to get confirmation : the granularity of file timestamps is different on NTFS and Linux filesystems (1 and 2000 respectively), however it seems that file entries in ZIP files have a different granularity. From my tests, I'm always gettings timestamps from ZIP file which are 1.5 seconds more recent than file timestamps, so the ZIP file is not updated on Unix (less than 2 seconds), but not on Windows (only 1ms granularity).
Does anybody have enough knowledge of ZIP files to confirm that ?
A fix could be to have a different granularity based on the resource type we're trying to update, but I don't know how easy it would be to do that.
Comment 4 Stefan Bodewig 2016-05-18 03:59:32 UTC
Yes, there are different granularities in this scenario. First of all, ZIPs store file times with a granularity of two seconds - and I think this is true for FAT and NTFS as well. Most file-system types on Unix use a granularity of seconds or even lower than that.

The default behavior if the zip task is to round the file time up to the next even number of seconds in order to avoid the situation you describe - see the task's roundup attribute. What you see implies it didn't work correctly.
Comment 5 Gilles QUERRET 2016-05-18 06:47:26 UTC
I'd say the roundup method is working correctly and as expected. To my mind, the problem lies in org.apache.tools.ant.types.selectors.SelectorUtils#isOutOfDate(Resource src, Resource target, long granularity) method which is called when we determine if a file has to be updated. This works correctly for filesystem resources on Windows, as the parameter granularity is set to 1 which is the right value on NTFS. This granularity is found in org.apache.tools.ant.util.FileUtils#getFileTimestampGranularity(). When working with ZIP file, this method should return 2000 in order to counterbalance the roundup.

An easy fix (but I don't know the impact yet) would be to replace at line 1545 of org.apache.tools.ant.taskdefs.Zip the call to ResourceUtils.selectOutOfDateSources(this, rs, mapper, getZipScanner()) with ResourceUtils.selectOutOfDateSources(this, rs, mapper, getZipScanner(), 2000L) so that granularity would be set at the ZIP file level instead of inheriting from the OS specific value.
Comment 6 Gilles QUERRET 2016-05-18 15:04:21 UTC
Unit tests are OK with this change, including the one I've added to test this behavior.
What does it take to have the change included in the master branch ?
Comment 7 Stefan Bodewig 2016-05-19 04:27:45 UTC
Your idea of a fix looks correct, I'm working on integrating your changes.
Comment 8 Stefan Bodewig 2016-05-19 04:40:51 UTC
Applied your patch and suggestion with commit 0edf3ca - will be fixed in 1.9.8 and 1.10.0.