Rewrite Migrations (#577)
* Rewrite Migrations * Fix Detekt errors * Do migrations synchronous * Filter and sort migrations * Review changes * Review changes 2 * Fix Detekt errors
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
package mihon.core.migration
|
||||
|
||||
interface Migration {
|
||||
val version: Float
|
||||
|
||||
suspend operator fun invoke(migrationContext: MigrationContext): Boolean
|
||||
|
||||
companion object {
|
||||
const val ALWAYS = -1f
|
||||
|
||||
fun of(version: Float, action: suspend (MigrationContext) -> Boolean): Migration = object : Migration {
|
||||
override val version: Float = version
|
||||
|
||||
override suspend operator fun invoke(migrationContext: MigrationContext): Boolean {
|
||||
return action(migrationContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package mihon.core.migration
|
||||
|
||||
import uy.kohesive.injekt.Injekt
|
||||
|
||||
class MigrationContext {
|
||||
|
||||
inline fun <reified T> get(): T? {
|
||||
return Injekt.getInstanceOrNull(T::class.java)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package mihon.core.migration
|
||||
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import tachiyomi.core.common.util.system.logcat
|
||||
|
||||
object Migrator {
|
||||
|
||||
@SuppressWarnings("ReturnCount")
|
||||
fun migrate(
|
||||
old: Int,
|
||||
new: Int,
|
||||
migrations: List<Migration>,
|
||||
dryrun: Boolean = false,
|
||||
onMigrationComplete: () -> Unit
|
||||
): Boolean {
|
||||
val migrationContext = MigrationContext()
|
||||
|
||||
if (old == 0) {
|
||||
return migrationContext.migrate(
|
||||
migrations = migrations.filter { it.isAlways() },
|
||||
dryrun = dryrun
|
||||
)
|
||||
.also { onMigrationComplete() }
|
||||
}
|
||||
|
||||
if (old >= new) {
|
||||
return false
|
||||
}
|
||||
|
||||
return migrationContext.migrate(
|
||||
migrations = migrations.filter { it.isAlways() || it.version.toInt() in (old + 1)..new },
|
||||
dryrun = dryrun
|
||||
)
|
||||
.also { onMigrationComplete() }
|
||||
}
|
||||
|
||||
private fun Migration.isAlways() = version == Migration.ALWAYS
|
||||
|
||||
@SuppressWarnings("MaxLineLength")
|
||||
private fun MigrationContext.migrate(migrations: List<Migration>, dryrun: Boolean): Boolean {
|
||||
return migrations.sortedBy { it.version }
|
||||
.map { migration ->
|
||||
if (!dryrun) {
|
||||
logcat { "Running migration: { name = ${migration::class.simpleName}, version = ${migration.version} }" }
|
||||
runBlocking { migration(this@migrate) }
|
||||
} else {
|
||||
logcat { "(Dry-run) Running migration: { name = ${migration::class.simpleName}, version = ${migration.version} }" }
|
||||
true
|
||||
}
|
||||
}
|
||||
.reduce { acc, b -> acc || b }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package mihon.core.migration.migrations
|
||||
|
||||
import mihon.core.migration.Migration
|
||||
|
||||
val migrations: List<Migration>
|
||||
get() = listOf(
|
||||
SetupBackupCreateMigration(),
|
||||
SetupLibraryUpdateMigration(),
|
||||
TrustExtensionRepositoryMigration(),
|
||||
)
|
||||
@@ -0,0 +1,16 @@
|
||||
package mihon.core.migration.migrations
|
||||
|
||||
import eu.kanade.tachiyomi.App
|
||||
import eu.kanade.tachiyomi.data.backup.create.BackupCreateJob
|
||||
import mihon.core.migration.Migration
|
||||
import mihon.core.migration.MigrationContext
|
||||
|
||||
class SetupBackupCreateMigration : Migration {
|
||||
override val version: Float = Migration.ALWAYS
|
||||
|
||||
override suspend fun invoke(migrationContext: MigrationContext): Boolean {
|
||||
val context = migrationContext.get<App>() ?: return false
|
||||
BackupCreateJob.setupTask(context)
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package mihon.core.migration.migrations
|
||||
|
||||
import eu.kanade.tachiyomi.App
|
||||
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
||||
import mihon.core.migration.Migration
|
||||
import mihon.core.migration.MigrationContext
|
||||
|
||||
class SetupLibraryUpdateMigration : Migration {
|
||||
override val version: Float = Migration.ALWAYS
|
||||
|
||||
override suspend fun invoke(migrationContext: MigrationContext): Boolean {
|
||||
val context = migrationContext.get<App>() ?: return false
|
||||
LibraryUpdateJob.setupTask(context)
|
||||
return true
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package mihon.core.migration.migrations
|
||||
|
||||
import eu.kanade.domain.source.service.SourcePreferences
|
||||
import logcat.LogPriority
|
||||
import mihon.core.migration.Migration
|
||||
import mihon.core.migration.MigrationContext
|
||||
import mihon.domain.extensionrepo.exception.SaveExtensionRepoException
|
||||
import mihon.domain.extensionrepo.repository.ExtensionRepoRepository
|
||||
import tachiyomi.core.common.util.lang.withIOContext
|
||||
import tachiyomi.core.common.util.system.logcat
|
||||
|
||||
class TrustExtensionRepositoryMigration : Migration {
|
||||
override val version: Float = 7f
|
||||
|
||||
override suspend fun invoke(migrationContext: MigrationContext): Boolean = withIOContext {
|
||||
val sourcePreferences = migrationContext.get<SourcePreferences>() ?: return@withIOContext false
|
||||
val extensionRepositoryRepository =
|
||||
migrationContext.get<ExtensionRepoRepository>() ?: return@withIOContext false
|
||||
for ((index, source) in sourcePreferences.extensionRepos().get().withIndex()) {
|
||||
try {
|
||||
extensionRepositoryRepository.upsertRepo(
|
||||
source,
|
||||
"Repo #${index + 1}",
|
||||
null,
|
||||
source,
|
||||
"NOFINGERPRINT-${index + 1}",
|
||||
)
|
||||
} catch (e: SaveExtensionRepoException) {
|
||||
logcat(LogPriority.ERROR, e) { "Error Migrating Extension Repo with baseUrl: $source" }
|
||||
}
|
||||
}
|
||||
sourcePreferences.extensionRepos().delete()
|
||||
return@withIOContext true
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user