Repositories / gitweb2.git
gitweb2.git
Clone (read-only): git clone http://git.guha-anderson.com/git/gitweb2.git
@@ -3,14 +3,14 @@ A Kotlin/Native, read-only web viewer for local Git repositories. The app uses Ktor Native with the CIO engine for HTTP and the local -`/home/arjun/repos/homebox/kotlin-git` library for repository reads. +`/media/external0/arjun/repos/homebox/kotlin-git` library for repository reads. ## Requirements - Kotlin/Native through the Gradle wrapper - system `libgit2` visible through `pkg-config` - the local `kotlin-git` klibs built at - `/home/arjun/repos/homebox/kotlin-git/.build/klib` + `/media/external0/arjun/repos/homebox/kotlin-git/.build/klib` - the included Gradle wrapper ## Build
@@ -9,7 +9,7 @@ val ktorVersion = "3.4.2" val okioVersion = "3.17.0" val processVersion = "0.5.0" val kotlinGitDir = providers.gradleProperty("kotlinGitDir") - .orElse("/home/arjun/repos/homebox/kotlin-git") + .orElse("/media/external0/arjun/repos/homebox/kotlin-git") val kotlinGitKlib = kotlinGitDir.map { file("$it/.build/klib/kotlin-git.klib") } val libgit2Klib = kotlinGitDir.map { file("$it/.build/klib/libgit2.klib") }
@@ -1,3 +1,5 @@ +@file:OptIn(ExperimentalForeignApi::class) + package gitweb import io.ktor.http.ContentType @@ -13,6 +15,13 @@ import io.ktor.server.routing.get import io.ktor.server.routing.routing import io.ktor.utils.io.charsets.Charsets import io.matthewnelson.kmp.process.Process as KmpProcess +import kotlinx.cinterop.ExperimentalForeignApi +import kotlinx.cinterop.IntVar +import kotlinx.cinterop.alloc +import kotlinx.cinterop.memScoped +import kotlinx.cinterop.ptr +import kotlinx.cinterop.staticCFunction +import kotlinx.cinterop.value import kotlinx.git.Blob import kotlinx.git.Branch import kotlinx.git.BranchType @@ -22,6 +31,14 @@ import kotlinx.git.Repository import kotlinx.git.TreeEntryKind import okio.FileSystem import okio.Path.Companion.toPath +import platform.posix.SIGINT +import platform.posix.SIGKILL +import platform.posix.SIGTERM +import platform.posix._exit +import platform.posix.fork +import platform.posix.kill +import platform.posix.signal +import platform.posix.waitpid import kotlin.system.exitProcess private const val DefaultHost = "127.0.0.1" @@ -31,7 +48,7 @@ private const val DefaultPygmentsCommand = "pygmentize" fun runGitWeb2(args: Array<String>) { val config = parseArgs(args) ?: return - GitWebServer(config.root, config.host, config.port, config.pygmentsCommand).start() + runServerProcess(config) } private data class Config(val root: String, val host: String, val port: Int, val pygmentsCommand: String) @@ -355,6 +372,34 @@ private fun readCommandOutput(command: String, input: String? = null): String? { return output.stdout.replace("\r\n", "\n").replace('\r', '\n') } +private var childPidForSignal: Int = 0 + +private val parentSignalHandler = staticCFunction<Int, Unit> { signal -> + val childPid = childPidForSignal + if (childPid > 0) { + kill(childPid, SIGKILL) + } + _exit(128 + signal) +} + +private fun runServerProcess(config: Config) { + val childPid = fork() + when { + childPid < 0 -> GitWebServer(config.root, config.host, config.port, config.pygmentsCommand).start() + childPid == 0 -> GitWebServer(config.root, config.host, config.port, config.pygmentsCommand).start() + else -> waitForServerProcess(childPid) + } +} + +private fun waitForServerProcess(childPid: Int): Nothing = memScoped { + childPidForSignal = childPid + signal(SIGINT, parentSignalHandler) + signal(SIGTERM, parentSignalHandler) + val status = alloc<IntVar>() + waitpid(childPid, status.ptr, 0) + exitProcess(0) +} + private fun discoverRepos(root: String): List<RepoInfo> { val fileSystem = FileSystem.SYSTEM val found = mutableListOf<RepoInfo>()