diff --git a/mirai-core-utils/src/commonMain/kotlin/File.kt b/mirai-core-utils/src/commonMain/kotlin/File.kt index 5a6e27350..74775a115 100644 --- a/mirai-core-utils/src/commonMain/kotlin/File.kt +++ b/mirai-core-utils/src/commonMain/kotlin/File.kt @@ -59,6 +59,8 @@ public expect interface MiraiFile { public companion object { public fun create(path: String): MiraiFile + + public fun getWorkingDir(): MiraiFile } } diff --git a/mirai-core-utils/src/jvmBaseMain/kotlin/MiraiFile.kt b/mirai-core-utils/src/jvmBaseMain/kotlin/MiraiFile.kt index 55a2336eb..73f8a3b67 100644 --- a/mirai-core-utils/src/jvmBaseMain/kotlin/MiraiFile.kt +++ b/mirai-core-utils/src/jvmBaseMain/kotlin/MiraiFile.kt @@ -60,6 +60,10 @@ public actual interface MiraiFile { public actual fun create(path: String): MiraiFile { return File(path).asMiraiFile() } + + public actual fun getWorkingDir(): MiraiFile { + return create(System.getProperty("user.dir")) + } } } diff --git a/mirai-core-utils/src/mingwMain/kotlin/MiraiFileImpl.kt b/mirai-core-utils/src/mingwMain/kotlin/MiraiFileImpl.kt index 441402c6c..1c09c4a82 100644 --- a/mirai-core-utils/src/mingwMain/kotlin/MiraiFileImpl.kt +++ b/mirai-core-utils/src/mingwMain/kotlin/MiraiFileImpl.kt @@ -11,7 +11,9 @@ package net.mamoe.mirai.utils import io.ktor.utils.io.core.* import kotlinx.cinterop.* +import platform.posix.PATH_MAX import platform.posix.fopen +import platform.posix.getcwd import platform.windows.* @@ -21,9 +23,21 @@ internal actual class MiraiFileImpl actual constructor( ) : MiraiFile { override val path = path.replace("/", "\\") - companion object { + actual companion object { private val ROOT_REGEX = Regex("""^([a-zA-z]+:[/\\])""") private const val SEPARATOR = '\\' + + @Suppress("UnnecessaryOptInAnnotation") + @OptIn(UnsafeNumber::class) + actual fun getWorkingDir(): MiraiFile { + val path = memScoped { + ByteArray(PATH_MAX).usePinned { + getcwd(it.addressOf(0), it.get().size.convert()) + it.get().toKString() + } + } + return MiraiFile.create(path) + } } override val absolutePath: String = kotlin.run { diff --git a/mirai-core-utils/src/mingwTest/kotlin/MiraiFileImplTest.kt b/mirai-core-utils/src/mingwTest/kotlin/MiraiFileImplTest.kt index 246eeec38..f8bfbee5d 100644 --- a/mirai-core-utils/src/mingwTest/kotlin/MiraiFileImplTest.kt +++ b/mirai-core-utils/src/mingwTest/kotlin/MiraiFileImplTest.kt @@ -13,15 +13,11 @@ import kotlin.math.absoluteValue import kotlin.random.Random import kotlin.test.Test import kotlin.test.assertEquals -import kotlin.test.assertTrue internal class WindowsMiraiFileImplTest : AbstractNativeMiraiFileImplTest() { private val rand = Random.nextInt().absoluteValue - override val baseTempDir: MiraiFile = MiraiFile.create("C:/Users/Shared/mirai_test") - override val tempPath = "C:/Users/Shared/mirai_test/temp$rand" - private val tempDir = MiraiFile.create(tempPath).apply { - assertTrue("Failed to make temp directory: ${this.absolutePath}") { mkdirs() } - } + override val baseTempDir: MiraiFile = MiraiFile.create("mirai_unit_tests") + override val tempPath = "mirai_unit_tests/temp$rand" @Test override fun parent() { diff --git a/mirai-core-utils/src/nativeMain/kotlin/MiraiFile.kt b/mirai-core-utils/src/nativeMain/kotlin/MiraiFile.kt index 4c9b3c412..f652d61cd 100644 --- a/mirai-core-utils/src/nativeMain/kotlin/MiraiFile.kt +++ b/mirai-core-utils/src/nativeMain/kotlin/MiraiFile.kt @@ -60,6 +60,7 @@ public actual interface MiraiFile { public actual companion object { public actual fun create(path: String): MiraiFile = MiraiFileImpl(path) + public actual fun getWorkingDir(): MiraiFile = MiraiFileImpl.getWorkingDir() } } @@ -78,7 +79,11 @@ public actual fun MiraiFile.deleteRecursively(): Boolean { return nftw(absolutePath, deleteFile, 10, FTW_DEPTH or FTW_MOUNT or FTW_PHYS) >= 0 } -internal expect class MiraiFileImpl(path: String) : MiraiFile +internal expect class MiraiFileImpl(path: String) : MiraiFile { + companion object { + public fun getWorkingDir(): MiraiFile + } +} /* diff --git a/mirai-core-utils/src/nativeTest/kotlin/AbstractNativeMiraiFileImplTest.kt b/mirai-core-utils/src/nativeTest/kotlin/AbstractNativeMiraiFileImplTest.kt index b5de22c6c..88515a7e2 100644 --- a/mirai-core-utils/src/nativeTest/kotlin/AbstractNativeMiraiFileImplTest.kt +++ b/mirai-core-utils/src/nativeTest/kotlin/AbstractNativeMiraiFileImplTest.kt @@ -15,7 +15,7 @@ import kotlin.test.* internal abstract class AbstractNativeMiraiFileImplTest { protected abstract val baseTempDir: MiraiFile // MiraiFile.create("/Users/Shared/mirai_test") protected abstract val tempPath: String - private val tempDir by lazy { + protected val tempDir by lazy { MiraiFile.create(tempPath).apply { assertTrue("Failed to make temp directory: ${this.absolutePath}") { mkdirs() } } diff --git a/mirai-core-utils/src/unixMain/kotlin/MiraiFileImpl.kt b/mirai-core-utils/src/unixMain/kotlin/MiraiFileImpl.kt index f7f4edaee..4e7c0e659 100644 --- a/mirai-core-utils/src/unixMain/kotlin/MiraiFileImpl.kt +++ b/mirai-core-utils/src/unixMain/kotlin/MiraiFileImpl.kt @@ -11,10 +11,7 @@ package net.mamoe.mirai.utils import io.ktor.utils.io.core.* import io.ktor.utils.io.errors.* -import kotlinx.cinterop.UnsafeNumber -import kotlinx.cinterop.convert -import kotlinx.cinterop.memScoped -import kotlinx.cinterop.toKString +import kotlinx.cinterop.* import platform.posix.* @OptIn(ExperimentalIoApi::class) @@ -42,16 +39,31 @@ private fun readlink(path: String): String = memScoped { internal actual class MiraiFileImpl actual constructor( override val path: String, ) : MiraiFile { - companion object { + actual companion object { private const val SEPARATOR = '/' + private val ROOT by lazy { MiraiFileImpl("/") } + + @Suppress("UnnecessaryOptInAnnotation") + @OptIn(UnsafeNumber::class) + actual fun getWorkingDir(): MiraiFile { + val path = memScoped { + ByteArray(PATH_MAX).usePinned { + getcwd(it.addressOf(0), it.get().size.convert()) + it.get().toKString() + } + } + return MiraiFile.create(path) + } } override val absolutePath: String by lazy { kotlin.run { readlink(path) } } override val parent: MiraiFile? by lazy { + val absolutePath = absolutePath val p = absolutePath.substringBeforeLast(SEPARATOR, "") if (p.isEmpty()) { - return@lazy null + if (absolutePath.singleOrNull() == SEPARATOR) return@lazy null // root + else return@lazy ROOT } MiraiFileImpl(p) } @@ -123,7 +135,7 @@ internal actual class MiraiFileImpl actual constructor( override fun mkdir(): Boolean { @Suppress("UnnecessaryOptInAnnotation") // bug @OptIn(UnsafeNumber::class) - return mkdir(absolutePath, "755".toUShort(8).convert()).convert<Int>() == 0 + return (mkdir("$absolutePath/", "755".toUShort(8).convert()).convert<Int>() == 0) } @OptIn(UnsafeNumber::class) diff --git a/mirai-core-utils/src/unixTest/kotlin/UnixMiraiFileImplTest.kt b/mirai-core-utils/src/unixTest/kotlin/UnixMiraiFileImplTest.kt index 688d8afa7..91d7751c8 100644 --- a/mirai-core-utils/src/unixTest/kotlin/UnixMiraiFileImplTest.kt +++ b/mirai-core-utils/src/unixTest/kotlin/UnixMiraiFileImplTest.kt @@ -13,19 +13,15 @@ import kotlin.math.absoluteValue import kotlin.random.Random import kotlin.test.Test import kotlin.test.assertEquals -import kotlin.test.assertTrue internal class UnixMiraiFileImplTest : AbstractNativeMiraiFileImplTest() { private val rand = Random.nextInt().absoluteValue - override val baseTempDir: MiraiFile = MiraiFile.create("/Users/Shared/mirai_test") - override val tempPath = "/Users/Shared/mirai_test/temp$rand" - private val tempDir = MiraiFile.create(tempPath).apply { - assertTrue("Failed to make temp directory: ${this.absolutePath}") { mkdirs() } - } + override val baseTempDir: MiraiFile by lazy { MiraiFile.create(MiraiFile.getWorkingDir().absolutePath + "/mirai_unit_tests") } + override val tempPath by lazy { "${baseTempDir.absolutePath}/temp$rand" } @Test override fun parent() { - assertEquals("/Users/Shared/mirai_test", tempDir.parent!!.absolutePath) + assertEquals(baseTempDir.absolutePath, tempDir.parent!!.absolutePath) assertEquals(null, MiraiFile.create("/").parent) assertEquals("/", MiraiFile.create("/dev").parent?.path) assertEquals("/", MiraiFile.create("/dev").parent?.absolutePath)