From 9b6c8f21f86385c993c0e34ba4b31348cae200cd Mon Sep 17 00:00:00 2001 From: Linnea Gräf Date: Sun, 28 Sep 2025 19:48:11 +0200 Subject: fix: improve config backups --- src/main/kotlin/util/data/IDataHolder.kt | 31 ++++++++--- src/main/kotlin/util/data/MultiFileDataHolder.kt | 62 ---------------------- .../kotlin/util/data/ProfileSpecificDataHolder.kt | 2 +- 3 files changed, 25 insertions(+), 70 deletions(-) delete mode 100644 src/main/kotlin/util/data/MultiFileDataHolder.kt (limited to 'src/main/kotlin/util/data') diff --git a/src/main/kotlin/util/data/IDataHolder.kt b/src/main/kotlin/util/data/IDataHolder.kt index 541fc1b..de6dff8 100644 --- a/src/main/kotlin/util/data/IDataHolder.kt +++ b/src/main/kotlin/util/data/IDataHolder.kt @@ -21,6 +21,7 @@ sealed class IDataHolder { abstract fun keys(): Collection abstract fun saveTo(key: T): JsonObject abstract fun loadFrom(key: T, jsonObject: JsonObject) + abstract fun explicitDefaultLoad() abstract fun clear() abstract val storageClass: ConfigStorageClass } @@ -28,18 +29,21 @@ sealed class IDataHolder { open class ProfileKeyedConfig( val prefix: String, val serializer: KSerializer, - val default: () -> T, + val default: () -> T & Any, ) : IDataHolder() { override val storageClass: ConfigStorageClass get() = ConfigStorageClass.PROFILE private var _data: MutableMap? = null - val data - get() = _data!!.let { map -> - map[SBData.profileIdOrNil] - ?: default().also { map[SBData.profileIdOrNil] = it } - } ?: error("Config $this not loaded — forgot to register?") + val data: T & Any + get() { + val map = _data ?: error("Config $this not loaded — forgot to register?") + map[SBData.profileIdOrNil]?.let { return it } + val newValue = default() + map[SBData.profileIdOrNil] = newValue + return newValue + } override fun keys(): Collection { return _data!!.keys @@ -53,13 +57,22 @@ open class ProfileKeyedConfig( } override fun loadFrom(key: UUID, jsonObject: JsonObject) { - (_data ?: mutableMapOf().also { _data = it })[key] = + var map = _data + if (map == null) { + map = mutableMapOf() + _data = map + } + map[key] = jsonObject[prefix] ?.let { Firmament.json.decodeFromJsonElement(serializer, it) } ?: default() } + override fun explicitDefaultLoad() { + _data = mutableMapOf() + } + override fun clear() { _data = null } @@ -79,6 +92,10 @@ abstract class GenericConfig( return listOf(Unit) } + override fun explicitDefaultLoad() { + _data = default() + } + open fun onLoad() { } diff --git a/src/main/kotlin/util/data/MultiFileDataHolder.kt b/src/main/kotlin/util/data/MultiFileDataHolder.kt deleted file mode 100644 index 209f780..0000000 --- a/src/main/kotlin/util/data/MultiFileDataHolder.kt +++ /dev/null @@ -1,62 +0,0 @@ -package moe.nea.firmament.util.data - -import kotlinx.serialization.KSerializer -import kotlin.io.path.createDirectories -import kotlin.io.path.deleteExisting -import kotlin.io.path.exists -import kotlin.io.path.extension -import kotlin.io.path.listDirectoryEntries -import kotlin.io.path.nameWithoutExtension -import kotlin.io.path.readText -import kotlin.io.path.writeText -import moe.nea.firmament.Firmament - -abstract class MultiFileDataHolder( - val dataSerializer: KSerializer, - val configName: String -) { // TODO: abstract this + ProfileSpecificDataHolder - val configDirectory = Firmament.CONFIG_DIR.resolve(configName) - private var allData = readValues() - protected fun readValues(): MutableMap { - if (!configDirectory.exists()) { - configDirectory.createDirectories() - } - val profileFiles = configDirectory.listDirectoryEntries() - return profileFiles - .filter { it.extension == "json" } - .mapNotNull { - try { - it.nameWithoutExtension to Firmament.json.decodeFromString(dataSerializer, it.readText()) - } catch (e: Exception) { /* Expecting IOException and SerializationException, but Kotlin doesn't allow multi catches*/ - Firmament.logger.error( - "Exception during loading of multi file data holder $it ($configName). This will reset that profiles config.", - e - ) - null - } - }.toMap().toMutableMap() - } - - fun save() { - if (!configDirectory.exists()) { - configDirectory.createDirectories() - } - val c = allData - configDirectory.listDirectoryEntries().forEach { - if (it.nameWithoutExtension !in c.mapKeys { it.toString() }) { - it.deleteExisting() - } - } - c.forEach { (name, value) -> - val f = configDirectory.resolve("$name.json") - f.writeText(Firmament.json.encodeToString(dataSerializer, value)) - } - } - - fun list(): Map = allData - val validPathRegex = "[a-zA-Z0-9_][a-zA-Z0-9\\-_.]*".toPattern() - fun insert(name: String, value: T) { - require(validPathRegex.matcher(name).matches()) { "Not a valid name: $name" } - allData[name] = value - } -} diff --git a/src/main/kotlin/util/data/ProfileSpecificDataHolder.kt b/src/main/kotlin/util/data/ProfileSpecificDataHolder.kt index 3922c34..853ba7d 100644 --- a/src/main/kotlin/util/data/ProfileSpecificDataHolder.kt +++ b/src/main/kotlin/util/data/ProfileSpecificDataHolder.kt @@ -5,5 +5,5 @@ import kotlinx.serialization.KSerializer abstract class ProfileSpecificDataHolder( dataSerializer: KSerializer, configName: String, - configDefault: () -> S + configDefault: () -> S & Any ) : ProfileKeyedConfig(configName, dataSerializer, configDefault) -- cgit