mirror of
https://github.com/gitbucket/gitbucket.git
synced 2025-11-05 04:56:02 +01:00
Plugin updating is executed asynchronously by Quartz Scheduler
This commit is contained in:
@@ -41,6 +41,7 @@ object MyBuild extends Build {
|
|||||||
"com.typesafe.slick" %% "slick" % "1.0.1",
|
"com.typesafe.slick" %% "slick" % "1.0.1",
|
||||||
"org.mozilla" % "rhino" % "1.7R4",
|
"org.mozilla" % "rhino" % "1.7R4",
|
||||||
"com.novell.ldap" % "jldap" % "2009-10-07",
|
"com.novell.ldap" % "jldap" % "2009-10-07",
|
||||||
|
"org.quartz-scheduler" % "quartz" % "2.2.1",
|
||||||
"com.h2database" % "h2" % "1.3.173",
|
"com.h2database" % "h2" % "1.3.173",
|
||||||
"ch.qos.logback" % "logback-classic" % "1.0.13" % "runtime",
|
"ch.qos.logback" % "logback-classic" % "1.0.13" % "runtime",
|
||||||
"org.eclipse.jetty" % "jetty-webapp" % "8.1.8.v20121106" % "container;provided",
|
"org.eclipse.jetty" % "jetty-webapp" % "8.1.8.v20121106" % "container;provided",
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import util.Directory._
|
|||||||
import util.ControlUtil._
|
import util.ControlUtil._
|
||||||
import jp.sf.amateras.scalatra.forms._
|
import jp.sf.amateras.scalatra.forms._
|
||||||
import ssh.SshServer
|
import ssh.SshServer
|
||||||
import org.scalatra.Ok
|
|
||||||
import org.apache.commons.io.FileUtils
|
import org.apache.commons.io.FileUtils
|
||||||
import java.io.FileInputStream
|
import java.io.FileInputStream
|
||||||
import plugin.{Plugin, PluginSystem}
|
import plugin.{Plugin, PluginSystem}
|
||||||
@@ -100,8 +99,6 @@ trait SystemSettingsControllerBase extends ControllerBase {
|
|||||||
})
|
})
|
||||||
|
|
||||||
get("/admin/plugins/available")(adminOnly {
|
get("/admin/plugins/available")(adminOnly {
|
||||||
// TODO Do periodical and asynchronous...?
|
|
||||||
PluginSystem.updateAllRepositories()
|
|
||||||
val installedPlugins = plugin.PluginSystem.plugins
|
val installedPlugins = plugin.PluginSystem.plugins
|
||||||
val availablePlugins = getAvailablePlugins(installedPlugins).filter(_.status == "available")
|
val availablePlugins = getAvailablePlugins(installedPlugins).filter(_.status == "available")
|
||||||
admin.plugins.html.available(availablePlugins)
|
admin.plugins.html.available(availablePlugins)
|
||||||
|
|||||||
@@ -87,25 +87,6 @@ object PluginSystem {
|
|||||||
case class RepositoryMenu(label: String, name: String, url: String, icon: String, condition: Context => Boolean)
|
case class RepositoryMenu(label: String, name: String, url: String, icon: String, condition: Context => Boolean)
|
||||||
case class Action(path: String, function: (HttpServletRequest, HttpServletResponse) => Any)
|
case class Action(path: String, function: (HttpServletRequest, HttpServletResponse) => Any)
|
||||||
|
|
||||||
/**
|
|
||||||
* Clone or pull all plugin repositories
|
|
||||||
*
|
|
||||||
* TODO Support plugin repository access through the proxy server
|
|
||||||
*/
|
|
||||||
def updateAllRepositories(): Unit = {
|
|
||||||
repositories.foreach { repository =>
|
|
||||||
val dir = getPluginCacheDir()
|
|
||||||
val repo = new java.io.File(dir, repository.id)
|
|
||||||
if(repo.exists){
|
|
||||||
// pull if the repository is already cloned
|
|
||||||
Git.open(repo).pull().call()
|
|
||||||
} else {
|
|
||||||
// clone if the repository is not exist
|
|
||||||
Git.cloneRepository().setURI(repository.url).setDirectory(repo).call()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether the plugin is updatable.
|
* Checks whether the plugin is updatable.
|
||||||
*/
|
*/
|
||||||
@@ -126,8 +107,6 @@ object PluginSystem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// TODO This is a test
|
// TODO This is a test
|
||||||
// addGlobalMenu("Google", "http://www.google.co.jp/", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAEvwAABL8BkeKJvAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAIgSURBVEiJtdZNiI1hFAfw36ORhSFFPgYLszOKJAsWRLGzks1gYyFZKFs7C7K2Y2XDRiwmq9kIJWQjJR9Tk48xRtTIRwjH4p473nm99yLNqdNTz/mf//+555x7ektEmEmbNaPs6OkUKKX0YBmWp6/IE8bwIs8xjEfEt0aiiJBl6sEuXMRLfEf8pX/PnIvJ0TPFWxE4+w+Ef/Kzbd5qDx5l8H8tkku7LG17gH7sxWatevdhEUoXsjda5RnDTZzH6jagtMe0lHIa23AJw3iOiSRZlmJ9mfcyfTzFl2AldmI3rkbEkbrAYKrX7S1eVRyWVnxhQ87eiLjQ+o2/mtyve+PuYy3W4+EfsP2/TVGKTHRI+Iz9Fdx8XOmAnZjGWRMYqoF/4ESW4hpOYk1iZ2WsLjDUTeBYBfgeuyux2XiNT5hXud+DD5W8Y90EtifoSfultfjx7MVtrKzcr8No5m7vJtCLx1hQJ8/4IZzClpyoy5ibsYUYQW81Z9o2jYgPeKr15+poEXE9+1XF9WIkOaasaV2P4k4pZUdDbEm+VEQcjIgtEfGxlLIVd/Gs6TX1MhzQquU3HK1t23f4IsuS94fxNXMO/MbXIDBg+tidw5yMbcCmylSdqWEH/kagYLKWeAt9Fcxi3KhhJuXq6SqQBMO15NDalvswmLWux4cbuToIbMS9BpJOfg8bm7imtmmTlVJWaa3hpnU9nufziBjtyDHTny0/AaA7Qnb4AM4aAAAAAElFTkSuQmCC")
|
// addGlobalMenu("Google", "http://www.google.co.jp/", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAEvwAABL8BkeKJvAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAIgSURBVEiJtdZNiI1hFAfw36ORhSFFPgYLszOKJAsWRLGzks1gYyFZKFs7C7K2Y2XDRiwmq9kIJWQjJR9Tk48xRtTIRwjH4p473nm99yLNqdNTz/mf//+555x7ektEmEmbNaPs6OkUKKX0YBmWp6/IE8bwIs8xjEfEt0aiiJBl6sEuXMRLfEf8pX/PnIvJ0TPFWxE4+w+Ef/Kzbd5qDx5l8H8tkku7LG17gH7sxWatevdhEUoXsjda5RnDTZzH6jagtMe0lHIa23AJw3iOiSRZlmJ9mfcyfTzFl2AldmI3rkbEkbrAYKrX7S1eVRyWVnxhQ87eiLjQ+o2/mtyve+PuYy3W4+EfsP2/TVGKTHRI+Iz9Fdx8XOmAnZjGWRMYqoF/4ESW4hpOYk1iZ2WsLjDUTeBYBfgeuyux2XiNT5hXud+DD5W8Y90EtifoSfultfjx7MVtrKzcr8No5m7vJtCLx1hQJ8/4IZzClpyoy5ibsYUYQW81Z9o2jYgPeKr15+poEXE9+1XF9WIkOaasaV2P4k4pZUdDbEm+VEQcjIgtEfGxlLIVd/Gs6TX1MhzQquU3HK1t23f4IsuS94fxNXMO/MbXIDBg+tidw5yMbcCmylSdqWEH/kagYLKWeAt9Fcxi3KhhJuXq6SqQBMO15NDalvswmLWux4cbuToIbMS9BpJOfg8bm7imtmmTlVJWaa3hpnU9nufziBjtyDHTny0/AaA7Qnb4AM4aAAAAAElFTkSuQmCC")
|
||||||
// { context => context.loginAccount.isDefined }
|
// { context => context.loginAccount.isDefined }
|
||||||
|
|||||||
66
src/main/scala/plugin/PluginUpdateJob.scala
Normal file
66
src/main/scala/plugin/PluginUpdateJob.scala
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
package plugin
|
||||||
|
|
||||||
|
import util.Directory._
|
||||||
|
import org.eclipse.jgit.api.Git
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
import org.quartz.{Scheduler, JobExecutionContext, Job}
|
||||||
|
import org.quartz.JobBuilder._
|
||||||
|
import org.quartz.TriggerBuilder._
|
||||||
|
import org.quartz.SimpleScheduleBuilder._
|
||||||
|
|
||||||
|
class PluginUpdateJob extends Job {
|
||||||
|
|
||||||
|
private val logger = LoggerFactory.getLogger(classOf[PluginUpdateJob])
|
||||||
|
private var failedCount = 0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clone or pull all plugin repositories
|
||||||
|
*
|
||||||
|
* TODO Support plugin repository access through the proxy server
|
||||||
|
*/
|
||||||
|
override def execute(context: JobExecutionContext): Unit = {
|
||||||
|
try {
|
||||||
|
if(failedCount > 3){
|
||||||
|
logger.error("Skip plugin information updating because failed count is over limit")
|
||||||
|
} else {
|
||||||
|
logger.info("Start plugin information updating")
|
||||||
|
PluginSystem.repositories.foreach { repository =>
|
||||||
|
logger.info(s"Updating ${repository.id}: ${repository.url}...")
|
||||||
|
val dir = getPluginCacheDir()
|
||||||
|
val repo = new java.io.File(dir, repository.id)
|
||||||
|
if(repo.exists){
|
||||||
|
// pull if the repository is already cloned
|
||||||
|
Git.open(repo).pull().call()
|
||||||
|
} else {
|
||||||
|
// clone if the repository is not exist
|
||||||
|
Git.cloneRepository().setURI(repository.url).setDirectory(repo).call()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.info("End plugin information updating")
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
case e: Exception => {
|
||||||
|
failedCount = failedCount + 1
|
||||||
|
logger.error("Failed to update plugin information", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object PluginUpdateJob {
|
||||||
|
|
||||||
|
def schedule(scheduler: Scheduler): Unit = {
|
||||||
|
val job = newJob(classOf[PluginUpdateJob])
|
||||||
|
.withIdentity("pluginUpdateJob")
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val trigger = newTrigger()
|
||||||
|
.withIdentity("pluginUpdateTrigger")
|
||||||
|
.startNow()
|
||||||
|
.withSchedule(simpleSchedule().withIntervalInHours(24).repeatForever())
|
||||||
|
.build()
|
||||||
|
|
||||||
|
scheduler.scheduleJob(job, trigger)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@ import util.Directory._
|
|||||||
import util.ControlUtil._
|
import util.ControlUtil._
|
||||||
import org.eclipse.jgit.api.Git
|
import org.eclipse.jgit.api.Git
|
||||||
import util.Directory
|
import util.Directory
|
||||||
|
import plugin.PluginUpdateJob
|
||||||
|
|
||||||
object AutoUpdate {
|
object AutoUpdate {
|
||||||
|
|
||||||
@@ -143,8 +144,14 @@ object AutoUpdate {
|
|||||||
* Update database schema automatically in the context initializing.
|
* Update database schema automatically in the context initializing.
|
||||||
*/
|
*/
|
||||||
class AutoUpdateListener extends ServletContextListener {
|
class AutoUpdateListener extends ServletContextListener {
|
||||||
|
import org.quartz.impl.StdSchedulerFactory
|
||||||
|
import org.quartz.JobBuilder._
|
||||||
|
import org.quartz.TriggerBuilder._
|
||||||
|
import org.quartz.SimpleScheduleBuilder._
|
||||||
import AutoUpdate._
|
import AutoUpdate._
|
||||||
|
|
||||||
private val logger = LoggerFactory.getLogger(classOf[AutoUpdateListener])
|
private val logger = LoggerFactory.getLogger(classOf[AutoUpdateListener])
|
||||||
|
private val scheduler = StdSchedulerFactory.getDefaultScheduler
|
||||||
|
|
||||||
override def contextInitialized(event: ServletContextEvent): Unit = {
|
override def contextInitialized(event: ServletContextEvent): Unit = {
|
||||||
val datadir = event.getServletContext.getInitParameter("gitbucket.home")
|
val datadir = event.getServletContext.getInitParameter("gitbucket.home")
|
||||||
@@ -181,11 +188,16 @@ class AutoUpdateListener extends ServletContextListener {
|
|||||||
|
|
||||||
logger.debug("Starting plugin system...")
|
logger.debug("Starting plugin system...")
|
||||||
plugin.PluginSystem.init()
|
plugin.PluginSystem.init()
|
||||||
|
|
||||||
|
scheduler.start()
|
||||||
|
PluginUpdateJob.schedule(scheduler)
|
||||||
|
logger.debug("PluginUpdateJob is started.")
|
||||||
|
|
||||||
logger.debug("Plugin system is initialized.")
|
logger.debug("Plugin system is initialized.")
|
||||||
}
|
}
|
||||||
|
|
||||||
def contextDestroyed(sce: ServletContextEvent): Unit = {
|
def contextDestroyed(sce: ServletContextEvent): Unit = {
|
||||||
// Nothing to do.
|
scheduler.shutdown()
|
||||||
}
|
}
|
||||||
|
|
||||||
private def getConnection(servletContext: ServletContext): Connection =
|
private def getConnection(servletContext: ServletContext): Connection =
|
||||||
|
|||||||
Reference in New Issue
Block a user