From 86853bec6ac7bcfe12726848e6bbae913cdddea3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Boutemy?= Date: Tue, 13 Aug 2019 17:56:21 +0100 Subject: [PATCH] added Archiver.get/setLastModifiedDate(Date) API to force entries value this API is a step to Reproducible Builds, to get reproducible archives --- pom.xml | 2 +- .../plexus/archiver/AbstractArchiver.java | 18 ++++++++++++++++++ .../org/codehaus/plexus/archiver/Archiver.java | 14 ++++++++++++++ .../archiver/diags/DelgatingArchiver.java | 13 +++++++++++++ .../plexus/archiver/diags/NoOpArchiver.java | 13 +++++++++++++ .../archiver/diags/TrackingArchiver.java | 15 +++++++++++++++ .../plexus/archiver/dir/DirectoryArchiver.java | 13 ++++++++++--- .../plexus/archiver/tar/TarArchiver.java | 15 +++++++++++---- .../archiver/zip/AbstractZipArchiver.java | 5 +++++ .../plexus/archiver/zip/ZipArchiverTest.java | 17 +++++++++++++++++ 10 files changed, 117 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index beb437766..f53268676 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ plexus-archiver - 4.1.1-SNAPSHOT + 4.2.0-SNAPSHOT Plexus Archiver Component diff --git a/src/main/java/org/codehaus/plexus/archiver/AbstractArchiver.java b/src/main/java/org/codehaus/plexus/archiver/AbstractArchiver.java index 76d21ec1d..7d23ab7ea 100755 --- a/src/main/java/org/codehaus/plexus/archiver/AbstractArchiver.java +++ b/src/main/java/org/codehaus/plexus/archiver/AbstractArchiver.java @@ -22,6 +22,7 @@ import java.lang.reflect.UndeclaredThrowableException; import java.nio.charset.Charset; import java.util.ArrayList; +import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -103,6 +104,11 @@ public abstract class AbstractArchiver */ private boolean useJvmChmod = true; + /** + * @since 4.2.0 + */ + private Date lastModifiedDate; + // contextualized. private ArchiverManager archiverManager; @@ -1133,4 +1139,16 @@ public void setIgnorePermissions( final boolean ignorePermissions ) this.ignorePermissions = ignorePermissions; } + @Override + public void setLastModifiedDate( Date lastModifiedDate ) + { + this.lastModifiedDate = lastModifiedDate; + } + + @Override + public Date getLastModifiedDate() + { + return lastModifiedDate; + } + } diff --git a/src/main/java/org/codehaus/plexus/archiver/Archiver.java b/src/main/java/org/codehaus/plexus/archiver/Archiver.java index ba11b9609..88cc55b71 100644 --- a/src/main/java/org/codehaus/plexus/archiver/Archiver.java +++ b/src/main/java/org/codehaus/plexus/archiver/Archiver.java @@ -19,6 +19,7 @@ import java.io.File; import java.io.IOException; import java.nio.charset.Charset; +import java.util.Date; import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -399,4 +400,17 @@ ResourceIterator getResources() */ void setIgnorePermissions( final boolean ignorePermissions ); + /** + * Define forced last modification date for entries (if non null). + * + * @param lastModifiedDate + * @since 4.2.0 + */ + void setLastModifiedDate( final Date lastModifiedDate ); + + /** + * @since 4.2.0 + */ + Date getLastModifiedDate(); + } diff --git a/src/main/java/org/codehaus/plexus/archiver/diags/DelgatingArchiver.java b/src/main/java/org/codehaus/plexus/archiver/diags/DelgatingArchiver.java index a470e2a16..af0ff69a6 100644 --- a/src/main/java/org/codehaus/plexus/archiver/diags/DelgatingArchiver.java +++ b/src/main/java/org/codehaus/plexus/archiver/diags/DelgatingArchiver.java @@ -18,6 +18,7 @@ import java.io.File; import java.io.IOException; import java.nio.charset.Charset; +import java.util.Date; import java.util.Map; import javax.annotation.Nonnull; import org.codehaus.plexus.archiver.ArchiveEntry; @@ -331,4 +332,16 @@ public void setIgnorePermissions( boolean ignorePermissions ) target.setIgnorePermissions( ignorePermissions ); } + @Override + public void setLastModifiedDate( final Date lastModifiedDate ) + { + target.setLastModifiedDate( lastModifiedDate ); + } + + @Override + public Date getLastModifiedDate() + { + return target.getLastModifiedDate(); + } + } diff --git a/src/main/java/org/codehaus/plexus/archiver/diags/NoOpArchiver.java b/src/main/java/org/codehaus/plexus/archiver/diags/NoOpArchiver.java index 2c649bc2c..1fe2309c2 100644 --- a/src/main/java/org/codehaus/plexus/archiver/diags/NoOpArchiver.java +++ b/src/main/java/org/codehaus/plexus/archiver/diags/NoOpArchiver.java @@ -19,6 +19,7 @@ import java.io.IOException; import java.nio.charset.Charset; import java.util.Collections; +import java.util.Date; import java.util.Map; import javax.annotation.Nonnull; import org.codehaus.plexus.archiver.ArchiveEntry; @@ -346,4 +347,16 @@ public void setIgnorePermissions( boolean ignorePermissions ) this.ignorePermissions = ignorePermissions; } + @Override + public void setLastModifiedDate( final Date lastModifiedDate ) + { + + } + + @Override + public Date getLastModifiedDate() + { + return null; + } + } diff --git a/src/main/java/org/codehaus/plexus/archiver/diags/TrackingArchiver.java b/src/main/java/org/codehaus/plexus/archiver/diags/TrackingArchiver.java index 3b2b8286f..9ad057090 100644 --- a/src/main/java/org/codehaus/plexus/archiver/diags/TrackingArchiver.java +++ b/src/main/java/org/codehaus/plexus/archiver/diags/TrackingArchiver.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.nio.charset.Charset; import java.util.ArrayList; +import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -52,6 +53,8 @@ public class TrackingArchiver private boolean ignorePermissions; + private Date lastModified; + @Override public void createArchive() throws ArchiverException, IOException @@ -400,4 +403,16 @@ public void setIgnorePermissions( final boolean ignorePermissions ) this.ignorePermissions = ignorePermissions; } + @Override + public void setLastModifiedDate( final Date lastModifiedDate ) + { + this.lastModified = lastModifiedDate; + } + + @Override + public Date getLastModifiedDate() + { + return lastModified; + } + } diff --git a/src/main/java/org/codehaus/plexus/archiver/dir/DirectoryArchiver.java b/src/main/java/org/codehaus/plexus/archiver/dir/DirectoryArchiver.java index 99f4f2f1b..f35569445 100644 --- a/src/main/java/org/codehaus/plexus/archiver/dir/DirectoryArchiver.java +++ b/src/main/java/org/codehaus/plexus/archiver/dir/DirectoryArchiver.java @@ -194,9 +194,16 @@ private void setFileModes( ArchiveEntry entry, File outFile, long inLastModified ArchiveEntryUtils.chmod( outFile, entry.getMode() ); } - outFile.setLastModified( inLastModified == PlexusIoResource.UNKNOWN_MODIFICATION_DATE - ? System.currentTimeMillis() - : inLastModified ); + if ( getLastModifiedDate() == null ) + { + outFile.setLastModified( inLastModified == PlexusIoResource.UNKNOWN_MODIFICATION_DATE + ? System.currentTimeMillis() + : inLastModified ); + } + else + { + outFile.setLastModified( getLastModifiedDate().getTime() ); + } } @Override diff --git a/src/main/java/org/codehaus/plexus/archiver/tar/TarArchiver.java b/src/main/java/org/codehaus/plexus/archiver/tar/TarArchiver.java index 8eec8817f..98e2c559e 100644 --- a/src/main/java/org/codehaus/plexus/archiver/tar/TarArchiver.java +++ b/src/main/java/org/codehaus/plexus/archiver/tar/TarArchiver.java @@ -281,10 +281,17 @@ else if ( longFileMode.isFailMode() ) te = new TarArchiveEntry( vPath ); } - long teLastModified = entry.getResource().getLastModified(); - te.setModTime( teLastModified == PlexusIoResource.UNKNOWN_MODIFICATION_DATE - ? System.currentTimeMillis() - : teLastModified ); + if ( getLastModifiedDate() == null ) + { + long teLastModified = entry.getResource().getLastModified(); + te.setModTime( teLastModified == PlexusIoResource.UNKNOWN_MODIFICATION_DATE + ? System.currentTimeMillis() + : teLastModified ); + } + else + { + te.setModTime( getLastModifiedDate() ); + } if ( entry.getType() == ArchiveEntry.SYMLINK ) { diff --git a/src/main/java/org/codehaus/plexus/archiver/zip/AbstractZipArchiver.java b/src/main/java/org/codehaus/plexus/archiver/zip/AbstractZipArchiver.java index f4448386e..bdc2fc93d 100755 --- a/src/main/java/org/codehaus/plexus/archiver/zip/AbstractZipArchiver.java +++ b/src/main/java/org/codehaus/plexus/archiver/zip/AbstractZipArchiver.java @@ -530,6 +530,11 @@ public InputStream get() private void setTime( java.util.zip.ZipEntry zipEntry, long lastModified ) { + if ( getLastModifiedDate() != null ) + { + lastModified = getLastModifiedDate().getTime(); + } + // Zip archives store file modification times with a // granularity of two seconds, so the times will either be rounded // up or down. If you round down, the archive will always seem diff --git a/src/test/java/org/codehaus/plexus/archiver/zip/ZipArchiverTest.java b/src/test/java/org/codehaus/plexus/archiver/zip/ZipArchiverTest.java index f6b560657..39cb9eeb3 100644 --- a/src/test/java/org/codehaus/plexus/archiver/zip/ZipArchiverTest.java +++ b/src/test/java/org/codehaus/plexus/archiver/zip/ZipArchiverTest.java @@ -886,4 +886,21 @@ public void testForcedFileModes() } } + public void testFixedEntryModificationTime() + throws IOException + { + final long almostMinDosTime = 315532802000L; + final File zipFile = getTestFile( "target/output/zip-with-fixed-entry-modification-times.zip" ); + final ZipArchiver archiver = getZipArchiver( zipFile ); + archiver.setLastModifiedDate( new Date( almostMinDosTime ) ); + archiver.addDirectory( new File( "src/test/resources/zip-timestamp" ) ); + archiver.createArchive(); + + assertTrue( zipFile.exists() ); + final ZipFile zf = new ZipFile( zipFile ); + assertEquals( almostMinDosTime, zf.getEntry( "file-with-even-time.txt" ).getTime() ); + assertEquals( almostMinDosTime, zf.getEntry( "file-with-odd-time.txt" ).getTime() ); + assertEquals( almostMinDosTime, zf.getEntry( "foo/" ).getTime() ); + } + }