Skip to content

Commit

Permalink
add configureReproducible( Date lastModifiedDate ) API
Browse files Browse the repository at this point in the history
this closes #121
  • Loading branch information
hboutemy committed Oct 16, 2019
1 parent e42b62e commit 98940db
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 0 deletions.
41 changes: 41 additions & 0 deletions src/main/java/org/codehaus/plexus/archiver/AbstractArchiver.java
Expand Up @@ -1257,4 +1257,45 @@ public String getOverrideGroupName()
{
return overrideGroupName;
}

@Override
public void configureReproducible( Date lastModifiedDate )
{
// 1. force last modified date
setLastModifiedDate( normalizeLastModifiedDate( lastModifiedDate ) );

// 2. sort filenames in each directory when scanning filesystem
setFilenameComparator( new Comparator<String>()
{
@Override
public int compare( String s1, String s2 )
{
return s1.compareTo( s2 );
}
} );

// 3. ignore file/directory mode from filesystem, since they may vary based on local user umask
// notice: this overrides execute bit on Unix (that is already ignored on Windows)
setFileMode( Archiver.DEFAULT_FILE_MODE );
setDirectoryMode( Archiver.DEFAULT_DIR_MODE );

// 4. ignore uid/gid from filesystem (for tar)
setOverrideUid( 0 );
setOverrideUserName( "root" ); // is it possible to avoid this, like "tar --numeric-owner"?
setOverrideGid( 0 );
setOverrideGroupName( "root" );
}

/**
* Normalize last modified time value to get reproducible archive entries, based on
* archive binary format (tar uses UTC timestamp but zip uses local time then requires
* tweaks to make the value reproducible whatever the current timezone is).
*
* @param lastModifiedDate
* @return
*/
protected Date normalizeLastModifiedDate( Date lastModifiedDate )
{
return lastModifiedDate;
}
}
17 changes: 17 additions & 0 deletions src/main/java/org/codehaus/plexus/archiver/Archiver.java
Expand Up @@ -415,6 +415,9 @@ ResourceIterator getResources()
Date getLastModifiedDate();

/**
* Set filename comparator, used to sort file entries when scanning directories since File.list() does not
* guarantee any order.
*
* @since 4.2.0
*/
void setFilenameComparator( Comparator<String> filenameComparator );
Expand Down Expand Up @@ -458,4 +461,18 @@ ResourceIterator getResources()
* @since 4.2.0
*/
String getOverrideGroupName();

/**
* Configure the archiver to create archives in a reproducible way (see <a
* href="https://reproducible-builds.org/>Reproducible Builds</a>). This will configure:
* <ul>
* <li>reproducible archive entries order,</li>
* <li>defined entries timestamp</li>
* <li>and reproducible entries Unix mode.</li>
* <ul>
*
* @param lastModifiedDate the date to use for archive entries last modified time
* @since 4.2.0
*/
void configureReproducible( Date lastModifiedDate );
}
Expand Up @@ -398,4 +398,11 @@ public String getOverrideGroupName()
{
return target.getOverrideGroupName();
}

@Override
public void configureReproducible( Date lastModifiedDate )
{
target.configureReproducible( lastModifiedDate );
}

}
Expand Up @@ -414,4 +414,10 @@ public String getOverrideGroupName()
return null;
}

@Override
public void configureReproducible( Date lastModifiedDate )
{

}

}
Expand Up @@ -468,4 +468,9 @@ public String getOverrideGroupName()
{
return null;
}

@Override
public void configureReproducible( Date lastModifiedDate )
{
}
}
Expand Up @@ -24,6 +24,8 @@
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.Calendar;
import java.util.Date;
import java.util.Hashtable;
import java.util.Stack;
import java.util.concurrent.ExecutionException;
Expand Down Expand Up @@ -833,4 +835,24 @@ protected String getArchiveType()
return archiveType;
}

@Override
protected Date normalizeLastModifiedDate( Date lastModifiedDate )
{
// timestamp of zip entries at zip storage level ignores timezone: managed in ZipEntry.setTime,
// that turns javaToDosTime: need to revert the operation here to get reproducible
// zip entry time
return new Date( dosToJavaTime( lastModifiedDate.getTime() ) );
}

/**
* Converts DOS time to Java time (number of milliseconds since epoch).
*
* @see java.util.zip.ZipEntry#setTime
* @see java.util.zip.ZipUtils#dosToJavaTime
*/
private static long dosToJavaTime( long dosTime )
{
Calendar cal = Calendar.getInstance();
return dosTime - ( cal.get( Calendar.ZONE_OFFSET ) + cal.get( Calendar.DST_OFFSET ) );
}
}

0 comments on commit 98940db

Please sign in to comment.