Ignore system timezone when applying outputTimestamp to entries
Update `JarWriter` so that entry times are set with the default TimeZone offset removed. The Javadoc for `ZipEntry.setTime` states: The file entry is "encoded in standard `MS-DOS date and time format`. The default TimeZone is used to convert the epoch time to the MS-DOS data and time. Removing the offset from our UTC time before calling `entry.setTime()` ensures that we get consistent bytes in the zip file when the output stream reapplies the offset during write. Fixes gh-34424
This commit is contained in:
@@ -21,6 +21,7 @@ import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -401,10 +402,12 @@ class JarIntegrationTests extends AbstractArchiveIntegrationTests {
|
||||
mavenBuild.project("jar-output-timestamp").execute((project) -> {
|
||||
File repackaged = new File(project, "target/jar-output-timestamp-0.0.1.BUILD-SNAPSHOT.jar");
|
||||
assertThat(repackaged).isFile();
|
||||
assertThat(repackaged.lastModified()).isEqualTo(1584352800000L);
|
||||
long expectedModified = 1584352800000L;
|
||||
long offsetExpectedModified = expectedModified - TimeZone.getDefault().getOffset(expectedModified);
|
||||
assertThat(repackaged.lastModified()).isEqualTo(expectedModified);
|
||||
try (JarFile jar = new JarFile(repackaged)) {
|
||||
List<String> unreproducibleEntries = jar.stream()
|
||||
.filter((entry) -> entry.getLastModifiedTime().toMillis() != 1584352800000L)
|
||||
.filter((entry) -> entry.getLastModifiedTime().toMillis() != offsetExpectedModified)
|
||||
.map((entry) -> entry.getName() + ": " + entry.getLastModifiedTime())
|
||||
.collect(Collectors.toList());
|
||||
assertThat(unreproducibleEntries).isEmpty();
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -96,10 +97,12 @@ class WarIntegrationTests extends AbstractArchiveIntegrationTests {
|
||||
mavenBuild.project("war-output-timestamp").execute((project) -> {
|
||||
File repackaged = new File(project, "target/war-output-timestamp-0.0.1.BUILD-SNAPSHOT.war");
|
||||
assertThat(repackaged).isFile();
|
||||
assertThat(repackaged.lastModified()).isEqualTo(1584352800000L);
|
||||
long expectedModified = 1584352800000L;
|
||||
assertThat(repackaged.lastModified()).isEqualTo(expectedModified);
|
||||
long offsetExpectedModified = expectedModified - TimeZone.getDefault().getOffset(expectedModified);
|
||||
try (JarFile jar = new JarFile(repackaged)) {
|
||||
List<String> unreproducibleEntries = jar.stream()
|
||||
.filter((entry) -> entry.getLastModifiedTime().toMillis() != 1584352800000L)
|
||||
.filter((entry) -> entry.getLastModifiedTime().toMillis() != offsetExpectedModified)
|
||||
.map((entry) -> entry.getName() + ": " + entry.getLastModifiedTime())
|
||||
.collect(Collectors.toList());
|
||||
assertThat(unreproducibleEntries).isEmpty();
|
||||
|
||||
Reference in New Issue
Block a user