[Gradle] copyZipFilePartially: Retain ZipEntry meta information
^KT-52741 Verification Pending This change leads to reproducible outputs when extracting zips using this function. KT-52741 in particular was invoking this function during metadata transformation rendering the extracted klibs as different between builds.
This commit is contained in:
committed by
Space
parent
e2ac24cc90
commit
e158cf5dd2
+11
@@ -20,6 +20,17 @@ internal fun copyZipFilePartially(sourceZipFile: File, destinationZipFile: File,
|
|||||||
ZipOutputStream(destinationZipFile.outputStream()).use { destinationZipOutputStream ->
|
ZipOutputStream(destinationZipFile.outputStream()).use { destinationZipOutputStream ->
|
||||||
entries.forEach { sourceEntry ->
|
entries.forEach { sourceEntry ->
|
||||||
val destinationEntry = ZipEntry(sourceEntry.name.substringAfter(path))
|
val destinationEntry = ZipEntry(sourceEntry.name.substringAfter(path))
|
||||||
|
|
||||||
|
sourceEntry.lastAccessTime?.let { destinationEntry.lastAccessTime = it }
|
||||||
|
sourceEntry.lastModifiedTime?.let { destinationEntry.lastModifiedTime = it }
|
||||||
|
sourceEntry.creationTime?.let { destinationEntry.creationTime = it }
|
||||||
|
destinationEntry.crc = sourceEntry.crc
|
||||||
|
destinationEntry.comment = sourceEntry.comment
|
||||||
|
destinationEntry.size = sourceEntry.size
|
||||||
|
destinationEntry.compressedSize = sourceEntry.compressedSize
|
||||||
|
destinationEntry.extra = sourceEntry.extra
|
||||||
|
destinationEntry.method = sourceEntry.method
|
||||||
|
|
||||||
destinationZipOutputStream.putNextEntry(destinationEntry)
|
destinationZipOutputStream.putNextEntry(destinationEntry)
|
||||||
|
|
||||||
if (!sourceEntry.isDirectory) {
|
if (!sourceEntry.isDirectory) {
|
||||||
|
|||||||
+80
-4
@@ -7,8 +7,8 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.gradle
|
package org.jetbrains.kotlin.gradle
|
||||||
|
|
||||||
|
import com.intellij.util.io.Compressor
|
||||||
import org.gradle.kotlin.dsl.support.unzipTo
|
import org.gradle.kotlin.dsl.support.unzipTo
|
||||||
import org.gradle.kotlin.dsl.support.zipTo
|
|
||||||
import org.jetbrains.kotlin.gradle.utils.copyZipFilePartially
|
import org.jetbrains.kotlin.gradle.utils.copyZipFilePartially
|
||||||
import org.jetbrains.kotlin.gradle.utils.listDescendants
|
import org.jetbrains.kotlin.gradle.utils.listDescendants
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
@@ -33,36 +33,45 @@ class ZipUtilsTest {
|
|||||||
resolve("stub0.txt").apply {
|
resolve("stub0.txt").apply {
|
||||||
parentFile.mkdirs()
|
parentFile.mkdirs()
|
||||||
writeText("stub0 content")
|
writeText("stub0 content")
|
||||||
|
setLastModified(2411)
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve("a/stub1.txt").apply {
|
resolve("a/stub1.txt").apply {
|
||||||
parentFile.mkdirs()
|
parentFile.mkdirs()
|
||||||
writeText("stub1 content")
|
writeText("stub1 content")
|
||||||
|
setLastModified(2412)
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve("a/b/stub2.txt").apply {
|
resolve("a/b/stub2.txt").apply {
|
||||||
parentFile.mkdirs()
|
parentFile.mkdirs()
|
||||||
writeText("stub2 content")
|
writeText("stub2 content")
|
||||||
|
setLastModified(2413)
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve("a/b/stub3.txt").apply {
|
resolve("a/b/stub3.txt").apply {
|
||||||
parentFile.mkdirs()
|
parentFile.mkdirs()
|
||||||
writeText("stub3 content")
|
writeText("stub3 content")
|
||||||
|
setLastModified(2414)
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve("c/stub4.txt").apply {
|
resolve("c/stub4.txt").apply {
|
||||||
parentFile.mkdirs()
|
parentFile.mkdirs()
|
||||||
writeText("stub4 content")
|
writeText("stub4 content")
|
||||||
|
setLastModified(2415)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val zipFile by lazy {
|
private fun zipDirectory(directory: File): File {
|
||||||
temporaryFolder.newFile().apply {
|
return temporaryFolder.newFile().apply {
|
||||||
zipTo(this, zipContentFolder)
|
Compressor.Zip(this).use { compressor -> compressor.addDirectory(directory) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val zipFile by lazy {
|
||||||
|
zipDirectory(zipContentFolder)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `test - listDescendants - malformed path string`() {
|
fun `test - listDescendants - malformed path string`() {
|
||||||
ZipFile(zipFile).use { zip ->
|
ZipFile(zipFile).use { zip ->
|
||||||
@@ -169,6 +178,72 @@ class ZipUtilsTest {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test copyZipFilePartially - creates exact same output file`() {
|
||||||
|
val root1 = temporaryFolder.newFile()
|
||||||
|
val root2 = temporaryFolder.newFile()
|
||||||
|
|
||||||
|
copyZipFilePartially(zipFile, root1, "")
|
||||||
|
copyZipFilePartially(zipFile, root2, "")
|
||||||
|
|
||||||
|
assertTrue(
|
||||||
|
root1.readBytes().contentEquals(root2.readBytes()),
|
||||||
|
"Expected output zip files to be identical"
|
||||||
|
)
|
||||||
|
|
||||||
|
ZipFile(zipFile).use { original ->
|
||||||
|
ZipFile(root1).use { copy ->
|
||||||
|
original.entries().toList().forEach { originalEntry ->
|
||||||
|
val copyEntry = copy.getEntry(originalEntry.name) ?: fail("Missing entry in copy: ${originalEntry.name}")
|
||||||
|
assertEquals(
|
||||||
|
originalEntry.comment, copyEntry.comment,
|
||||||
|
"Expected same comment on entry ${originalEntry.name}"
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
originalEntry.compressedSize, copyEntry.compressedSize,
|
||||||
|
"Expected same compressedSize on entry ${originalEntry.name}"
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
originalEntry.size, copyEntry.size,
|
||||||
|
"Expected same size on entry ${originalEntry.name}"
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
originalEntry.crc, copyEntry.crc,
|
||||||
|
"Expected same crc on entry ${originalEntry.name}"
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
originalEntry.creationTime, copyEntry.creationTime,
|
||||||
|
"Expected same creationTime on entry ${originalEntry.name}"
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
originalEntry.time, copyEntry.time,
|
||||||
|
"Expected same time on entry ${originalEntry.name}"
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
originalEntry.lastAccessTime, copyEntry.lastAccessTime,
|
||||||
|
"Expected same lastAccessTime on entry ${originalEntry.name}"
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
originalEntry.lastModifiedTime, copyEntry.lastModifiedTime,
|
||||||
|
"Expected same lastModifiedTime on entry ${originalEntry.name}"
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
originalEntry.method, copyEntry.method,
|
||||||
|
"Expected same method on entry ${originalEntry.name}"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun assertZipContentEquals(
|
fun assertZipContentEquals(
|
||||||
@@ -206,3 +281,4 @@ fun assertDirectoryContentEquals(expected: File, actual: File, message: String)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user