From 1fbfcfb4460b5c12689aa5e97519d47fdc8768ad Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Tue, 5 Sep 2017 15:14:54 +0900 Subject: [PATCH 01/37] Add ssh_url to API response --- .../scala/gitbucket/core/api/ApiPath.scala | 9 +++++- .../gitbucket/core/api/ApiRepository.scala | 18 +++++++----- .../scala/gitbucket/core/api/JsonFormat.scala | 29 ++++++++++--------- .../core/service/SystemSettingsService.scala | 19 ++++++------ .../core/servlet/GitRepositoryServlet.scala | 16 ++++++---- .../scala/gitbucket/core/ssh/GitCommand.scala | 8 ++--- .../core/ssh/SshServerListener.scala | 2 +- .../scala/gitbucket/core/util/Implicits.scala | 8 ++--- 8 files changed, 60 insertions(+), 49 deletions(-) diff --git a/src/main/scala/gitbucket/core/api/ApiPath.scala b/src/main/scala/gitbucket/core/api/ApiPath.scala index 661ce47c5..dc96a7c89 100644 --- a/src/main/scala/gitbucket/core/api/ApiPath.scala +++ b/src/main/scala/gitbucket/core/api/ApiPath.scala @@ -1,6 +1,13 @@ package gitbucket.core.api /** - * path for api url. if set path '/repos/aa/bb' then, expand 'http://server:post/repos/aa/bb' when converted to json. + * Path for API url. + * If set path '/repos/aa/bb' then, expand 'http://server:port/repos/aa/bb' when converted to json. */ case class ApiPath(path: String) + +/** + * Path for git repository via SSH. + * If set path '/aa/bb.git' then, expand 'git@server:port/aa/bb.git' when converted to json. + */ +case class SshPath(path: String) diff --git a/src/main/scala/gitbucket/core/api/ApiRepository.scala b/src/main/scala/gitbucket/core/api/ApiRepository.scala index 1f790727e..f5d74f60f 100644 --- a/src/main/scala/gitbucket/core/api/ApiRepository.scala +++ b/src/main/scala/gitbucket/core/api/ApiRepository.scala @@ -24,6 +24,7 @@ case class ApiRepository( val http_url = ApiPath(s"/git/${full_name}.git") val clone_url = ApiPath(s"/git/${full_name}.git") val html_url = ApiPath(s"/${full_name}") + val ssh_url = Some(SshPath(s":${full_name}.git")) } object ApiRepository{ @@ -55,12 +56,13 @@ object ApiRepository{ def forDummyPayload(owner: ApiUser): ApiRepository = ApiRepository( - name="dummy", - full_name=s"${owner.login}/dummy", - description="", - watchers=0, - forks=0, - `private`=false, - default_branch="master", - owner=owner)(true) + name = "dummy", + full_name = s"${owner.login}/dummy", + description = "", + watchers = 0, + forks = 0, + `private` = false, + default_branch = "master", + owner = owner + )(true) } diff --git a/src/main/scala/gitbucket/core/api/JsonFormat.scala b/src/main/scala/gitbucket/core/api/JsonFormat.scala index 7164cf643..6533272be 100644 --- a/src/main/scala/gitbucket/core/api/JsonFormat.scala +++ b/src/main/scala/gitbucket/core/api/JsonFormat.scala @@ -10,7 +10,7 @@ import scala.util.Try object JsonFormat { - case class Context(baseUrl: String) + case class Context(baseUrl: String, sshUrl: Option[String]) val parserISO = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss'Z'") @@ -40,21 +40,24 @@ object JsonFormat { FieldSerializer[ApiCommits.File]() + ApiBranchProtection.enforcementLevelSerializer - def apiPathSerializer(c: Context) = new CustomSerializer[ApiPath](format => - ( - { - case JString(s) if s.startsWith(c.baseUrl) => ApiPath(s.substring(c.baseUrl.length)) - case JString(s) => throw new MappingException("Can't convert " + s + " to ApiPath") - }, - { - case ApiPath(path) => JString(c.baseUrl + path) - } - ) - ) + def apiPathSerializer(c: Context) = new CustomSerializer[ApiPath](_ => ({ + case JString(s) if s.startsWith(c.baseUrl) => ApiPath(s.substring(c.baseUrl.length)) + case JString(s) => throw new MappingException("Can't convert " + s + " to ApiPath") + }, { + case ApiPath(path) => JString(c.baseUrl + path) + })) + + def sshPathSerializer(c: Context) = new CustomSerializer[SshPath](_ => ({ + case JString(s) if c.sshUrl.exists(sshUrl => s.startsWith(sshUrl)) => SshPath(s.substring(c.sshUrl.get.length)) + case JString(s) => throw new MappingException("Can't convert " + s + " to ApiPath") + }, { + case SshPath(path) => c.sshUrl.map { sshUrl => JString(sshUrl + path) } getOrElse JNothing + })) /** * convert object to json string */ - def apply(obj: AnyRef)(implicit c: Context): String = Serialization.write(obj)(jsonFormats + apiPathSerializer(c)) + def apply(obj: AnyRef)(implicit c: Context): String = + Serialization.write(obj)(jsonFormats + apiPathSerializer(c) + sshPathSerializer(c)) } diff --git a/src/main/scala/gitbucket/core/service/SystemSettingsService.scala b/src/main/scala/gitbucket/core/service/SystemSettingsService.scala index c73ed3591..bb50df4e2 100644 --- a/src/main/scala/gitbucket/core/service/SystemSettingsService.scala +++ b/src/main/scala/gitbucket/core/service/SystemSettingsService.scala @@ -140,17 +140,16 @@ object SystemSettingsService { ldapAuthentication: Boolean, ldap: Option[Ldap], skinName: String){ - def baseUrl(request: HttpServletRequest): String = baseUrl.fold(request.baseUrl)(_.stripSuffix("/")) - def sshAddress:Option[SshAddress] = - for { - host <- sshHost if ssh - } - yield SshAddress( - host, - sshPort.getOrElse(DefaultSshPort), - "git" - ) + def baseUrl(request: HttpServletRequest): String = baseUrl.fold { + val url = request.getRequestURL.toString + val len = url.length - (request.getRequestURI.length - request.getContextPath.length) + url.substring(0, len).stripSuffix("/") + } (_.stripSuffix("/")) + + def sshAddress:Option[SshAddress] = sshHost.collect { case host if ssh => + SshAddress(host, sshPort.getOrElse(DefaultSshPort), "git") + } } case class Ldap( diff --git a/src/main/scala/gitbucket/core/servlet/GitRepositoryServlet.scala b/src/main/scala/gitbucket/core/servlet/GitRepositoryServlet.scala index 6d14d2c06..521f1397a 100644 --- a/src/main/scala/gitbucket/core/servlet/GitRepositoryServlet.scala +++ b/src/main/scala/gitbucket/core/servlet/GitRepositoryServlet.scala @@ -156,9 +156,13 @@ class GitBucketReceivePackFactory extends ReceivePackFactory[HttpServletRequest] logger.debug("repository:" + owner + "/" + repository) + val settings = loadSystemSettings() + val baseUrl = settings.baseUrl(request) + val sshUrl = settings.sshAddress.map { x => s"${x.genericUser}@${x.host}:${x.port}" } + if(!repository.endsWith(".wiki")){ defining(request) { implicit r => - val hook = new CommitLogHook(owner, repository, pusher, baseUrl) + val hook = new CommitLogHook(owner, repository, pusher, baseUrl, sshUrl) receivePack.setPreReceiveHook(hook) receivePack.setPostReceiveHook(hook) } @@ -166,7 +170,7 @@ class GitBucketReceivePackFactory extends ReceivePackFactory[HttpServletRequest] if(repository.endsWith(".wiki")){ defining(request) { implicit r => - receivePack.setPostReceiveHook(new WikiCommitHook(owner, repository.stripSuffix(".wiki"), pusher, baseUrl)) + receivePack.setPostReceiveHook(new WikiCommitHook(owner, repository.stripSuffix(".wiki"), pusher, baseUrl, sshUrl)) } } } @@ -178,7 +182,7 @@ class GitBucketReceivePackFactory extends ReceivePackFactory[HttpServletRequest] import scala.collection.JavaConverters._ -class CommitLogHook(owner: String, repository: String, pusher: String, baseUrl: String) +class CommitLogHook(owner: String, repository: String, pusher: String, baseUrl: String, sshUrl: Option[String]) extends PostReceiveHook with PreReceiveHook with RepositoryService with AccountService with IssuesService with ActivityService with PullRequestService with WebHookService with WebHookPullRequestService with CommitsService { @@ -219,7 +223,7 @@ class CommitLogHook(owner: String, repository: String, pusher: String, baseUrl: val pushedIds = scala.collection.mutable.Set[String]() commands.asScala.foreach { command => logger.debug(s"commandType: ${command.getType}, refName: ${command.getRefName}") - implicit val apiContext = api.JsonFormat.Context(baseUrl) + implicit val apiContext = api.JsonFormat.Context(baseUrl, sshUrl) val refName = command.getRefName.split("/") val branchName = refName.drop(2).mkString("/") val commits = if (refName(1) == "tags") { @@ -320,7 +324,7 @@ class CommitLogHook(owner: String, repository: String, pusher: String, baseUrl: } -class WikiCommitHook(owner: String, repository: String, pusher: String, baseUrl: String) +class WikiCommitHook(owner: String, repository: String, pusher: String, baseUrl: String, sshUrl: Option[String]) extends PostReceiveHook with WebHookService with AccountService with RepositoryService { private val logger = LoggerFactory.getLogger(classOf[WikiCommitHook]) @@ -329,7 +333,7 @@ class WikiCommitHook(owner: String, repository: String, pusher: String, baseUrl: Database() withTransaction { implicit session => try { commands.asScala.headOption.foreach { command => - implicit val apiContext = api.JsonFormat.Context(baseUrl) + implicit val apiContext = api.JsonFormat.Context(baseUrl, sshUrl) val refName = command.getRefName.split("/") val commitIds = if (refName(1) == "tags") { None diff --git a/src/main/scala/gitbucket/core/ssh/GitCommand.scala b/src/main/scala/gitbucket/core/ssh/GitCommand.scala index 9d7345dee..3be9f8746 100644 --- a/src/main/scala/gitbucket/core/ssh/GitCommand.scala +++ b/src/main/scala/gitbucket/core/ssh/GitCommand.scala @@ -154,7 +154,7 @@ class DefaultGitUploadPack(owner: String, repoName: String) extends DefaultGitCo } } -class DefaultGitReceivePack(owner: String, repoName: String, baseUrl: String) extends DefaultGitCommand(owner, repoName) +class DefaultGitReceivePack(owner: String, repoName: String, baseUrl: String, sshUrl: Option[String]) extends DefaultGitCommand(owner, repoName) with RepositoryService with AccountService with DeployKeyService { override protected def runTask(authType: AuthType): Unit = { @@ -169,7 +169,7 @@ class DefaultGitReceivePack(owner: String, repoName: String, baseUrl: String) ex val repository = git.getRepository val receive = new ReceivePack(repository) if (!repoName.endsWith(".wiki")) { - val hook = new CommitLogHook(owner, repoName, userName(authType), baseUrl) + val hook = new CommitLogHook(owner, repoName, userName(authType), baseUrl, sshUrl) receive.setPreReceiveHook(hook) receive.setPostReceiveHook(hook) } @@ -216,7 +216,7 @@ class PluginGitReceivePack(repoName: String, routing: GitRepositoryRouting) exte } -class GitCommandFactory(baseUrl: String) extends CommandFactory { +class GitCommandFactory(baseUrl: String, sshUrl: Option[String]) extends CommandFactory { private val logger = LoggerFactory.getLogger(classOf[GitCommandFactory]) override def createCommand(command: String): Command = { @@ -227,7 +227,7 @@ class GitCommandFactory(baseUrl: String) extends CommandFactory { case SimpleCommandRegex ("upload" , repoName) if(pluginRepository(repoName)) => new PluginGitUploadPack (repoName, routing(repoName)) case SimpleCommandRegex ("receive", repoName) if(pluginRepository(repoName)) => new PluginGitReceivePack(repoName, routing(repoName)) case DefaultCommandRegex("upload" , owner, repoName) => new DefaultGitUploadPack (owner, repoName) - case DefaultCommandRegex("receive", owner, repoName) => new DefaultGitReceivePack(owner, repoName, baseUrl) + case DefaultCommandRegex("receive", owner, repoName) => new DefaultGitReceivePack(owner, repoName, baseUrl, sshUrl) case _ => new UnknownCommand(command) } } diff --git a/src/main/scala/gitbucket/core/ssh/SshServerListener.scala b/src/main/scala/gitbucket/core/ssh/SshServerListener.scala index 6ff1d0e40..857db45cb 100644 --- a/src/main/scala/gitbucket/core/ssh/SshServerListener.scala +++ b/src/main/scala/gitbucket/core/ssh/SshServerListener.scala @@ -22,7 +22,7 @@ object SshServer { provider.setOverwriteAllowed(false) server.setKeyPairProvider(provider) server.setPublickeyAuthenticator(new PublicKeyAuthenticator(sshAddress.genericUser)) - server.setCommandFactory(new GitCommandFactory(baseUrl)) + server.setCommandFactory(new GitCommandFactory(baseUrl, Some(s"${sshAddress.genericUser}@${sshAddress.host}:${sshAddress.port}"))) server.setShellFactory(new NoShell(sshAddress)) } diff --git a/src/main/scala/gitbucket/core/util/Implicits.scala b/src/main/scala/gitbucket/core/util/Implicits.scala index 77767a3bc..393dbbf88 100644 --- a/src/main/scala/gitbucket/core/util/Implicits.scala +++ b/src/main/scala/gitbucket/core/util/Implicits.scala @@ -22,7 +22,8 @@ object Implicits { // Convert to slick session. implicit def request2Session(implicit request: HttpServletRequest): JdbcBackend#Session = Database.getSession(request) - implicit def context2ApiJsonFormatContext(implicit context: Context): JsonFormat.Context = JsonFormat.Context(context.baseUrl) + implicit def context2ApiJsonFormatContext(implicit context: Context): JsonFormat.Context = + JsonFormat.Context(context.baseUrl, context.settings.sshAddress.map { x => s"${x.genericUser}@${x.host}:${x.port}" }) implicit class RichSeq[A](private val seq: Seq[A]) extends AnyVal { @@ -77,11 +78,6 @@ object Implicits { def gitRepositoryPath: String = request.getRequestURI.replaceFirst("^" + quote(request.getContextPath) + "/git/", "/") - def baseUrl:String = { - val url = request.getRequestURL.toString - val len = url.length - (request.getRequestURI.length - request.getContextPath.length) - url.substring(0, len).stripSuffix("/") - } } implicit class RichSession(private val session: HttpSession) extends AnyVal { From d0c99727e9d6d4a6dd7b0996b1724e2944fc1bee Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Tue, 5 Sep 2017 16:06:06 +0900 Subject: [PATCH 02/37] Fix testcases --- src/test/scala/gitbucket/core/api/JsonFormatSpec.scala | 2 +- src/test/scala/gitbucket/core/ssh/GitCommandSpec.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/scala/gitbucket/core/api/JsonFormatSpec.scala b/src/test/scala/gitbucket/core/api/JsonFormatSpec.scala index ecf421aac..310a34d91 100644 --- a/src/test/scala/gitbucket/core/api/JsonFormatSpec.scala +++ b/src/test/scala/gitbucket/core/api/JsonFormatSpec.scala @@ -22,7 +22,7 @@ class JsonFormatSpec extends FunSuite { } val sha1 = "6dcb09b5b57875f334f61aebed695e2e4193db5e" val repo1Name = RepositoryName("octocat/Hello-World") - implicit val context = JsonFormat.Context("http://gitbucket.exmple.com") + implicit val context = JsonFormat.Context("http://gitbucket.exmple.com", None) val apiUser = ApiUser( login = "octocat", diff --git a/src/test/scala/gitbucket/core/ssh/GitCommandSpec.scala b/src/test/scala/gitbucket/core/ssh/GitCommandSpec.scala index 101352c9c..a3afc823d 100644 --- a/src/test/scala/gitbucket/core/ssh/GitCommandSpec.scala +++ b/src/test/scala/gitbucket/core/ssh/GitCommandSpec.scala @@ -5,7 +5,7 @@ import org.scalatest.FunSpec class GitCommandFactorySpec extends FunSpec { - val factory = new GitCommandFactory("http://localhost:8080") + val factory = new GitCommandFactory("http://localhost:8080", None) describe("createCommand") { it("should return GitReceivePack when command is git-receive-pack"){ From 407c742596ff4d246ff438c64e46f08aeaf4ec2e Mon Sep 17 00:00:00 2001 From: KOUNOIKE Yuusuke Date: Tue, 19 Sep 2017 23:06:04 +0900 Subject: [PATCH 03/37] Use account.fullName instead of userName for Web UI edit, Wiki uploads. --- .../scala/gitbucket/core/controller/FileUploadController.scala | 2 +- .../gitbucket/core/controller/RepositoryViewerController.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/gitbucket/core/controller/FileUploadController.scala b/src/main/scala/gitbucket/core/controller/FileUploadController.scala index 9f27caacd..49915f0ab 100644 --- a/src/main/scala/gitbucket/core/controller/FileUploadController.scala +++ b/src/main/scala/gitbucket/core/controller/FileUploadController.scala @@ -80,7 +80,7 @@ class FileUploadController extends ScalatraServlet with FileUploadSupport with R builder.finish() val newHeadId = JGitUtil.createNewCommit(git, inserter, headId, builder.getDirCache.writeTree(inserter), - Constants.HEAD, loginAccount.userName, loginAccount.mailAddress, s"Uploaded ${fileName}") + Constants.HEAD, loginAccount.fullName, loginAccount.mailAddress, s"Uploaded ${fileName}") fileName } diff --git a/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala b/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala index b13dde1a6..4114242bf 100644 --- a/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala +++ b/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala @@ -717,7 +717,7 @@ trait RepositoryViewerControllerBase extends ControllerBase { f(git, headTip, builder, inserter) val commitId = JGitUtil.createNewCommit(git, inserter, headTip, builder.getDirCache.writeTree(inserter), - headName, loginAccount.userName, loginAccount.mailAddress, message) + headName, loginAccount.fullName, loginAccount.mailAddress, message) inserter.flush() inserter.close() From 2044f5b8380a74ca1ae9fefffaf31c7f897ed4a0 Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Wed, 20 Sep 2017 17:46:53 +0900 Subject: [PATCH 04/37] Refuse deletion of the default branch --- .../gitbucket/core/service/ProtectedBranchService.scala | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/scala/gitbucket/core/service/ProtectedBranchService.scala b/src/main/scala/gitbucket/core/service/ProtectedBranchService.scala index 5cbb77c86..14c993a28 100644 --- a/src/main/scala/gitbucket/core/service/ProtectedBranchService.scala +++ b/src/main/scala/gitbucket/core/service/ProtectedBranchService.scala @@ -51,7 +51,11 @@ object ProtectedBranchService { (implicit session: Session): Option[String] = { val branch = command.getRefName.stripPrefix("refs/heads/") if(branch != command.getRefName){ - getProtectedBranchInfo(owner, repository, branch).getStopReason(receivePack.isAllowNonFastForwards, command, pusher) + if(command.getType == ReceiveCommand.Type.DELETE && branch == "test1"){ // TODO check default branch + Some(s"refusing to delete the branch: ${command.getRefName}.") + } else { + getProtectedBranchInfo(owner, repository, branch).getStopReason(receivePack.isAllowNonFastForwards, command, pusher) + } } else { None } From d99898e191579afb1206d1f412b9d486877cf088 Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Thu, 21 Sep 2017 02:08:19 +0900 Subject: [PATCH 05/37] Implement checking whether a deleting branch is the default branch --- .../gitbucket/core/service/ProtectedBranchService.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/scala/gitbucket/core/service/ProtectedBranchService.scala b/src/main/scala/gitbucket/core/service/ProtectedBranchService.scala index 14c993a28..36b00bf12 100644 --- a/src/main/scala/gitbucket/core/service/ProtectedBranchService.scala +++ b/src/main/scala/gitbucket/core/service/ProtectedBranchService.scala @@ -46,12 +46,13 @@ trait ProtectedBranchService { object ProtectedBranchService { - class ProtectedBranchReceiveHook extends ReceiveHook with ProtectedBranchService { + class ProtectedBranchReceiveHook extends ReceiveHook with ProtectedBranchService with RepositoryService with AccountService { override def preReceive(owner: String, repository: String, receivePack: ReceivePack, command: ReceiveCommand, pusher: String) (implicit session: Session): Option[String] = { val branch = command.getRefName.stripPrefix("refs/heads/") if(branch != command.getRefName){ - if(command.getType == ReceiveCommand.Type.DELETE && branch == "test1"){ // TODO check default branch + val repositoryInfo = getRepository(owner, repository) + if(command.getType == ReceiveCommand.Type.DELETE && repositoryInfo.exists(_.repository.defaultBranch == branch)){ Some(s"refusing to delete the branch: ${command.getRefName}.") } else { getProtectedBranchInfo(owner, repository, branch).getStopReason(receivePack.isAllowNonFastForwards, command, pusher) From 8d52fc06edd2c372dd06104b0622cee50068c143 Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Thu, 21 Sep 2017 16:01:07 +0900 Subject: [PATCH 06/37] Update doc for JRebel --- doc/jrebel.md | 90 ++++++++++++++++++--------------------------------- 1 file changed, 31 insertions(+), 59 deletions(-) diff --git a/doc/jrebel.md b/doc/jrebel.md index 86a086381..456497df9 100644 --- a/doc/jrebel.md +++ b/doc/jrebel.md @@ -2,23 +2,15 @@ JRebel integration (optional) ============================= [JRebel](https://zeroturnaround.com/software/jrebel/) is a JVM plugin that makes developing web apps much faster. -JRebel is generally able to eliminate the need for the following slow "app restart" in sbt following a code change: +JRebel is generally able to eliminate the need for the slow "app restart" per modification of codes. Alsp it's only used during development, and doesn't change your deployed app in any way. -``` -> jetty:start -``` - -While JRebel is not open source, it does reload your code faster than the `~;copy-resources;aux-compile` way of doing things using `sbt`. - -It's only used during development, and doesn't change your deployed app in any way. - -JRebel used to be free for Scala developers, but that changed recently, and now there's a cost associated with usage for Scala. There are trial plans and free non-commercial licenses available if you just want to try it out. +JRebel is not open source, but we can use it free for non-commercial use. ---- ## 1. Get a JRebel license -Sign up for a [usage plan](https://my.jrebel.com/). You will need to create an account. +Sign up for a [myJRebel](https://my.jrebel.com/register). You will need to create an account. ## 2. Download JRebel @@ -27,9 +19,7 @@ Next, unzip the downloaded file. ## 3. Activate -Follow the [instructions on the JRebel website](https://zeroturnaround.com/software/jrebel/download/prev-releases/) to activate your downloaded JRebel. - -You can use the default settings for all the configurations. +Follow `readme.txt` in the extracted directory to activate your downloaded JRebel. You don't need to integrate with your IDE, since we're using sbt to do the servlet deployment. @@ -41,13 +31,13 @@ You only need to tell jvm where to find the jrebel jar. To do so, edit your shell resource file (usually `~/.bash_profile` on Mac, and `~/.bashrc` on Linux), and add the following line: ```bash -export JREBEL=/path/to/jrebel/jrebel.jar +export JREBEL=/path/to/jrebel/legacy/jrebel.jar ``` For example, if you unzipped your JRebel download in your home directory, you whould use: ```bash -export JREBEL=~/jrebel/jrebel.jar +export JREBEL=~/jrebel/legacy/jrebel.jar ``` Now reload your shell: @@ -73,39 +63,26 @@ $ ./sbt You will start the servlet container slightly differently now that you're using sbt. ``` -> jetty:start +> jetty:quickstart : -[info] starting server ... -[success] Total time: 3 s, completed Jan 3, 2016 9:47:55 PM -2016-01-03 21:47:57 JRebel: -2016-01-03 21:47:57 JRebel: A newer version '6.3.1' is available for download -2016-01-03 21:47:57 JRebel: from http://zeroturnaround.com/software/jrebel/download/ -2016-01-03 21:47:57 JRebel: -2016-01-03 21:47:58 JRebel: Contacting myJRebel server .. -2016-01-03 21:47:59 JRebel: Directory '/git/gitbucket/target/scala-2.11/classes' will be monitored for changes. -2016-01-03 21:47:59 JRebel: Directory '/git/gitbucket/target/scala-2.11/test-classes' will be monitored for changes. -2016-01-03 21:47:59 JRebel: Directory '/git/gitbucket/target/webapp' will be monitored for changes. -2016-01-03 21:48:00 JRebel: -2016-01-03 21:48:00 JRebel: ############################################################# -2016-01-03 21:48:00 JRebel: -2016-01-03 21:48:00 JRebel: JRebel Legacy Agent 6.2.5 (201509291538) -2016-01-03 21:48:00 JRebel: (c) Copyright ZeroTurnaround AS, Estonia, Tartu. -2016-01-03 21:48:00 JRebel: -2016-01-03 21:48:00 JRebel: Over the last 30 days JRebel prevented -2016-01-03 21:48:00 JRebel: at least 182 redeploys/restarts saving you about 7.4 hours. -2016-01-03 21:48:00 JRebel: -2016-01-03 21:48:00 JRebel: Over the last 324 days JRebel prevented -2016-01-03 21:48:00 JRebel: at least 1538 redeploys/restarts saving you about 62.4 hours. -2016-01-03 21:48:00 JRebel: -2016-01-03 21:48:00 JRebel: Licensed to nazo king (using myJRebel). -2016-01-03 21:48:00 JRebel: -2016-01-03 21:48:00 JRebel: -2016-01-03 21:48:00 JRebel: ############################################################# -2016-01-03 21:48:00 JRebel: +2017-09-21 15:46:35 JRebel: +2017-09-21 15:46:35 JRebel: ############################################################# +2017-09-21 15:46:35 JRebel: +2017-09-21 15:46:35 JRebel: Legacy Agent 7.0.15 (201709080836) +2017-09-21 15:46:35 JRebel: (c) Copyright ZeroTurnaround AS, Estonia, Tartu. +2017-09-21 15:46:35 JRebel: +2017-09-21 15:46:35 JRebel: Over the last 2 days JRebel prevented +2017-09-21 15:46:35 JRebel: at least 8 redeploys/restarts saving you about 0.3 hours. +2017-09-21 15:46:35 JRebel: +2017-09-21 15:46:35 JRebel: Licensed to Naoki Takezoe (using myJRebel). +2017-09-21 15:46:35 JRebel: +2017-09-21 15:46:35 JRebel: +2017-09-21 15:46:35 JRebel: ############################################################# +2017-09-21 15:46:35 JRebel: : -> ~ copy-resources -[success] Total time: 0 s, completed Jan 3, 2016 9:13:54 PM +> ~compile +[success] Total time: 2 s, completed 2017/09/21 15:50:06 1. Waiting for source changes... (press enter to interrupt) ``` @@ -114,12 +91,11 @@ For example, you can change the title on `src/main/twirl/gitbucket/core/main.sca ```html : - - GitBucket - @defining(AutoUpdate.getCurrentVersion){ version => - @version.majorVersion.@version.minorVersion - } + : ``` @@ -128,21 +104,17 @@ If JRebel is doing is correctly installed you will see a notice for you: ``` 1. Waiting for source changes... (press enter to interrupt) -2016-01-03 21:48:42 JRebel: Reloading class 'gitbucket.core.html.main$'. -[info] Wrote rebel.xml to /git/gitbucket/target/scala-2.11/resource_managed/main/rebel.xml -[info] Compiling 1 Scala source to /git/gitbucket/target/scala-2.11/classes... -[success] Total time: 3 s, completed Jan 3, 2016 9:48:55 PM -2. Waiting for source changes... (press enter to interrupt) +[info] Compiling 1 Scala source to /Users/naoki.takezoe/gitbucket/target/scala-2.12/classes... +[success] Total time: 1 s, completed 2017/09/21 15:55:40 ``` And you reload browser, JRebel give notice of that it has reloaded classes: ``` -[success] Total time: 3 s, completed Jan 3, 2016 9:48:55 PM 2. Waiting for source changes... (press enter to interrupt) -2016-01-03 21:49:13 JRebel: Reloading class 'gitbucket.core.html.main$'. +2017-09-21 15:55:40 JRebel: Reloading class 'gitbucket.core.html.main$'. ``` ## 6. Limitations -JRebel is nearly always able to eliminate the need to explicitly reload your container after a code change. However, if you change any of your routes patterns, there is nothing JRebel can do, you will have to run `jetty:start`. +JRebel is nearly always able to eliminate the need to explicitly reload your container after a code change. However, if you change any of your routes patterns, there is nothing JRebel can do, you will have to restart Jetty by `jetty:quickstart`. From 8d5b494785125236f24d9124c320694582f36e73 Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Thu, 21 Sep 2017 16:09:52 +0900 Subject: [PATCH 07/37] Update doc for JRebel --- doc/jrebel.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/jrebel.md b/doc/jrebel.md index 456497df9..4a597d929 100644 --- a/doc/jrebel.md +++ b/doc/jrebel.md @@ -117,4 +117,4 @@ And you reload browser, JRebel give notice of that it has reloaded classes: ## 6. Limitations -JRebel is nearly always able to eliminate the need to explicitly reload your container after a code change. However, if you change any of your routes patterns, there is nothing JRebel can do, you will have to restart Jetty by `jetty:quickstart`. +JRebel is nearly always able to eliminate the need to explicitly reload your container after a code change. However, if you change any of your routing patterns, there is nothing JRebel can do, you will have to restart by `jetty:quickstart`. From 08295afb510cfc235b4a3cda6997b0782cc1bd4f Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Thu, 21 Sep 2017 16:51:15 +0900 Subject: [PATCH 08/37] (refs #1714)Drop uploadable file type limitation --- .../core/controller/FileUploadController.scala | 6 +++--- src/main/scala/gitbucket/core/util/FileUtil.scala | 12 ------------ .../twirl/gitbucket/core/helper/attached.scala.html | 2 -- src/main/twirl/gitbucket/core/wiki/edit.scala.html | 6 +----- 4 files changed, 4 insertions(+), 22 deletions(-) diff --git a/src/main/scala/gitbucket/core/controller/FileUploadController.scala b/src/main/scala/gitbucket/core/controller/FileUploadController.scala index 9f27caacd..861bbe60a 100644 --- a/src/main/scala/gitbucket/core/controller/FileUploadController.scala +++ b/src/main/scala/gitbucket/core/controller/FileUploadController.scala @@ -48,7 +48,7 @@ class FileUploadController extends ScalatraServlet with FileUploadSupport with R FileUtils.writeByteArrayToFile(new java.io.File( getAttachedDir(params("owner"), params("repository")), fileId + "." + FileUtil.getExtension(file.getName)), file.get) - }, FileUtil.isUploadableType) + }, _ => true) } post("/wiki/:owner/:repository"){ @@ -85,7 +85,7 @@ class FileUploadController extends ScalatraServlet with FileUploadSupport with R fileName } } - }, FileUtil.isUploadableType) + }, _ => true) } } getOrElse BadRequest() } @@ -113,7 +113,7 @@ class FileUploadController extends ScalatraServlet with FileUploadSupport with R } } - private def execute(f: (FileItem, String) => Unit, mimeTypeChcker: (String) => Boolean) = fileParams.get("file") match { + private def execute(f: (FileItem, String) => Unit , mimeTypeChcker: (String) => Boolean) = fileParams.get("file") match { case Some(file) if(mimeTypeChcker(file.name)) => defining(FileUtil.generateFileId){ fileId => f(file, fileId) diff --git a/src/main/scala/gitbucket/core/util/FileUtil.scala b/src/main/scala/gitbucket/core/util/FileUtil.scala index e31dd6bb3..6b082d164 100644 --- a/src/main/scala/gitbucket/core/util/FileUtil.scala +++ b/src/main/scala/gitbucket/core/util/FileUtil.scala @@ -28,8 +28,6 @@ object FileUtil { def isImage(name: String): Boolean = getMimeType(name).startsWith("image/") - def isUploadableType(name: String): Boolean = mimeTypeWhiteList contains getMimeType(name) - def isLarge(size: Long): Boolean = (size > 1024 * 1000) def isText(content: Array[Byte]): Boolean = !content.contains(0) @@ -53,16 +51,6 @@ object FileUtil { } } - val mimeTypeWhiteList: Array[String] = Array( - "application/pdf", - "application/vnd.openxmlformats-officedocument.presentationml.presentation", - "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", - "application/vnd.openxmlformats-officedocument.wordprocessingml.document", - "image/gif", - "image/jpeg", - "image/png", - "text/plain") - def getLfsFilePath(owner: String, repository: String, oid: String): String = Directory.getLfsDir(owner, repository) + "/" + oid diff --git a/src/main/twirl/gitbucket/core/helper/attached.scala.html b/src/main/twirl/gitbucket/core/helper/attached.scala.html index b8ac1330c..26ade3fd5 100644 --- a/src/main/twirl/gitbucket/core/helper/attached.scala.html +++ b/src/main/twirl/gitbucket/core/helper/attached.scala.html @@ -65,8 +65,6 @@ $(function(){ url: '@context.path/upload/file/@repository.owner/@repository.name', maxFilesize: 10, clickable: @clickable, - acceptedFiles: @Html(FileUtil.mimeTypeWhiteList.mkString("'", ",", "'")), - dictInvalidFileType: 'Unfortunately, we don\'t support that file type. Try again with a PNG, GIF, JPG, DOCX, PPTX, XLSX, TXT, or PDF.', previewTemplate: "
\n
Uploading your files...
\n
\n
", success: function(file, id) { var attachFile = (file.type.match(/image\/.*/) ? '\n![' + file.name.split('.')[0] : '\n[' + file.name) + diff --git a/src/main/twirl/gitbucket/core/wiki/edit.scala.html b/src/main/twirl/gitbucket/core/wiki/edit.scala.html index 10ddf2f70..e1f5e557a 100644 --- a/src/main/twirl/gitbucket/core/wiki/edit.scala.html +++ b/src/main/twirl/gitbucket/core/wiki/edit.scala.html @@ -50,8 +50,6 @@ $(function(){ url: '@context.path/upload/wiki/@repository.owner/@repository.name', maxFilesize: 10, clickable: false, - acceptedFiles: @Html(FileUtil.mimeTypeWhiteList.mkString("'", ",", "'")), - dictInvalidFileType: 'Unfortunately, we don\'t support that file type. Try again with a PNG, GIF, JPG, DOCX, PPTX, XLSX, TXT, or PDF.', previewTemplate: "
\n
Uploading your files...
\n
\n
", success: function(file, id) { var attachFile = (file.type.match(/image\/.*/) ? '\n![' + file.name.split('.')[0] : '\n[' + file.name) + '](' + file.name + ')'; @@ -62,8 +60,6 @@ $(function(){ $('.clickable').dropzone({ url: '@context.path/upload/wiki/@repository.owner/@repository.name', maxFilesize: 10, - acceptedFiles: @Html(FileUtil.mimeTypeWhiteList.mkString("'", ",", "'")), - dictInvalidFileType: 'Unfortunately, we don\'t support that file type. Try again with a PNG, GIF, JPG, DOCX, PPTX, XLSX, TXT, or PDF.', previewTemplate: "
\n
Uploading your files...
\n
\n
", success: function(file, id) { var attachFile = (file.type.match(/image\/.*/) ? '\n![' + file.name.split('.')[0] : '\n[' + file.name) + '](' + file.name + ')'; @@ -78,7 +74,7 @@ $(function(){ } $('#delete').click(function(){ - return confirm('Are you sure you want to delete this page?'); + return confirm('Are you sure you want to delete this page?'); }); }); From 62e6d0d6e84e44cda02ae39e42fed98fb6762ffc Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Sun, 24 Sep 2017 12:30:44 +0900 Subject: [PATCH 09/37] (refs #1722)Bump markedj to 1.0.15 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index e0b78977d..dd806a6fe 100644 --- a/build.sbt +++ b/build.sbt @@ -29,7 +29,7 @@ libraryDependencies ++= Seq( "io.github.gitbucket" %% "scalatra-forms" % "1.1.0", "commons-io" % "commons-io" % "2.5", "io.github.gitbucket" % "solidbase" % "1.0.2", - "io.github.gitbucket" % "markedj" % "1.0.14", + "io.github.gitbucket" % "markedj" % "1.0.15", "org.apache.commons" % "commons-compress" % "1.13", "org.apache.commons" % "commons-email" % "1.4", "org.apache.httpcomponents" % "httpclient" % "4.5.3", From 6b762b0693859141f45d1820b02ab76d4bef38cd Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Sun, 24 Sep 2017 12:34:00 +0900 Subject: [PATCH 10/37] Fix version as 4.17.0 --- build.sbt | 2 +- src/main/scala/gitbucket/core/GitBucketCoreModule.scala | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/build.sbt b/build.sbt index dd806a6fe..ea471afcf 100644 --- a/build.sbt +++ b/build.sbt @@ -1,6 +1,6 @@ val Organization = "io.github.gitbucket" val Name = "gitbucket" -val GitBucketVersion = "4.17.0-SNAPSHOT" +val GitBucketVersion = "4.17.0" val ScalatraVersion = "2.5.0" val JettyVersion = "9.3.19.v20170502" diff --git a/src/main/scala/gitbucket/core/GitBucketCoreModule.scala b/src/main/scala/gitbucket/core/GitBucketCoreModule.scala index 6db2af3b6..029e3b903 100644 --- a/src/main/scala/gitbucket/core/GitBucketCoreModule.scala +++ b/src/main/scala/gitbucket/core/GitBucketCoreModule.scala @@ -41,5 +41,6 @@ object GitBucketCoreModule extends Module("gitbucket-core", ), new Version("4.14.1"), new Version("4.15.0"), - new Version("4.16.0") + new Version("4.16.0"), + new Version("4.17.0") ) From ed0c8e3f2c5da2ba069a9a9511c8aa5f877974cf Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Sun, 24 Sep 2017 14:00:33 +0900 Subject: [PATCH 11/37] Bump gitbucket-notifications-plugin to 1.2.0 --- plugins.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins.json b/plugins.json index 6d8d98a71..d63c66d88 100644 --- a/plugins.json +++ b/plugins.json @@ -5,9 +5,9 @@ "description": "Provides notifications feature on GitBucket.", "versions": [ { - "version": "1.1.0", - "range": ">=4.16.0", - "file": "gitbucket-notifications-plugin_2.12-1.1.0.jar" + "version": "1.2.0", + "range": ">=4.17.0", + "file": "gitbucket-notifications-plugin_2.12-1.2.0.jar" } ], "default": true From 17ff024166620a741614402eb4cd2c51559b356f Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Sun, 24 Sep 2017 14:14:00 +0900 Subject: [PATCH 12/37] Update README.md --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index c5e69f803..4d2e13710 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,13 @@ Support Release Notes ------------- +### 4.17.0 - 30 Sep 2017 +- [gitbucket-ci-plugin](https://github.com/takezoe/gitbucket-ci-plugin) is available +- Transfer URL with commit ID +- Drop uploadable file type limitation +- Improve Mailer API +- Web API and webhook enhancement + ### 4.16.0 - 2 Sep 2017 - Support AdminLTE color skin - Improve unexpected error handling From a51b57af2a4a04c801db88c09c54e1925f149cd1 Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Sun, 24 Sep 2017 14:23:43 +0900 Subject: [PATCH 13/37] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4d2e13710..09127247f 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ Release Notes ------------- ### 4.17.0 - 30 Sep 2017 - [gitbucket-ci-plugin](https://github.com/takezoe/gitbucket-ci-plugin) is available -- Transfer URL with commit ID +- Transferring to URL with commit ID - Drop uploadable file type limitation - Improve Mailer API - Web API and webhook enhancement From 4bd05835a52f70b0df8168d5e850ee2442dadde1 Mon Sep 17 00:00:00 2001 From: Reap3r119 Date: Fri, 29 Sep 2017 11:57:56 -0600 Subject: [PATCH 14/37] Reserve "assets" and "plugin-assets" --- src/main/scala/gitbucket/core/controller/ControllerBase.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/gitbucket/core/controller/ControllerBase.scala b/src/main/scala/gitbucket/core/controller/ControllerBase.scala index 41b45cd11..3f04352c7 100644 --- a/src/main/scala/gitbucket/core/controller/ControllerBase.scala +++ b/src/main/scala/gitbucket/core/controller/ControllerBase.scala @@ -321,7 +321,7 @@ trait AccountManagementControllerBase extends ControllerBase { .map { _ => "Mail address is already registered." } } - val allReservedNames = Set("git", "admin", "upload", "api") + val allReservedNames = Set("git", "admin", "upload", "api", "assets", "plugin-assets") protected def reservedNames(): Constraint = new Constraint(){ override def validate(name: String, value: String, messages: Messages): Option[String] = if(allReservedNames.contains(value)){ Some(s"${value} is reserved") From 832733330541ce67ec6508816459e5b1a9e306a6 Mon Sep 17 00:00:00 2001 From: Reap3r119 Date: Fri, 29 Sep 2017 12:13:15 -0600 Subject: [PATCH 15/37] Reserve additional system paths --- src/main/scala/gitbucket/core/controller/ControllerBase.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/gitbucket/core/controller/ControllerBase.scala b/src/main/scala/gitbucket/core/controller/ControllerBase.scala index 3f04352c7..f6f785700 100644 --- a/src/main/scala/gitbucket/core/controller/ControllerBase.scala +++ b/src/main/scala/gitbucket/core/controller/ControllerBase.scala @@ -321,7 +321,7 @@ trait AccountManagementControllerBase extends ControllerBase { .map { _ => "Mail address is already registered." } } - val allReservedNames = Set("git", "admin", "upload", "api", "assets", "plugin-assets") + val allReservedNames = Set("git", "admin", "upload", "api", "assets", "plugin-assets", "signin", "signout", "register", "activities.atom", "sidebar-collapse") protected def reservedNames(): Constraint = new Constraint(){ override def validate(name: String, value: String, messages: Messages): Option[String] = if(allReservedNames.contains(value)){ Some(s"${value} is reserved") From f47e389a9bf491a41b17504d85538cbc0bd4c8b3 Mon Sep 17 00:00:00 2001 From: Reap3r119 Date: Fri, 29 Sep 2017 12:34:30 -0600 Subject: [PATCH 16/37] Reserve "groups" and "new" --- src/main/scala/gitbucket/core/controller/ControllerBase.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/gitbucket/core/controller/ControllerBase.scala b/src/main/scala/gitbucket/core/controller/ControllerBase.scala index f6f785700..928e5f6f8 100644 --- a/src/main/scala/gitbucket/core/controller/ControllerBase.scala +++ b/src/main/scala/gitbucket/core/controller/ControllerBase.scala @@ -321,7 +321,7 @@ trait AccountManagementControllerBase extends ControllerBase { .map { _ => "Mail address is already registered." } } - val allReservedNames = Set("git", "admin", "upload", "api", "assets", "plugin-assets", "signin", "signout", "register", "activities.atom", "sidebar-collapse") + val allReservedNames = Set("git", "admin", "upload", "api", "assets", "plugin-assets", "signin", "signout", "register", "activities.atom", "sidebar-collapse", "groups", "new") protected def reservedNames(): Constraint = new Constraint(){ override def validate(name: String, value: String, messages: Messages): Option[String] = if(allReservedNames.contains(value)){ Some(s"${value} is reserved") From 5257c4fc2cf2d61d1eef9dc781fc367719ff1968 Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Tue, 3 Oct 2017 01:52:30 +0900 Subject: [PATCH 17/37] Apply commit hook to online editing (#1729) Apply commit hook to online file editing --- .../RepositoryViewerController.scala | 71 +++++++++++++------ 1 file changed, 48 insertions(+), 23 deletions(-) diff --git a/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala b/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala index b13dde1a6..1f55d4362 100644 --- a/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala +++ b/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala @@ -24,6 +24,7 @@ import org.eclipse.jgit.archive.{TgzFormat, ZipFormat} import org.eclipse.jgit.dircache.{DirCache, DirCacheBuilder} import org.eclipse.jgit.errors.MissingObjectException import org.eclipse.jgit.lib._ +import org.eclipse.jgit.transport.{ReceiveCommand, ReceivePack} import org.scalatra._ import org.scalatra.i18n.Messages @@ -722,34 +723,58 @@ trait RepositoryViewerControllerBase extends ControllerBase { inserter.flush() inserter.close() - // update refs - val refUpdate = git.getRepository.updateRef(headName) - refUpdate.setNewObjectId(commitId) - refUpdate.setForceUpdate(false) - refUpdate.setRefLogIdent(new PersonIdent(loginAccount.fullName, loginAccount.mailAddress)) - refUpdate.update() + val receivePack = new ReceivePack(git.getRepository) + val receiveCommand = new ReceiveCommand(headTip, commitId, headName) - // update pull request - updatePullRequests(repository.owner, repository.name, branch) + // call post commit hook + val error = PluginRegistry().getReceiveHooks.flatMap { hook => + hook.preReceive(repository.owner, repository.name, receivePack, receiveCommand, loginAccount.userName) + }.headOption - // record activity - val commitInfo = new CommitInfo(JGitUtil.getRevCommitFromId(git, commitId)) - recordPushActivity(repository.owner, repository.name, loginAccount.userName, branch, List(commitInfo)) + error match { + case Some(error) => + // commit is rejected + // TODO Notify commit failure to edited user + val refUpdate = git.getRepository.updateRef(headName) + refUpdate.setNewObjectId(headTip) + refUpdate.setForceUpdate(true) + refUpdate.update() - // create issue comment by commit message - createIssueComment(repository.owner, repository.name, commitInfo) + case None => + // update refs + val refUpdate = git.getRepository.updateRef(headName) + refUpdate.setNewObjectId(commitId) + refUpdate.setForceUpdate(false) + refUpdate.setRefLogIdent(new PersonIdent(loginAccount.fullName, loginAccount.mailAddress)) + refUpdate.update() - // close issue by commit message - closeIssuesFromMessage(message, loginAccount.userName, repository.owner, repository.name) + // update pull request + updatePullRequests(repository.owner, repository.name, branch) - //call web hook - callPullRequestWebHookByRequestBranch("synchronize", repository, branch, context.baseUrl, loginAccount) - val commit = new JGitUtil.CommitInfo(JGitUtil.getRevCommitFromId(git, commitId)) - callWebHookOf(repository.owner, repository.name, WebHook.Push) { - getAccountByUserName(repository.owner).map{ ownerAccount => - WebHookPushPayload(git, loginAccount, headName, repository, List(commit), ownerAccount, - oldId = headTip, newId = commitId) - } + // record activity + val commitInfo = new CommitInfo(JGitUtil.getRevCommitFromId(git, commitId)) + recordPushActivity(repository.owner, repository.name, loginAccount.userName, branch, List(commitInfo)) + + // create issue comment by commit message + createIssueComment(repository.owner, repository.name, commitInfo) + + // close issue by commit message + closeIssuesFromMessage(message, loginAccount.userName, repository.owner, repository.name) + + // call post commit hook + PluginRegistry().getReceiveHooks.foreach { hook => + hook.postReceive(repository.owner, repository.name, receivePack, receiveCommand, loginAccount.userName) + } + + //call web hook + callPullRequestWebHookByRequestBranch("synchronize", repository, branch, context.baseUrl, loginAccount) + val commit = new JGitUtil.CommitInfo(JGitUtil.getRevCommitFromId(git, commitId)) + callWebHookOf(repository.owner, repository.name, WebHook.Push) { + getAccountByUserName(repository.owner).map{ ownerAccount => + WebHookPushPayload(git, loginAccount, headName, repository, List(commit), ownerAccount, + oldId = headTip, newId = commitId) + } + } } } } From 5e7afa0f416a13e17fca5cc6520fcdbbf352cc5e Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Wed, 4 Oct 2017 18:16:56 +0900 Subject: [PATCH 18/37] (refs #1727) Repair the commit diff view --- .../gitbucket/core/controller/RepositoryViewerController.scala | 2 +- .../scala/gitbucket/core/servlet/GitRepositoryServlet.scala | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala b/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala index 1f55d4362..ea2d903ca 100644 --- a/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala +++ b/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala @@ -432,7 +432,7 @@ trait RepositoryViewerControllerBase extends ControllerBase { try { using(Git.open(getRepositoryDir(repository.owner, repository.name))) { git => defining(JGitUtil.getRevCommitFromId(git, git.getRepository.resolve(id))) { revCommit => - JGitUtil.getDiffs(git, id, false) match { + JGitUtil.getDiffs(git, id, true) match { case (diffs, oldCommitId) => html.commit(id, new JGitUtil.CommitInfo(revCommit), JGitUtil.getBranchesOfCommit(git, revCommit.getName), diff --git a/src/main/scala/gitbucket/core/servlet/GitRepositoryServlet.scala b/src/main/scala/gitbucket/core/servlet/GitRepositoryServlet.scala index 521f1397a..2fa3859b2 100644 --- a/src/main/scala/gitbucket/core/servlet/GitRepositoryServlet.scala +++ b/src/main/scala/gitbucket/core/servlet/GitRepositoryServlet.scala @@ -351,7 +351,6 @@ class WikiCommitHook(owner: String, repository: String, pusher: String, baseUrl: diffs._1.collect { case diff if diff.newPath.toLowerCase.endsWith(".md") => val action = if(diff.changeType == ChangeType.ADD) "created" else "edited" val fileName = diff.newPath - //println(action + " - " + fileName + " - " + commit.id) (action, fileName, commit.id) } } From 37b181c5d02a7396c10bf5f90b10d735b9ac737e Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Sun, 8 Oct 2017 04:17:05 +0900 Subject: [PATCH 19/37] (refs #1725) Allow administrators in collaborators to force to merge PR --- .../core/service/ProtectedBranchService.scala | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/main/scala/gitbucket/core/service/ProtectedBranchService.scala b/src/main/scala/gitbucket/core/service/ProtectedBranchService.scala index 36b00bf12..65d0aaa6a 100644 --- a/src/main/scala/gitbucket/core/service/ProtectedBranchService.scala +++ b/src/main/scala/gitbucket/core/service/ProtectedBranchService.scala @@ -1,11 +1,10 @@ package gitbucket.core.service -import gitbucket.core.model.{ProtectedBranch, ProtectedBranchContext, CommitState} +import gitbucket.core.model.{Session => _, _} import gitbucket.core.plugin.ReceiveHook import gitbucket.core.model.Profile._ import gitbucket.core.model.Profile.profile.blockingApi._ - -import org.eclipse.jgit.transport.{ReceivePack, ReceiveCommand} +import org.eclipse.jgit.transport.{ReceiveCommand, ReceivePack} trait ProtectedBranchService { @@ -79,10 +78,19 @@ object ProtectedBranchService { * Include administrators * Enforce required status checks for repository administrators. */ - includeAdministrators: Boolean) extends AccountService with CommitStatusService { + includeAdministrators: Boolean) extends AccountService with RepositoryService with CommitStatusService { def isAdministrator(pusher: String)(implicit session: Session): Boolean = - pusher == owner || getGroupMembers(owner).exists(gm => gm.userName == pusher && gm.isManager) + pusher == owner || getGroupMembers(owner).exists(gm => gm.userName == pusher && gm.isManager) || + getCollaborators(owner, repository).exists { case (collaborator, isGroup) => + if(collaborator.role == Role.ADMIN.name){ + if(isGroup){ + getGroupMembers(collaborator.collaboratorName).exists(gm => gm.userName == pusher) + } else { + collaborator.collaboratorName == pusher + } + } else false + } /** * Can't be force pushed From e6838d88911381ca806ccacbf579aeb1aec4dc0b Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Sun, 8 Oct 2017 14:35:23 +0900 Subject: [PATCH 20/37] Enhance SuggestionProvider to be able to supply label and value --- .../core/controller/IndexController.scala | 7 +- .../core/plugin/SuggestionProvider.scala | 85 +++++++++++++++++-- .../gitbucket/core/helper/attached.scala.html | 12 +-- 3 files changed, 93 insertions(+), 11 deletions(-) diff --git a/src/main/scala/gitbucket/core/controller/IndexController.scala b/src/main/scala/gitbucket/core/controller/IndexController.scala index ddcaa6cd8..a4cf49f8b 100644 --- a/src/main/scala/gitbucket/core/controller/IndexController.scala +++ b/src/main/scala/gitbucket/core/controller/IndexController.scala @@ -121,7 +121,12 @@ trait IndexControllerBase extends ControllerBase { case (true, false) => !t.isGroupAccount case (false, true) => t.isGroupAccount case (false, false) => false - }}.map { t => t.userName } + }}.map { t => + Map( + "label" -> s"@${t.userName} ${t.fullName}", + "value" -> t.userName + ) + } )) ) }) diff --git a/src/main/scala/gitbucket/core/plugin/SuggestionProvider.scala b/src/main/scala/gitbucket/core/plugin/SuggestionProvider.scala index 3aafa11d3..e7d49df5c 100644 --- a/src/main/scala/gitbucket/core/plugin/SuggestionProvider.scala +++ b/src/main/scala/gitbucket/core/plugin/SuggestionProvider.scala @@ -3,15 +3,92 @@ package gitbucket.core.plugin import gitbucket.core.controller.Context import gitbucket.core.service.RepositoryService.RepositoryInfo +/** + * The base trait of suggestion providers which supplies completion proposals in some text areas. + */ trait SuggestionProvider { + /** + * The identifier of this suggestion provider. + * You must specify the unique identifier in the all suggestion providers. + */ val id: String + + /** + * The trigger of this suggestion provider. When user types this character, the proposal list would be displayed. + * Also this is used as the prefix of the replaced string. + */ val prefix: String + + /** + * The suffix of the replaced string. The default is `" "`. + */ val suffix: String = " " + + /** + * Which contexts is this suggestion provider enabled. Currently, available contexts are `"issues"` and `"wiki"`. + */ val context: Seq[String] - def values(repository: RepositoryInfo): Seq[String] - def template(implicit context: Context): String = "value" + /** + * If this suggestion provider has static proposal list, override this method to return it. + * + * The returned sequence is rendered as follows: + *
+   * [
+   *   {
+   *     "label" -> "value1",
+   *     "value" -> "value1"
+   *   },
+   *   {
+   *     "label" -> "value2",
+   *     "value" -> "value2"
+   *   },
+   * ]
+   * 
+ * + * Each element can be accessed as `option` in `template()` or `replace()` method. + */ + def values(repository: RepositoryInfo): Seq[String] = Nil + + /** + * If this suggestion provider has static proposal list, override this method to return it. + * + * If your proposals have label and value, use this method instead of `values()`. + * The first element of tuple is used as a value, and the second element is used as a label. + * + * The returned sequence is rendered as follows: + *
+   * [
+   *   {
+   *     "label" -> "label1",
+   *     "value" -> "value1"
+   *   },
+   *   {
+   *     "label" -> "label2",
+   *     "value" -> "value2"
+   *   },
+   * ]
+   * 
+ * + * Each element can be accessed as `option` in `template()` or `replace()` method. + */ + def options(repository: RepositoryInfo): Seq[(String, String)] = values(repository).map { value => (value, value) } + + /** + * JavaScript fragment to generate a label of completion proposal. The default is: `option.label`. + */ + def template(implicit context: Context): String = "option.label" + + /** + * JavaScript fragment to generate a replaced value of completion proposal. The default is: `option.value` + */ + def replace(implicit context: Context): String = "option.value" + + /** + * If this suggestion provider needs some additional process to assemble the proposal list (e.g. It need to use Ajax + * to get a proposal list from the server), then override this method and return any JavaScript code. + */ def additionalScript(implicit context: Context): String = "" } @@ -20,8 +97,6 @@ class UserNameSuggestionProvider extends SuggestionProvider { override val id: String = "user" override val prefix: String = "@" override val context: Seq[String] = Seq("issues") - override def values(repository: RepositoryInfo): Seq[String] = Nil - override def template(implicit context: Context): String = "'@' + value" override def additionalScript(implicit context: Context): String = s"""$$.get('${context.path}/_user/proposals', { query: '', user: true, group: false }, function (data) { user = data.options; });""" -} \ No newline at end of file +} diff --git a/src/main/twirl/gitbucket/core/helper/attached.scala.html b/src/main/twirl/gitbucket/core/helper/attached.scala.html index 26ade3fd5..c68c2bf23 100644 --- a/src/main/twirl/gitbucket/core/helper/attached.scala.html +++ b/src/main/twirl/gitbucket/core/helper/attached.scala.html @@ -11,7 +11,9 @@ $(function(){ @gitbucket.core.plugin.PluginRegistry().getSuggestionProviders.map { provider => @if(provider.context.contains(completionContext)){ - var @provider.id = @Html(helpers.json(provider.values(repository))); + var @provider.id = @Html(helpers.json(provider.options(repository).map { case (value, label) => + Map("value" -> value, "label" -> label) + })); @Html(provider.additionalScript) } } @@ -23,14 +25,14 @@ $(function(){ match: /\B@{provider.prefix}([\-+\w]*)$/, search: function (term, callback) { callback($.map(@{provider.id}, function (proposal) { - return proposal.indexOf(term) === 0 ? proposal : null; + return proposal.value.indexOf(term) === 0 ? proposal : null; })); }, - template: function (value) { + template: function (option) { return @{Html(provider.template)}; }, - replace: function (value) { - return '@{provider.prefix}' + value + '@{provider.suffix}'; + replace: function (option) { + return '@{provider.prefix}' + @{Html(provider.replace)} + '@{provider.suffix}'; }, index: 1 }, From f767e621a4eca73ce7930d686623622cecdc6d76 Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Mon, 9 Oct 2017 03:31:38 +0900 Subject: [PATCH 21/37] Fix CSS style --- src/main/webapp/assets/common/css/gitbucket.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/webapp/assets/common/css/gitbucket.css b/src/main/webapp/assets/common/css/gitbucket.css index 7aae5feba..a5ec12dd2 100644 --- a/src/main/webapp/assets/common/css/gitbucket.css +++ b/src/main/webapp/assets/common/css/gitbucket.css @@ -1161,7 +1161,8 @@ table.diff tbody tr.not-diff:hover td { .not-diff > .comment-box-container { white-space: normal; line-height: initial; - padding: 10px; + padding-left: 10px; + padding-right: 10px; } .diff .oldline:before, .diff .newline:before { From 00009499667f93bff730228046bc3453163b2bae Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Mon, 9 Oct 2017 03:32:10 +0900 Subject: [PATCH 22/37] Adding reply comment form to diff view --- .../gitbucket/core/helper/diff.scala.html | 138 ++++++++++++++---- .../core/issues/commentlist.scala.html | 2 - .../core/repo/commentform.scala.html | 13 +- .../webapp/assets/common/css/gitbucket.css | 5 - 4 files changed, 121 insertions(+), 37 deletions(-) diff --git a/src/main/twirl/gitbucket/core/helper/diff.scala.html b/src/main/twirl/gitbucket/core/helper/diff.scala.html index ddb997c36..2cc6f9f7d 100644 --- a/src/main/twirl/gitbucket/core/helper/diff.scala.html +++ b/src/main/twirl/gitbucket/core/helper/diff.scala.html @@ -10,7 +10,7 @@ @import org.eclipse.jgit.diff.DiffEntry.ChangeType @if(showIndex){
-
+
@@ -151,20 +151,21 @@ $(function(){ } window.viewType = 1; if(("&" + location.search.substring(1)).indexOf("&diff=split") != -1){ - $('.container').removeClass('container').addClass('container-wide'); window.viewType = 0; } renderDiffs(); $('#btn-unified').click(function(){ window.viewType = 1; - $('.container-wide').removeClass('container-wide').addClass('container'); + $('#btn-unified').addClass('active'); + $('#btn-split').removeClass('active'); renderDiffs(); }); $('#btn-split').click(function(){ window.viewType = 0; - $('.container').removeClass('container').addClass('container-wide'); + $('#btn-unified').removeClass('active'); + $('#btn-split').addClass('active'); renderDiffs(); }); @@ -174,6 +175,7 @@ $(function(){ } $(this).closest('table').find('.not-diff').toggle(); }); + $('.ignore-whitespace').change(function() { renderOneDiff($(this).closest("table").find(".diffText"), viewType); }); @@ -188,22 +190,56 @@ $(function(){ } return $(''); } + if (typeof $('#show-notes')[0] !== 'undefined' && !$('#show-notes')[0].checked) { $('#comment-list').children('.inline-comment').hide(); } + + function showCommentForm(commitId, fileName, oldLineNumber, newLineNumber, $tr){ + // assemble Ajax url + var url = '@helpers.url(repository)/commit/' + commitId + '/comment/_form?fileName=' + fileName@issueId.map { id => + '&issueId=@id' }; + if (!isNaN(oldLineNumber) && oldLineNumber) { + url += ('&oldLineNumber=' + oldLineNumber) + } + if (!isNaN(newLineNumber) && newLineNumber) { + url += ('&newLineNumber=' + newLineNumber) + } + // send Ajax request + $.get(url, { dataType : 'html' }, function(responseContent) { + // create container + var tmp; + if (!isNaN(oldLineNumber) && oldLineNumber) { + if (!isNaN(newLineNumber) && newLineNumber) { + tmp = getInlineContainer(); + } else { + tmp = getInlineContainer('old'); + } + } else { + tmp = getInlineContainer('new'); + } + // add comment textarea + tmp.addClass('inline-comment-form').children('.comment-box-container').html(responseContent); + $tr.nextAll(':not(.not-diff):first').before(tmp); + // hide reply comment field + $(tmp).closest('.not-diff').prev().find('.reply-comment').closest('.not-diff').hide(); + // focus textarea + tmp.find('textarea').focus(); + }); + } + + // Add comment button $('.diff-outside').on('click','table.diff .add-comment',function() { var $this = $(this); var $tr = $this.closest('tr'); var $check = $this.closest('table:not(.diff)').find('.toggle-notes'); - var url = ''; + //var url = ''; if (!$check.prop('checked')) { $check.prop('checked', true).trigger('change'); } if (!$tr.nextAll(':not(.not-diff):first').prev().hasClass('inline-comment-form')) { var commitId = $this.closest('.table-bordered').attr('commitId'), fileName = $this.closest('.table-bordered').attr('fileName'), - oldLineNumber, newLineNumber, - url = '@helpers.url(repository)/commit/' + commitId + '/comment/_form?fileName=' + fileName@issueId.map { id => + '&issueId=@id' }; + oldLineNumber, newLineNumber; if (viewType == 0) { oldLineNumber = $this.parent().prev('.oldline').attr('line-number'); newLineNumber = $this.parent().prev('.newline').attr('line-number'); @@ -211,30 +247,27 @@ $(function(){ oldLineNumber = $this.parent().prevAll('.oldline').attr('line-number'); newLineNumber = $this.parent().prevAll('.newline').attr('line-number'); } - if (!isNaN(oldLineNumber) && oldLineNumber) { - url += ('&oldLineNumber=' + oldLineNumber) - } - if (!isNaN(newLineNumber) && newLineNumber) { - url += ('&newLineNumber=' + newLineNumber) - } - $.get(url, { dataType : 'html' }, function(responseContent) { - var tmp; - if (!isNaN(oldLineNumber) && oldLineNumber) { - if (!isNaN(newLineNumber) && newLineNumber) { - tmp = getInlineContainer(); - } else { - tmp = getInlineContainer('old'); - } - } else { - tmp = getInlineContainer('new'); - } - tmp.addClass('inline-comment-form').children('.comment-box-container').html(responseContent); - $tr.nextAll(':not(.not-diff):first').before(tmp); - }); + + showCommentForm(commitId, fileName, oldLineNumber, newLineNumber, $tr); } }).on('click', 'table.diff .btn-default', function() { + // Cancel comment form + $(this).closest('.not-diff').prev().find('.reply-comment').closest('.not-diff').show(); $(this).closest('.inline-comment-form').remove(); }); + + // Reply comment + $('.diff-outside').on('click', '.reply-comment',function(){ + var $this = $(this); + var $tr = $this.closest('tr'); + var commitId = $this.closest('.table-bordered').attr('commitId'); + var fileName = $this.data('filename'); + var oldLineNumber = $this.data('oldline'); + var newLineNumber = $this.data('newline'); + + showCommentForm(commitId, fileName, oldLineNumber, newLineNumber, $tr); + }); + function renderOneCommitCommentIntoDiff($v, diff){ var filename = $v.attr('filename'); var oldline = $v.attr('oldline'); @@ -257,6 +290,7 @@ $(function(){ tmp.hide(); } } + function renderStatBar(add, del){ if(add + del > 5){ if(add){ @@ -282,6 +316,7 @@ $(function(){ } return ret; } + function renderOneDiff(diffText, viewType){ var table = diffText.closest("table[data-diff-id]"); var i = table.data("diff-id"); @@ -305,12 +340,59 @@ $(function(){ } }); } + return table; } + + function renderReplyComment($table){ + var elements = {}; + var filename, newline, oldline; + $table.find('.comment-box-container .inline-comment').each(function(i, e){ + filename = $(e).attr('filename'); + newline = $(e).attr('newline'); + oldline = $(e).attr('oldline'); + var key = filename + '-' + newline + '-' + oldline; + elements[key] = { + element: $(e), + filename: filename, + newline: newline, + oldline: oldline + }; + }); + for(var key in elements){ + filename = elements[key]['filename']; + oldline = elements[key]['oldline']; + newline = elements[key]['newline']; + + var $v = $('
') + .append($('') + .data('filename', filename) + .data('newline', newline) + .data('oldline', oldline)); + + var tmp; + if (typeof oldline !== 'undefined') { + if (typeof newline !== 'undefined') { + tmp = getInlineContainer(); + } else { + tmp = getInlineContainer('old'); + } + tmp.children('td:first').html($v); + } else { + tmp = getInlineContainer('new'); + tmp.children('td:last').html($v); + } + elements[key]['element'].closest('.not-diff').after(tmp); + } + } + function renderDiffs(){ var i = 0, diffs = $('.diffText'); function render(){ if(diffs[i]){ - renderOneDiff($(diffs[i]), viewType); + var $table = renderOneDiff($(diffs[i]), viewType); + @if(hasWritePermission) { + renderReplyComment($table); + } i++; setTimeout(render); } diff --git a/src/main/twirl/gitbucket/core/issues/commentlist.scala.html b/src/main/twirl/gitbucket/core/issues/commentlist.scala.html index 976969dd5..0211a2d70 100644 --- a/src/main/twirl/gitbucket/core/issues/commentlist.scala.html +++ b/src/main/twirl/gitbucket/core/issues/commentlist.scala.html @@ -201,7 +201,6 @@ $(function(){ $.post('@helpers.url(repository)/issue_comments/delete/' + id, function(data){ if(data > 0) { - $('#comment-' + id).prev('div.issue-avatar-image').remove(); $('#comment-' + id).remove(); } }); @@ -230,7 +229,6 @@ $(function(){ function(data){ if(data > 0) { $('.commit-comment-' + id).closest('.not-diff').remove(); - $('.commit-comment-' + id).closest('.inline-comment').remove(); } }); } diff --git a/src/main/twirl/gitbucket/core/repo/commentform.scala.html b/src/main/twirl/gitbucket/core/repo/commentform.scala.html index 1908c00df..1e0b20c58 100644 --- a/src/main/twirl/gitbucket/core/repo/commentform.scala.html +++ b/src/main/twirl/gitbucket/core/repo/commentform.scala.html @@ -44,7 +44,7 @@ } -} \ No newline at end of file +} diff --git a/src/main/twirl/gitbucket/core/repo/upload.scala.html b/src/main/twirl/gitbucket/core/repo/upload.scala.html index e2ee77e06..8221359fe 100644 --- a/src/main/twirl/gitbucket/core/repo/upload.scala.html +++ b/src/main/twirl/gitbucket/core/repo/upload.scala.html @@ -13,7 +13,7 @@
@repository.name / @pathList.zipWithIndex.map { case (section, i) => - @section / + @section / } @@ -38,7 +38,7 @@
From a2e8d24fdbd79cd07519b36dd622a4d07df9596e Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Mon, 16 Oct 2017 18:23:48 +0900 Subject: [PATCH 35/37] Fix path encoding in JavaScript --- src/main/twirl/gitbucket/core/repo/find.scala.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/twirl/gitbucket/core/repo/find.scala.html b/src/main/twirl/gitbucket/core/repo/find.scala.html index a5de59dda..833fa5e32 100644 --- a/src/main/twirl/gitbucket/core/repo/find.scala.html +++ b/src/main/twirl/gitbucket/core/repo/find.scala.html @@ -105,7 +105,9 @@ $(function(){ $(".no-results").hide(); for(var i = 0; i < p.length; i++){ var row = template.clone(); - row.find("a").attr("href", pathBase + "/" + p[i].string).html(string_score_highlight(p[i], '')); +// console.log('Path base: ' + pathBase); +// console.log('Path rest ' + p[i].string); + row.find("a").attr("href", pathBase + "/" + encodeURIComponent(p[i].string).replace('%2F', '/')).html(string_score_highlight(p[i], '')); if(cursor == i){ row.addClass("navigation-focus"); } From f402587a9acacfd13aee769ac2569a421068a2df Mon Sep 17 00:00:00 2001 From: reap3r119 Date: Fri, 13 Oct 2017 13:29:55 -0600 Subject: [PATCH 36/37] Update dependencies for the web interface --- src/main/twirl/gitbucket/core/main.scala.html | 28 +- .../AdminLTE-2.3.11/css/AdminLTE.min.css | 7 - .../css/alt/AdminLTE-bootstrap-social.css | 760 --- .../css/alt/AdminLTE-bootstrap-social.min.css | 1 - .../css/alt/AdminLTE-fullcalendar.css | 93 - .../css/alt/AdminLTE-fullcalendar.min.css | 1 - .../css/alt/AdminLTE-select2.css | 97 - .../css/alt/AdminLTE-select2.min.css | 1 - .../css/alt/AdminLTE-without-plugins.css | 3992 -------------- .../css/alt/AdminLTE-without-plugins.min.css | 7 - .../css/skins/_all-skins.min.css | 1 - .../css/skins/skin-black-light.min.css | 1 - .../css/skins/skin-blue-light.min.css | 1 - .../css/skins/skin-green-light.min.css | 1 - .../css/skins/skin-purple-light.min.css | 1 - .../css/skins/skin-red-light.min.css | 1 - .../css/skins/skin-yellow-light.min.css | 1 - .../vendors/AdminLTE-2.3.11/img/avatar.png | Bin 8117 -> 0 bytes .../vendors/AdminLTE-2.3.11/img/avatar04.png | Bin 13539 -> 0 bytes .../vendors/AdminLTE-2.3.11/img/avatar2.png | Bin 8262 -> 0 bytes .../vendors/AdminLTE-2.3.11/img/avatar3.png | Bin 9241 -> 0 bytes .../vendors/AdminLTE-2.3.11/img/avatar5.png | Bin 7578 -> 0 bytes .../img/credit/american-express.png | Bin 2163 -> 0 bytes .../AdminLTE-2.3.11/img/credit/cirrus.png | Bin 1582 -> 0 bytes .../AdminLTE-2.3.11/img/credit/mastercard.png | Bin 1589 -> 0 bytes .../AdminLTE-2.3.11/img/credit/mestro.png | Bin 1581 -> 0 bytes .../AdminLTE-2.3.11/img/credit/paypal.png | Bin 2033 -> 0 bytes .../AdminLTE-2.3.11/img/credit/paypal2.png | Bin 1219 -> 0 bytes .../AdminLTE-2.3.11/img/credit/visa.png | Bin 1061 -> 0 bytes .../vendors/AdminLTE-2.3.11/img/photo1.png | Bin 672008 -> 0 bytes .../vendors/AdminLTE-2.3.11/img/photo2.png | Bin 422438 -> 0 bytes .../vendors/AdminLTE-2.3.11/img/photo3.jpg | Bin 392079 -> 0 bytes .../vendors/AdminLTE-2.3.11/img/photo4.jpg | Bin 1179224 -> 0 bytes .../AdminLTE-2.3.11/img/user1-128x128.jpg | Bin 2879 -> 0 bytes .../AdminLTE-2.3.11/img/user2-160x160.jpg | Bin 7070 -> 0 bytes .../AdminLTE-2.3.11/img/user3-128x128.jpg | Bin 3511 -> 0 bytes .../AdminLTE-2.3.11/img/user4-128x128.jpg | Bin 3477 -> 0 bytes .../AdminLTE-2.3.11/img/user5-128x128.jpg | Bin 6446 -> 0 bytes .../AdminLTE-2.3.11/img/user6-128x128.jpg | Bin 4342 -> 0 bytes .../AdminLTE-2.3.11/img/user7-128x128.jpg | Bin 6434 -> 0 bytes .../AdminLTE-2.3.11/img/user8-128x128.jpg | Bin 5060 -> 0 bytes .../assets/vendors/AdminLTE-2.3.11/js/app.js | 772 --- .../vendors/AdminLTE-2.3.11/js/app.min.js | 13 - .../assets/vendors/AdminLTE-2.3.11/js/demo.js | 340 -- .../AdminLTE-2.3.11/js/pages/dashboard.js | 210 - .../AdminLTE-2.3.11/js/pages/dashboard2.js | 274 - .../css/AdminLTE.css | 914 +++- .../AdminLTE-2.4.2/css/AdminLTE.min.css | 7 + .../AdminLTE-2.4.2/css/adminlte.css.map | 140 + .../AdminLTE-2.4.2/css/adminlte.min.css.map | 140 + .../css/skins/_all-skins.css | 157 +- .../css/skins/_all-skins.min.css | 1 + .../css/skins/skin-black-light.css | 26 +- .../css/skins/skin-black-light.min.css | 1 + .../css/skins/skin-black.css | 11 +- .../css/skins/skin-black.min.css | 2 +- .../css/skins/skin-blue-light.css | 13 +- .../css/skins/skin-blue-light.min.css | 1 + .../css/skins/skin-blue.css | 11 +- .../css/skins/skin-blue.min.css | 2 +- .../css/skins/skin-green-light.css | 13 +- .../css/skins/skin-green-light.min.css | 1 + .../css/skins/skin-green.css | 11 +- .../css/skins/skin-green.min.css | 2 +- .../css/skins/skin-purple-light.css | 13 +- .../css/skins/skin-purple-light.min.css | 1 + .../css/skins/skin-purple.css | 11 +- .../css/skins/skin-purple.min.css | 2 +- .../css/skins/skin-red-light.css | 13 +- .../css/skins/skin-red-light.min.css | 1 + .../css/skins/skin-red.css | 11 +- .../css/skins/skin-red.min.css | 2 +- .../css/skins/skin-yellow-light.css | 13 +- .../css/skins/skin-yellow-light.min.css | 1 + .../css/skins/skin-yellow.css | 11 +- .../css/skins/skin-yellow.min.css | 2 +- .../img/boxed-bg.jpg | Bin .../img/boxed-bg.png | Bin .../img/default-50x50.gif | Bin .../img/icons.png | Bin .../vendors/AdminLTE-2.4.2/js/adminlte.js | 1127 ++++ .../vendors/AdminLTE-2.4.2/js/adminlte.min.js | 14 + .../bootstrap-3.3.6/css/bootstrap-theme.css | 587 --- .../css/bootstrap-theme.css.map | 1 - .../css/bootstrap-theme.min.css | 6 - .../css/bootstrap-theme.min.css.map | 1 - .../bootstrap-3.3.6/css/bootstrap.css.map | 1 - .../bootstrap-3.3.6/css/bootstrap.min.css | 6 - .../bootstrap-3.3.6/css/bootstrap.min.css.map | 1 - .../bootstrap-3.3.6/js/bootstrap.min.js | 7 - .../assets/vendors/bootstrap-3.3.6/js/npm.js | 13 - .../css/bootstrap.css | 7 +- .../bootstrap-3.3.7/css/bootstrap.css.map | 1 + .../bootstrap-3.3.7/css/bootstrap.min.css | 6 + .../bootstrap-3.3.7/css/bootstrap.min.css.map | 1 + .../fonts/glyphicons-halflings-regular.eot | Bin .../fonts/glyphicons-halflings-regular.svg | 0 .../fonts/glyphicons-halflings-regular.ttf | Bin .../fonts/glyphicons-halflings-regular.woff | Bin .../fonts/glyphicons-halflings-regular.woff2 | Bin .../js/bootstrap.js | 114 +- .../bootstrap-3.3.7/js/bootstrap.min.js | 7 + .../bootstrap3-typeahead.js | 1043 ++-- .../bootstrap3-typeahead.min.js | 1 + .../colorpicker/css/bootstrap-colorpicker.css | 211 +- .../css/bootstrap-colorpicker.css.map | 1 + .../css/bootstrap-colorpicker.min.css | 7 +- .../css/bootstrap-colorpicker.min.css.map | 1 + .../alpha-horizontal.png | Bin 3635 -> 557 bytes .../img/bootstrap-colorpicker/alpha.png | Bin 3271 -> 488 bytes .../bootstrap-colorpicker/hue-horizontal.png | Bin 2837 -> 478 bytes .../img/bootstrap-colorpicker/hue.png | Bin 2972 -> 504 bytes .../img/bootstrap-colorpicker/saturation.png | Bin 8817 -> 4143 bytes .../colorpicker/js/bootstrap-colorpicker.js | 2285 ++++---- .../js/bootstrap-colorpicker.min.js | 6 +- .../assets/vendors/dropzone/dropzone.js | 4658 +++++++++++------ .../assets/vendors/dropzone/dropzone.min.js | 2 + .../font-awesome-4.6.3/fonts/FontAwesome.otf | Bin 124988 -> 0 bytes .../fonts/fontawesome-webfont.eot | Bin 76518 -> 0 bytes .../fonts/fontawesome-webfont.svg | 685 --- .../fonts/fontawesome-webfont.woff | Bin 90412 -> 0 bytes .../fonts/fontawesome-webfont.woff2 | Bin 71896 -> 0 bytes .../css/font-awesome.css | 144 +- .../css/font-awesome.min.css | 4 +- .../font-awesome-4.7.0/fonts/FontAwesome.otf | Bin 0 -> 134808 bytes .../fonts/fontawesome-webfont.eot | Bin 0 -> 165742 bytes .../fonts/fontawesome-webfont.svg | 2671 ++++++++++ .../fonts/fontawesome-webfont.ttf | Bin 152796 -> 165548 bytes .../fonts/fontawesome-webfont.woff | Bin 0 -> 98024 bytes .../fonts/fontawesome-webfont.woff2 | Bin 0 -> 77160 bytes .../jquery.textcomplete.min.js | 3 - .../jquery.textcomplete.min.map | 1 - .../jquery.textcomplete.js | 73 +- .../jquery.textcomplete.min.js | 3 + .../jquery.textcomplete.min.map | 1 + .../vendors/jquery/jquery-1.12.2.min.js | 5 - .../assets/vendors/jquery/jquery-3.2.1.min.js | 4 + .../vendors/octicons-4.2.0/octicons.eot | Bin 44886 -> 0 bytes .../vendors/octicons-4.2.0/octicons.min.css | 2 - .../vendors/octicons-4.2.0/octicons.ttf | Bin 44708 -> 0 bytes .../vendors/octicons-4.2.0/octicons.woff | Bin 24536 -> 0 bytes .../vendors/octicons-4.2.0/octicons.woff2 | Bin 20736 -> 0 bytes .../_octicons.scss | 10 +- .../octicons.css | 10 +- .../vendors/octicons-4.4.0/octicons.eot | Bin 0 -> 44098 bytes .../vendors/octicons-4.4.0/octicons.min.css | 1 + .../octicons.svg | 13 +- .../vendors/octicons-4.4.0/octicons.ttf | Bin 0 -> 43920 bytes .../vendors/octicons-4.4.0/octicons.woff | Bin 0 -> 24004 bytes .../vendors/octicons-4.4.0/octicons.woff2 | Bin 0 -> 20248 bytes 150 files changed, 10554 insertions(+), 11328 deletions(-) delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/css/AdminLTE.min.css delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/css/alt/AdminLTE-bootstrap-social.css delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/css/alt/AdminLTE-bootstrap-social.min.css delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/css/alt/AdminLTE-fullcalendar.css delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/css/alt/AdminLTE-fullcalendar.min.css delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/css/alt/AdminLTE-select2.css delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/css/alt/AdminLTE-select2.min.css delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/css/alt/AdminLTE-without-plugins.css delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/css/alt/AdminLTE-without-plugins.min.css delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/css/skins/_all-skins.min.css delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/css/skins/skin-black-light.min.css delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/css/skins/skin-blue-light.min.css delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/css/skins/skin-green-light.min.css delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/css/skins/skin-purple-light.min.css delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/css/skins/skin-red-light.min.css delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/css/skins/skin-yellow-light.min.css delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/img/avatar.png delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/img/avatar04.png delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/img/avatar2.png delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/img/avatar3.png delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/img/avatar5.png delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/img/credit/american-express.png delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/img/credit/cirrus.png delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/img/credit/mastercard.png delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/img/credit/mestro.png delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/img/credit/paypal.png delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/img/credit/paypal2.png delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/img/credit/visa.png delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/img/photo1.png delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/img/photo2.png delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/img/photo3.jpg delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/img/photo4.jpg delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/img/user1-128x128.jpg delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/img/user2-160x160.jpg delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/img/user3-128x128.jpg delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/img/user4-128x128.jpg delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/img/user5-128x128.jpg delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/img/user6-128x128.jpg delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/img/user7-128x128.jpg delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/img/user8-128x128.jpg delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/js/app.js delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/js/app.min.js delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/js/demo.js delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/js/pages/dashboard.js delete mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.3.11/js/pages/dashboard2.js rename src/main/webapp/assets/vendors/{AdminLTE-2.3.11 => AdminLTE-2.4.2}/css/AdminLTE.css (83%) create mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.4.2/css/AdminLTE.min.css create mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.4.2/css/adminlte.css.map create mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.4.2/css/adminlte.min.css.map rename src/main/webapp/assets/vendors/{AdminLTE-2.3.11 => AdminLTE-2.4.2}/css/skins/_all-skins.css (92%) create mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.4.2/css/skins/_all-skins.min.css rename src/main/webapp/assets/vendors/{AdminLTE-2.3.11 => AdminLTE-2.4.2}/css/skins/skin-black-light.css (89%) create mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.4.2/css/skins/skin-black-light.min.css rename src/main/webapp/assets/vendors/{AdminLTE-2.3.11 => AdminLTE-2.4.2}/css/skins/skin-black.css (93%) rename src/main/webapp/assets/vendors/{AdminLTE-2.3.11 => AdminLTE-2.4.2}/css/skins/skin-black.min.css (58%) rename src/main/webapp/assets/vendors/{AdminLTE-2.3.11 => AdminLTE-2.4.2}/css/skins/skin-blue-light.css (93%) create mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.4.2/css/skins/skin-blue-light.min.css rename src/main/webapp/assets/vendors/{AdminLTE-2.3.11 => AdminLTE-2.4.2}/css/skins/skin-blue.css (93%) rename src/main/webapp/assets/vendors/{AdminLTE-2.3.11 => AdminLTE-2.4.2}/css/skins/skin-blue.min.css (52%) rename src/main/webapp/assets/vendors/{AdminLTE-2.3.11 => AdminLTE-2.4.2}/css/skins/skin-green-light.css (92%) create mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.4.2/css/skins/skin-green-light.min.css rename src/main/webapp/assets/vendors/{AdminLTE-2.3.11 => AdminLTE-2.4.2}/css/skins/skin-green.css (92%) rename src/main/webapp/assets/vendors/{AdminLTE-2.3.11 => AdminLTE-2.4.2}/css/skins/skin-green.min.css (55%) rename src/main/webapp/assets/vendors/{AdminLTE-2.3.11 => AdminLTE-2.4.2}/css/skins/skin-purple-light.css (92%) create mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.4.2/css/skins/skin-purple-light.min.css rename src/main/webapp/assets/vendors/{AdminLTE-2.3.11 => AdminLTE-2.4.2}/css/skins/skin-purple.css (92%) rename src/main/webapp/assets/vendors/{AdminLTE-2.3.11 => AdminLTE-2.4.2}/css/skins/skin-purple.min.css (56%) rename src/main/webapp/assets/vendors/{AdminLTE-2.3.11 => AdminLTE-2.4.2}/css/skins/skin-red-light.css (92%) create mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.4.2/css/skins/skin-red-light.min.css rename src/main/webapp/assets/vendors/{AdminLTE-2.3.11 => AdminLTE-2.4.2}/css/skins/skin-red.css (92%) rename src/main/webapp/assets/vendors/{AdminLTE-2.3.11 => AdminLTE-2.4.2}/css/skins/skin-red.min.css (54%) rename src/main/webapp/assets/vendors/{AdminLTE-2.3.11 => AdminLTE-2.4.2}/css/skins/skin-yellow-light.css (92%) create mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.4.2/css/skins/skin-yellow-light.min.css rename src/main/webapp/assets/vendors/{AdminLTE-2.3.11 => AdminLTE-2.4.2}/css/skins/skin-yellow.css (92%) rename src/main/webapp/assets/vendors/{AdminLTE-2.3.11 => AdminLTE-2.4.2}/css/skins/skin-yellow.min.css (56%) rename src/main/webapp/assets/vendors/{AdminLTE-2.3.11 => AdminLTE-2.4.2}/img/boxed-bg.jpg (100%) rename src/main/webapp/assets/vendors/{AdminLTE-2.3.11 => AdminLTE-2.4.2}/img/boxed-bg.png (100%) rename src/main/webapp/assets/vendors/{AdminLTE-2.3.11 => AdminLTE-2.4.2}/img/default-50x50.gif (100%) rename src/main/webapp/assets/vendors/{AdminLTE-2.3.11 => AdminLTE-2.4.2}/img/icons.png (100%) create mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.4.2/js/adminlte.js create mode 100644 src/main/webapp/assets/vendors/AdminLTE-2.4.2/js/adminlte.min.js delete mode 100644 src/main/webapp/assets/vendors/bootstrap-3.3.6/css/bootstrap-theme.css delete mode 100644 src/main/webapp/assets/vendors/bootstrap-3.3.6/css/bootstrap-theme.css.map delete mode 100644 src/main/webapp/assets/vendors/bootstrap-3.3.6/css/bootstrap-theme.min.css delete mode 100644 src/main/webapp/assets/vendors/bootstrap-3.3.6/css/bootstrap-theme.min.css.map delete mode 100644 src/main/webapp/assets/vendors/bootstrap-3.3.6/css/bootstrap.css.map delete mode 100644 src/main/webapp/assets/vendors/bootstrap-3.3.6/css/bootstrap.min.css delete mode 100644 src/main/webapp/assets/vendors/bootstrap-3.3.6/css/bootstrap.min.css.map delete mode 100644 src/main/webapp/assets/vendors/bootstrap-3.3.6/js/bootstrap.min.js delete mode 100644 src/main/webapp/assets/vendors/bootstrap-3.3.6/js/npm.js rename src/main/webapp/assets/vendors/{bootstrap-3.3.6 => bootstrap-3.3.7}/css/bootstrap.css (99%) create mode 100644 src/main/webapp/assets/vendors/bootstrap-3.3.7/css/bootstrap.css.map create mode 100644 src/main/webapp/assets/vendors/bootstrap-3.3.7/css/bootstrap.min.css create mode 100644 src/main/webapp/assets/vendors/bootstrap-3.3.7/css/bootstrap.min.css.map rename src/main/webapp/assets/vendors/{bootstrap-3.3.6 => bootstrap-3.3.7}/fonts/glyphicons-halflings-regular.eot (100%) rename src/main/webapp/assets/vendors/{bootstrap-3.3.6 => bootstrap-3.3.7}/fonts/glyphicons-halflings-regular.svg (100%) rename src/main/webapp/assets/vendors/{bootstrap-3.3.6 => bootstrap-3.3.7}/fonts/glyphicons-halflings-regular.ttf (100%) rename src/main/webapp/assets/vendors/{bootstrap-3.3.6 => bootstrap-3.3.7}/fonts/glyphicons-halflings-regular.woff (100%) rename src/main/webapp/assets/vendors/{bootstrap-3.3.6 => bootstrap-3.3.7}/fonts/glyphicons-halflings-regular.woff2 (100%) rename src/main/webapp/assets/vendors/{bootstrap-3.3.6 => bootstrap-3.3.7}/js/bootstrap.js (96%) create mode 100644 src/main/webapp/assets/vendors/bootstrap-3.3.7/js/bootstrap.min.js create mode 100644 src/main/webapp/assets/vendors/bootstrap3-typeahead/bootstrap3-typeahead.min.js create mode 100644 src/main/webapp/assets/vendors/colorpicker/css/bootstrap-colorpicker.css.map create mode 100644 src/main/webapp/assets/vendors/colorpicker/css/bootstrap-colorpicker.min.css.map create mode 100644 src/main/webapp/assets/vendors/dropzone/dropzone.min.js delete mode 100644 src/main/webapp/assets/vendors/font-awesome-4.6.3/fonts/FontAwesome.otf delete mode 100644 src/main/webapp/assets/vendors/font-awesome-4.6.3/fonts/fontawesome-webfont.eot delete mode 100644 src/main/webapp/assets/vendors/font-awesome-4.6.3/fonts/fontawesome-webfont.svg delete mode 100644 src/main/webapp/assets/vendors/font-awesome-4.6.3/fonts/fontawesome-webfont.woff delete mode 100644 src/main/webapp/assets/vendors/font-awesome-4.6.3/fonts/fontawesome-webfont.woff2 rename src/main/webapp/assets/vendors/{font-awesome-4.6.3 => font-awesome-4.7.0}/css/font-awesome.css (92%) rename src/main/webapp/assets/vendors/{font-awesome-4.6.3 => font-awesome-4.7.0}/css/font-awesome.min.css (76%) create mode 100644 src/main/webapp/assets/vendors/font-awesome-4.7.0/fonts/FontAwesome.otf create mode 100644 src/main/webapp/assets/vendors/font-awesome-4.7.0/fonts/fontawesome-webfont.eot create mode 100644 src/main/webapp/assets/vendors/font-awesome-4.7.0/fonts/fontawesome-webfont.svg rename src/main/webapp/assets/vendors/{font-awesome-4.6.3 => font-awesome-4.7.0}/fonts/fontawesome-webfont.ttf (75%) create mode 100644 src/main/webapp/assets/vendors/font-awesome-4.7.0/fonts/fontawesome-webfont.woff create mode 100644 src/main/webapp/assets/vendors/font-awesome-4.7.0/fonts/fontawesome-webfont.woff2 delete mode 100755 src/main/webapp/assets/vendors/jquery-textcomplete-1.6.2/jquery.textcomplete.min.js delete mode 100755 src/main/webapp/assets/vendors/jquery-textcomplete-1.6.2/jquery.textcomplete.min.map rename src/main/webapp/assets/vendors/{jquery-textcomplete-1.6.2 => jquery-textcomplete-1.8.4}/jquery.textcomplete.js (95%) mode change 100755 => 100644 create mode 100644 src/main/webapp/assets/vendors/jquery-textcomplete-1.8.4/jquery.textcomplete.min.js create mode 100644 src/main/webapp/assets/vendors/jquery-textcomplete-1.8.4/jquery.textcomplete.min.map delete mode 100644 src/main/webapp/assets/vendors/jquery/jquery-1.12.2.min.js create mode 100644 src/main/webapp/assets/vendors/jquery/jquery-3.2.1.min.js delete mode 100755 src/main/webapp/assets/vendors/octicons-4.2.0/octicons.eot delete mode 100755 src/main/webapp/assets/vendors/octicons-4.2.0/octicons.min.css delete mode 100755 src/main/webapp/assets/vendors/octicons-4.2.0/octicons.ttf delete mode 100755 src/main/webapp/assets/vendors/octicons-4.2.0/octicons.woff delete mode 100755 src/main/webapp/assets/vendors/octicons-4.2.0/octicons.woff2 rename src/main/webapp/assets/vendors/{octicons-4.2.0 => octicons-4.4.0}/_octicons.scss (94%) mode change 100755 => 100644 rename src/main/webapp/assets/vendors/{octicons-4.2.0 => octicons-4.4.0}/octicons.css (96%) mode change 100755 => 100644 create mode 100644 src/main/webapp/assets/vendors/octicons-4.4.0/octicons.eot create mode 100644 src/main/webapp/assets/vendors/octicons-4.4.0/octicons.min.css rename src/main/webapp/assets/vendors/{octicons-4.2.0 => octicons-4.4.0}/octicons.svg (97%) mode change 100755 => 100644 create mode 100644 src/main/webapp/assets/vendors/octicons-4.4.0/octicons.ttf create mode 100644 src/main/webapp/assets/vendors/octicons-4.4.0/octicons.woff create mode 100644 src/main/webapp/assets/vendors/octicons-4.4.0/octicons.woff2 diff --git a/src/main/twirl/gitbucket/core/main.scala.html b/src/main/twirl/gitbucket/core/main.scala.html index 68e84f938..4500b03f1 100644 --- a/src/main/twirl/gitbucket/core/main.scala.html +++ b/src/main/twirl/gitbucket/core/main.scala.html @@ -10,38 +10,38 @@ - - + + - + - - - + + + - + - + - - + + - + - + @repository.map { repository => } - +
@@ -54,7 +54,7 @@