Fix script classpath utility functions that use classpath filtering by "keys"

The problem was that only the first matching classpath entry were used.
The problem was reported by @lion7 on github (https://github.com/JetBrains/kotlin/commit/67ad3773de2b12f7e1d29e00151b997a4f6373ba#commitcomment-34443927)
This commit is contained in:
Ilya Chernikov
2019-07-25 17:33:28 +02:00
parent ec3ccf1ba8
commit a858607fac
2 changed files with 29 additions and 7 deletions
@@ -16,6 +16,7 @@ import java.util.jar.JarOutputStream
import java.util.jar.Manifest
import kotlin.script.experimental.jvm.util.classPathFromTypicalResourceUrls
import kotlin.script.experimental.jvm.util.classpathFromClassloader
import kotlin.script.experimental.jvm.util.scriptCompilationClasspathFromContextOrNull
class ClassPathTest : TestCase() {
@@ -57,6 +58,28 @@ class ClassPathTest : TestCase() {
Assert.assertTrue(cp.contains(File(root1, el).canonicalFile))
}
}
@Test
fun testFilterClasspath() {
val tempDir = createTempDir().canonicalFile
try {
val files = listOf(
File(tempDir, "projX/classes"),
File(tempDir, "projX/test-classes"),
File(tempDir, "projY/classes")
)
files.forEach { it.mkdirs() }
val classloader = URLClassLoader(files.map { it.toURI().toURL() }.toTypedArray(), null)
val classpath =
scriptCompilationClasspathFromContextOrNull("projX", classLoader = classloader)!!.map { it.toRelativeString(tempDir) }
Assert.assertEquals(files.dropLast(1).map { it.toRelativeString(tempDir) }, classpath)
} finally {
tempDir.deleteRecursively()
}
}
}
private val emulatedCollectionFiles = arrayOf(
@@ -228,19 +228,18 @@ internal fun List<File>.takeIfContainsAll(vararg keyNames: String): List<File>?
}
internal fun List<File>.filterIfContainsAll(vararg keyNames: String): List<File>? {
val res = hashMapOf<String, File>()
val foundKeys = mutableSetOf<String>()
val res = arrayListOf<File>()
for (cpentry in this) {
for (prefix in keyNames) {
if (!res.containsKey(prefix) &&
(cpentry.matchMaybeVersionedFile(prefix) || (cpentry.isDirectory && cpentry.hasParentNamed(prefix)))
) {
res[prefix] = cpentry
if (cpentry.matchMaybeVersionedFile(prefix) || (cpentry.isDirectory && cpentry.hasParentNamed(prefix))) {
foundKeys.add(prefix)
res.add(cpentry)
break
}
}
}
return if (keyNames.all { res.containsKey(it) }) res.values.toList()
else null
return res.takeIf { foundKeys.containsAll(keyNames.asList()) }
}
internal fun List<File>.takeIfContainsAny(vararg keyNames: String): List<File>? =