Skip to content

Commit 1708728

Browse files
authored
fix(server): produce deterministic JARs (#1483)
Part of #1461.
1 parent 39c6956 commit 1708728

File tree

1 file changed

+30
-8
lines changed
  • maven-binding-builder/src/main/kotlin/io/github/typesafegithub/workflows/mavenbinding

1 file changed

+30
-8
lines changed

maven-binding-builder/src/main/kotlin/io/github/typesafegithub/workflows/mavenbinding/ZipUtils.kt

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,27 @@ import java.io.FileNotFoundException
88
import java.io.IOException
99
import java.io.OutputStream
1010
import java.nio.file.Path
11+
import java.nio.file.attribute.FileTime
1112
import java.util.zip.ZipEntry
1213
import java.util.zip.ZipOutputStream
14+
import kotlin.io.path.absolute
1315
import kotlin.io.path.isDirectory
1416
import kotlin.io.path.listDirectoryEntries
1517
import kotlin.io.path.name
1618

1719
internal fun OutputStream.createZipFile(contents: Path) =
1820
ZipOutputStream(this).use { zipOutputStream ->
19-
contents.listDirectoryEntries().forEach { file ->
20-
if (file.isDirectory()) {
21-
zipDirectory(file.toFile(), file.name, zipOutputStream)
22-
} else {
23-
zipFile(file.toFile(), zipOutputStream)
21+
contents.listDirectoryEntries()
22+
// Sorting to add ZIP entries in deterministic order, to provide exactly the same ZIP regardless of
23+
// generation time.
24+
.sortedBy { it.absolute().toString() }
25+
.forEach { file ->
26+
if (file.isDirectory()) {
27+
zipDirectory(file.toFile(), file.name, zipOutputStream)
28+
} else {
29+
zipFile(file.toFile(), zipOutputStream)
30+
}
2431
}
25-
}
2632
zipOutputStream.flush()
2733
}
2834

@@ -45,7 +51,15 @@ private fun zipDirectory(
4551
zipDirectory(file, parentFolder + "/" + file.getName(), zos)
4652
continue
4753
}
48-
zos.putNextEntry(ZipEntry(parentFolder + "/" + file.getName()))
54+
val zipEntry =
55+
ZipEntry(parentFolder + "/" + file.getName()).apply {
56+
// Resetting various timestamps to provide exactly the same ZIP regardless of generation time.
57+
time = 0
58+
creationTime = FileTime.fromMillis(0)
59+
lastModifiedTime = FileTime.fromMillis(0)
60+
lastAccessTime = FileTime.fromMillis(0)
61+
}
62+
zos.putNextEntry(zipEntry)
4963
val bis =
5064
BufferedInputStream(
5165
FileInputStream(file),
@@ -73,7 +87,15 @@ private fun zipFile(
7387
file: File,
7488
zos: ZipOutputStream,
7589
) {
76-
zos.putNextEntry(ZipEntry(file.getName()))
90+
val zipEntry =
91+
ZipEntry(file.getName()).apply {
92+
// Resetting various timestamps to provide exactly the same ZIP regardless of generation time.
93+
time = 0
94+
creationTime = FileTime.fromMillis(0)
95+
lastModifiedTime = FileTime.fromMillis(0)
96+
lastAccessTime = FileTime.fromMillis(0)
97+
}
98+
zos.putNextEntry(zipEntry)
7799
val bis =
78100
BufferedInputStream(
79101
FileInputStream(

0 commit comments

Comments
 (0)