diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml new file mode 100644 index 0000000..0d4701f --- /dev/null +++ b/.github/workflows/build-windows.yml @@ -0,0 +1,42 @@ +name: Build Linux + +on: + workflow_call: + workflow_dispatch: + +jobs: + build: + runs-on: windows-latest + env: + GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3g" + + steps: + - uses: actions/checkout@v4 + + - name: JDK setup + uses: actions/setup-java@v4 + with: + java-version: | + 11 + 17 + distribution: corretto + + - name: Cache + uses: actions/cache@v4 + with: + path: | + ./build + ./.gradle + ~/.gradle/caches + ~/.gradle/wrapper + ~/.m2/repository + key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }} + restore-keys: | + ${{ runner.os }}-gradle- + + - name: Tests + run: ./gradlew allTest --parallel --no-daemon --stacktrace + + - name: Build Artifacts + run: ./gradlew publishToMavenLocal + diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8353777..a4b86b2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,3 +23,6 @@ jobs: name: Build macOS uses: ./.github/workflows/build-macos.yml + build-windows: + name: Build Windows + uses: ./.github/workflows/build-windows.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e37f00..8095b43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,12 @@ All notable changes to this project will be documented in this file. ### Changed +## [0.2.1] - 2024-04-23 + +### Fixes + +- NSHomeDirectory is only allowed to be written on iOS Simulators, but not on physical devices #33 + ## [0.2.0] - 2024-04-21 This version contains general house keeping, dependencies updates and ci improvement for better maintainability. diff --git a/README.md b/README.md index 8679fa5..536baa2 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ repositories { } dependencies { - implementation("me.sujanpoudel.multiplatform.utils:multiplatform-paths:0.2.0") + implementation("me.sujanpoudel.multiplatform.utils:multiplatform-paths:0.2.1") } ``` @@ -113,7 +113,7 @@ repositories { } dependencies { - implementation("me.sujanpoudel.multiplatform.utils:platform-identifier:0.2.0") + implementation("me.sujanpoudel.multiplatform.utils:platform-identifier:0.2.1") } ``` @@ -177,7 +177,7 @@ repositories { } dependencies { - implementation("me.sujanpoudel.multiplatform.utils:context-provider:0.2.0") + implementation("me.sujanpoudel.multiplatform.utils:context-provider:0.2.1") } ``` diff --git a/multiplatform-paths/build.gradle.kts b/multiplatform-paths/build.gradle.kts index 1acaa52..f586965 100644 --- a/multiplatform-paths/build.gradle.kts +++ b/multiplatform-paths/build.gradle.kts @@ -52,6 +52,15 @@ kotlin { } } + val androidUnitTest by getting { + dependencies { + implementation(libs.junit) + implementation(libs.ext.junit) + implementation(libs.espresso.core) + implementation(libs.robolectric) + } + } + val darwinMain by creating { dependsOn(commonMain) } @@ -90,6 +99,14 @@ kotlin { } } +android { + testOptions { + unitTests { + isIncludeAndroidResources = true + } + } +} + @Suppress("ktlint:standard:max-line-length") mavenPublishing { pom { diff --git a/multiplatform-paths/src/androidUnitTest/kotlin/me/sujanpoudel/utils/paths/AndroidDirectoriesTest.kt b/multiplatform-paths/src/androidUnitTest/kotlin/me/sujanpoudel/utils/paths/AndroidDirectoriesTest.kt new file mode 100644 index 0000000..7009a81 --- /dev/null +++ b/multiplatform-paths/src/androidUnitTest/kotlin/me/sujanpoudel/utils/paths/AndroidDirectoriesTest.kt @@ -0,0 +1,51 @@ +/* + * Copyright 2024 Sujan Poudel + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package me.sujanpoudel.utils.paths + +import android.content.Context +import androidx.test.core.app.ApplicationProvider +import kotlinx.io.files.Path +import me.sujanpoudel.utils.paths.utils.toPath +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import kotlin.test.assertEquals + +@RunWith(RobolectricTestRunner::class) +class AndroidDirectoriesTest { + private val appId: String = "me.sujanpoudel.utils.paths.test" + + private fun exceptedCacheDir(appId: String): Path { + val applicationContext = ApplicationProvider.getApplicationContext() + return applicationContext.cacheDir.absolutePath.toPath() + } + + private fun exceptedDataDir(appId: String): Path { + val applicationContext = ApplicationProvider.getApplicationContext() + return applicationContext.dataDir.absolutePath.toPath() + } + + @Test + fun testCacheDirectory() { + assertEquals(exceptedCacheDir(appId), cacheDirectory(appId)) + } + + @Test + fun testDataDirectory() { + assertEquals(exceptedDataDir(appId), dataDirectory(appId)) + } +} diff --git a/multiplatform-paths/src/commonTest/kotlin/me/sujanpoudel/utils/paths/DirectoriesTest.kt b/multiplatform-paths/src/commonTest/kotlin/me/sujanpoudel/utils/paths/DirectoriesTest.kt new file mode 100644 index 0000000..fdb56ae --- /dev/null +++ b/multiplatform-paths/src/commonTest/kotlin/me/sujanpoudel/utils/paths/DirectoriesTest.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2024 Sujan Poudel + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package me.sujanpoudel.utils.paths + +import kotlinx.io.files.Path +import kotlin.test.Test +import kotlin.test.assertEquals + +abstract class DirectoriesTest { + private val appId: String = "me.sujanpoudel.utils.paths.test" + + abstract fun exceptedCacheDir(appId: String): Path + + abstract fun exceptedDataDir(appId: String): Path + + @Test + fun testCacheDirectory() { + assertEquals(exceptedCacheDir(appId), cacheDirectory(appId)) + } + + @Test + fun testDataDirectory() { + assertEquals(exceptedDataDir(appId), dataDirectory(appId)) + } +} diff --git a/multiplatform-paths/src/desktopTest/kotlin/me/sujanpoudel/utils/paths/DesktopDirectoriesTest.kt b/multiplatform-paths/src/desktopTest/kotlin/me/sujanpoudel/utils/paths/DesktopDirectoriesTest.kt new file mode 100644 index 0000000..5ee4437 --- /dev/null +++ b/multiplatform-paths/src/desktopTest/kotlin/me/sujanpoudel/utils/paths/DesktopDirectoriesTest.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2024 Sujan Poudel + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package me.sujanpoudel.utils.paths + +import kotlinx.io.files.Path +import me.sujanpoudel.utils.paths.utils.div +import me.sujanpoudel.utils.paths.utils.toPath +import me.sujanpoudel.utils.platformIdentifier.Platform +import me.sujanpoudel.utils.platformIdentifier.hostOs + +class DesktopDirectoriesTest : DirectoriesTest() { + private fun getEnv(key: String) = System.getenv(key) as String + + override fun exceptedCacheDir(appId: String): Path { + return when (hostOs) { + is Platform.OS.Linux -> getEnv("HOME").toPath() / ".cache" / appId + is Platform.OS.MacOs -> getEnv("HOME").toPath() / "Library/Caches" / appId + is Platform.OS.Windows -> getEnv("APPDATA").toPath() / "Caches" / appId + else -> error("not supported") + } + } + + override fun exceptedDataDir(appId: String): Path { + return when (hostOs) { + is Platform.OS.Linux -> getEnv("HOME").toPath() / ".local/share" / appId + is Platform.OS.MacOs -> getEnv("HOME").toPath() / "Library/Application Support" / appId + is Platform.OS.Windows -> getEnv("APPDATA").toPath() / appId + else -> error("not supported") + } + } +} diff --git a/multiplatform-paths/src/iosTest/kotlin/me/sujanpoudel/utils/paths/IosDirectoriesTest.kt b/multiplatform-paths/src/iosTest/kotlin/me/sujanpoudel/utils/paths/IosDirectoriesTest.kt new file mode 100644 index 0000000..cf1f975 --- /dev/null +++ b/multiplatform-paths/src/iosTest/kotlin/me/sujanpoudel/utils/paths/IosDirectoriesTest.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2024 Sujan Poudel + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package me.sujanpoudel.utils.paths + +import kotlinx.io.files.Path +import me.sujanpoudel.utils.paths.utils.div +import me.sujanpoudel.utils.paths.utils.toPath +import platform.Foundation.NSApplicationSupportDirectory +import platform.Foundation.NSCachesDirectory +import platform.Foundation.NSSearchPathForDirectoriesInDomains +import platform.Foundation.NSUserDomainMask + +class IosDirectoriesTest : DirectoriesTest() { + override fun exceptedCacheDir(appId: String): Path { + return NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, true) + .firstOrNull()?.toString()?.toPath() ?: error("Unable to get 'NSCachesDirectory'") + } + + override fun exceptedDataDir(appId: String): Path { + return NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, true) + .firstOrNull()?.toString()?.toPath() + ?.let { it / appId } ?: error("Unable to get 'NSApplicationSupportDirectory'") + } +} diff --git a/multiplatform-paths/src/jsTest/kotlin/me/sujanpoudel/utils/paths/NodeDirectoriesTest.kt b/multiplatform-paths/src/jsTest/kotlin/me/sujanpoudel/utils/paths/NodeDirectoriesTest.kt new file mode 100644 index 0000000..39e3092 --- /dev/null +++ b/multiplatform-paths/src/jsTest/kotlin/me/sujanpoudel/utils/paths/NodeDirectoriesTest.kt @@ -0,0 +1,50 @@ +/* + * Copyright 2024 Sujan Poudel + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package me.sujanpoudel.utils.paths + +import kotlinx.io.files.Path +import me.sujanpoudel.utils.paths.utils.div +import me.sujanpoudel.utils.paths.utils.toPath +import me.sujanpoudel.utils.platformIdentifier.Platform +import me.sujanpoudel.utils.platformIdentifier.platform + +class NodeDirectoriesTest : DirectoriesTest() { + private fun getEnv(key: String) = eval("""process.env["$key"]""") as String + + override fun exceptedCacheDir(appId: String): Path { + val platform = platform() as? Platform.JS.Node ?: error("not supported") + + return when (platform.os) { + is Platform.OS.Linux -> getEnv("HOME").toPath() / ".cache" / appId + is Platform.OS.MacOs -> getEnv("HOME").toPath() / "Library/Caches" / appId + is Platform.OS.Windows -> getEnv("APPDATA").toPath() / "Caches" / appId + + else -> error("not supported") + } + } + + override fun exceptedDataDir(appId: String): Path { + val platform = platform() as? Platform.JS.Node ?: error("not supported") + + return when (platform.os) { + is Platform.OS.Linux -> getEnv("HOME").toPath() / ".local/share" / appId + is Platform.OS.MacOs -> getEnv("HOME").toPath() / "Library/Application Support" / appId + is Platform.OS.Windows -> getEnv("APPDATA").toPath() / appId + else -> error("not supported") + } + } +} diff --git a/multiplatform-paths/src/macosTest/kotlin/me/sujanpoudel/utils/paths/MacosDirectoriesTest.kt b/multiplatform-paths/src/macosTest/kotlin/me/sujanpoudel/utils/paths/MacosDirectoriesTest.kt new file mode 100644 index 0000000..375eb95 --- /dev/null +++ b/multiplatform-paths/src/macosTest/kotlin/me/sujanpoudel/utils/paths/MacosDirectoriesTest.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2024 Sujan Poudel + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package me.sujanpoudel.utils.paths + +import kotlinx.io.files.Path +import me.sujanpoudel.utils.paths.utils.div +import me.sujanpoudel.utils.paths.utils.toPath +import platform.Foundation.NSApplicationSupportDirectory +import platform.Foundation.NSCachesDirectory +import platform.Foundation.NSSearchPathForDirectoriesInDomains +import platform.Foundation.NSUserDomainMask + +class MacosDirectoriesTest : DirectoriesTest() { + override fun exceptedCacheDir(appId: String): Path { + return NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, true) + .firstOrNull()?.toString()?.toPath()?.let { it / appId } ?: error("Unable to get 'NSCachesDirectory'") + } + + override fun exceptedDataDir(appId: String): Path { + return NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, true) + .firstOrNull()?.toString()?.toPath()?.let { it / appId } ?: error("Unable to get 'NSApplicationSupportDirectory'") + } +} diff --git a/platform-identifier/src/desktopCommonMain/kotlin/me/sujanpoudel/utils/platformIdentifier/os.kt b/platform-identifier/src/desktopCommonMain/kotlin/me/sujanpoudel/utils/platformIdentifier/os.kt index 2bfc35f..93f49c0 100644 --- a/platform-identifier/src/desktopCommonMain/kotlin/me/sujanpoudel/utils/platformIdentifier/os.kt +++ b/platform-identifier/src/desktopCommonMain/kotlin/me/sujanpoudel/utils/platformIdentifier/os.kt @@ -40,7 +40,7 @@ internal fun hostOs(osName: String, archName: String, version: String): Platform return when (hostOs(osName)) { DesktopOs.Macos -> Platform.OS.MacOs(arch, version) DesktopOs.Linux -> Platform.OS.Linux(arch, version) - DesktopOs.Windows -> Platform.OS.Linux(arch, version) + DesktopOs.Windows -> Platform.OS.Windows(arch, version) DesktopOs.Unknown -> Platform.OS.Unknown(arch, version) } }