mirror of
https://github.com/gitbucket/gitbucket.git
synced 2025-11-08 14:35:52 +01:00
Add migration system for plugins
This commit is contained in:
@@ -1,11 +1,13 @@
|
|||||||
package plugin
|
package plugin
|
||||||
|
|
||||||
|
import util.Version
|
||||||
|
|
||||||
trait Plugin {
|
trait Plugin {
|
||||||
|
|
||||||
val pluginId: String
|
val pluginId: String
|
||||||
val pluginName: String
|
val pluginName: String
|
||||||
val description: String
|
val description: String
|
||||||
val version: String
|
val versions: List[Version]
|
||||||
|
|
||||||
def initialize(registry: PluginRegistry): Unit
|
def initialize(registry: PluginRegistry): Unit
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import org.slf4j.LoggerFactory
|
|||||||
import service.RepositoryService.RepositoryInfo
|
import service.RepositoryService.RepositoryInfo
|
||||||
import util.Directory._
|
import util.Directory._
|
||||||
import util.JDBCUtil._
|
import util.JDBCUtil._
|
||||||
|
import util.{Version, Versions}
|
||||||
|
|
||||||
import scala.collection.mutable.ListBuffer
|
import scala.collection.mutable.ListBuffer
|
||||||
|
|
||||||
@@ -88,24 +89,36 @@ object PluginRegistry {
|
|||||||
val classLoader = new URLClassLoader(Array(pluginJar.toURI.toURL), Thread.currentThread.getContextClassLoader)
|
val classLoader = new URLClassLoader(Array(pluginJar.toURI.toURL), Thread.currentThread.getContextClassLoader)
|
||||||
try {
|
try {
|
||||||
val plugin = classLoader.loadClass("Plugin").newInstance().asInstanceOf[Plugin]
|
val plugin = classLoader.loadClass("Plugin").newInstance().asInstanceOf[Plugin]
|
||||||
|
|
||||||
|
// Migration
|
||||||
|
val headVersion = plugin.versions.head
|
||||||
|
val currentVersion = conn.find("SELECT * FROM PLUGIN WHERE PLUGIN_ID = ?", plugin.pluginId)(_.getString("VERSION")) match {
|
||||||
|
case Some(x) => {
|
||||||
|
val dim = x.split("\\.")
|
||||||
|
Version(dim(0).toInt, dim(1).toInt)
|
||||||
|
}
|
||||||
|
case None => Version(0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
Versions.update(conn, headVersion, currentVersion, plugin.versions, new URLClassLoader(Array(pluginJar.toURI.toURL))){ conn =>
|
||||||
|
currentVersion.versionString match {
|
||||||
|
case "0.0" =>
|
||||||
|
conn.update("INSERT INTO PLUGIN (PLUGIN_ID, VERSION) VALUES (?, ?)", plugin.pluginId, headVersion.versionString)
|
||||||
|
case _ =>
|
||||||
|
conn.update("UPDATE PLUGIN SET VERSION = ? WHERE PLUGIN_ID = ?", headVersion.versionString, plugin.pluginId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize
|
||||||
plugin.initialize(instance)
|
plugin.initialize(instance)
|
||||||
instance.addPlugin(PluginInfo(
|
instance.addPlugin(PluginInfo(
|
||||||
pluginId = plugin.pluginId,
|
pluginId = plugin.pluginId,
|
||||||
pluginName = plugin.pluginName,
|
pluginName = plugin.pluginName,
|
||||||
version = plugin.version,
|
version = plugin.versions.head.versionString,
|
||||||
description = plugin.description,
|
description = plugin.description,
|
||||||
pluginClass = plugin
|
pluginClass = plugin
|
||||||
))
|
))
|
||||||
|
|
||||||
conn.find("SELECT * FROM PLUGIN WHERE PLUGIN_ID = ?", plugin.pluginId)(_.getString("VERSION")) match {
|
|
||||||
// Update if the plugin is already registered
|
|
||||||
case Some(currentVersion) => conn.update("UPDATE PLUGIN SET VERSION = ? WHERE PLUGIN_ID = ?", plugin.version, plugin.pluginId)
|
|
||||||
// Insert if the plugin does not exist
|
|
||||||
case None => conn.update("INSERT INTO PLUGIN (PLUGIN_ID, VERSION) VALUES (?, ?)", plugin.pluginId, plugin.version)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO Migration
|
|
||||||
|
|
||||||
} catch {
|
} catch {
|
||||||
case e: Exception => {
|
case e: Exception => {
|
||||||
logger.error(s"Error during plugin initialization", e)
|
logger.error(s"Error during plugin initialization", e)
|
||||||
|
|||||||
@@ -13,8 +13,6 @@ import org.eclipse.jgit.api.Git
|
|||||||
import util.Directory
|
import util.Directory
|
||||||
import plugin._
|
import plugin._
|
||||||
|
|
||||||
import scala.slick.jdbc.meta.MBestRowIdentifierColumn.Scope.Session
|
|
||||||
|
|
||||||
object AutoUpdate {
|
object AutoUpdate {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
67
src/main/scala/util/Version.scala
Normal file
67
src/main/scala/util/Version.scala
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
package util
|
||||||
|
|
||||||
|
import java.sql.Connection
|
||||||
|
|
||||||
|
import org.apache.commons.io.IOUtils
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
import util.ControlUtil._
|
||||||
|
|
||||||
|
case class Version(majorVersion: Int, minorVersion: Int) {
|
||||||
|
|
||||||
|
private val logger = LoggerFactory.getLogger(classOf[Version])
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute update/MAJOR_MINOR.sql to update schema to this version.
|
||||||
|
* If corresponding SQL file does not exist, this method do nothing.
|
||||||
|
*/
|
||||||
|
def update(conn: Connection, cl: ClassLoader): Unit = {
|
||||||
|
val sqlPath = s"update/${majorVersion}_${minorVersion}.sql"
|
||||||
|
|
||||||
|
using(cl.getResourceAsStream(sqlPath)){ in =>
|
||||||
|
if(in != null){
|
||||||
|
val sql = IOUtils.toString(in, "UTF-8")
|
||||||
|
using(conn.createStatement()){ stmt =>
|
||||||
|
logger.debug(sqlPath + "=" + sql)
|
||||||
|
stmt.executeUpdate(sql)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MAJOR.MINOR
|
||||||
|
*/
|
||||||
|
val versionString = s"${majorVersion}.${minorVersion}"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
object Versions {
|
||||||
|
|
||||||
|
private val logger = LoggerFactory.getLogger(Versions.getClass)
|
||||||
|
|
||||||
|
def update(conn: Connection, headVersion: Version, currentVersion: Version, versions: List[Version], cl: ClassLoader)
|
||||||
|
(save: Connection => Unit): Unit = {
|
||||||
|
logger.debug("Start schema update")
|
||||||
|
try {
|
||||||
|
if(currentVersion == headVersion){
|
||||||
|
logger.debug("No update")
|
||||||
|
} else if(currentVersion.versionString != "0.0" && !versions.contains(currentVersion)){
|
||||||
|
logger.warn(s"Skip migration because ${currentVersion.versionString} is illegal version.")
|
||||||
|
} else {
|
||||||
|
versions.takeWhile(_ != currentVersion).reverse.foreach(_.update(conn, cl))
|
||||||
|
save(conn)
|
||||||
|
logger.debug(s"Updated from ${currentVersion.versionString} to ${headVersion.versionString}")
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
case ex: Throwable => {
|
||||||
|
logger.error("Failed to schema update", ex)
|
||||||
|
ex.printStackTrace()
|
||||||
|
conn.rollback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.debug("End schema update")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user