mirror of
https://github.com/mamoe/mirai.git
synced 2026-08-22 14:13:32 +08:00
[console] Pre check plugin duplication & console requirement (#2703)
* feat: check in load plugin * feat: console requirement * feat: dependsOn mirai * feat: dependsOn docs * fix: docs * use: net.mamoe.mirai-console * revert * [console] Wrap mirai-console as a plugin * [console] Fix plugin dependencies checking skipped already loaded plugins * [console/tests] Check plugin can depends on mirai-console --------- Co-authored-by: Karlatemp <kar@kasukusakura.com>
This commit is contained in:
@@ -0,0 +1,10 @@
|
|||||||
|
#
|
||||||
|
# Copyright 2019-2023 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/dev/LICENSE
|
||||||
|
#
|
||||||
|
|
||||||
|
net.mamoe.console.itest.plugincandependsonmiraiconsole.PluginCanDependsOnMiraiConsole
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2023 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/dev/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.mamoe.console.itest.plugincandependsonmiraiconsole
|
||||||
|
|
||||||
|
import net.mamoe.mirai.console.plugin.jvm.JvmPluginDescription
|
||||||
|
import net.mamoe.mirai.console.plugin.jvm.KotlinPlugin
|
||||||
|
|
||||||
|
internal object PluginCanDependsOnMiraiConsole : KotlinPlugin(
|
||||||
|
JvmPluginDescription("net.mamoe.tester.plugin-can-depends-mirai-console", "1.0.0") {
|
||||||
|
dependsOn("net.mamoe.mirai-console")
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -39,6 +39,7 @@ import net.mamoe.mirai.console.internal.extension.GlobalComponentStorage
|
|||||||
import net.mamoe.mirai.console.internal.permission.BuiltInPermissionService
|
import net.mamoe.mirai.console.internal.permission.BuiltInPermissionService
|
||||||
import net.mamoe.mirai.console.internal.permission.getPermittedPermissionsAndSource
|
import net.mamoe.mirai.console.internal.permission.getPermittedPermissionsAndSource
|
||||||
import net.mamoe.mirai.console.internal.plugin.JvmPluginInternal
|
import net.mamoe.mirai.console.internal.plugin.JvmPluginInternal
|
||||||
|
import net.mamoe.mirai.console.internal.plugin.MiraiConsoleAsPlugin
|
||||||
import net.mamoe.mirai.console.internal.pluginManagerImpl
|
import net.mamoe.mirai.console.internal.pluginManagerImpl
|
||||||
import net.mamoe.mirai.console.internal.util.runIgnoreException
|
import net.mamoe.mirai.console.internal.util.runIgnoreException
|
||||||
import net.mamoe.mirai.console.permission.Permission
|
import net.mamoe.mirai.console.permission.Permission
|
||||||
@@ -633,10 +634,15 @@ public object BuiltInCommands {
|
|||||||
reset().append("\n\n")
|
reset().append("\n\n")
|
||||||
|
|
||||||
append("Plugins: ")
|
append("Plugins: ")
|
||||||
if (MiraiConsole.pluginManagerImpl.resolvedPlugins.isEmpty()) {
|
|
||||||
|
val resolvedPlugins = MiraiConsole.pluginManagerImpl.resolvedPlugins.asSequence()
|
||||||
|
.filter { it !is MiraiConsoleAsPlugin } // skip mirai-console in status
|
||||||
|
.toList()
|
||||||
|
|
||||||
|
if (resolvedPlugins.isEmpty()) {
|
||||||
gray().append("<none>")
|
gray().append("<none>")
|
||||||
} else {
|
} else {
|
||||||
MiraiConsole.pluginManagerImpl.resolvedPlugins.joinTo(this) { plugin ->
|
resolvedPlugins.joinTo(this) { plugin ->
|
||||||
if (plugin.isEnabled) {
|
if (plugin.isEnabled) {
|
||||||
green().append(plugin.name).reset().append(" v").gold()
|
green().append(plugin.name).reset().append(" v").gold()
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -287,7 +287,7 @@ internal class BuiltInJvmPluginLoaderImpl(
|
|||||||
return filePlugins.toSet().map { it.second }
|
return filePlugins.toSet().map { it.second }
|
||||||
}
|
}
|
||||||
|
|
||||||
private val loadedPlugins = ConcurrentHashMap<JvmPlugin, Unit>()
|
private val loadedPlugins = ConcurrentHashMap<String, JvmPlugin>()
|
||||||
|
|
||||||
private fun Path.moveNameFolder(plugin: JvmPlugin) {
|
private fun Path.moveNameFolder(plugin: JvmPlugin) {
|
||||||
val nameFolder = this.resolve(plugin.description.name).toFile()
|
val nameFolder = this.resolve(plugin.description.name).toFile()
|
||||||
@@ -324,8 +324,8 @@ internal class BuiltInJvmPluginLoaderImpl(
|
|||||||
override fun load(plugin: JvmPlugin) {
|
override fun load(plugin: JvmPlugin) {
|
||||||
ensureActive()
|
ensureActive()
|
||||||
|
|
||||||
if (loadedPlugins.put(plugin, Unit) != null) {
|
if (loadedPlugins.put(plugin.id, plugin) != null) {
|
||||||
error("Plugin '${plugin.name}' is already loaded and cannot be reloaded.")
|
error("Plugin '${plugin.id}' is already loaded and cannot be reloaded.")
|
||||||
}
|
}
|
||||||
logger.verbose { "Loading plugin ${plugin.description.smartToString()}" }
|
logger.verbose { "Loading plugin ${plugin.description.smartToString()}" }
|
||||||
runCatching {
|
runCatching {
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2023 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/dev/LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.mamoe.mirai.console.internal.plugin
|
||||||
|
|
||||||
|
import net.mamoe.mirai.console.command.ConsoleCommandOwner
|
||||||
|
import net.mamoe.mirai.console.internal.MiraiConsoleBuildConstants
|
||||||
|
import net.mamoe.mirai.console.permission.Permission
|
||||||
|
import net.mamoe.mirai.console.permission.PermissionId
|
||||||
|
import net.mamoe.mirai.console.plugin.Plugin
|
||||||
|
import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.description
|
||||||
|
import net.mamoe.mirai.console.plugin.description.PluginDependency
|
||||||
|
import net.mamoe.mirai.console.plugin.description.PluginDescription
|
||||||
|
import net.mamoe.mirai.console.plugin.loader.PluginLoader
|
||||||
|
import net.mamoe.mirai.console.util.SemVersion
|
||||||
|
|
||||||
|
internal object MiraiConsoleAsPlugin : Plugin {
|
||||||
|
// MiraiConsole always enabled
|
||||||
|
override val isEnabled: Boolean get() = true
|
||||||
|
|
||||||
|
override val loader: PluginLoader<*, *> get() = TheLoader
|
||||||
|
|
||||||
|
override val parentPermission: Permission
|
||||||
|
get() = ConsoleCommandOwner.parentPermission
|
||||||
|
|
||||||
|
override fun permissionId(name: String): PermissionId {
|
||||||
|
return ConsoleCommandOwner.permissionId(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal object TheLoader : PluginLoader<Plugin, PluginDescription> {
|
||||||
|
override fun listPlugins(): List<Plugin> = listOf(MiraiConsoleAsPlugin)
|
||||||
|
|
||||||
|
override fun disable(plugin: Plugin) {
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun enable(plugin: Plugin) {
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun load(plugin: Plugin) {
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getPluginDescription(plugin: Plugin): PluginDescription {
|
||||||
|
if (plugin !== MiraiConsoleAsPlugin) {
|
||||||
|
error("loader not match with " + plugin.description.id)
|
||||||
|
}
|
||||||
|
return TheDescription
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal object TheDescription : PluginDescription {
|
||||||
|
override val id: String get() = "net.mamoe.mirai-console"
|
||||||
|
override val name: String get() = "Console"
|
||||||
|
override val author: String get() = "Mamoe Technologies"
|
||||||
|
override val version: SemVersion get() = MiraiConsoleBuildConstants.version
|
||||||
|
override val info: String get() = ""
|
||||||
|
override val dependencies: Set<PluginDependency> get() = setOf()
|
||||||
|
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return "PluginDescription[ mirai-console ]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,6 +20,7 @@ import net.mamoe.mirai.console.internal.extension.GlobalComponentStorage
|
|||||||
import net.mamoe.mirai.console.plugin.NotYetLoadedPlugin
|
import net.mamoe.mirai.console.plugin.NotYetLoadedPlugin
|
||||||
import net.mamoe.mirai.console.plugin.Plugin
|
import net.mamoe.mirai.console.plugin.Plugin
|
||||||
import net.mamoe.mirai.console.plugin.PluginManager
|
import net.mamoe.mirai.console.plugin.PluginManager
|
||||||
|
import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.description
|
||||||
import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.safeLoader
|
import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.safeLoader
|
||||||
import net.mamoe.mirai.console.plugin.description.PluginDependency
|
import net.mamoe.mirai.console.plugin.description.PluginDependency
|
||||||
import net.mamoe.mirai.console.plugin.description.PluginDescription
|
import net.mamoe.mirai.console.plugin.description.PluginDescription
|
||||||
@@ -88,6 +89,8 @@ internal class PluginManagerImpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resolvedPlugins.add(MiraiConsoleAsPlugin)
|
||||||
}
|
}
|
||||||
|
|
||||||
// region LOADING
|
// region LOADING
|
||||||
@@ -207,6 +210,8 @@ internal class PluginManagerImpl(
|
|||||||
|
|
||||||
@Throws(PluginResolutionException::class)
|
@Throws(PluginResolutionException::class)
|
||||||
private fun <D : PluginDescription> List<D>.sortByDependencies(): List<D> {
|
private fun <D : PluginDescription> List<D>.sortByDependencies(): List<D> {
|
||||||
|
val alreadyLoadedPlugins = resolvedPlugins.asSequence().map { it.description }.toList() // snapshot
|
||||||
|
|
||||||
val originPluginDescriptions = this@sortByDependencies
|
val originPluginDescriptions = this@sortByDependencies
|
||||||
val pending2BeResolved = originPluginDescriptions.toMutableList()
|
val pending2BeResolved = originPluginDescriptions.toMutableList()
|
||||||
val resolved = ArrayList<D>(pending2BeResolved.size)
|
val resolved = ArrayList<D>(pending2BeResolved.size)
|
||||||
@@ -252,6 +257,8 @@ internal class PluginManagerImpl(
|
|||||||
pending2BeResolved.forEach { pluginDesc ->
|
pending2BeResolved.forEach { pluginDesc ->
|
||||||
val missed = pluginDesc.dependencies.filter { dependency ->
|
val missed = pluginDesc.dependencies.filter { dependency ->
|
||||||
val resolvedDep = originPluginDescriptions.findDependency(dependency)
|
val resolvedDep = originPluginDescriptions.findDependency(dependency)
|
||||||
|
?: alreadyLoadedPlugins.findDependency(dependency)
|
||||||
|
|
||||||
if (resolvedDep != null) {
|
if (resolvedDep != null) {
|
||||||
resolvedDep.checkSatisfies(dependency, pluginDesc)
|
resolvedDep.checkSatisfies(dependency, pluginDesc)
|
||||||
false
|
false
|
||||||
|
|||||||
@@ -104,6 +104,8 @@ public interface PluginDescription {
|
|||||||
/**
|
/**
|
||||||
* 此插件依赖的其他插件, 将会在这些插件加载之后加载此插件
|
* 此插件依赖的其他插件, 将会在这些插件加载之后加载此插件
|
||||||
*
|
*
|
||||||
|
* 特别的, 可以使用 `net.mamoe.mirai-console` 作为插件 id 限制 mirai-console 版本 (自 2.16.0 后)
|
||||||
|
*
|
||||||
* @see PluginDependency
|
* @see PluginDependency
|
||||||
*/
|
*/
|
||||||
public val dependencies: Set<PluginDependency>
|
public val dependencies: Set<PluginDependency>
|
||||||
|
|||||||
@@ -18,11 +18,11 @@ class FrameworkInstanceTest : AbstractConsoleInstanceTest() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testConsole1() {
|
fun testConsole1() {
|
||||||
assertEquals(0, PluginManager.plugins.size)
|
assertEquals(1, PluginManager.plugins.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testConsole2() {
|
fun testConsole2() {
|
||||||
assertEquals(0, PluginManager.plugins.size)
|
assertEquals(1, PluginManager.plugins.size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user