From 2679f688d52f65c092a591f79512d1c0dc10d645 Mon Sep 17 00:00:00 2001 From: Infendro Date: Sun, 15 Feb 2026 14:06:35 +0100 Subject: [PATCH] split ci --- .gitea/workflows/{ci.yaml => publish.yaml} | 8 ++--- README.md | 19 ++---------- build.gradle.kts | 10 ++++--- gradle/libs.versions.toml | 6 ++-- .../kotlin/com/infendro/shell/Shell.kt | 30 +++++++++---------- .../kotlin/com/infendro/shell/Shell.js.kt | 16 +++++----- .../kotlin/com/infendro/shell/Shell.jvm.kt | 15 +++++----- .../kotlin/com/infendro/shell/Shell.native.kt | 16 +++++----- 8 files changed, 53 insertions(+), 67 deletions(-) rename .gitea/workflows/{ci.yaml => publish.yaml} (90%) diff --git a/.gitea/workflows/ci.yaml b/.gitea/workflows/publish.yaml similarity index 90% rename from .gitea/workflows/ci.yaml rename to .gitea/workflows/publish.yaml index a63d994..dad1306 100644 --- a/.gitea/workflows/ci.yaml +++ b/.gitea/workflows/publish.yaml @@ -3,7 +3,7 @@ on: branches: [ main ] jobs: - test: + publish: runs-on: linux steps: - name: Checkout @@ -19,7 +19,7 @@ jobs: uses: actions/cache@v4 with: key: gradle-${{ hashFiles('**/libs.versions.toml') }} - restore-keys: gradle- + restore-keys: gradle path: | ~/.gradle/caches/ ~/.gradle/wrapper/ @@ -28,7 +28,7 @@ jobs: uses: actions/cache@v4 with: key: konan-${{ hashFiles('**/libs.versions.toml') }} - restore-keys: konan- + restore-keys: konan path: | ~/.konan/ @@ -36,7 +36,7 @@ jobs: uses: actions/cache@v4 with: key: node-${{ hashFiles('**/libs.versions.toml') }} - restore-keys: node- + restore-keys: node path: | ~/.gradle/nodejs ~/.gradle/yarn diff --git a/README.md b/README.md index 08719f5..72154c0 100644 --- a/README.md +++ b/README.md @@ -2,15 +2,6 @@ `shell-kt` is a Kotlin Multiplatform library that enables the execution of shell commands. -## Targets - -| Target | Status | -|------------------|---------------| -| JVM | Supported | -| JavaScript | Supported | -| Native (Linux) | Supported | -| Native (Windows) | Not Supported | - ## Installation Add the following to your `build.gradle.kts`. @@ -21,21 +12,15 @@ repositories { } dependencies { - implementation("com.infendro:shell:1.0.0") + implementation("com.infendro:shell:1.1.0") } ``` ## Usage ```kotlin -import com.infendro.shell.Shell - suspend fun main() { - // the command to execute - val command = arrayOf("echo", "Hello World!") - - // execute the command - val result = Shell.run(command) + val result = execute("echo", "Hello World!") println(result.code) // 0 println(result.value) // Hello World! diff --git a/build.gradle.kts b/build.gradle.kts index 5e42033..ce92cbb 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,7 +2,7 @@ import com.infendro.plugin.infendro import com.infendro.plugin.token group = "com.infendro" -version = "1.0.0" +version = "1.1.0" plugins { alias(libs.plugins.infendro) @@ -13,9 +13,11 @@ plugins { kotlin { jvm() linuxX64() - js { - nodejs() - } + linuxArm64() + mingwX64() + macosX64() + macosArm64() + js { nodejs() } repositories { mavenCentral() diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 66207cb..717ea07 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] -infendro = "1.0.0" -kotlin = "2.2.21" -node = "2025.12.5-24.7.1" +infendro = "1.1.0" +kotlin = "2.3.0" +node = "2026.2.11-24.10.4" [plugins] infendro = { id = "com.infendro.plugin", version.ref = "infendro" } diff --git a/src/commonMain/kotlin/com/infendro/shell/Shell.kt b/src/commonMain/kotlin/com/infendro/shell/Shell.kt index 5c5badf..6c99885 100644 --- a/src/commonMain/kotlin/com/infendro/shell/Shell.kt +++ b/src/commonMain/kotlin/com/infendro/shell/Shell.kt @@ -1,20 +1,20 @@ package com.infendro.shell -object Shell { - suspend fun run( - command: Array, - directory: String? = null, - ): Result { - return execute(command, directory) - } +data class Result( + val code: Int, + val value: String, +) { + val success: Boolean + get() = code == 0 - class Result( - val code: Int, - val value: String, - ) + internal companion object { + fun from(code: Int, value: String) = Result(code, value) + + fun from(code: Int, success: () -> String, error: () -> String) = when (code) { + 0 -> Result(code, success()) + else -> Result(code, error()) + } + } } -internal expect suspend fun execute( - command: Array, - directory: String?, -): Shell.Result +expect suspend fun execute(vararg command: String, directory: String? = null): Result diff --git a/src/jsMain/kotlin/com/infendro/shell/Shell.js.kt b/src/jsMain/kotlin/com/infendro/shell/Shell.js.kt index d5b7826..9ad0fc9 100644 --- a/src/jsMain/kotlin/com/infendro/shell/Shell.js.kt +++ b/src/jsMain/kotlin/com/infendro/shell/Shell.js.kt @@ -5,15 +5,13 @@ import node.childProcess.exec import kotlin.coroutines.resume import kotlin.coroutines.suspendCoroutine -internal actual suspend fun execute( - command: Array, - directory: String?, -): Shell.Result = suspendCoroutine { continuation -> - val command = command.joinToString(" ") { "\"$it\"" } - val options = ExecOptions.invoke(cwd = directory) +actual suspend fun execute(vararg command: String, directory: String?): Result = suspendCoroutine { continuation -> + val command = command.joinToString(" ") { """"$it"""" } + val options = ExecOptions(cwd = directory) exec(command, options) { error, stdout, stderr -> - val code = if (error == null) 0 else error.code!!.toInt() - val value = (if (error == null) stdout else stderr) as String - continuation.resume(Shell.Result(code, value)) + val code = error?.code?.toInt() ?: 0 + + val result = Result.from(code, { stdout as String }, { stderr as String }) + continuation.resume(result) } } diff --git a/src/jvmMain/kotlin/com/infendro/shell/Shell.jvm.kt b/src/jvmMain/kotlin/com/infendro/shell/Shell.jvm.kt index e47b3d6..d74f7de 100644 --- a/src/jvmMain/kotlin/com/infendro/shell/Shell.jvm.kt +++ b/src/jvmMain/kotlin/com/infendro/shell/Shell.jvm.kt @@ -1,17 +1,18 @@ package com.infendro.shell import java.io.File +import kotlin.coroutines.resume +import kotlin.coroutines.suspendCoroutine -internal actual suspend fun execute( - command: Array, - directory: String?, -): Shell.Result { +actual suspend fun execute(vararg command: String, directory: String?): Result = suspendCoroutine { continuation -> val process = ProcessBuilder(*command).also { if (directory != null) { - it.directory(File(directory)) + val dir = File(directory) + it.directory(dir) } }.start() val code = process.waitFor() - val value = (if (code == 0) process.inputReader() else process.errorReader()).readText() - return Shell.Result(code, value) + + val result = Result.from(code, { process.inputReader().readText() }, { process.errorReader().readText() }) + continuation.resume(result) } diff --git a/src/nativeMain/kotlin/com/infendro/shell/Shell.native.kt b/src/nativeMain/kotlin/com/infendro/shell/Shell.native.kt index c3371d3..f05bb42 100644 --- a/src/nativeMain/kotlin/com/infendro/shell/Shell.native.kt +++ b/src/nativeMain/kotlin/com/infendro/shell/Shell.native.kt @@ -4,27 +4,27 @@ import kotlinx.cinterop.CPointer import kotlinx.cinterop.refTo import kotlinx.cinterop.toKString import platform.posix.* +import kotlin.coroutines.resume +import kotlin.coroutines.suspendCoroutine -internal actual suspend fun execute( - command: Array, - directory: String?, -): Shell.Result { - val command = command.joinToString(" ") { "\"$it\"" } +actual suspend fun execute(vararg command: String, directory: String?): Result = suspendCoroutine { continuation -> + val command = command.joinToString(" ") { """"$it"""" } if (directory != null) { chdir(directory) } val stream = popen(command, "r")!! val value = stream.readLines().joinToString("") val code = pclose(stream) - return Shell.Result(code, value) + + val result = Result.from(code, value) + continuation.resume(result) } private fun CPointer.readLines(): List { val lines = mutableListOf() val buffer = ByteArray(4096) while (true) { - val line = fgets(buffer.refTo(0), buffer.size, this) - if (line == null) break + val line = fgets(buffer.refTo(0), buffer.size, this) ?: break lines.add(line.toKString()) } return lines