diff --git a/.travis.yml b/.travis.yml
index d39e7f9..dc863a8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,5 +1,7 @@
language: scala
sudo: true
+jdk:
+ - oraclejdk8
script:
- sbt test
before_script:
@@ -14,40 +16,3 @@
- $HOME/.coursier
- $HOME/.embedmysql
- $HOME/.embedpostgresql
-matrix:
- include:
- - jdk: oraclejdk8
- addons:
- apt:
- packages:
- - libaio1
- - dist: trusty
- group: edge
- sudo: required
- jdk: oraclejdk9
- addons:
- apt:
- packages:
- - libaio1
- before_install:
- - cd ~
- - JDK9_URL=`curl http://jdk.java.net/9/ | grep "lin64JDK" | grep "tar.gz\"" | sed -e "s/\"/ /g" | awk '{print $5}'`
- - wget -O jdk-9_linux-x64_bin.tar.gz $JDK9_URL
- - tar -xzf jdk-9_linux-x64_bin.tar.gz
- - cd -
- script:
- # https://github.com/sbt/sbt/pull/2951
- - git clone https://github.com/retronym/java9-rt-export
- - cd java9-rt-export/
- - git checkout 1019a2873d057dd7214f4135e84283695728395d
- - jdk_switcher use oraclejdk8
- - sbt package
-# - jdk_switcher use oraclejdk9
- - export JAVA_HOME=~/jdk-9
- - PATH=$JAVA_HOME/bin:$PATH
- - java -version
- - mkdir -p $HOME/.sbt/0.13/java9-rt-ext; java -jar target/java9-rt-export-*.jar $HOME/.sbt/0.13/java9-rt-ext/rt.jar
- - jar tf $HOME/.sbt/0.13/java9-rt-ext/rt.jar | grep java/lang/Object
- - cd ..
- - wget https://raw.githubusercontent.com/paulp/sbt-extras/9ade5fa54914ca8aded44105bf4b9a60966f3ccd/sbt && chmod +x ./sbt
- - ./sbt -Dscala.ext.dirs=$HOME/.sbt/0.13/java9-rt-ext test
diff --git a/README.md b/README.md
index ea6a1a0..cb016bd 100644
--- a/README.md
+++ b/README.md
@@ -72,6 +72,11 @@
Release Notes
-------------
+### 4.16.0 - 2 Sep 2017
+- Support AdminLTE color skin
+- Improve unexpected error handling
+- Show commit status on the commits list
+
### 4.15.0 - 5 Aug 2017
- Bundle GitBucket organization plugins
- Notifications plugin
diff --git a/build.sbt b/build.sbt
index a2be14c..47a87c7 100644
--- a/build.sbt
+++ b/build.sbt
@@ -1,6 +1,6 @@
val Organization = "io.github.gitbucket"
val Name = "gitbucket"
-val GitBucketVersion = "4.15.0"
+val GitBucketVersion = "4.16.0"
val ScalatraVersion = "2.5.0"
val JettyVersion = "9.3.19.v20170502"
@@ -29,13 +29,13 @@
"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-SNAPSHOT",
+ "io.github.gitbucket" % "markedj" % "1.0.14",
"org.apache.commons" % "commons-compress" % "1.13",
"org.apache.commons" % "commons-email" % "1.4",
"org.apache.httpcomponents" % "httpclient" % "4.5.3",
"org.apache.sshd" % "apache-sshd" % "1.4.0" exclude("org.slf4j","slf4j-jdk14"),
"org.apache.tika" % "tika-core" % "1.14",
- "com.github.takezoe" %% "blocking-slick-32" % "0.0.9",
+ "com.github.takezoe" %% "blocking-slick-32" % "0.0.10",
"joda-time" % "joda-time" % "2.9.9",
"com.novell.ldap" % "jldap" % "2009-10-07",
"com.h2database" % "h2" % "1.4.195",
diff --git a/plugins.json b/plugins.json
index 835a742..6d8d98a 100644
--- a/plugins.json
+++ b/plugins.json
@@ -5,9 +5,9 @@
"description": "Provides notifications feature on GitBucket.",
"versions": [
{
- "version": "1.0.0",
- "range": ">=4.15.0",
- "file": "gitbucket-notifications-plugin_2.12-1.0.0.jar"
+ "version": "1.1.0",
+ "range": ">=4.16.0",
+ "file": "gitbucket-notifications-plugin_2.12-1.1.0.jar"
}
],
"default": true
diff --git a/src/main/scala/ScalatraBootstrap.scala b/src/main/scala/ScalatraBootstrap.scala
index 7bc40ca..80e3a58 100644
--- a/src/main/scala/ScalatraBootstrap.scala
+++ b/src/main/scala/ScalatraBootstrap.scala
@@ -25,11 +25,9 @@
context.getFilterRegistration("gitAuthenticationFilter").addMappingForUrlPatterns(EnumSet.allOf(classOf[DispatcherType]), true, "/git/*")
context.addFilter("apiAuthenticationFilter", new ApiAuthenticationFilter)
context.getFilterRegistration("apiAuthenticationFilter").addMappingForUrlPatterns(EnumSet.allOf(classOf[DispatcherType]), true, "/api/v3/*")
- context.addFilter("ghCompatRepositoryAccessFilter", new GHCompatRepositoryAccessFilter)
- context.getFilterRegistration("ghCompatRepositoryAccessFilter").addMappingForUrlPatterns(EnumSet.allOf(classOf[DispatcherType]), true, "/*")
// Register controllers
- context.mount(new AnonymousAccessController, "/*")
+ context.mount(new PreProcessController, "/*")
context.addFilter("pluginControllerFilter", new PluginControllerFilter)
context.getFilterRegistration("pluginControllerFilter").addMappingForUrlPatterns(EnumSet.allOf(classOf[DispatcherType]), true, "/*")
diff --git a/src/main/scala/gitbucket/core/GitBucketCoreModule.scala b/src/main/scala/gitbucket/core/GitBucketCoreModule.scala
index 9f933c2..6db2af3 100644
--- a/src/main/scala/gitbucket/core/GitBucketCoreModule.scala
+++ b/src/main/scala/gitbucket/core/GitBucketCoreModule.scala
@@ -40,5 +40,6 @@
new SqlMigration("update/gitbucket-core_4.14.sql")
),
new Version("4.14.1"),
- new Version("4.15.0")
+ new Version("4.15.0"),
+ new Version("4.16.0")
)
diff --git a/src/main/scala/gitbucket/core/controller/AnonymousAccessController.scala b/src/main/scala/gitbucket/core/controller/AnonymousAccessController.scala
deleted file mode 100644
index 180b164..0000000
--- a/src/main/scala/gitbucket/core/controller/AnonymousAccessController.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package gitbucket.core.controller
-
-class AnonymousAccessController extends AnonymousAccessControllerBase
-
-trait AnonymousAccessControllerBase extends ControllerBase {
- get(!context.settings.allowAnonymousAccess, context.loginAccount.isEmpty) {
- if(!context.currentPath.startsWith("/assets") && !context.currentPath.startsWith("/signin") &&
- !context.currentPath.startsWith("/register")) {
- Unauthorized()
- } else {
- pass()
- }
- }
-}
diff --git a/src/main/scala/gitbucket/core/controller/ApiController.scala b/src/main/scala/gitbucket/core/controller/ApiController.scala
index 04e60de..384fa9d 100644
--- a/src/main/scala/gitbucket/core/controller/ApiController.scala
+++ b/src/main/scala/gitbucket/core/controller/ApiController.scala
@@ -5,14 +5,13 @@
import gitbucket.core.service.IssuesService.IssueSearchCondition
import gitbucket.core.service.PullRequestService._
import gitbucket.core.service._
-import gitbucket.core.util.SyntaxSugars._
import gitbucket.core.util.Directory._
-import gitbucket.core.util.JGitUtil._
-import gitbucket.core.util._
import gitbucket.core.util.Implicits._
+import gitbucket.core.util.JGitUtil._
+import gitbucket.core.util.SyntaxSugars._
+import gitbucket.core.util._
import gitbucket.core.view.helpers.{isRenderable, renderMarkup}
import org.eclipse.jgit.api.Git
-import org.eclipse.jgit.revwalk.RevWalk
import org.scalatra.{Created, NoContent, UnprocessableEntity}
import scala.collection.JavaConverters._
@@ -127,10 +126,10 @@
/**
* https://developer.github.com/v3/repos/branches/#get-branch
*/
- get ("/api/v3/repos/:owner/:repo/branches/:branch")(referrersOnly { repository =>
+ get ("/api/v3/repos/:owner/:repo/branches/*")(referrersOnly { repository =>
//import gitbucket.core.api._
(for{
- branch <- params.get("branch") if repository.branchList.contains(branch)
+ branch <- params.get("splat") if repository.branchList.contains(branch)
br <- getBranches(repository.owner, repository.name, repository.repository.defaultBranch, repository.repository.originUserName.isEmpty).find(_.name == branch)
} yield {
val protection = getProtectedBranchInfo(repository.owner, repository.name, branch)
@@ -289,10 +288,10 @@
/**
* https://developer.github.com/v3/repos/#enabling-and-disabling-branch-protection
*/
- patch("/api/v3/repos/:owner/:repo/branches/:branch")(ownerOnly { repository =>
+ patch("/api/v3/repos/:owner/:repo/branches/*")(ownerOnly { repository =>
import gitbucket.core.api._
(for{
- branch <- params.get("branch") if repository.branchList.contains(branch)
+ branch <- params.get("splat") if repository.branchList.contains(branch)
protection <- extractFromJsonBody[ApiBranchProtection.EnablingAndDisabling].map(_.protection)
br <- getBranches(repository.owner, repository.name, repository.repository.defaultBranch, repository.repository.originUserName.isEmpty).find(_.name == branch)
} yield {
diff --git a/src/main/scala/gitbucket/core/controller/ControllerBase.scala b/src/main/scala/gitbucket/core/controller/ControllerBase.scala
index 60e7893..41b45cd 100644
--- a/src/main/scala/gitbucket/core/controller/ControllerBase.scala
+++ b/src/main/scala/gitbucket/core/controller/ControllerBase.scala
@@ -26,6 +26,7 @@
import org.eclipse.jgit.revwalk.RevCommit
import org.eclipse.jgit.treewalk._
import org.apache.commons.io.IOUtils
+import org.slf4j.LoggerFactory
/**
* Provides generic features for controller implementations.
@@ -34,6 +35,8 @@
with ClientSideValidationFormSupport with JacksonJsonSupport with I18nSupport with FlashMapSupport with Validations
with SystemSettingsService {
+ private val logger = LoggerFactory.getLogger(getClass)
+
implicit val jsonFormats = gitbucket.core.api.JsonFormat.jsonFormats
before("/api/v3/*") {
@@ -147,6 +150,20 @@
}
}
+ error{
+ case e => {
+ logger.error(s"Catch unhandled error in request: ${request}", e)
+ if(request.hasAttribute(Keys.Request.Ajax)){
+ org.scalatra.InternalServerError()
+ } else if(request.hasAttribute(Keys.Request.APIv3)){
+ contentType = formats("json")
+ org.scalatra.InternalServerError(ApiError("Internal Server Error"))
+ } else {
+ org.scalatra.InternalServerError(gitbucket.core.html.error("Internal Server Error", Some(e)))
+ }
+ }
+ }
+
override def url(path: String, params: Iterable[(String, Any)] = Iterable.empty,
includeContextPath: Boolean = true, includeServletPath: Boolean = true,
absolutize: Boolean = true, withSessionId: Boolean = true)
diff --git a/src/main/scala/gitbucket/core/controller/PreProcessController.scala b/src/main/scala/gitbucket/core/controller/PreProcessController.scala
new file mode 100644
index 0000000..1c5d263
--- /dev/null
+++ b/src/main/scala/gitbucket/core/controller/PreProcessController.scala
@@ -0,0 +1,40 @@
+package gitbucket.core.controller
+
+import org.scalatra.MovedPermanently
+
+class PreProcessController extends PreProcessControllerBase
+
+trait PreProcessControllerBase extends ControllerBase {
+
+ /**
+ * Provides GitHub compatible URLs for Git client.
+ *
+ *
+ * - git clone http://localhost:8080/owner/repo
+ * - git clone http://localhost:8080/owner/repo.git
+ *
+ *
+ * @see https://git-scm.com/book/en/v2/Git-Internals-Transfer-Protocols
+ */
+ get("/*/*/info/refs") {
+ val query = Option(request.getQueryString).map("?" + _).getOrElse("")
+ halt(MovedPermanently(baseUrl + "/git" + request.getRequestURI + query))
+ }
+
+ /**
+ * Filter requests from anonymous users.
+ *
+ * If anonymous access is allowed, pass all requests.
+ * But if it's not allowed, demands authentication except some paths.
+ */
+ get(!context.settings.allowAnonymousAccess, context.loginAccount.isEmpty) {
+ if(!context.currentPath.startsWith("/assets") && !context.currentPath.startsWith("/signin") &&
+ !context.currentPath.startsWith("/register")) {
+ Unauthorized()
+ } else {
+ pass()
+ }
+ }
+
+
+}
diff --git a/src/main/scala/gitbucket/core/controller/PullRequestsController.scala b/src/main/scala/gitbucket/core/controller/PullRequestsController.scala
index 88328e1..839da3f 100644
--- a/src/main/scala/gitbucket/core/controller/PullRequestsController.scala
+++ b/src/main/scala/gitbucket/core/controller/PullRequestsController.scala
@@ -251,7 +251,7 @@
using(Git.open(getRepositoryDir(owner, name))) { git =>
// mark issue as merged and close.
val loginAccount = context.loginAccount.get
- createComment(owner, name, loginAccount.userName, issueId, form.message, "merge")
+ val commentId = createComment(owner, name, loginAccount.userName, issueId, form.message, "merge")
createComment(owner, name, loginAccount.userName, issueId, "Close", "close")
updateClosed(owner, name, issueId, true)
@@ -282,7 +282,10 @@
callPullRequestWebHook("closed", repository, issueId, context.baseUrl, context.loginAccount.get)
// call hooks
- PluginRegistry().getPullRequestHooks.foreach(_.merged(issue, repository))
+ PluginRegistry().getPullRequestHooks.foreach{ h =>
+ h.addedComment(commentId, form.message, issue, repository)
+ h.merged(issue, repository)
+ }
redirect(s"/${owner}/${name}/pull/${issueId}")
}
@@ -321,8 +324,8 @@
get("/:owner/:repository/compare/*...*")(referrersOnly { forkedRepository =>
val Seq(origin, forked) = multiParams("splat")
- val (originOwner, originId) = parseCompareIdentifie(origin, forkedRepository.owner)
- val (forkedOwner, forkedId) = parseCompareIdentifie(forked, forkedRepository.owner)
+ val (originOwner, originId) = parseCompareIdentifier(origin, forkedRepository.owner)
+ val (forkedOwner, forkedId) = parseCompareIdentifier(forked, forkedRepository.owner)
(for(
originRepositoryName <- if(originOwner == forkedOwner) {
@@ -408,8 +411,8 @@
ajaxGet("/:owner/:repository/compare/*...*/mergecheck")(readableUsersOnly { forkedRepository =>
val Seq(origin, forked) = multiParams("splat")
- val (originOwner, tmpOriginBranch) = parseCompareIdentifie(origin, forkedRepository.owner)
- val (forkedOwner, tmpForkedBranch) = parseCompareIdentifie(forked, forkedRepository.owner)
+ val (originOwner, tmpOriginBranch) = parseCompareIdentifier(origin, forkedRepository.owner)
+ val (forkedOwner, tmpForkedBranch) = parseCompareIdentifier(forked, forkedRepository.owner)
(for(
originRepositoryName <- if(originOwner == forkedOwner){
@@ -502,7 +505,7 @@
* - "owner:branch" to ("owner", "branch")
* - "branch" to ("defaultOwner", "branch")
*/
- private def parseCompareIdentifie(value: String, defaultOwner: String): (String, String) =
+ private def parseCompareIdentifier(value: String, defaultOwner: String): (String, String) =
if(value.contains(':')){
val array = value.split(":")
(array(0), array(1))
diff --git a/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala b/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala
index 8d68272..df4af27 100644
--- a/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala
+++ b/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala
@@ -13,7 +13,7 @@
import gitbucket.core.util.SyntaxSugars._
import gitbucket.core.util.Implicits._
import gitbucket.core.util.Directory._
-import gitbucket.core.model.{Account, WebHook}
+import gitbucket.core.model.{Account, CommitState, CommitStatus, WebHook}
import gitbucket.core.service.WebHookService._
import gitbucket.core.view
import gitbucket.core.view.helpers
@@ -174,13 +174,24 @@
val (branchName, path) = repository.splitPath(multiParams("splat").head)
val page = params.get("page").flatMap(_.toIntOpt).getOrElse(1)
+ def getStatuses(sha: String): List[CommitStatus] = {
+ getCommitStatues(repository.owner, repository.name, sha)
+ }
+
+ def getSummary(statuses: List[CommitStatus]): (CommitState, String) = {
+ val stateMap = statuses.groupBy(_.state)
+ val state = CommitState.combine(stateMap.keySet)
+ val summary = stateMap.map{ case (keyState, states) => states.size+" "+keyState.name }.mkString(", ")
+ state -> summary
+ }
+
using(Git.open(getRepositoryDir(repository.owner, repository.name))){ git =>
JGitUtil.getCommitLog(git, branchName, page, 30, path) match {
case Right((logs, hasNext)) =>
html.commits(if(path.isEmpty) Nil else path.split("/").toList, branchName, repository,
logs.splitWith{ (commit1, commit2) =>
view.helpers.date(commit1.commitTime) == view.helpers.date(commit2.commitTime)
- }, page, hasNext, hasDeveloperRole(repository.owner, repository.name, context.loginAccount))
+ }, page, hasNext, hasDeveloperRole(repository.owner, repository.name, context.loginAccount), getStatuses, getSummary)
case Left(_) => NotFound()
}
}
@@ -467,9 +478,13 @@
val comment = getCommitComment(repository.owner, repository.name, commentId.toString).get
form.issueId match {
case Some(issueId) =>
- recordCommentPullRequestActivity(repository.owner, repository.name, context.loginAccount.get.userName, issueId, form.content)
- callPullRequestReviewCommentWebHook("create", comment, repository, issueId, context.baseUrl, context.loginAccount.get)
- case None => recordCommentCommitActivity(repository.owner, repository.name, context.loginAccount.get.userName, id, form.content)
+ getPullRequest(repository.owner, repository.name, issueId).foreach { case (issue, pullRequest) =>
+ recordCommentPullRequestActivity(repository.owner, repository.name, context.loginAccount.get.userName, issueId, form.content)
+ PluginRegistry().getPullRequestHooks.foreach(_.addedComment(commentId, form.content, issue, repository))
+ callPullRequestReviewCommentWebHook("create", comment, repository, issue, pullRequest, context.baseUrl, context.loginAccount.get)
+ }
+ case None =>
+ recordCommentCommitActivity(repository.owner, repository.name, context.loginAccount.get.userName, id, form.content)
}
helper.html.commitcomment(comment, hasDeveloperRole(repository.owner, repository.name, context.loginAccount), repository)
})
diff --git a/src/main/scala/gitbucket/core/controller/SystemSettingsController.scala b/src/main/scala/gitbucket/core/controller/SystemSettingsController.scala
index 7841721..080d499 100644
--- a/src/main/scala/gitbucket/core/controller/SystemSettingsController.scala
+++ b/src/main/scala/gitbucket/core/controller/SystemSettingsController.scala
@@ -63,7 +63,8 @@
"tls" -> trim(label("Enable TLS", optional(boolean()))),
"ssl" -> trim(label("Enable SSL", optional(boolean()))),
"keystore" -> trim(label("Keystore", optional(text())))
- )(Ldap.apply))
+ )(Ldap.apply)),
+ "skinName" -> trim(label("AdminLTE skin name", text(required)))
)(SystemSettings.apply).verifying { settings =>
Vector(
if(settings.ssh && settings.baseUrl.isEmpty){
@@ -174,8 +175,9 @@
post("/admin/system/sendmail", sendMailForm)(adminOnly { form =>
try {
new Mailer(form.smtp).send(form.testAddress,
- "Test message from GitBucket", "This is a test message from GitBucket.",
- context.loginAccount.get)
+ "Test message from GitBucket", context.loginAccount.get,
+ "This is a test message from GitBucket.", None
+ )
"Test mail has been sent to: " + form.testAddress
diff --git a/src/main/scala/gitbucket/core/plugin/PluginRegistory.scala b/src/main/scala/gitbucket/core/plugin/PluginRegistory.scala
index 075dfd5..3d3d597 100644
--- a/src/main/scala/gitbucket/core/plugin/PluginRegistory.scala
+++ b/src/main/scala/gitbucket/core/plugin/PluginRegistory.scala
@@ -264,6 +264,7 @@
(extraJars ++ pluginJars).foreach { pluginJar =>
val installedJar = new File(installedDir, pluginJar.getName)
+
FileUtils.copyFile(pluginJar, installedJar)
logger.info(s"Initialize ${pluginJar.getName}")
@@ -400,12 +401,15 @@
events.foreach { event =>
logger.info(event.kind + ": " + event.context)
}
-
- gitbucket.core.servlet.Database() withTransaction { session =>
- logger.info("Reloading plugins...")
- PluginRegistry.reload(context, loadSystemSettings(), session.conn)
- logger.info("Reloading finished.")
- }
+ new Thread {
+ override def run(): Unit = {
+ gitbucket.core.servlet.Database() withTransaction { session =>
+ logger.info("Reloading plugins...")
+ PluginRegistry.reload(context, loadSystemSettings(), session.conn)
+ logger.info("Reloading finished.")
+ }
+ }
+ }.start()
}
detectedWatchKey.reset()
}
diff --git a/src/main/scala/gitbucket/core/service/IssuesService.scala b/src/main/scala/gitbucket/core/service/IssuesService.scala
index ed82f9f..8c183b8 100644
--- a/src/main/scala/gitbucket/core/service/IssuesService.scala
+++ b/src/main/scala/gitbucket/core/service/IssuesService.scala
@@ -455,9 +455,8 @@
def createIssueComment(owner: String, repository: String, commit: CommitInfo)(implicit s: Session): Unit = {
extractIssueId(commit.fullMessage).foreach { issueId =>
if(getIssue(owner, repository, issueId).isDefined){
- getAccountByMailAddress(commit.committerEmailAddress).foreach { account =>
- createComment(owner, repository, account.userName, issueId.toInt, commit.fullMessage + " " + commit.id, "commit")
- }
+ val userName = getAccountByMailAddress(commit.committerEmailAddress).map(_.userName).getOrElse(commit.committerName)
+ createComment(owner, repository, userName, issueId.toInt, commit.fullMessage + " " + commit.id, "commit")
}
}
}
diff --git a/src/main/scala/gitbucket/core/service/SystemSettingsService.scala b/src/main/scala/gitbucket/core/service/SystemSettingsService.scala
index 248d122..c73ed35 100644
--- a/src/main/scala/gitbucket/core/service/SystemSettingsService.scala
+++ b/src/main/scala/gitbucket/core/service/SystemSettingsService.scala
@@ -54,6 +54,7 @@
ldap.keystore.foreach(x => props.setProperty(LdapKeystore, x))
}
}
+ props.setProperty(SkinName, settings.skinName.toString)
using(new java.io.FileOutputStream(GitBucketConf)){ out =>
props.store(out, null)
}
@@ -111,7 +112,8 @@
getOptionValue(props, LdapKeystore, None)))
} else {
None
- }
+ },
+ getValue(props, SkinName, "skin-blue")
)
}
}
@@ -136,7 +138,8 @@
useSMTP: Boolean,
smtp: Option[Smtp],
ldapAuthentication: Boolean,
- ldap: Option[Ldap]){
+ ldap: Option[Ldap],
+ skinName: String){
def baseUrl(request: HttpServletRequest): String = baseUrl.fold(request.baseUrl)(_.stripSuffix("/"))
def sshAddress:Option[SshAddress] =
@@ -219,6 +222,7 @@
private val LdapTls = "ldap.tls"
private val LdapSsl = "ldap.ssl"
private val LdapKeystore = "ldap.keystore"
+ private val SkinName = "skinName"
private def getValue[A: ClassTag](props: java.util.Properties, key: String, default: A): A = {
getSystemProperty(key).getOrElse(getEnvironmentVariable(key).getOrElse {
diff --git a/src/main/scala/gitbucket/core/service/WebHookService.scala b/src/main/scala/gitbucket/core/service/WebHookService.scala
index dc2b9b6..1558115 100644
--- a/src/main/scala/gitbucket/core/service/WebHookService.scala
+++ b/src/main/scala/gitbucket/core/service/WebHookService.scala
@@ -296,13 +296,13 @@
trait WebHookPullRequestReviewCommentService extends WebHookService {
self: AccountService with RepositoryService with PullRequestService with IssuesService with CommitsService =>
- def callPullRequestReviewCommentWebHook(action: String, comment: CommitComment, repository: RepositoryService.RepositoryInfo, issueId: Int, baseUrl: String, sender: Account)
+ def callPullRequestReviewCommentWebHook(action: String, comment: CommitComment, repository: RepositoryService.RepositoryInfo,
+ issue: Issue, pullRequest: PullRequest, baseUrl: String, sender: Account)
(implicit s: Session, c: JsonFormat.Context): Unit = {
import WebHookService._
callWebHookOf(repository.owner, repository.name, WebHook.PullRequestReviewComment){
+ val users = getAccountsByUserNames(Set(repository.owner, pullRequest.requestUserName, issue.openedUserName), Set(sender))
for{
- (issue, pullRequest) <- getPullRequest(repository.owner, repository.name, issueId)
- users = getAccountsByUserNames(Set(repository.owner, pullRequest.requestUserName, issue.openedUserName), Set(sender))
baseOwner <- users.get(repository.owner)
headOwner <- users.get(pullRequest.requestUserName)
issueUser <- users.get(issue.openedUserName)
diff --git a/src/main/scala/gitbucket/core/servlet/GHCompatRepositoryAccessFilter.scala b/src/main/scala/gitbucket/core/servlet/GHCompatRepositoryAccessFilter.scala
deleted file mode 100644
index c712dd9..0000000
--- a/src/main/scala/gitbucket/core/servlet/GHCompatRepositoryAccessFilter.scala
+++ /dev/null
@@ -1,37 +0,0 @@
-package gitbucket.core.servlet
-
-import javax.servlet._
-import javax.servlet.http.{HttpServletRequest, HttpServletResponse}
-
-import gitbucket.core.service.SystemSettingsService
-
-/**
- * A controller to provide GitHub compatible URL for Git clients.
- */
-class GHCompatRepositoryAccessFilter extends Filter with SystemSettingsService {
-
- /**
- * Pattern of GitHub compatible repository URL.
- * /:user/:repo.git/
- */
- private val githubRepositoryPattern = """^/[^/]+/[^/]+\.git/.*""".r
-
- override def init(filterConfig: FilterConfig) = {}
-
- override def doFilter(req: ServletRequest, res: ServletResponse, chain: FilterChain) = {
- implicit val request = req.asInstanceOf[HttpServletRequest]
- val agent = request.getHeader("USER-AGENT")
- val response = res.asInstanceOf[HttpServletResponse]
- val requestPath = request.getRequestURI.substring(request.getContextPath.length)
-
- requestPath match {
- case githubRepositoryPattern() if agent != null && agent.toLowerCase.indexOf("git") >= 0 =>
- response.sendRedirect(baseUrl + "/git" + requestPath)
- case _ =>
- chain.doFilter(req, res)
- }
- }
-
- override def destroy() = {}
-
-}
diff --git a/src/main/scala/gitbucket/core/servlet/PluginControllerFilter.scala b/src/main/scala/gitbucket/core/servlet/PluginControllerFilter.scala
index 06c6ba5..f8be024 100644
--- a/src/main/scala/gitbucket/core/servlet/PluginControllerFilter.scala
+++ b/src/main/scala/gitbucket/core/servlet/PluginControllerFilter.scala
@@ -24,7 +24,7 @@
val controller = PluginRegistry().getControllers().filter { case (_, path) =>
val requestUri = request.asInstanceOf[HttpServletRequest].getRequestURI
val start = path.replaceFirst("/\\*$", "/")
- path.endsWith("/*") && (requestUri + "/").startsWith(start)
+ (requestUri + "/").startsWith(start)
}
val filterChainWrapper = controller.foldLeft(chain){ case (chain, (controller, _)) =>
diff --git a/src/main/scala/gitbucket/core/ssh/GitCommand.scala b/src/main/scala/gitbucket/core/ssh/GitCommand.scala
index 0629c14..9d7345d 100644
--- a/src/main/scala/gitbucket/core/ssh/GitCommand.scala
+++ b/src/main/scala/gitbucket/core/ssh/GitCommand.scala
@@ -19,7 +19,7 @@
import org.eclipse.jgit.errors.RepositoryNotFoundException
object GitCommand {
- val DefaultCommandRegex = """\Agit-(upload|receive)-pack '/([a-zA-Z0-9\-_.]+)/([a-zA-Z0-9\-_.]+).git'\Z""".r
+ val DefaultCommandRegex = """\Agit-(upload|receive)-pack '/([a-zA-Z0-9\-_.]+)/([a-zA-Z0-9\-\+_.]+).git'\Z""".r
val SimpleCommandRegex = """\Agit-(upload|receive)-pack '/(.+\.git)'\Z""".r
}
diff --git a/src/main/scala/gitbucket/core/util/Notifier.scala b/src/main/scala/gitbucket/core/util/Notifier.scala
index 0c7d861..61f3c68 100644
--- a/src/main/scala/gitbucket/core/util/Notifier.scala
+++ b/src/main/scala/gitbucket/core/util/Notifier.scala
@@ -19,8 +19,12 @@
* Please see the plugin for details.
*/
trait Notifier {
+ def toNotify(subject: String, textMsg: String)
+ (recipients: Account => Session => Seq[String])(implicit context: Context): Unit = {
+ toNotify(subject, textMsg, None)(recipients)
+ }
- def toNotify(subject: String, msg: String)
+ def toNotify(subject: String, textMsg: String, htmlMsg: Option[String])
(recipients: Account => Session => Seq[String])(implicit context: Context): Unit
}
@@ -35,7 +39,7 @@
class Mailer(private val smtp: Smtp) extends Notifier {
private val logger = LoggerFactory.getLogger(classOf[Mailer])
- def toNotify(subject: String, msg: String)
+ def toNotify(subject: String, textMsg: String, htmlMsg: Option[String] = None)
(recipients: Account => Session => Seq[String])(implicit context: Context): Unit = {
context.loginAccount.foreach { loginAccount =>
val database = Database()
@@ -43,7 +47,7 @@
val f = Future {
database withSession { session =>
recipients(loginAccount)(session) foreach { to =>
- send(to, subject, msg, loginAccount)
+ send(to, subject, loginAccount, textMsg, htmlMsg)
}
}
"Notifications Successful."
@@ -55,7 +59,7 @@
}
}
- def send(to: String, subject: String, msg: String, loginAccount: Account): Unit = {
+ def send(to: String, subject: String, loginAccount: Account, textMsg: String, htmlMsg: Option[String] = None): Unit = {
val email = new HtmlEmail
email.setHostName(smtp.host)
email.setSmtpPort(smtp.port.get)
@@ -80,13 +84,16 @@
}
email.setCharset("UTF-8")
email.setSubject(subject)
- email.setHtmlMsg(msg)
+ email.setTextMsg(textMsg)
+ htmlMsg.foreach { msg =>
+ email.setHtmlMsg(msg)
+ }
email.addTo(to).send
}
}
class MockMailer extends Notifier {
- def toNotify(subject: String, msg: String)
+ def toNotify(subject: String, textMsg: String, htmlMsg: Option[String] = None)
(recipients: Account => Session => Seq[String])(implicit context: Context): Unit = ()
}
diff --git a/src/main/twirl/gitbucket/core/admin/system.scala.html b/src/main/twirl/gitbucket/core/admin/system.scala.html
index 4234243..4496e65 100644
--- a/src/main/twirl/gitbucket/core/admin/system.scala.html
+++ b/src/main/twirl/gitbucket/core/admin/system.scala.html
@@ -1,5 +1,6 @@
@(info: Option[Any])(implicit context: gitbucket.core.controller.Context)
@import gitbucket.core.util.DatabaseConfig
+@import gitbucket.core.view.helpers
@gitbucket.core.html.main("System settings"){
@gitbucket.core.admin.html.menu("system"){
@gitbucket.core.helper.html.information(info)
@@ -344,6 +345,36 @@
*@
+
+
+
+
+
+
diff --git a/src/main/twirl/gitbucket/core/error.scala.html b/src/main/twirl/gitbucket/core/error.scala.html
index 3c987d8..cd01eda 100644
--- a/src/main/twirl/gitbucket/core/error.scala.html
+++ b/src/main/twirl/gitbucket/core/error.scala.html
@@ -1,8 +1,22 @@
-@(title: String)(implicit context: gitbucket.core.controller.Context)
+@(title: String, e: Option[Throwable]=None)(implicit context: gitbucket.core.controller.Context)
@gitbucket.core.html.main("Error"){
@title
+ @if(context.loginAccount.map{_.isAdmin}.getOrElse(false)){
+ @e.map { ex =>
+
@ex.getMessage
+
+
+ @ex.getStackTrace.map{ st =>
+ @st |
+ }
+
+
+ }
+ } else {
+
Please contact your administrator.
+ }
-}
\ No newline at end of file
+}
diff --git a/src/main/twirl/gitbucket/core/main.scala.html b/src/main/twirl/gitbucket/core/main.scala.html
index 2324f6e..612491a 100644
--- a/src/main/twirl/gitbucket/core/main.scala.html
+++ b/src/main/twirl/gitbucket/core/main.scala.html
@@ -16,7 +16,7 @@
-
+
@@ -42,7 +42,7 @@
}
-
+
diff --git a/src/main/twirl/gitbucket/core/repo/commits.scala.html b/src/main/twirl/gitbucket/core/repo/commits.scala.html
index 0eca2c9..63b272c 100644
--- a/src/main/twirl/gitbucket/core/repo/commits.scala.html
+++ b/src/main/twirl/gitbucket/core/repo/commits.scala.html
@@ -4,7 +4,9 @@
commits: Seq[Seq[gitbucket.core.util.JGitUtil.CommitInfo]],
page: Int,
hasNext: Boolean,
- hasWritePermission: Boolean)(implicit context: gitbucket.core.controller.Context)
+ hasWritePermission: Boolean,
+ getStatuses: String => List[gitbucket.core.model.CommitStatus],
+ getSummary: List[gitbucket.core.model.CommitStatus] => (gitbucket.core.model.CommitState, String))(implicit context: gitbucket.core.controller.Context)
@import gitbucket.core.view.helpers
@gitbucket.core.html.main(s"${repository.owner}/${repository.name}", Some(repository)) {
@gitbucket.core.html.menu("files", repository){
@@ -63,6 +65,30 @@
}
@helpers.user(commit.committerName, commit.committerEmailAddress, "username")
committed @gitbucket.core.helper.html.datetimeago(commit.commitTime)
+ @defining({
+ val statuses = getStatuses(commit.id)
+ val (summary, summaryText) = getSummary(statuses)
+ (statuses, summary, summaryText)
+ }){ case (statuses, summaryState, summaryText) =>
+ @if(statuses.nonEmpty){
+ @helpers.commitStateIcon(summaryState)
+ @helpers.commitStateText(summaryState, commit.id)
+ - @summaryText checks
+ Show all checks
+
+ @statuses.map{ status =>
+
+
@helpers.commitStateIcon(status.state)
+
@status.context
+ @status.description.map { desc =>
- @desc }
+
+ @status.targetUrl.map { url => - Details }
+
+
+ }
+
+ }
+ }
@@ -86,5 +112,19 @@
}
+
}
}
diff --git a/src/test/scala/gitbucket/core/view/AvatarImageProviderSpec.scala b/src/test/scala/gitbucket/core/view/AvatarImageProviderSpec.scala
index 27d8c7d..ba24069 100644
--- a/src/test/scala/gitbucket/core/view/AvatarImageProviderSpec.scala
+++ b/src/test/scala/gitbucket/core/view/AvatarImageProviderSpec.scala
@@ -118,7 +118,9 @@
useSMTP = false,
smtp = None,
ldapAuthentication = false,
- ldap = None)
+ ldap = None,
+ skinName = "skin-blue"
+ )
/**
* Adapter to test AvatarImageProviderImpl.