Convert to Go build system #2
19
.gitignore
vendored
19
.gitignore
vendored
@@ -1,14 +1,11 @@
|
|||||||
.gradle
|
### Gradle/Java ###
|
||||||
build/
|
**/.gradle
|
||||||
!gradle/wrapper/gradle-wrapper.jar
|
**/build/
|
||||||
!**/src/main/**/build/
|
!**/src/main/**/build/
|
||||||
!**/src/test/**/build/
|
!**/src/test/**/build/
|
||||||
|
|
||||||
### IntelliJ IDEA ###
|
### IntelliJ IDEA ###
|
||||||
.idea/modules.xml
|
**/.idea
|
||||||
.idea/jarRepositories.xml
|
|
||||||
.idea/compiler.xml
|
|
||||||
.idea/libraries/
|
|
||||||
*.iws
|
*.iws
|
||||||
*.iml
|
*.iml
|
||||||
*.ipr
|
*.ipr
|
||||||
@@ -42,4 +39,10 @@ bin/
|
|||||||
.vscode/
|
.vscode/
|
||||||
|
|
||||||
### Mac OS ###
|
### Mac OS ###
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
|
### Go ###
|
||||||
|
go.sum
|
||||||
|
|
||||||
|
### Build ###
|
||||||
|
/hakureiUpdate.sh
|
||||||
3
.idea/.gitignore
generated
vendored
3
.idea/.gitignore
generated
vendored
@@ -1,3 +0,0 @@
|
|||||||
# Default ignored files
|
|
||||||
/shelf/
|
|
||||||
/workspace.xml
|
|
||||||
10
.idea/codeStyles/Project.xml
generated
10
.idea/codeStyles/Project.xml
generated
@@ -1,10 +0,0 @@
|
|||||||
<component name="ProjectCodeStyleConfiguration">
|
|
||||||
<code_scheme name="Project" version="173">
|
|
||||||
<JetCodeStyleSettings>
|
|
||||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
|
||||||
</JetCodeStyleSettings>
|
|
||||||
<codeStyleSettings language="kotlin">
|
|
||||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
|
||||||
</codeStyleSettings>
|
|
||||||
</code_scheme>
|
|
||||||
</component>
|
|
||||||
5
.idea/codeStyles/codeStyleConfig.xml
generated
5
.idea/codeStyles/codeStyleConfig.xml
generated
@@ -1,5 +0,0 @@
|
|||||||
<component name="ProjectCodeStyleConfiguration">
|
|
||||||
<state>
|
|
||||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
|
||||||
</state>
|
|
||||||
</component>
|
|
||||||
35
.idea/gradle.xml
generated
35
.idea/gradle.xml
generated
@@ -1,35 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="GradleMigrationSettings" migrationVersion="1" />
|
|
||||||
<component name="GradleSettings">
|
|
||||||
<option name="linkedExternalProjectsSettings">
|
|
||||||
<GradleProjectSettings>
|
|
||||||
<compositeConfiguration>
|
|
||||||
<compositeBuild compositeDefinitionSource="SCRIPT">
|
|
||||||
<builds>
|
|
||||||
<build path="$PROJECT_DIR$/buildSrc" name="buildSrc">
|
|
||||||
<projects>
|
|
||||||
<project path="$PROJECT_DIR$/buildSrc" />
|
|
||||||
</projects>
|
|
||||||
</build>
|
|
||||||
</builds>
|
|
||||||
</compositeBuild>
|
|
||||||
</compositeConfiguration>
|
|
||||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
|
||||||
<option name="gradleHome" value="" />
|
|
||||||
<option name="modules">
|
|
||||||
<set>
|
|
||||||
<option value="$PROJECT_DIR$" />
|
|
||||||
<option value="$PROJECT_DIR$/buildSrc" />
|
|
||||||
<option value="$PROJECT_DIR$/plt-build" />
|
|
||||||
<option value="$PROJECT_DIR$/plt-build-wrapper" />
|
|
||||||
<option value="$PROJECT_DIR$/plt-fetch" />
|
|
||||||
<option value="$PROJECT_DIR$/plt-pkg" />
|
|
||||||
<option value="$PROJECT_DIR$/plt-server" />
|
|
||||||
<option value="$PROJECT_DIR$/plt-updated" />
|
|
||||||
</set>
|
|
||||||
</option>
|
|
||||||
</GradleProjectSettings>
|
|
||||||
</option>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
6
.idea/kotlinc.xml
generated
6
.idea/kotlinc.xml
generated
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="KotlinJpsPluginSettings">
|
|
||||||
<option name="version" value="2.2.20" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
10
.idea/misc.xml
generated
10
.idea/misc.xml
generated
@@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
|
||||||
<component name="FrameworkDetectionExcludesConfiguration">
|
|
||||||
<file type="web" url="file://$PROJECT_DIR$" />
|
|
||||||
</component>
|
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_24" default="true" project-jdk-name="openjdk-24" project-jdk-type="JavaSDK">
|
|
||||||
<output url="file://$PROJECT_DIR$/out" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
6
.idea/vcs.xml
generated
6
.idea/vcs.xml
generated
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="VcsDirectoryMappings">
|
|
||||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
tasks.register("build").configure {
|
|
||||||
group = "build"
|
|
||||||
dependsOn("test")
|
|
||||||
dependsOn(":plt-build:build")
|
|
||||||
dependsOn(":plt-build-wrapper:compileGo")
|
|
||||||
dependsOn(":plt-fetch:compileGo")
|
|
||||||
dependsOn(":plt-pkg:compileGo")
|
|
||||||
dependsOn(":plt-server:compileGo")
|
|
||||||
dependsOn(":plt-updated:compileGo")
|
|
||||||
}
|
|
||||||
tasks.register("test").configure {
|
|
||||||
group = "verification"
|
|
||||||
dependsOn(":plt-build:test")
|
|
||||||
dependsOn(":plt-build-wrapper:testGo")
|
|
||||||
dependsOn(":plt-fetch:testGo")
|
|
||||||
dependsOn(":plt-pkg:testGo")
|
|
||||||
dependsOn(":plt-server:testGo")
|
|
||||||
dependsOn(":plt-updated:testGo")
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
plugins {
|
|
||||||
`kotlin-dsl`
|
|
||||||
}
|
|
||||||
repositories {
|
|
||||||
gradlePluginPortal()
|
|
||||||
}
|
|
||||||
|
|
||||||
gradlePlugin {
|
|
||||||
plugins {
|
|
||||||
create("goPlugin") {
|
|
||||||
id = "goPlugin"
|
|
||||||
implementationClass = "moe.rosa.planterette.buildsrc.GoPlugin"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
package moe.rosa.planterette.buildsrc
|
|
||||||
|
|
||||||
import org.gradle.api.Plugin
|
|
||||||
import org.gradle.api.Project
|
|
||||||
import org.gradle.api.tasks.Exec
|
|
||||||
|
|
||||||
@Suppress("unused") // FIXME(mae) i have literally no clue why idea thinks GoPlugin is unused
|
|
||||||
class GoPlugin : Plugin<Project> {
|
|
||||||
override fun apply(project: Project) {
|
|
||||||
project.tasks.register("compileGo", Exec::class.java) {
|
|
||||||
group = "go"
|
|
||||||
description = "compile all go source files and output into build directory"
|
|
||||||
workingDir(project.layout.projectDirectory)
|
|
||||||
commandLine("go", "build", "-o", "../build/go/${project.name}")
|
|
||||||
}
|
|
||||||
project.tasks.register("runGo", Exec::class.java) {
|
|
||||||
group = "go"
|
|
||||||
description = "run go application"
|
|
||||||
workingDir(project.layout.projectDirectory)
|
|
||||||
commandLine("go", "run", "main.go")
|
|
||||||
}
|
|
||||||
project.tasks.register("testGo", Exec::class.java) {
|
|
||||||
group = "go"
|
|
||||||
description = "run go test"
|
|
||||||
workingDir(project.layout.projectDirectory)
|
|
||||||
commandLine("go", "test")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
9
cmd/plt-build-wrapper/main_test.go
Normal file
9
cmd/plt-build-wrapper/main_test.go
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPltBuildWrapper(t *testing.T) {
|
||||||
|
|
||||||
|
}
|
||||||
0
gradlew → cmd/plt-build/gradlew
vendored
0
gradlew → cmd/plt-build/gradlew
vendored
2
cmd/plt-build/main.go
Normal file
2
cmd/plt-build/main.go
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
//go:generate ./gradlew build
|
||||||
|
package plt_build
|
||||||
19
cmd/plt-build/main_test.go
Normal file
19
cmd/plt-build/main_test.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package plt_build
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPltBuild(t *testing.T) {
|
||||||
|
cmd := exec.CommandContext(t.Context(), "./gradlew", "test")
|
||||||
|
cmd.WaitDelay = 100 * time.Millisecond
|
||||||
|
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
|
||||||
|
err := cmd.Run()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,4 +2,8 @@ package moe.rosa.planterette
|
|||||||
|
|
||||||
import moe.rosa.planterette.hakurei.HakureiConfig
|
import moe.rosa.planterette.hakurei.HakureiConfig
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a Planterette build configuration.
|
||||||
|
* @param hakurei Hakurei container configuration for the application.
|
||||||
|
*/
|
||||||
data class PlanteretteConfig(var hakurei: HakureiConfig?)
|
data class PlanteretteConfig(var hakurei: HakureiConfig?)
|
||||||
@@ -44,11 +44,7 @@ annotation class FSOverlayDSL
|
|||||||
fun PlanteretteConfig.hakurei(id: String, init: @HakureiDSL HakureiConfig.() -> Unit) {
|
fun PlanteretteConfig.hakurei(id: String, init: @HakureiDSL HakureiConfig.() -> Unit) {
|
||||||
this.hakurei = HakureiConfig(id).apply(init)
|
this.hakurei = HakureiConfig(id).apply(init)
|
||||||
}
|
}
|
||||||
@HakureiDSL
|
|
||||||
fun HakureiConfig.executable(path: String, vararg args: String) {
|
|
||||||
this.path = AbsolutePath(path)
|
|
||||||
this.args = args.toList()
|
|
||||||
}
|
|
||||||
@HakureiDSL
|
@HakureiDSL
|
||||||
enum class DSLEnablements {
|
enum class DSLEnablements {
|
||||||
Wayland,
|
Wayland,
|
||||||
@@ -73,18 +69,7 @@ fun HakureiConfig.enable(vararg enablements: DSLEnablements) {
|
|||||||
fun HakureiConfig.directWayland(directWayland: Boolean = true) {
|
fun HakureiConfig.directWayland(directWayland: Boolean = true) {
|
||||||
this.directWayland = directWayland
|
this.directWayland = directWayland
|
||||||
}
|
}
|
||||||
@HakureiDSL
|
|
||||||
fun HakureiConfig.username(username: String) {
|
|
||||||
this.username = username
|
|
||||||
}
|
|
||||||
@HakureiDSL
|
|
||||||
fun HakureiConfig.shell(shell: String) {
|
|
||||||
this.shell = AbsolutePath(shell)
|
|
||||||
}
|
|
||||||
@HakureiDSL
|
|
||||||
fun HakureiConfig.home(home: String) {
|
|
||||||
this.home = AbsolutePath(home)
|
|
||||||
}
|
|
||||||
//TODO(mae) automatic identity?
|
//TODO(mae) automatic identity?
|
||||||
@HakureiDSL
|
@HakureiDSL
|
||||||
fun HakureiConfig.identity(identity: Int? = null) {
|
fun HakureiConfig.identity(identity: Int? = null) {
|
||||||
@@ -237,7 +222,23 @@ fun ContainerConfig.mapRealUid(mapRealUid: Boolean = true) {
|
|||||||
fun ContainerConfig.device(device: Boolean = true) {
|
fun ContainerConfig.device(device: Boolean = true) {
|
||||||
this.device = device
|
this.device = device
|
||||||
}
|
}
|
||||||
|
@ContainerDSL
|
||||||
|
fun ContainerConfig.username(username: String) {
|
||||||
|
this.username = username
|
||||||
|
}
|
||||||
|
@ContainerDSL
|
||||||
|
fun ContainerConfig.shell(shell: String) {
|
||||||
|
this.shell = AbsolutePath(shell)
|
||||||
|
}
|
||||||
|
@ContainerDSL
|
||||||
|
fun ContainerConfig.home(home: String) {
|
||||||
|
this.home = AbsolutePath(home)
|
||||||
|
}
|
||||||
|
@ContainerDSL
|
||||||
|
fun ContainerConfig.executable(path: String, vararg args: String) {
|
||||||
|
this.path = AbsolutePath(path)
|
||||||
|
this.args = args.toList()
|
||||||
|
}
|
||||||
@FilesystemDSL
|
@FilesystemDSL
|
||||||
data class FilesystemConfigs(val configs: MutableList<FilesystemConfig> = mutableListOf())
|
data class FilesystemConfigs(val configs: MutableList<FilesystemConfig> = mutableListOf())
|
||||||
|
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package moe.rosa.planterette.dsl
|
||||||
|
|
||||||
|
import moe.rosa.planterette.PlanteretteConfig
|
||||||
|
|
||||||
|
@PlanteretteDSL
|
||||||
|
fun PlanteretteConfig.metadata() {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,181 @@
|
|||||||
|
package moe.rosa.planterette.hakurei
|
||||||
|
|
||||||
|
import kotlinx.serialization.*
|
||||||
|
import kotlinx.serialization.descriptors.*
|
||||||
|
import kotlinx.serialization.encoding.*
|
||||||
|
|
||||||
|
import java.nio.file.Path
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Points to the file system root.
|
||||||
|
*/
|
||||||
|
val ROOT = AbsolutePath("/")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Points to the directory for system-specific configuration.
|
||||||
|
*/
|
||||||
|
val ETC = AbsolutePath("/etc")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Points to the place for small temporary files.
|
||||||
|
*/
|
||||||
|
val TMP = AbsolutePath("/tmp")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Points to a "tmpfs" file system for system packages to place runtime data, socket files, and similar.
|
||||||
|
*/
|
||||||
|
val RUN = AbsolutePath("/run")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Points to a directory containing per-user runtime directories,
|
||||||
|
* each usually individually mounted "tmpfs" instances.
|
||||||
|
*/
|
||||||
|
val RUN_USER: AbsolutePath = RUN + "user/"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Points to persistent, variable system data. Writable during normal system operation.
|
||||||
|
*/
|
||||||
|
val VAR = AbsolutePath("/var/")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Points to persistent system data.
|
||||||
|
*/
|
||||||
|
val VAR_LIB: AbsolutePath = VAR + "lib/"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Points to a nonstandard directory that is usually empty.
|
||||||
|
*/
|
||||||
|
val VAR_EMPTY: AbsolutePath = VAR + "empty/"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Points to the root directory for device nodes.
|
||||||
|
*/
|
||||||
|
val DEV = AbsolutePath("/dev/")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Points to a virtual kernel file system exposing the process list and other functionality.
|
||||||
|
*/
|
||||||
|
val PROC = AbsolutePath("/proc/")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Points to a hierarchy below `/proc/` that exposes a number of kernel tunables.
|
||||||
|
*/
|
||||||
|
val PROC_SYS: AbsolutePath = PROC + "sys/"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Points to a virtual kernel file system exposing discovered devices and other functionality.
|
||||||
|
*/
|
||||||
|
val SYS = AbsolutePath("/sys")
|
||||||
|
/**
|
||||||
|
* Holds a pathname checked to be absolute.
|
||||||
|
* @constructor checks pathname and returns a new [AbsolutePath] if pathname is absolute.
|
||||||
|
*/
|
||||||
|
@Serializable(with = AbsolutePathSerializer::class)
|
||||||
|
data class AbsolutePath(val pathname: String, @Transient val path: Path = Path.of(pathname)) {
|
||||||
|
init {
|
||||||
|
if(!isAbsolute(pathname)) {
|
||||||
|
throw AbsolutePathException(pathname)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//TODO discuss if we should keep this operator overloading around, i think it makes things cleaner but ik ozy doesn't like operator overloading
|
||||||
|
operator fun plus(other: String): AbsolutePath {
|
||||||
|
return AbsolutePath(pathname + other)
|
||||||
|
}
|
||||||
|
operator fun plus(other: AbsolutePath): AbsolutePath {
|
||||||
|
return AbsolutePath(pathname + other.pathname)
|
||||||
|
}
|
||||||
|
companion object {
|
||||||
|
fun isAbsolute(pathname: String): Boolean {
|
||||||
|
return Path.of(pathname).isAbsolute
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
object AbsolutePathSerializer : KSerializer<AbsolutePath> {
|
||||||
|
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor(this::class.qualifiedName!!, PrimitiveKind.STRING)
|
||||||
|
override fun serialize(encoder: Encoder, value: AbsolutePath) {
|
||||||
|
encoder.encodeString(value.pathname)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun deserialize(decoder: Decoder): AbsolutePath {
|
||||||
|
val path = decoder.decodeString()
|
||||||
|
return AbsolutePath(path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returned by [AbsolutePath()] and holds the invalid pathname.
|
||||||
|
*/
|
||||||
|
data class AbsolutePathException(val pathname: String) : IllegalArgumentException("Path $pathname is not absolute")
|
||||||
|
|
||||||
|
@Serializable sealed interface FilesystemConfig
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a host to container bind mount.
|
||||||
|
* @param target mount point in container, same as source if empty
|
||||||
|
* @param source host filesystem path to make available to the container
|
||||||
|
* @param write do not mount target read only
|
||||||
|
* @param device do not disable device files on target, implies write
|
||||||
|
* @param ensure create source as a directory if it does not exist
|
||||||
|
* @param optional skip this mount point if source does not exist
|
||||||
|
* @param special enable special behavior:
|
||||||
|
* for autoroot, target must be set to [Filesystem.ROOT];
|
||||||
|
* for autoetc, target must be set to [Filesystem.ETC]
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
@SerialName("bind")
|
||||||
|
data class FSBind(
|
||||||
|
@SerialName("dst") val target: AbsolutePath? = null,
|
||||||
|
@SerialName("src") val source: AbsolutePath,
|
||||||
|
val write: Boolean? = null,
|
||||||
|
@SerialName("dev") val device: Boolean? = null,
|
||||||
|
val ensure: Boolean? = null,
|
||||||
|
val optional: Boolean? = null,
|
||||||
|
val special: Boolean? = null,
|
||||||
|
) : FilesystemConfig
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an ephemeral (temporary) container mount point.
|
||||||
|
* @param target mount point in container
|
||||||
|
* @param write do not mount filesystem read-only
|
||||||
|
* @param size upper limit on the size of the filesystem
|
||||||
|
* @param perm initial permission bits of the new filesystem
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
@SerialName("ephemeral")
|
||||||
|
data class FSEphemeral(
|
||||||
|
@SerialName("dst") val target: AbsolutePath,
|
||||||
|
val write: Boolean,
|
||||||
|
val size: Int? = null,
|
||||||
|
val perm: Int,
|
||||||
|
) : FilesystemConfig
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a symlink in the container filesystem.
|
||||||
|
* @param target link path in container
|
||||||
|
* @param linkname linkname the symlink points to
|
||||||
|
* @param dereference whether to dereference linkname before creating the link
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
@SerialName("link")
|
||||||
|
data class FSLink(
|
||||||
|
@SerialName("dst") val target: AbsolutePath,
|
||||||
|
val linkname: String,
|
||||||
|
val dereference: Boolean,
|
||||||
|
) : FilesystemConfig
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an overlay mount point.
|
||||||
|
* @param target mount point in container
|
||||||
|
* @param lower any filesystem, does not need to be on a writable filesystem
|
||||||
|
* @param upper the upperdir is normally on a writable filesystem, leave as null to mount Lower readonly
|
||||||
|
* @param work the workdir needs to be an empty directory on the same filesystem as `upper`, must not be null if `upper` is populated
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
@SerialName("overlay")
|
||||||
|
data class FSOverlay(
|
||||||
|
@SerialName("dst") val target: AbsolutePath,
|
||||||
|
val lower: List<AbsolutePath>,
|
||||||
|
val upper: AbsolutePath? = null,
|
||||||
|
val work: AbsolutePath? = null,
|
||||||
|
) : FilesystemConfig
|
||||||
@@ -0,0 +1,162 @@
|
|||||||
|
package moe.rosa.planterette.hakurei
|
||||||
|
|
||||||
|
import kotlinx.serialization.*
|
||||||
|
import java.time.Duration
|
||||||
|
|
||||||
|
val WAIT_DELAY_DEFAULT = Duration.ofSeconds(1)!!
|
||||||
|
val WAIT_DELAY_MAX = Duration.ofSeconds(30)!!
|
||||||
|
|
||||||
|
const val IDENTITY_MIN = 0
|
||||||
|
const val IDENTITY_MAX = 9999
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [HakureiConfig] configures an application container.
|
||||||
|
* @param id Reverse-DNS style configured arbitrary identifier string.
|
||||||
|
* Passed to wayland security-context-v1 and used as part of defaults in dbus session proxy.
|
||||||
|
* @param enablements System services to make available in the container.
|
||||||
|
* @param sessionBus Session D-Bus proxy configuration.
|
||||||
|
* If set to null, session bus proxy assume built-in defaults.
|
||||||
|
* @param systemBus System D-Bus proxy configuration.
|
||||||
|
* If set to nil, system bus proxy is disabled.
|
||||||
|
* @param directWayland Direct access to wayland socket, no attempt is made to attach security-context-v1
|
||||||
|
* and the bare socket is made available to the container.
|
||||||
|
* @param extraPerms Extra acl update ops to perform before setuid.
|
||||||
|
* @param identity Numerical application id, passed to hsu, used to derive init user namespace credentials.
|
||||||
|
* @param groups Init user namespace supplementary groups inherited by all container processes.
|
||||||
|
* @param container High level container configuration.
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
data class HakureiConfig(
|
||||||
|
var id: String? = null,
|
||||||
|
|
||||||
|
var enablements: Enablements? = null,
|
||||||
|
@SerialName("session_bus") var sessionBus: DBusConfig? = null,
|
||||||
|
@SerialName("system_bus") var systemBus: DBusConfig? = null,
|
||||||
|
@SerialName("direct_wayland") var directWayland: Boolean? = null,
|
||||||
|
|
||||||
|
@SerialName("extra_perms") var extraPerms: List<ExtraPermsConfig>? = null,
|
||||||
|
var identity: Int? = null,
|
||||||
|
var groups: List<String>? = null,
|
||||||
|
|
||||||
|
var container: ContainerConfig? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes the container configuration to be applied to the container.
|
||||||
|
* @param hostname Container UTS namespace hostname.
|
||||||
|
* @param waitDelay Duration in nanoseconds to wait for after interrupting the initial process.
|
||||||
|
* Defaults to [WAIT_DELAY_DEFAULT] if less than or equals to zero,
|
||||||
|
* or [WAIT_DELAY_MAX] if greater than [WAIT_DELAY_MAX].
|
||||||
|
*
|
||||||
|
* @param seccompCompat Emit Flatpak-compatible seccomp filter programs.
|
||||||
|
* @param devel Allow ptrace and friends.
|
||||||
|
* @param userns Allow userns creation and container setup syscalls.
|
||||||
|
* @param hostNet Share host net namespace.
|
||||||
|
* @param hostAbstract Share abstract unix socket scope.
|
||||||
|
* @param tty Allow dangerous terminal I/O (faking input).
|
||||||
|
* @param multiarch Allow multiarch.
|
||||||
|
*
|
||||||
|
* @param env Initial process environment variables.
|
||||||
|
*
|
||||||
|
* @param mapRealUid Map target user uid to privileged user uid in the container user namespace.
|
||||||
|
* Some programs fail to connect to dbus session running as a different uid,
|
||||||
|
* this option works around it by mapping priv-side caller uid in container.
|
||||||
|
*
|
||||||
|
* @param device Mount `/dev/` from the init mount namespace as-is in the container mount namespace.
|
||||||
|
* @param filesystem Container mount points.
|
||||||
|
* If the first element targets /, it is inserted early and excluded from path hiding.
|
||||||
|
* @param username String used as the username of the emulated user, validated against the default `NAME_REGEX` from adduser.
|
||||||
|
* @param shell Pathname of shell in the container filesystem to use for the emulated user.
|
||||||
|
* @param home Directory in the container filesystem to enter and use as the home directory of the emulated user.
|
||||||
|
* @param path Pathname to executable file in the container filesystem.
|
||||||
|
* @param args Final args passed to the initial program.
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
data class ContainerConfig(
|
||||||
|
var hostname: String? = null,
|
||||||
|
@SerialName("wait_delay") var waitDelay: Long? = null,
|
||||||
|
@SerialName("seccomp_compat") var seccompCompat: Boolean? = null,
|
||||||
|
var devel: Boolean? = null,
|
||||||
|
var userns: Boolean? = null,
|
||||||
|
@SerialName("host_net") var hostNet: Boolean? = null,
|
||||||
|
@SerialName("host_abstract") var hostAbstract: Boolean? = null,
|
||||||
|
var tty: Boolean? = null,
|
||||||
|
var multiarch: Boolean? = null,
|
||||||
|
|
||||||
|
var env: Map<String, String>? = null,
|
||||||
|
|
||||||
|
@SerialName("map_real_uid") var mapRealUid: Boolean? = null,
|
||||||
|
var device: Boolean? = null,
|
||||||
|
|
||||||
|
var filesystem: List<FilesystemConfig>? = null,
|
||||||
|
|
||||||
|
var username: String? = "chronos",
|
||||||
|
var shell: AbsolutePath? = null,
|
||||||
|
var home: AbsolutePath? = null,
|
||||||
|
var path: AbsolutePath? = null,
|
||||||
|
var args: List<String>? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes an acl update op.
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
data class ExtraPermsConfig(
|
||||||
|
var ensure: Boolean? = null,
|
||||||
|
var path: AbsolutePath,
|
||||||
|
@SerialName("r") var read: Boolean? = null,
|
||||||
|
@SerialName("w") var write: Boolean? = null,
|
||||||
|
@SerialName("x") var execute: Boolean? = null,
|
||||||
|
) {
|
||||||
|
override fun toString(): String {
|
||||||
|
val buffer = StringBuffer(5 + path.toString().length)
|
||||||
|
buffer.append("---")
|
||||||
|
if(ensure == true) {
|
||||||
|
buffer.append("+")
|
||||||
|
}
|
||||||
|
buffer.append(":")
|
||||||
|
buffer.append(path.toString())
|
||||||
|
if(read == true) {
|
||||||
|
buffer.setCharAt(0, 'r')
|
||||||
|
}
|
||||||
|
if(write == true) {
|
||||||
|
buffer.setCharAt(1, 'w')
|
||||||
|
}
|
||||||
|
if(execute == true) {
|
||||||
|
buffer.setCharAt(2, 'x')
|
||||||
|
}
|
||||||
|
return buffer.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the `xdg-dbus-proxy` process.
|
||||||
|
* @param see Set `see` policy for `NAME` (`--see=NAME`)
|
||||||
|
* @param talk Set `talk` policy for `NAME` (`--talk=NAME`)
|
||||||
|
* @param own Set `own` policy for `NAME` (`--own=NAME)
|
||||||
|
* @param call Set `RULE` for calls on `NAME` (`--call=NAME=RULE`)
|
||||||
|
* @param broadcast Set `RULE` for broadcasts from `NAME` (`--broadcast=NAME=RULE`)
|
||||||
|
* @param log Turn on logging (`--log`)
|
||||||
|
* @param filter Enable filtering (`--filter`)
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
data class DBusConfig(
|
||||||
|
var see: List<String>? = null,
|
||||||
|
var talk: List<String>? = null,
|
||||||
|
var own: List<String>? = null,
|
||||||
|
var call: Map<String, String>? = null,
|
||||||
|
var broadcast: Map<String, String>? = null,
|
||||||
|
var log: Boolean? = null,
|
||||||
|
var filter: Boolean? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an optional host service to export to the target user.
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
data class Enablements(
|
||||||
|
var wayland: Boolean? = null,
|
||||||
|
var x11: Boolean? = null,
|
||||||
|
var dbus: Boolean? = null,
|
||||||
|
var pulse: Boolean? = null,
|
||||||
|
)
|
||||||
@@ -1,19 +1,12 @@
|
|||||||
import moe.rosa.planterette.dsl.*
|
import moe.rosa.planterette.dsl.*
|
||||||
import moe.rosa.planterette.dsl.DSLEnablements.*
|
import moe.rosa.planterette.dsl.DSLEnablements.*
|
||||||
import kotlin.test.Test
|
import kotlin.test.*
|
||||||
import kotlin.test.assertEquals
|
|
||||||
|
|
||||||
class DSLTest {
|
class HakureiDSLTest {
|
||||||
companion object {
|
companion object {
|
||||||
val HAKUREI_DSL_TEST = planterette {
|
val HAKUREI_DSL_TEST = planterette {
|
||||||
hakurei("org.chromium.Chromium") {
|
hakurei("org.chromium.Chromium") {
|
||||||
executable("/run/current-system/sw/bin/chromium",
|
|
||||||
"chromium",
|
|
||||||
"--ignore-gpu-blocklist",
|
|
||||||
"--disable-smooth-scrolling",
|
|
||||||
"--enable-features=UseOzonePlatform",
|
|
||||||
"--ozone-platform=wayland"
|
|
||||||
)
|
|
||||||
enable(Wayland, DBus, Pulse)
|
enable(Wayland, DBus, Pulse)
|
||||||
dbus {
|
dbus {
|
||||||
session {
|
session {
|
||||||
@@ -38,9 +31,7 @@ class DSLTest {
|
|||||||
filter()
|
filter()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
username("chronos")
|
|
||||||
shell("/run/current-system/sw/bin/zsh")
|
|
||||||
home("/data/data/org.chromium.Chromium")
|
|
||||||
extraPerms(
|
extraPerms(
|
||||||
perm("/var/lib/hakurei/u0") {
|
perm("/var/lib/hakurei/u0") {
|
||||||
ensure()
|
ensure()
|
||||||
@@ -67,6 +58,16 @@ class DSLTest {
|
|||||||
"GOOGLE_DEFAULT_CLIENT_SECRET" to "OTJgUOQcT7lO7GsGZq2G4IlT")
|
"GOOGLE_DEFAULT_CLIENT_SECRET" to "OTJgUOQcT7lO7GsGZq2G4IlT")
|
||||||
mapRealUid()
|
mapRealUid()
|
||||||
device()
|
device()
|
||||||
|
executable("/run/current-system/sw/bin/chromium",
|
||||||
|
"chromium",
|
||||||
|
"--ignore-gpu-blocklist",
|
||||||
|
"--disable-smooth-scrolling",
|
||||||
|
"--enable-features=UseOzonePlatform",
|
||||||
|
"--ozone-platform=wayland"
|
||||||
|
)
|
||||||
|
username("chronos")
|
||||||
|
shell("/run/current-system/sw/bin/zsh")
|
||||||
|
home("/data/data/org.chromium.Chromium")
|
||||||
filesystem {
|
filesystem {
|
||||||
bind("/var/lib/hakurei/base/org.debian" to "/") {
|
bind("/var/lib/hakurei/base/org.debian" to "/") {
|
||||||
write()
|
write()
|
||||||
@@ -80,11 +81,10 @@ class DSLTest {
|
|||||||
perm(493)
|
perm(493)
|
||||||
}
|
}
|
||||||
overlay("/nix/store") {
|
overlay("/nix/store") {
|
||||||
lower("/mnt-root/nix/.ro-store")
|
lower("/var/lib/hakurei/base/org.nixos/ro-store")
|
||||||
upper("/mnt-root/nix/.rw-store/upper")
|
upper("/var/lib/hakurei/nix/u0/org.chromium.Chromium/rw-store/upper")
|
||||||
work("/mnt-root/nix/.rw-store/work")
|
work("/var/lib/hakurei/nix/u0/org.chromium.Chromium/rw-store/work")
|
||||||
}
|
}
|
||||||
bind("/nix/store")
|
|
||||||
link("/run/current-system") {
|
link("/run/current-system") {
|
||||||
dereference()
|
dereference()
|
||||||
}
|
}
|
||||||
@@ -8,14 +8,7 @@ class HakureiTest {
|
|||||||
companion object {
|
companion object {
|
||||||
val TEMPLATE_DATA = HakureiConfig(
|
val TEMPLATE_DATA = HakureiConfig(
|
||||||
id = "org.chromium.Chromium",
|
id = "org.chromium.Chromium",
|
||||||
path = AbsolutePath("/run/current-system/sw/bin/chromium"),
|
|
||||||
args = listOf(
|
|
||||||
"chromium",
|
|
||||||
"--ignore-gpu-blocklist",
|
|
||||||
"--disable-smooth-scrolling",
|
|
||||||
"--enable-features=UseOzonePlatform",
|
|
||||||
"--ozone-platform=wayland"
|
|
||||||
),
|
|
||||||
enablements = Enablements(
|
enablements = Enablements(
|
||||||
wayland = true,
|
wayland = true,
|
||||||
dbus = true,
|
dbus = true,
|
||||||
@@ -57,9 +50,7 @@ class HakureiTest {
|
|||||||
broadcast = null,
|
broadcast = null,
|
||||||
filter = true
|
filter = true
|
||||||
),
|
),
|
||||||
username = "chronos",
|
|
||||||
shell = AbsolutePath("/run/current-system/sw/bin/zsh"),
|
|
||||||
home = AbsolutePath("/data/data/org.chromium.Chromium"),
|
|
||||||
extraPerms = listOf(
|
extraPerms = listOf(
|
||||||
ExtraPermsConfig(
|
ExtraPermsConfig(
|
||||||
ensure = true,
|
ensure = true,
|
||||||
@@ -119,13 +110,10 @@ class HakureiTest {
|
|||||||
FSOverlay(
|
FSOverlay(
|
||||||
target = AbsolutePath("/nix/store"),
|
target = AbsolutePath("/nix/store"),
|
||||||
lower = listOf(
|
lower = listOf(
|
||||||
AbsolutePath("/mnt-root/nix/.ro-store")
|
AbsolutePath("/var/lib/hakurei/base/org.nixos/ro-store")
|
||||||
),
|
),
|
||||||
upper = AbsolutePath("/mnt-root/nix/.rw-store/upper"),
|
upper = AbsolutePath("/var/lib/hakurei/nix/u0/org.chromium.Chromium/rw-store/upper"),
|
||||||
work = AbsolutePath("/mnt-root/nix/.rw-store/work")
|
work = AbsolutePath("/var/lib/hakurei/nix/u0/org.chromium.Chromium/rw-store/work")
|
||||||
),
|
|
||||||
FSBind(
|
|
||||||
source = AbsolutePath("/nix/store")
|
|
||||||
),
|
),
|
||||||
FSLink(
|
FSLink(
|
||||||
target = AbsolutePath("/run/current-system"),
|
target = AbsolutePath("/run/current-system"),
|
||||||
@@ -148,7 +136,19 @@ class HakureiTest {
|
|||||||
device = true,
|
device = true,
|
||||||
optional = true
|
optional = true
|
||||||
)
|
)
|
||||||
)
|
),
|
||||||
|
|
||||||
|
username = "chronos",
|
||||||
|
shell = AbsolutePath("/run/current-system/sw/bin/zsh"),
|
||||||
|
home = AbsolutePath("/data/data/org.chromium.Chromium"),
|
||||||
|
path = AbsolutePath("/run/current-system/sw/bin/chromium"),
|
||||||
|
args = listOf(
|
||||||
|
"chromium",
|
||||||
|
"--ignore-gpu-blocklist",
|
||||||
|
"--disable-smooth-scrolling",
|
||||||
|
"--enable-features=UseOzonePlatform",
|
||||||
|
"--ozone-platform=wayland"
|
||||||
|
),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
val TEMPLATE_JSON = ProcessBuilder("hakurei", "template")
|
val TEMPLATE_JSON = ProcessBuilder("hakurei", "template")
|
||||||
@@ -4,6 +4,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHelloWorld(t *testing.T) {
|
func TestPltFetch(t *testing.T) {
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHelloWorld(t *testing.T) {
|
func TestPltPkg(t *testing.T) {
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHelloWorld(t *testing.T) {
|
func TestPltServer(t *testing.T) {
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHelloWorld(t *testing.T) {
|
func TestPltUpdated(t *testing.T) {
|
||||||
|
|
||||||
}
|
}
|
||||||
5
go.mod
Normal file
5
go.mod
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
module rosa.moe/planterette
|
||||||
|
|
||||||
|
go 1.24.9
|
||||||
|
|
||||||
|
require hakurei.app v0.3.1 // indirect
|
||||||
89
gradlew.bat
vendored
89
gradlew.bat
vendored
@@ -1,89 +0,0 @@
|
|||||||
@rem
|
|
||||||
@rem Copyright 2015 the original author or authors.
|
|
||||||
@rem
|
|
||||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
@rem you may not use this file except in compliance with the License.
|
|
||||||
@rem You may obtain a copy of the License at
|
|
||||||
@rem
|
|
||||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
@rem
|
|
||||||
@rem Unless required by applicable law or agreed to in writing, software
|
|
||||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
@rem See the License for the specific language governing permissions and
|
|
||||||
@rem limitations under the License.
|
|
||||||
@rem
|
|
||||||
|
|
||||||
@if "%DEBUG%" == "" @echo off
|
|
||||||
@rem ##########################################################################
|
|
||||||
@rem
|
|
||||||
@rem Gradle startup script for Windows
|
|
||||||
@rem
|
|
||||||
@rem ##########################################################################
|
|
||||||
|
|
||||||
@rem Set local scope for the variables with windows NT shell
|
|
||||||
if "%OS%"=="Windows_NT" setlocal
|
|
||||||
|
|
||||||
set DIRNAME=%~dp0
|
|
||||||
if "%DIRNAME%" == "" set DIRNAME=.
|
|
||||||
set APP_BASE_NAME=%~n0
|
|
||||||
set APP_HOME=%DIRNAME%
|
|
||||||
|
|
||||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
|
||||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
|
||||||
|
|
||||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
|
||||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
|
||||||
|
|
||||||
@rem Find java.exe
|
|
||||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
|
||||||
|
|
||||||
set JAVA_EXE=java.exe
|
|
||||||
%JAVA_EXE% -version >NUL 2>&1
|
|
||||||
if "%ERRORLEVEL%" == "0" goto execute
|
|
||||||
|
|
||||||
echo.
|
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
|
||||||
echo.
|
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
|
||||||
echo location of your Java installation.
|
|
||||||
|
|
||||||
goto fail
|
|
||||||
|
|
||||||
:findJavaFromJavaHome
|
|
||||||
set JAVA_HOME=%JAVA_HOME:"=%
|
|
||||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
|
||||||
|
|
||||||
if exist "%JAVA_EXE%" goto execute
|
|
||||||
|
|
||||||
echo.
|
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
|
||||||
echo.
|
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
|
||||||
echo location of your Java installation.
|
|
||||||
|
|
||||||
goto fail
|
|
||||||
|
|
||||||
:execute
|
|
||||||
@rem Setup the command line
|
|
||||||
|
|
||||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
|
||||||
|
|
||||||
|
|
||||||
@rem Execute Gradle
|
|
||||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
|
||||||
|
|
||||||
:end
|
|
||||||
@rem End local scope for the variables with windows NT shell
|
|
||||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
|
||||||
|
|
||||||
:fail
|
|
||||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
|
||||||
rem the _cmd.exe /c_ return code!
|
|
||||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
|
||||||
exit /b 1
|
|
||||||
|
|
||||||
:mainEnd
|
|
||||||
if "%OS%"=="Windows_NT" endlocal
|
|
||||||
|
|
||||||
:omega
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id("goPlugin")
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
module plt-build-wrapper
|
|
||||||
|
|
||||||
go 1.24
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
package moe.rosa.planterette
|
|
||||||
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
package moe.rosa.planterette.hakurei
|
|
||||||
|
|
||||||
import kotlinx.serialization.*
|
|
||||||
import kotlinx.serialization.descriptors.*
|
|
||||||
import kotlinx.serialization.encoding.*
|
|
||||||
|
|
||||||
import java.nio.file.Path
|
|
||||||
|
|
||||||
/**
|
|
||||||
* AbsolutePath holds a pathname checked to be absolute.
|
|
||||||
* @constructor checks pathname and returns a new AbsolutePath if pathname is absolute.
|
|
||||||
*/
|
|
||||||
@Serializable(with = AbsolutePathSerializer::class)
|
|
||||||
data class AbsolutePath(val pathname: String, @Transient val path: Path = Path.of(pathname)) {
|
|
||||||
init {
|
|
||||||
if(!isAbsolute(pathname)) {
|
|
||||||
throw AbsolutePathException(pathname)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
operator fun plus(other: String): AbsolutePath {
|
|
||||||
return AbsolutePath(pathname + other)
|
|
||||||
}
|
|
||||||
companion object {
|
|
||||||
fun isAbsolute(pathname: String): Boolean {
|
|
||||||
return Path.of(pathname).isAbsolute
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
object AbsolutePathSerializer : KSerializer<AbsolutePath> {
|
|
||||||
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor(this::class.qualifiedName!!, PrimitiveKind.STRING)
|
|
||||||
override fun serialize(encoder: Encoder, value: AbsolutePath) {
|
|
||||||
encoder.encodeString(value.pathname)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun deserialize(decoder: Decoder): AbsolutePath {
|
|
||||||
val path = decoder.decodeString()
|
|
||||||
return AbsolutePath(path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* AbsolutePathException is returned by @see AbsolutePath() and holds the invalid pathname.
|
|
||||||
*/
|
|
||||||
data class AbsolutePathException(val pathname: String) : IllegalArgumentException("Path $pathname is not absolute")
|
|
||||||
|
|
||||||
@Serializable sealed interface FilesystemConfig
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
@SerialName("bind")
|
|
||||||
data class FSBind(
|
|
||||||
@SerialName("dst") val target: AbsolutePath? = null,
|
|
||||||
@SerialName("src") val source: AbsolutePath,
|
|
||||||
val write: Boolean? = null,
|
|
||||||
@SerialName("dev") val device: Boolean? = null,
|
|
||||||
val ensure: Boolean? = null,
|
|
||||||
val optional: Boolean? = null,
|
|
||||||
val special: Boolean? = null,
|
|
||||||
) : FilesystemConfig
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
@SerialName("ephemeral")
|
|
||||||
data class FSEphemeral(
|
|
||||||
@SerialName("dst") val target: AbsolutePath,
|
|
||||||
val write: Boolean,
|
|
||||||
val size: Int? = null,
|
|
||||||
val perm: Int,
|
|
||||||
) : FilesystemConfig
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
@SerialName("link")
|
|
||||||
data class FSLink(
|
|
||||||
@SerialName("dst") val target: AbsolutePath,
|
|
||||||
val linkname: String,
|
|
||||||
val dereference: Boolean,
|
|
||||||
) : FilesystemConfig
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
@SerialName("overlay")
|
|
||||||
data class FSOverlay(
|
|
||||||
@SerialName("dst") val target: AbsolutePath,
|
|
||||||
val lower: List<AbsolutePath>,
|
|
||||||
val upper: AbsolutePath,
|
|
||||||
val work: AbsolutePath,
|
|
||||||
) : FilesystemConfig
|
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
package moe.rosa.planterette.hakurei
|
|
||||||
|
|
||||||
import kotlinx.serialization.*
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class HakureiConfig(
|
|
||||||
var id: String? = null,
|
|
||||||
var path: AbsolutePath? = null,
|
|
||||||
var args: List<String>? = null,
|
|
||||||
var enablements: Enablements? = null,
|
|
||||||
@SerialName("session_bus") var sessionBus: DBusConfig? = null,
|
|
||||||
@SerialName("system_bus") var systemBus: DBusConfig? = null,
|
|
||||||
@SerialName("direct_wayland") var directWayland: Boolean? = null,
|
|
||||||
var username: String? = null,
|
|
||||||
var shell: AbsolutePath? = null,
|
|
||||||
var home: AbsolutePath? = null,
|
|
||||||
|
|
||||||
@SerialName("extra_perms") var extraPerms: List<ExtraPermsConfig>? = null,
|
|
||||||
var identity: Int? = null,
|
|
||||||
var groups: List<String>? = null,
|
|
||||||
|
|
||||||
var container: ContainerConfig? = null,
|
|
||||||
)
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class ContainerConfig(
|
|
||||||
var hostname: String? = null,
|
|
||||||
@SerialName("wait_delay") var waitDelay: Long? = null,
|
|
||||||
@SerialName("seccomp_compat") var seccompCompat: Boolean? = null,
|
|
||||||
var devel: Boolean? = null,
|
|
||||||
var userns: Boolean? = null,
|
|
||||||
@SerialName("host_net") var hostNet: Boolean? = null,
|
|
||||||
@SerialName("host_abstract") var hostAbstract: Boolean? = null,
|
|
||||||
var tty: Boolean? = null,
|
|
||||||
var multiarch: Boolean? = null,
|
|
||||||
|
|
||||||
var env: Map<String, String>? = null,
|
|
||||||
|
|
||||||
@SerialName("map_real_uid") var mapRealUid: Boolean? = null,
|
|
||||||
var device: Boolean? = null,
|
|
||||||
|
|
||||||
var filesystem: List<FilesystemConfig>? = null,
|
|
||||||
)
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class ExtraPermsConfig(
|
|
||||||
var ensure: Boolean? = null,
|
|
||||||
var path: AbsolutePath,
|
|
||||||
@SerialName("r") var read: Boolean? = null,
|
|
||||||
@SerialName("w") var write: Boolean? = null,
|
|
||||||
@SerialName("x") var execute: Boolean? = null,
|
|
||||||
) {
|
|
||||||
override fun toString(): String {
|
|
||||||
val buffer = StringBuffer(5 + path.toString().length)
|
|
||||||
buffer.append("---")
|
|
||||||
if(ensure == true) {
|
|
||||||
buffer.append("+")
|
|
||||||
}
|
|
||||||
buffer.append(":")
|
|
||||||
buffer.append(path.toString())
|
|
||||||
if(read == true) {
|
|
||||||
buffer.setCharAt(0, 'r')
|
|
||||||
}
|
|
||||||
if(write == true) {
|
|
||||||
buffer.setCharAt(1, 'w')
|
|
||||||
}
|
|
||||||
if(execute == true) {
|
|
||||||
buffer.setCharAt(2, 'x')
|
|
||||||
}
|
|
||||||
return buffer.toString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class DBusConfig(
|
|
||||||
var see: List<String>? = null,
|
|
||||||
var talk: List<String>? = null,
|
|
||||||
var own: List<String>? = null,
|
|
||||||
var call: Map<String, String>? = null,
|
|
||||||
var broadcast: Map<String, String>? = null,
|
|
||||||
var log: Boolean? = null,
|
|
||||||
var filter: Boolean? = null,
|
|
||||||
)
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class Enablements(
|
|
||||||
var wayland: Boolean? = null,
|
|
||||||
var x11: Boolean? = null,
|
|
||||||
var dbus: Boolean? = null,
|
|
||||||
var pulse: Boolean? = null,
|
|
||||||
)
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id("goPlugin")
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
module plt-fetch
|
|
||||||
|
|
||||||
go 1.24
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id("goPlugin")
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
module plt-pkg
|
|
||||||
|
|
||||||
go 1.24
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id("goPlugin")
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
module plt-server
|
|
||||||
|
|
||||||
go 1.24
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id("goPlugin")
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
module plt-updated
|
|
||||||
|
|
||||||
go 1.24
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestHelloWorld(t *testing.T) {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
include("plt-build")
|
|
||||||
include("plt-build-wrapper")
|
|
||||||
include("plt-fetch")
|
|
||||||
include("plt-pkg")
|
|
||||||
include("plt-server")
|
|
||||||
include("plt-updated")
|
|
||||||
Reference in New Issue
Block a user