diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/Migration.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/Migration.kt new file mode 100644 index 000000000..381b504ae --- /dev/null +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/Migration.kt @@ -0,0 +1,86 @@ +package suwayomi.tachidesk.server + +import android.app.Application +import android.content.Context +import mu.KotlinLogging +import uy.kohesive.injekt.Injekt +import uy.kohesive.injekt.api.get +import java.io.File +import java.util.prefs.Preferences + +private fun migratePreferences( + parent: String?, + rootNode: Preferences, +) { + val subNodes = rootNode.childrenNames() + + for (subNodeName in subNodes) { + val subNode = rootNode.node(subNodeName) + val key = + if (parent != null) { + "$parent/$subNodeName" + } else { + subNodeName + } + val preferences = Injekt.get().getSharedPreferences(key, Context.MODE_PRIVATE) + + val items: Map = + subNode.keys().associateWith { + subNode[it, null]?.ifBlank { null } + } + + preferences.edit().apply { + items.forEach { (key, value) -> + if (value != null) { + putString(key, value) + } + } + }.apply() + + migratePreferences(key, subNode) // Recursively migrate sub-level nodes + } +} + +const val MIGRATION_VERSION = 1 + +fun runMigrations(applicationDirs: ApplicationDirs) { + val migrationPreferences = + Injekt.get() + .getSharedPreferences( + "migrations", + Context.MODE_PRIVATE, + ) + val version = migrationPreferences.getInt("version", 0) + val logger = KotlinLogging.logger("Migration") + logger.info { "Running migrations, previous version $version, target version $MIGRATION_VERSION" } + + if (version < 1) { + logger.info { "Running migration for version: 1" } + val oldMangaDownloadDir = File(applicationDirs.downloadsRoot) + val newMangaDownloadDir = File(applicationDirs.mangaDownloadsRoot) + val downloadDirs = oldMangaDownloadDir.listFiles().orEmpty() + + val moveDownloadsToNewFolder = !newMangaDownloadDir.exists() && downloadDirs.isNotEmpty() + if (moveDownloadsToNewFolder) { + newMangaDownloadDir.mkdirs() + + for (downloadDir in downloadDirs) { + if (downloadDir == File(applicationDirs.thumbnailDownloadsRoot)) { + continue + } + + downloadDir.renameTo(File(newMangaDownloadDir, downloadDir.name)) + } + } + + // Migrate from old preferences api + val prefRootNode = "suwayomi/tachidesk" + val isMigrationRequired = Preferences.userRoot().nodeExists(prefRootNode) + if (isMigrationRequired) { + val preferences = Preferences.userRoot().node(prefRootNode) + migratePreferences(null, preferences) + preferences.removeNode() + } + } + migrationPreferences.edit().putInt("version", MIGRATION_VERSION).apply() +} diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/ServerSetup.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/ServerSetup.kt index f1b9cbc65..864c2a3f3 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/ServerSetup.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/ServerSetup.kt @@ -7,8 +7,6 @@ package suwayomi.tachidesk.server * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import android.app.Application -import android.content.Context import ch.qos.logback.classic.Level import com.typesafe.config.ConfigRenderOptions import eu.kanade.tachiyomi.App @@ -34,7 +32,6 @@ import suwayomi.tachidesk.server.database.databaseUp import suwayomi.tachidesk.server.generated.BuildConfig import suwayomi.tachidesk.server.util.AppMutex.handleAppMutex import suwayomi.tachidesk.server.util.SystemTray -import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import xyz.nulldev.androidcompat.AndroidCompat import xyz.nulldev.androidcompat.AndroidCompatInitializer @@ -47,7 +44,6 @@ import xyz.nulldev.ts.config.setLogLevelFor import java.io.File import java.security.Security import java.util.Locale -import java.util.prefs.Preferences private val logger = KotlinLogging.logger {} @@ -126,23 +122,6 @@ fun applicationSetup() { File("$ApplicationRootDir/manga-local").renameTo(applicationDirs.localMangaRoot) File("$ApplicationRootDir/anime-thumbnails").delete() - val oldMangaDownloadDir = File(applicationDirs.downloadsRoot) - val newMangaDownloadDir = File(applicationDirs.mangaDownloadsRoot) - val downloadDirs = oldMangaDownloadDir.listFiles().orEmpty() - - val moveDownloadsToNewFolder = !newMangaDownloadDir.exists() && downloadDirs.isNotEmpty() - if (moveDownloadsToNewFolder) { - newMangaDownloadDir.mkdirs() - - for (downloadDir in downloadDirs) { - if (downloadDir == File(applicationDirs.thumbnailDownloadsRoot)) { - continue - } - - downloadDir.renameTo(File(newMangaDownloadDir, downloadDir.name)) - } - } - // make dirs we need listOf( applicationDirs.dataRoot, @@ -217,13 +196,7 @@ fun applicationSetup() { } }, ignoreInitialValue = false) - val prefRootNode = "suwayomi/tachidesk" - val isMigrationRequired = Preferences.userRoot().nodeExists(prefRootNode) - if (isMigrationRequired) { - val preferences = Preferences.userRoot().node(prefRootNode) - migratePreferences(null, preferences) - preferences.removeNode() - } + runMigrations(applicationDirs) // Disable jetty's logging System.setProperty("org.eclipse.jetty.util.log.announce", "false") @@ -265,36 +238,3 @@ fun applicationSetup() { // start DownloadManager and restore + resume downloads DownloadManager.restoreAndResumeDownloads() } - -fun migratePreferences( - parent: String?, - rootNode: Preferences, -) { - val subNodes = rootNode.childrenNames() - - for (subNodeName in subNodes) { - val subNode = rootNode.node(subNodeName) - val key = - if (parent != null) { - "$parent/$subNodeName" - } else { - subNodeName - } - val preferences = Injekt.get().getSharedPreferences(key, Context.MODE_PRIVATE) - - val items: Map = - subNode.keys().associateWith { - subNode[it, null]?.ifBlank { null } - } - - preferences.edit().apply { - items.forEach { (key, value) -> - if (value != null) { - putString(key, value) - } - } - }.apply() - - migratePreferences(key, subNode) // Recursively migrate sub-level nodes - } -}