Use system-specific user cache directory in main-kts
#KT-38222 fixed
This commit is contained in:
committed by
Ilya Chernikov
parent
8f80cf5664
commit
71da941c8b
+88
@@ -5,11 +5,13 @@
|
||||
package org.jetbrains.kotlin.mainKts.test
|
||||
|
||||
import org.jetbrains.kotlin.mainKts.COMPILED_SCRIPTS_CACHE_DIR_PROPERTY
|
||||
import org.jetbrains.kotlin.mainKts.impl.Directories
|
||||
import org.jetbrains.kotlin.mainKts.MainKtsScript
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
import java.io.*
|
||||
import java.net.URLClassLoader
|
||||
import java.util.*
|
||||
import kotlin.script.experimental.api.*
|
||||
import kotlin.script.experimental.host.toScriptSource
|
||||
import kotlin.script.experimental.jvm.baseClassLoader
|
||||
@@ -173,6 +175,92 @@ class MainKtsTest {
|
||||
}.lines()
|
||||
}
|
||||
|
||||
class CacheDirectoryDetectorTest {
|
||||
private val temp = "/test-temp-dir"
|
||||
private val home = "/test-home-dir"
|
||||
private val localAppData = "C:\\test-local-app-data"
|
||||
private val xdgCache = "/test-xdg-cache-dir"
|
||||
|
||||
@Test
|
||||
fun `Windows uses local app data dir`() {
|
||||
setOSName("Windows 10")
|
||||
assertCacheDir(localAppData)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Windows falls back to temp dir when no app data dir`() {
|
||||
setOSName("Windows 10")
|
||||
environment.remove("LOCALAPPDATA")
|
||||
assertCacheDir(temp)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `OS X uses user cache dir`() {
|
||||
setOSName("Mac OS X")
|
||||
assertCacheDir("$home/Library/Caches")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Linux uses XDG cache dir`() {
|
||||
setOSName("Linux")
|
||||
assertCacheDir(xdgCache)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Linux falls back to dot cache when no XDG dir`() {
|
||||
setOSName("Linux")
|
||||
environment.remove("XDG_CACHE_HOME")
|
||||
assertCacheDir("$home/.cache")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `FreeBSD uses XDG cache dir`() {
|
||||
setOSName("FreeBSD")
|
||||
assertCacheDir(xdgCache)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `FreeBSD falls back to dot cache when no XDG dir`() {
|
||||
setOSName("FreeBSD")
|
||||
environment.remove("XDG_CACHE_HOME")
|
||||
assertCacheDir("$home/.cache")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Unknown OS uses dot cache`() {
|
||||
setOSName("")
|
||||
assertCacheDir("$home/.cache")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Unknown OS and unknown home directory gives null`() {
|
||||
setOSName("")
|
||||
systemProperties.setProperty("user.home", "")
|
||||
assertCacheDir(null)
|
||||
}
|
||||
|
||||
private fun setOSName(name: String?) {
|
||||
systemProperties.setProperty("os.name", name)
|
||||
}
|
||||
|
||||
private fun assertCacheDir(path: String?) {
|
||||
val file = path?.let(::File)
|
||||
Assert.assertEquals(file, directories.cache)
|
||||
}
|
||||
|
||||
private val systemProperties = Properties().apply {
|
||||
setProperty("java.io.tmpdir", temp)
|
||||
setProperty("user.home", home)
|
||||
}
|
||||
|
||||
private val environment = mutableMapOf(
|
||||
"LOCALAPPDATA" to localAppData,
|
||||
"XDG_CACHE_HOME" to xdgCache
|
||||
)
|
||||
|
||||
private val directories = Directories(systemProperties, environment)
|
||||
}
|
||||
|
||||
internal fun captureOut(body: () -> Unit): String {
|
||||
val outStream = ByteArrayOutputStream()
|
||||
val prevOut = System.out
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
|
||||
package org.jetbrains.kotlin.mainKts.impl
|
||||
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
class Directories(
|
||||
private val systemProperties: Properties,
|
||||
private val environment: Map<String, String>)
|
||||
{
|
||||
// Links to recommendations for storing various kinds of files on different platforms:
|
||||
// Windows: http://www.microsoft.com/security/portal/mmpc/shared/variables.aspx
|
||||
// unix (freedesktop): http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
|
||||
// OS X: https://developer.apple.com/library/mac/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/AccessingFilesandDirectories/AccessingFilesandDirectories.html
|
||||
//
|
||||
// Note that the temp directory must not be used on Unix, as it is shared between users.
|
||||
val cache: File?
|
||||
get() = when (os) {
|
||||
OSKind.Windows -> getEnv("LOCALAPPDATA")?.toFile() ?: temp
|
||||
OSKind.OSX -> userHome?.resolve("Library/Caches")
|
||||
OSKind.Unix -> getEnv("XDG_CACHE_HOME")?.toFile() ?: userHome?.resolve(".cache")
|
||||
OSKind.Unknown -> userHome?.resolve(".cache")
|
||||
}
|
||||
|
||||
private val userHome: File?
|
||||
get() = getProperty("user.home")?.toFile()
|
||||
|
||||
private val temp: File?
|
||||
get() = getProperty("java.io.tmpdir")?.toFile()
|
||||
|
||||
private enum class OSKind {
|
||||
Windows,
|
||||
OSX,
|
||||
Unix,
|
||||
Unknown
|
||||
}
|
||||
|
||||
// OS detection based on
|
||||
// compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/FileSystemUtils.kt
|
||||
// which in turn is based on: http://www.code4copy.com/java/post/detecting-os-type-in-java
|
||||
private val os: OSKind
|
||||
get() = getProperty("os.name")?.toLowerCase().let { name ->
|
||||
when {
|
||||
name == null -> OSKind.Unknown
|
||||
name.startsWith("windows") -> OSKind.Windows
|
||||
name.startsWith("mac os") -> OSKind.OSX
|
||||
name.contains("unix") -> OSKind.Unix
|
||||
name.startsWith("linux") -> OSKind.Unix
|
||||
name.contains("bsd") -> OSKind.Unix
|
||||
name.startsWith("irix") -> OSKind.Unix
|
||||
name.startsWith("mpe/ix") -> OSKind.Unix
|
||||
name.startsWith("aix") -> OSKind.Unix
|
||||
name.startsWith("hp-ux") -> OSKind.Unix
|
||||
name.startsWith("sunos") -> OSKind.Unix
|
||||
name.startsWith("sun os") -> OSKind.Unix
|
||||
name.startsWith("solaris") -> OSKind.Unix
|
||||
else -> OSKind.Unknown
|
||||
}
|
||||
}
|
||||
|
||||
private fun getProperty(name: String) = systemProperties.getProperty(name).nullIfBlank()
|
||||
|
||||
private fun getEnv(name: String) = environment[name].nullIfBlank()
|
||||
|
||||
private fun String.toFile() = File(this)
|
||||
|
||||
private fun String?.nullIfBlank() = if (this == null || this.isBlank()) null else this
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.mainKts
|
||||
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.jetbrains.kotlin.mainKts.impl.Directories
|
||||
import org.jetbrains.kotlin.mainKts.impl.IvyResolver
|
||||
import java.io.File
|
||||
import java.nio.ByteBuffer
|
||||
@@ -72,8 +73,8 @@ class MainKtsHostConfiguration : ScriptingHostConfiguration(
|
||||
val cacheExtSetting = System.getProperty(COMPILED_SCRIPTS_CACHE_DIR_PROPERTY)
|
||||
?: System.getenv(COMPILED_SCRIPTS_CACHE_DIR_ENV_VAR)
|
||||
val cacheBaseDir = when {
|
||||
cacheExtSetting == null -> System.getProperty("java.io.tmpdir")
|
||||
?.let(::File)?.takeIf { it.exists() && it.isDirectory }
|
||||
cacheExtSetting == null -> Directories(System.getProperties(), System.getenv()).cache
|
||||
?.takeIf { it.exists() && it.isDirectory }
|
||||
?.let { File(it, "main.kts.compiled.cache").apply { mkdir() } }
|
||||
cacheExtSetting.isBlank() -> null
|
||||
else -> File(cacheExtSetting)
|
||||
@@ -173,3 +174,4 @@ private fun compiledScriptUniqueName(script: SourceCode, scriptCompilationConfig
|
||||
private fun ByteArray.toHexString(): String = joinToString("", transform = { "%02x".format(it) })
|
||||
|
||||
private fun Int.toByteArray() = ByteBuffer.allocate(Int.SIZE_BYTES).also { it.putInt(this) }.array()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user