Minor multisrc cleanup, support versionId

This commit is contained in:
arkon 2021-02-07 14:30:39 -05:00
parent ee33c8fa02
commit bec4c0a666
9 changed files with 146 additions and 139 deletions

View File

@ -20,28 +20,31 @@ repositories {
// dependencies // dependencies
apply("$rootDir/common-dependencies.gradle") apply("$rootDir/common-dependencies.gradle")
tasks.register("runAllGenerators") { tasks {
doLast { val runAllGenerators by registering {
val isWindows = System.getProperty("os.name").toString().toLowerCase().contains("win") doLast {
val classPath = (configurations.debugCompileOnly.get().asFileTree.toList() + val isWindows = System.getProperty("os.name").toString().toLowerCase().contains("win")
val classPath = (configurations.debugCompileOnly.get().asFileTree.toList() +
listOf( listOf(
configurations.androidApis.get().asFileTree.first().absolutePath, // android.jar path configurations.androidApis.get().asFileTree.first().absolutePath, // android.jar path
"$projectDir/build/intermediates/aar_main_jar/debug/classes.jar" // jar made from this module "$projectDir/build/intermediates/aar_main_jar/debug/classes.jar" // jar made from this module
)) ))
.joinToString(if (isWindows) ";" else ":") .joinToString(if (isWindows) ";" else ":")
val javaPath = "${System.getProperty("java.home")}/bin/java" val javaPath = "${System.getProperty("java.home")}/bin/java"
val mainClass = "eu.kanade.tachiyomi.multisrc.GeneratorMainKt" // Main class we want to execute val mainClass =
"eu.kanade.tachiyomi.multisrc.GeneratorMainKt" // Main class we want to execute
val javaCommand = if (isWindows) { val javaCommand = if (isWindows) {
"\"$javaPath\" -classpath $classPath $mainClass".replace("/", "\\") "\"$javaPath\" -classpath $classPath $mainClass".replace("/", "\\")
} else { } else {
"$javaPath -classpath $classPath $mainClass" "$javaPath -classpath $classPath $mainClass"
} }
val javaProcess = Runtime.getRuntime().exec(javaCommand) val javaProcess = Runtime.getRuntime().exec(javaCommand)
val exitCode = javaProcess.waitFor() val exitCode = javaProcess.waitFor()
if (exitCode != 0){ if (exitCode != 0) {
throw Exception("Java process failed with exit code: $exitCode") throw Exception("Java process failed with exit code: $exitCode")
}
} }
} }
} }

View File

@ -5,29 +5,24 @@ import java.io.File
/** /**
* Finds and calls all `ThemeSourceGenerator`s * Finds and calls all `ThemeSourceGenerator`s
*/ */
fun main(args: Array<String>) { fun main(args: Array<String>) {
val userDir = System.getProperty("user.dir")!! val userDir = System.getProperty("user.dir")!!
val sourcesDirPath = "$userDir/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc" val sourcesDirPath = "$userDir/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc"
val sourcesDir = File(sourcesDirPath) val sourcesDir = File(sourcesDirPath)
val directories = sourcesDir.list()!!.filter {
File(sourcesDir, it).isDirectory
}
// find all theme packages // find all theme packages
directories.forEach { themeSource -> sourcesDir.list()!!
// find all XxxGenerator.kt files and invoke main from them .filter { File(sourcesDir, it).isDirectory }
File("$sourcesDirPath/$themeSource").list()!! .forEach { themeSource ->
.filter { // Find all XxxGenerator.kt files and invoke main from them
it.endsWith("Generator.kt") File("$sourcesDirPath/$themeSource").list()!!
}.map {// find java class and extract method lists .filter { it.endsWith("Generator.kt") }
Class.forName("eu/kanade/tachiyomi/multisrc/$themeSource/$it".replace("/", ".").substringBefore(".kt")).methods.asList() .mapNotNull { generatorClass ->
} // Find Java class and extract method lists
.flatten() Class.forName("eu/kanade/tachiyomi/multisrc/$themeSource/$generatorClass".replace("/", ".").substringBefore(".kt"))
.filter { it.name == "main" } .methods
.forEach { it.invoke(null, emptyArray<String>()) } .find { it.name == "main" }
} }
.forEach { it.invoke(null, emptyArray<String>()) }
}
} }

View File

@ -22,7 +22,6 @@ interface ThemeSourceGenerator {
*/ */
val themePkg: String val themePkg: String
/** /**
* Base theme version, starts with 1 and should be increased when based theme class changes * Base theme version, starts with 1 and should be increased when based theme class changes
*/ */
@ -35,10 +34,7 @@ interface ThemeSourceGenerator {
fun createAll() { fun createAll() {
val userDir = System.getProperty("user.dir")!! val userDir = System.getProperty("user.dir")!!
sources.forEach { createGradleProject(it, themePkg, themeClass, baseVersionCode, userDir) }
sources.forEach { source ->
createGradleProject(source, themePkg, themeClass, baseVersionCode, userDir)
}
} }
companion object { companion object {
@ -54,40 +50,33 @@ interface ThemeSourceGenerator {
} }
private fun writeGradle(gradle: File, source: ThemeSourceData, baseVersionCode: Int) { private fun writeGradle(gradle: File, source: ThemeSourceData, baseVersionCode: Int) {
gradle.writeText("""apply plugin: 'com.android.application' gradle.writeText("""
apply plugin: 'kotlin-android' // THIS FILE IS AUTO-GENERATED; DO NOT EDIT
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
ext { ext {
extName = '${source.name}' extName = '${source.name}'
pkgNameSuffix = '${pkgNameSuffix(source, ".")}' pkgNameSuffix = '${pkgNameSuffix(source, ".")}'
extClass = '.${source.className}' extClass = '.${source.className}'
extVersionCode = ${baseVersionCode + source.overrideVersionCode + multisrcLibraryVersion} extVersionCode = ${baseVersionCode + source.overrideVersionCode + multisrcLibraryVersion}
libVersion = '1.2' libVersion = '1.2'
${if (source.isNsfw) " containsNsfw = true\n" else ""}} ${if (source.isNsfw) "containsNsfw = true\n" else ""}
}
apply from: "${'$'}rootDir/common.gradle" apply from: "${'$'}rootDir/common.gradle"
""" """.trimIndent())
)
} }
private fun writeAndroidManifest(androidManifestFile: File) { private fun writeAndroidManifest(androidManifestFile: File) {
androidManifestFile.writeText( androidManifestFile.writeText("""
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + <?xml version="1.0" encoding="utf-8"?>
"<manifest package=\"eu.kanade.tachiyomi.extension\" />\n" <!-- THIS FILE IS AUTO-GENERATED; DO NOT EDIT -->
) <manifest package="eu.kanade.tachiyomi.extension" />
""".trimIndent())
} }
/** private fun createGradleProject(source: ThemeSourceData, themePkg: String, themeClass: String, baseVersionCode: Int, userDir: String) {
* Clears directory recursively
*/
private fun purgeDirectory(dir: File) {
for (file in dir.listFiles()!!) {
if (file.isDirectory) purgeDirectory(file)
file.delete()
}
}
fun createGradleProject(source: ThemeSourceData, themePkg: String, themeClass: String, baseVersionCode: Int, userDir: String) {
val projectRootPath = "$userDir/generated-src/${pkgNameSuffix(source, "/")}" val projectRootPath = "$userDir/generated-src/${pkgNameSuffix(source, "/")}"
val projectSrcPath = "$projectRootPath/src/eu/kanade/tachiyomi/extension/${pkgNameSuffix(source, "/")}" val projectSrcPath = "$projectRootPath/src/eu/kanade/tachiyomi/extension/${pkgNameSuffix(source, "/")}"
val overridesPath = "$userDir/multisrc/overrides" // userDir = tachiyomi-extensions project root path val overridesPath = "$userDir/multisrc/overrides" // userDir = tachiyomi-extensions project root path
@ -96,13 +85,12 @@ apply from: "${'$'}rootDir/common.gradle"
val projectGradleFile = File("$projectRootPath/build.gradle") val projectGradleFile = File("$projectRootPath/build.gradle")
val projectAndroidManifestFile = File("$projectRootPath/AndroidManifest.xml") val projectAndroidManifestFile = File("$projectRootPath/AndroidManifest.xml")
File(projectRootPath).let { projectRootFile -> File(projectRootPath).let { projectRootFile ->
println("Working on $source") println("Working on $source")
projectRootFile.mkdirs() projectRootFile.mkdirs()
// remove everything from past runs // remove everything from past runs
purgeDirectory(projectRootFile) cleanDirectory(projectRootFile)
writeGradle(projectGradleFile, source, baseVersionCode) writeGradle(projectGradleFile, source, baseVersionCode)
writeAndroidManifest(projectAndroidManifestFile) writeAndroidManifest(projectAndroidManifestFile)
@ -150,74 +138,97 @@ apply from: "${'$'}rootDir/common.gradle"
private fun writeSourceClass(classPath: File, source: ThemeSourceData, themePkg: String, themeClass: String) { private fun writeSourceClass(classPath: File, source: ThemeSourceData, themePkg: String, themeClass: String) {
fun factoryClassText(): String { fun factoryClassText(): String {
val sourceListString = return when (source) {
(source as ThemeSourceData.MultiLang).lang.map { is ThemeSourceData.SingleLang -> {
" $themeClass(\"${source.name}\", \"${source.baseUrl}\", \"$it\")," """
}.joinToString("\n") class ${source.className} : $themeClass("${source.name}", "${source.baseUrl}", "${source.lang}") {
override val versionId = ${source.versionId}
}
""".trimIndent()
}
is ThemeSourceData.MultiLang -> {
val sourceClasses = source.lang.mapIndexed { index, lang ->
val indexedClassName = "$themeClass${index}"
indexedClassName to """$indexedClassName : $themeClass("${source.name}", "${source.baseUrl}", "$lang") {
override val versionId = ${source.versionId}
}""".trimIndent()
}
return """class ${source.className} : SourceFactory { """
override fun createSources(): List<Source> = listOf( class ${source.className} : SourceFactory {
$sourceListString ${sourceClasses.joinToString("\n") { it.second }}
)
}""" override fun createSources() = listOf(
} ${sourceClasses.joinToString(",\n") { "${it.first}()" }}
File("$classPath/${source.className}.kt").writeText( )
"""package eu.kanade.tachiyomi.extension.${pkgNameSuffix(source, ".")} }
${if (source.isNsfw) "\nimport eu.kanade.tachiyomi.annotations.Nsfw" else ""} """.trimIndent()
import eu.kanade.tachiyomi.multisrc.$themePkg.$themeClass }
${if (source is ThemeSourceData.MultiLang)
"""import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceFactory
"""
else ""}${if (source.isNsfw) "\n@Nsfw" else ""}
${if (source is ThemeSourceData.SingleLang) {
"class ${source.className} : $themeClass(\"${source.name}\", \"${source.baseUrl}\", \"${source.lang}\")\n"
} else
factoryClassText()
} }
""") }
File("$classPath/${source.className}.kt").writeText("""
// THIS FILE IS AUTO-GENERATED; DO NOT EDIT???
package eu.kanade.tachiyomi.extension.${pkgNameSuffix(source, ".")}
import eu.kanade.tachiyomi.multisrc.$themePkg.$themeClass
${if (source is ThemeSourceData.MultiLang) "import eu.kanade.tachiyomi.source.SourceFactory" else ""}
${if (source.isNsfw) "import eu.kanade.tachiyomi.annotations.Nsfw" else ""}
${if (source.isNsfw) "\n@Nsfw" else ""}
${factoryClassText()}
""".trimIndent())
} }
sealed class ThemeSourceData { private fun cleanDirectory(dir: File) {
abstract val name: String for (file in dir.listFiles()!!) {
abstract val baseUrl: String if (file.isDirectory) cleanDirectory(file)
abstract val isNsfw: Boolean file.delete()
abstract val className: String }
abstract val pkgName: String
/**
* overrideVersionCode defaults to 0, if a source changes their source override code or
* a previous existing source suddenly needs source code overrides, overrideVersionCode
* should be increased.
* When a new source is added with overrides, overrideVersionCode should still be set to 0
*
* Note: source code overrides are located in "multisrc/overrides/src/<themeName>/<sourceName>"
*/
abstract val overrideVersionCode: Int
data class SingleLang(
override val name: String,
override val baseUrl: String,
val lang: String,
override val isNsfw: Boolean = false,
override val className: String = name.replace(" ", ""),
override val pkgName: String = className.toLowerCase(Locale.ENGLISH),
override val overrideVersionCode: Int = 0,
) : ThemeSourceData()
data class MultiLang(
override val name: String,
override val baseUrl: String,
val lang: List<String>,
override val isNsfw: Boolean = false,
override val className: String = name.replace(" ", "") + "Factory",
override val pkgName: String = className.substringBefore("Factory").toLowerCase(Locale.ENGLISH),
override val overrideVersionCode: Int = 0,
) : ThemeSourceData()
} }
} }
} }
sealed class ThemeSourceData {
abstract val name: String
abstract val baseUrl: String
abstract val isNsfw: Boolean
abstract val className: String
abstract val pkgName: String
abstract val versionId: Int
/**
* overrideVersionCode defaults to 0, if a source changes their source override code or
* a previous existing source suddenly needs source code overrides, overrideVersionCode
* should be increased.
* When a new source is added with overrides, overrideVersionCode should still be set to 0
*
* Note: source code overrides are located in "multisrc/overrides/src/<themeName>/<sourceName>"
*/
abstract val overrideVersionCode: Int
data class SingleLang(
override val name: String,
override val baseUrl: String,
val lang: String,
override val isNsfw: Boolean = false,
override val className: String = name.replace(" ", ""),
override val pkgName: String = className.toLowerCase(Locale.ENGLISH),
override val versionId: Int = 1,
override val overrideVersionCode: Int = 0,
) : ThemeSourceData()
data class MultiLang(
override val name: String,
override val baseUrl: String,
val lang: List<String>,
override val isNsfw: Boolean = false,
override val className: String = name.replace(" ", "") + "Factory",
override val pkgName: String = className.substringBefore("Factory").toLowerCase(Locale.ENGLISH),
override val versionId: Int = 1,
override val overrideVersionCode: Int = 0,
) : ThemeSourceData()
}
/** /**
* This variable should be increased when the multisrc library changes in a way that prompts global extension upgrade * This variable should be increased when the multisrc library changes in a way that prompts global extension upgrade

View File

@ -1,7 +1,7 @@
package eu.kanade.tachiyomi.multisrc.comicake package eu.kanade.tachiyomi.multisrc.comicake
import eu.kanade.tachiyomi.multisrc.ThemeSourceData.SingleLang
import eu.kanade.tachiyomi.multisrc.ThemeSourceGenerator import eu.kanade.tachiyomi.multisrc.ThemeSourceGenerator
import eu.kanade.tachiyomi.multisrc.ThemeSourceGenerator.Companion.ThemeSourceData.SingleLang
class ComiCakeGenerator : ThemeSourceGenerator { class ComiCakeGenerator : ThemeSourceGenerator {

View File

@ -1,7 +1,7 @@
package eu.kanade.tachiyomi.multisrc.genkan package eu.kanade.tachiyomi.multisrc.genkan
import eu.kanade.tachiyomi.multisrc.ThemeSourceData
import eu.kanade.tachiyomi.multisrc.ThemeSourceGenerator import eu.kanade.tachiyomi.multisrc.ThemeSourceGenerator
import eu.kanade.tachiyomi.multisrc.ThemeSourceGenerator.Companion.ThemeSourceData
class GenkanGenerator : ThemeSourceGenerator { class GenkanGenerator : ThemeSourceGenerator {
@ -14,7 +14,7 @@ class GenkanGenerator : ThemeSourceGenerator {
override val sources = listOf( override val sources = listOf(
ThemeSourceData.MultiLang("Leviatan Scans", "https://leviatanscans.com", listOf("en", "es"), ThemeSourceData.MultiLang("Leviatan Scans", "https://leviatanscans.com", listOf("en", "es"),
className = "LeviatanScansFactory", pkgName = "leviatanscans", overrideVersionCode = 1), className = "LeviatanScansFactory", pkgName = "leviatanscans", overrideVersionCode = 1),
ThemeSourceGenerator.Companion.ThemeSourceData.SingleLang("Hunlight Scans", "https://hunlight-scans.info", "en"), ThemeSourceData.SingleLang("Hunlight Scans", "https://hunlight-scans.info", "en"),
ThemeSourceData.SingleLang("ZeroScans", "https://zeroscans.com", "en"), ThemeSourceData.SingleLang("ZeroScans", "https://zeroscans.com", "en"),
ThemeSourceData.SingleLang("The Nonames Scans", "https://the-nonames.com", "en"), ThemeSourceData.SingleLang("The Nonames Scans", "https://the-nonames.com", "en"),
ThemeSourceData.SingleLang("Edelgarde Scans", "https://edelgardescans.com", "en"), ThemeSourceData.SingleLang("Edelgarde Scans", "https://edelgardescans.com", "en"),

View File

@ -1,7 +1,7 @@
package eu.kanade.tachiyomi.multisrc.genkan package eu.kanade.tachiyomi.multisrc.genkan
import eu.kanade.tachiyomi.multisrc.ThemeSourceData
import eu.kanade.tachiyomi.multisrc.ThemeSourceGenerator import eu.kanade.tachiyomi.multisrc.ThemeSourceGenerator
import eu.kanade.tachiyomi.multisrc.ThemeSourceGenerator.Companion.ThemeSourceData
class GenkanOriginalGenerator : ThemeSourceGenerator { class GenkanOriginalGenerator : ThemeSourceGenerator {
@ -13,7 +13,7 @@ class GenkanOriginalGenerator : ThemeSourceGenerator {
override val sources = listOf( override val sources = listOf(
ThemeSourceData.SingleLang("Reaper Scans", "https://reaperscans.com", "en"), ThemeSourceData.SingleLang("Reaper Scans", "https://reaperscans.com", "en"),
ThemeSourceData.SingleLang("Hatigarm Scans", "https://hatigarmscanz.net", "en"), ThemeSourceData.SingleLang("Hatigarm Scans", "https://hatigarmscanz.net", "en", versionId = 2),
ThemeSourceData.SingleLang("SecretScans", "https://secretscans.co", "en"), ThemeSourceData.SingleLang("SecretScans", "https://secretscans.co", "en"),
) )

View File

@ -1,7 +1,7 @@
package eu.kanade.tachiyomi.multisrc.madara package eu.kanade.tachiyomi.multisrc.madara
import eu.kanade.tachiyomi.multisrc.ThemeSourceData.SingleLang
import eu.kanade.tachiyomi.multisrc.ThemeSourceGenerator import eu.kanade.tachiyomi.multisrc.ThemeSourceGenerator
import eu.kanade.tachiyomi.multisrc.ThemeSourceGenerator.Companion.ThemeSourceData.SingleLang
class MadaraGenerator : ThemeSourceGenerator { class MadaraGenerator : ThemeSourceGenerator {

View File

@ -23,7 +23,6 @@ import java.util.Locale
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
// Based off of Mangakakalot 1.2.8 // Based off of Mangakakalot 1.2.8
abstract class MangaBox( abstract class MangaBox(
override val name: String, override val name: String,
override val baseUrl: String, override val baseUrl: String,

View File

@ -1,8 +1,7 @@
package eu.kanade.tachiyomi.multisrc.mangabox package eu.kanade.tachiyomi.multisrc.mangabox
import eu.kanade.tachiyomi.multisrc.ThemeSourceData.SingleLang
import eu.kanade.tachiyomi.multisrc.ThemeSourceGenerator import eu.kanade.tachiyomi.multisrc.ThemeSourceGenerator
import eu.kanade.tachiyomi.multisrc.ThemeSourceGenerator.Companion.ThemeSourceData.SingleLang
class MangaBoxGenerator : ThemeSourceGenerator { class MangaBoxGenerator : ThemeSourceGenerator {