[IC] Handle custom source set located outside project directory

To support build cache relocatability, we need to convert absolute paths
into relative paths before storing them in IC caches.

Before this commit, we computed relative paths based on the (root)
project directory and FAIL if some source files are located outside the
project directory.

With this commit, we will NOT FAIL in that case. This means relative
paths may start with "../". It's not "clean", but it can work.

Test: New test in BuildCacheRelocationIT
^KT-61852 Fixed
This commit is contained in:
Hung Nguyen
2023-09-19 18:08:02 +01:00
committed by Space Team
parent ff812197a8
commit 0d04b8783c
5 changed files with 85 additions and 96 deletions
@@ -16,12 +16,9 @@ import java.io.File
*/
class RelocatableFileToPathConverter(private val baseDir: File) : FileToPathConverter {
private val unixStyleBaseDirPathPrefix = "${baseDir.invariantSeparatorsPath}/"
override fun toPath(file: File): String {
check(file.invariantSeparatorsPath.startsWith(unixStyleBaseDirPathPrefix)) {
"The given file '${file.path}' is located outside the base directory '${baseDir.path}'"
}
// Note: If the given file is located outside `baseDir`, the relative path will start with "../". It's not "clean", but it can work.
// TODO: Re-design the code such that `baseDir` always contains the given file (also add a precondition check here).
return file.relativeTo(baseDir).invariantSeparatorsPath
}
@@ -5,34 +5,43 @@
package org.jetbrains.kotlin.incremental.storage
import org.jetbrains.kotlin.TestWithWorkingDir
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import kotlin.test.assertFailsWith
import org.junit.rules.TemporaryFolder
import java.io.File
class RelocatableFileToPathConverterTest : TestWithWorkingDir() {
class RelocatableFileToPathConverterTest {
@get:Rule
val tmpDir = TemporaryFolder()
private lateinit var baseDir: File
private lateinit var pathConverter: RelocatableFileToPathConverter
override fun setUp() {
super.setUp()
pathConverter = RelocatableFileToPathConverter(workingDir)
@Before
fun setUp() {
baseDir = tmpDir.newFolder("baseDir")
pathConverter = RelocatableFileToPathConverter(baseDir)
}
@Test
fun testToPath() {
assertEquals("com/example/Foo.kt", pathConverter.toPath(workingDir.resolve("com/example/Foo.kt")))
}
@Test
fun testToPathFails() {
assertFailsWith(IllegalStateException::class) {
pathConverter.toPath(workingDir.resolve("../outsideWorkingDir/com/example/Foo.kt").normalize())
}
assertEquals("com/example/Foo.kt", pathConverter.toPath(baseDir.resolve("com/example/Foo.kt")))
}
@Test
fun testToFile() {
assertEquals(workingDir.resolve("com/example/Foo.kt"), pathConverter.toFile("com/example/Foo.kt"))
assertEquals(baseDir.resolve("com/example/Foo.kt"), pathConverter.toFile("com/example/Foo.kt"))
}
@Test
fun testFileOutsideBaseDirectory() {
val fileOutsideBaseDir = baseDir.resolve("../outsideBaseDir/com/example/Foo.kt").normalize()
assertEquals("../outsideBaseDir/com/example/Foo.kt", pathConverter.toPath(fileOutsideBaseDir))
assertEquals(fileOutsideBaseDir, pathConverter.toFile("../outsideBaseDir/com/example/Foo.kt"))
}
}