Use Semver for plugin version and its dependencies

This commit is contained in:
Him188 2020-07-19 22:45:06 +08:00
parent 54e64082b6
commit ead891e223
6 changed files with 58 additions and 44 deletions

View File

@ -66,12 +66,14 @@ kotlin {
dependencies {
compileAndRuntime("net.mamoe:mirai-core:${Versions.core}")
compileAndRuntime(kotlin("stdlib", Versions.kotlinStdlib))
compileAndRuntime(kotlin("stdlib-jdk8", Versions.kotlinStdlib))
api("net.mamoe.yamlkt:yamlkt:0.3.1")
api("org.jetbrains:annotations:19.0.0")
api(kotlinx("coroutines-jdk8", Versions.coroutines))
api("com.vdurmont:semver4j:3.1.0")
testApi("net.mamoe:mirai-core-qqandroid:${Versions.core}")
testApi(kotlin("stdlib-jdk8"))
testApi(kotlin("test"))
@ -80,6 +82,7 @@ dependencies {
testImplementation("org.junit.jupiter:junit-jupiter-api:5.2.0")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.2.0")
}
ext.apply {
// 傻逼 compileAndRuntime 没 exclude 掉
// 傻逼 gradle 第二次配置 task 会覆盖掉第一次的配置
@ -109,9 +112,11 @@ tasks {
file.writeText(file.readText()
.replace(Regex("""val buildDate: Date = Date\((.*)\) //(.*)""")) {
"""
val buildDate: Date = Date(${System.currentTimeMillis()}L) // ${SimpleDateFormat("yyyy-MM-dd HH:mm:ss").apply {
timeZone = TimeZone.getTimeZone("GMT+8")
}.format(Date())}
val buildDate: Date = Date(${System.currentTimeMillis()}L) // ${
SimpleDateFormat("yyyy-MM-dd HH:mm:ss").apply {
timeZone = TimeZone.getTimeZone("GMT+8")
}.format(Date())
}
""".trimIndent()
}
.replace(Regex("""const val version: String = "(.*)"""")) {

View File

@ -105,8 +105,8 @@ internal object MiraiConsoleInitializer {
internal object MiraiConsoleBuildConstants { // auto-filled on build (task :mirai-console:fillBuildConstants)
@JvmStatic
val buildDate: Date = Date(1594475138828L) // 2020-07-11 21:45:38
const val version: String = "1.0-dev-3"
val buildDate: Date = Date(1595136353901L) // 2020-07-19 13:25:53
const val version: String = "1.0-dev-4"
}
/**

View File

@ -9,10 +9,12 @@
package net.mamoe.mirai.console.plugin
import com.vdurmont.semver4j.Semver
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.builtins.serializer
import net.mamoe.mirai.console.setting.internal.map
import net.mamoe.mirai.console.utils.SemverAsStringSerializerIvy
import net.mamoe.yamlkt.Yaml
import net.mamoe.yamlkt.YamlDynamicSerializer
import java.io.File
@ -45,7 +47,7 @@ public interface PluginDescription {
public val name: String
public val author: String
public val version: String
public val version: Semver
public val info: String
/** 此插件依赖的其他插件, 将会在这些插件加载之后加载此插件 */
@ -59,42 +61,21 @@ public data class PluginDependency(
public val name: String,
/**
* 依赖版本号. null 时则为不限制版本.
*
* 版本遵循 [语义化版本 2.0 规范](https://semver.org/lang/zh-CN/),
*
* 允许 [Apache Ivy 格式版本号](http://ant.apache.org/ivy/history/latest-milestone/ivyfile/dependency.html)
*
* @see versionKind 版本号类型
*/
public val version: String? = null,
/** 版本号类型 */
public val versionKind: VersionKind = VersionKind.AT_LEAST,
public val version: @Serializable(SemverAsStringSerializerIvy::class) Semver? = null,
/**
* 若为 `false`, 插件在找不到此依赖时也能正常加载.
*/
public val isOptional: Boolean = false
) {
/** 版本号类型 */
@Serializable(with = VersionKind.AsStringSerializer::class)
public enum class VersionKind(
private vararg val serialNames: String
) {
/** 要求依赖精确的版本 */
EXACT("exact"),
/** 要求依赖最低版本 */
AT_LEAST("at_least", "AtLeast", "least", "lowest", "+"),
/** 要求依赖最高版本 */
AT_MOST("at_most", "AtMost", "most", "highest", "-");
public object AsStringSerializer : KSerializer<VersionKind> by String.serializer().map(
serializer = { it.serialNames.first() },
deserializer = { str ->
values().firstOrNull {
it.serialNames.any { name -> name.equals(str, ignoreCase = true) }
} ?: AT_LEAST
}
)
}
public override fun toString(): String {
return "$name ${versionKind.toEnglishString()}v$version"
return "$name v$version"
}
@ -118,9 +99,3 @@ public data class PluginDependency(
public interface FilePluginDescription : PluginDescription {
public val file: File
}
internal fun PluginDependency.VersionKind.toEnglishString(): String = when (this) {
PluginDependency.VersionKind.EXACT -> ""
PluginDependency.VersionKind.AT_LEAST -> "at least "
PluginDependency.VersionKind.AT_MOST -> "at most "
}

View File

@ -89,7 +89,11 @@ internal object JarPluginLoaderImpl :
override fun load(description: JvmPluginDescription): JvmPlugin =
description.runCatching<JvmPluginDescription, JvmPlugin> {
ensureActive()
val main = classLoader.loadPluginMainClassByJarFile(name, mainClassName, file).kotlin.run {
val main = classLoader.loadPluginMainClassByJarFile(
pluginName = name,
mainClass = mainClassName,
jarFile = file
).kotlin.run {
objectInstance
?: kotlin.runCatching { createInstance() }.getOrNull()
?: (java.constructors + java.declaredConstructors)

View File

@ -9,6 +9,7 @@
package net.mamoe.mirai.console.plugin.jvm
import com.vdurmont.semver4j.Semver
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
@ -16,6 +17,7 @@ import net.mamoe.mirai.console.plugin.FilePluginDescription
import net.mamoe.mirai.console.plugin.PluginDependency
import net.mamoe.mirai.console.plugin.PluginDescription
import net.mamoe.mirai.console.plugin.PluginKind
import net.mamoe.mirai.console.utils.SemverAsStringSerializerLoose
import java.io.File
@Serializable
@ -25,7 +27,7 @@ public class JvmPluginDescription internal constructor(
@SerialName("main")
public val mainClassName: String,
public override val author: String = "",
public override val version: String,
public override val version: @Serializable(with = SemverAsStringSerializerLoose::class) Semver,
public override val info: String = "",
@SerialName("depends")
public override val dependencies: List<@Serializable(with = PluginDependency.SmartSerializer::class) PluginDependency> = listOf()
@ -37,7 +39,7 @@ public class JvmPluginDescription internal constructor(
@Suppress("unused")
public constructor(
kind: PluginKind, name: String, mainClassName: String, author: String,
version: String, info: String, depends: List<PluginDependency>,
version: Semver, info: String, depends: List<PluginDependency>,
file: File
) : this(kind, name, mainClassName, author, version, info, depends) {
this._file = file

View File

@ -0,0 +1,28 @@
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package net.mamoe.mirai.console.utils
import com.vdurmont.semver4j.Semver
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializer
import kotlinx.serialization.builtins.serializer
import net.mamoe.mirai.console.setting.internal.map
@Serializer(forClass = Semver::class)
internal object SemverAsStringSerializerLoose : KSerializer<Semver> by String.serializer().map(
serializer = { it.toString() },
deserializer = { Semver(it, Semver.SemverType.LOOSE) }
)
@Serializer(forClass = Semver::class)
internal object SemverAsStringSerializerIvy : KSerializer<Semver> by String.serializer().map(
serializer = { it.toString() },
deserializer = { Semver(it, Semver.SemverType.IVY) }
)