[build-scripts] Preserve sorted order when traversing directories in ZipKt#archiveDir (IJI-2835)

Also adds ZipTest#`ensure entries are in sorted order` test (in intellij.platform.buildScripts.tests module).

GitOrigin-RevId: bd8ecaee539d0d0806240882fe722f72a4c87e22
This commit is contained in:
Ilia Kirianovskii
2025-10-07 07:18:15 +00:00
committed by intellij-monorepo-bot
parent ce8096f876
commit 807be9b250
2 changed files with 35 additions and 23 deletions
+13 -23
View File
@@ -11,7 +11,7 @@ import java.nio.file.StandardCopyOption
import java.nio.file.attribute.DosFileAttributeView
import java.nio.file.attribute.PosixFileAttributeView
import java.nio.file.attribute.PosixFilePermission
import java.util.ArrayDeque
import java.util.PriorityQueue
import java.util.zip.Deflater
enum class AddDirEntriesMode {
@@ -187,22 +187,22 @@ class ZipArchiver(@JvmField val fileAdded: ((String, Path) -> Boolean)? = null)
}
inline fun archiveDir(startDir: Path, addFile: (file: Path) -> Unit, excludes: List<PathMatcher>? = null) {
val dirCandidates = ArrayDeque<Path>()
dirCandidates.add(startDir)
val tempList = ArrayList<Path>()
if (Files.notExists(startDir)) {
return // empty
}
val priorityQueue = PriorityQueue<Path>()
priorityQueue.add(startDir)
while (true) {
val dir = dirCandidates.pollFirst() ?: break
tempList.clear()
val dirStream = try {
Files.newDirectoryStream(dir)
}
catch (_: NoSuchFileException) {
val path = priorityQueue.poll() ?: break // preserve sorted order
if (!Files.isDirectory(path)) {
addFile(path)
continue
}
dirStream.use {
Files.newDirectoryStream(path).use {
if (excludes == null) {
tempList.addAll(it)
priorityQueue.addAll(it)
}
else {
l@ for (child in it) {
@@ -212,20 +212,10 @@ inline fun archiveDir(startDir: Path, addFile: (file: Path) -> Unit, excludes: L
continue@l
}
}
tempList.add(child)
priorityQueue.add(child)
}
}
}
tempList.sort()
for (file in tempList) {
if (Files.isDirectory(file)) {
dirCandidates.add(file)
}
else {
addFile(file)
}
}
}
}
@@ -38,6 +38,7 @@ import java.util.zip.CRC32
import java.util.zip.Deflater
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
import kotlin.io.path.createDirectories
import kotlin.io.path.name
import kotlin.random.Random
@@ -643,6 +644,27 @@ class ZipTest {
}
}
}
@Test
fun `ensure entries are in sorted order`(@TempDir tempDir: Path) {
val dir = Files.createDirectories(tempDir.resolve("dir"))
Files.writeString(dir.resolve("1"), "1")
Files.writeString(dir.resolve("2").resolve("1").createDirectories().resolve("1"), "2.1.1")
Files.writeString(dir.resolve("3").createDirectories().resolve("1"), "3.1")
Files.writeString(dir.resolve("4"), "4")
val archiveFile = tempDir.resolve("archive.zip")
zip(archiveFile, mapOf(dir to ""), addDirEntriesMode = AddDirEntriesMode.NONE)
HashMapZipFile.load(archiveFile).use { zipFile ->
assertThat(zipFile.entries.map { it.name }).containsExactly(
"1",
"2/1/1",
"3/1",
"4",
)
}
}
}
private fun createTestFileInDir(dir: Path): String {