mirror of
https://github.com/gitbucket/gitbucket.git
synced 2026-05-08 18:45:31 +02:00
Compare commits
63 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8ab6b386a3 | ||
|
|
2dd2c4f568 | ||
|
|
36f7011ebf | ||
|
|
fbcf962630 | ||
|
|
3b9b261878 | ||
|
|
b334809e3e | ||
|
|
9a1324a870 | ||
|
|
b7c39e90d2 | ||
|
|
63b4f25687 | ||
|
|
b582af4469 | ||
|
|
ecd3f5b4eb | ||
|
|
7be433d331 | ||
|
|
154be0f425 | ||
|
|
9ddd2065b7 | ||
|
|
6917cbf224 | ||
|
|
637b033782 | ||
|
|
7aee451a55 | ||
|
|
e1e369d653 | ||
|
|
c2ad66438c | ||
|
|
c88e5adac2 | ||
|
|
703fb4a650 | ||
|
|
465282580f | ||
|
|
e041f8ffa0 | ||
|
|
094386bb65 | ||
|
|
b9e830f06e | ||
|
|
bdbfbc62a9 | ||
|
|
5787a02daa | ||
|
|
0d6e5af8d7 | ||
|
|
88a8973685 | ||
|
|
e640cec323 | ||
|
|
5a4226db1d | ||
|
|
fb48c2a874 | ||
|
|
28da703052 | ||
|
|
2568171083 | ||
|
|
2dff7f1b9e | ||
|
|
8a79de8b50 | ||
|
|
1b763c753c | ||
|
|
3bb1b1269c | ||
|
|
dbbaf3cc9c | ||
|
|
4465a62b5f | ||
|
|
fb48e75ecf | ||
|
|
a79142074f | ||
|
|
9f58c6dce7 | ||
|
|
6fe903afab | ||
|
|
0d94865633 | ||
|
|
2fbdead64b | ||
|
|
72a354931e | ||
|
|
cb8affcd0d | ||
|
|
a5a997eb40 | ||
|
|
b4220aab68 | ||
|
|
c8a4798f86 | ||
|
|
6b8e9e8892 | ||
|
|
9ab9363d0b | ||
|
|
1edb18a147 | ||
|
|
d8b4bf3033 | ||
|
|
6597c4490b | ||
|
|
daaf1696ad | ||
|
|
53a1ca7874 | ||
|
|
f045fa4c6a | ||
|
|
53a7c5adf8 | ||
|
|
b142eca9a5 | ||
|
|
ba753a373b | ||
|
|
95ceca75a4 |
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
@@ -3,3 +3,4 @@
|
||||
build.sbt @xuwei-k
|
||||
project/* @xuwei-k
|
||||
.github/workflows/* @xuwei-k
|
||||
.scalafmt.conf @xuwei-k
|
||||
|
||||
8
.github/workflows/build.yml
vendored
8
.github/workflows/build.yml
vendored
@@ -9,11 +9,11 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
java: [17, 21]
|
||||
java: [17, 25]
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v6
|
||||
- name: Cache
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v5
|
||||
env:
|
||||
cache-name: cache-sbt-libs
|
||||
with:
|
||||
@@ -36,7 +36,7 @@ jobs:
|
||||
- name: Build executable
|
||||
run: sbt executable
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: gitbucket-java${{ matrix.java }}-${{ github.sha }}
|
||||
path: ./target/executable/gitbucket.*
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
version = "3.9.10"
|
||||
version = "3.10.3"
|
||||
project.git = true
|
||||
|
||||
maxColumn = 120
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
# Changelog
|
||||
All changes to the project will be documented in this file.
|
||||
|
||||
## 4.45.0 - 11 Jan 2026
|
||||
- Add new option to show full username on UI
|
||||
- Support render plugin in issues, pull requests, wiki and commit comments
|
||||
- Support link to other pages from Wiki page using Wiki link syntax
|
||||
|
||||
## 4.44.0 - 23 Sep 2025
|
||||
- Enhanced branch protection which supports rejecting users fo push, etc.
|
||||
- Enhanced branch protection which supports the following settings:
|
||||
- Prevent pushes from non-allowed users
|
||||
- Whether to apply restrictions to administrator users as well
|
||||
- Improve logging for initialization errors
|
||||
|
||||
## 4.43.0 - 29 Jun 2025
|
||||
|
||||
11
README.md
11
README.md
@@ -44,7 +44,7 @@ GitBucket has a plug-in system that allows extra functionality. Officially the f
|
||||
- [gitbucket-pages-plugin](https://github.com/gitbucket/gitbucket-pages-plugin)
|
||||
- [gitbucket-notifications-plugin](https://github.com/gitbucket/gitbucket-notifications-plugin)
|
||||
|
||||
You can find more plugins made by the community at [GitBucket community plugins](https://gitbucket-plugins.github.io/).
|
||||
You can find more plugins made by the community at [GitBucket community plugins](https://github.com/gitbucket/gitbucket/wiki/Community-Plugins).
|
||||
|
||||
Building and Development
|
||||
-----------
|
||||
@@ -59,11 +59,12 @@ Support
|
||||
- If you can't find same question and report, send it to our [Gitter chat room](https://gitter.im/gitbucket/gitbucket) before raising an issue.
|
||||
- The highest priority of GitBucket is the ease of installation and API compatibility with GitHub, so your feature request might be rejected if they go against those principles.
|
||||
|
||||
What's New in 4.44.x
|
||||
What's New in 4.45.x
|
||||
-------------
|
||||
## 4.44.0 - 23 Sep 2025
|
||||
- Enhanced branch protection which supports rejecting users fo push, etc.
|
||||
- Improve logging for initialization errors
|
||||
## 4.45.0 - 11 Jan 2026
|
||||
- Add new option to show full username on UI
|
||||
- Support render plugin in issues, pull requests, wiki and commit comments
|
||||
- Support link to other pages from Wiki page using Wiki link syntax
|
||||
|
||||
Note that you have to migrate h2 database file if you will upgrade GitBucket from 4.42 or before to 4.43 or later and you are using the default h2 database because h2 1.x and h2.x don't have compatibility: https://www.h2database.com/html/migration-to-v2.html
|
||||
|
||||
|
||||
63
build.sbt
63
build.sbt
@@ -2,7 +2,7 @@ import com.jsuereth.sbtpgp.PgpKeys._
|
||||
|
||||
val Organization = "io.github.gitbucket"
|
||||
val Name = "gitbucket"
|
||||
val GitBucketVersion = "4.44.0"
|
||||
val GitBucketVersion = "4.45.0"
|
||||
val ScalatraVersion = "3.1.2"
|
||||
val JettyVersion = "10.0.26"
|
||||
val JgitVersion = "6.10.1.202505221210-r"
|
||||
@@ -14,9 +14,9 @@ sourcesInBase := false
|
||||
organization := Organization
|
||||
name := Name
|
||||
version := GitBucketVersion
|
||||
scalaVersion := "2.13.16"
|
||||
scalaVersion := "2.13.18"
|
||||
|
||||
crossScalaVersions += "3.7.3"
|
||||
crossScalaVersions += "3.7.4"
|
||||
|
||||
// scalafmtOnCompile := true
|
||||
|
||||
@@ -29,10 +29,10 @@ libraryDependencies ++= Seq(
|
||||
"org.scalatra" %% "scalatra-json-javax" % ScalatraVersion,
|
||||
"org.scalatra" %% "scalatra-forms-javax" % ScalatraVersion,
|
||||
"org.json4s" %% "json4s-jackson" % "4.1.0-M8",
|
||||
"commons-io" % "commons-io" % "2.20.0",
|
||||
"commons-io" % "commons-io" % "2.21.0",
|
||||
"io.github.gitbucket" % "solidbase" % "1.1.0",
|
||||
"io.github.gitbucket" % "markedj" % "1.0.20",
|
||||
"org.tukaani" % "xz" % "1.10",
|
||||
"org.tukaani" % "xz" % "1.11",
|
||||
"org.apache.commons" % "commons-compress" % "1.28.0",
|
||||
"org.apache.commons" % "commons-email" % "1.6.0",
|
||||
"commons-net" % "commons-net" % "3.12.0",
|
||||
@@ -42,33 +42,32 @@ libraryDependencies ++= Seq(
|
||||
"sshd-mina"
|
||||
) exclude ("org.apache.sshd", "sshd-netty")
|
||||
exclude ("org.apache.sshd", "sshd-spring-sftp"),
|
||||
"org.apache.tika" % "tika-core" % "3.2.3",
|
||||
"com.github.takezoe" %% "blocking-slick" % "0.0.14",
|
||||
"com.novell.ldap" % "jldap" % "2009-10-07",
|
||||
"com.h2database" % "h2" % "2.3.232",
|
||||
"org.mariadb.jdbc" % "mariadb-java-client" % "2.7.12",
|
||||
"org.postgresql" % "postgresql" % "42.7.8",
|
||||
"ch.qos.logback" % "logback-classic" % "1.5.18",
|
||||
"com.zaxxer" % "HikariCP" % "7.0.2" exclude ("org.slf4j", "slf4j-api"),
|
||||
"com.typesafe" % "config" % "1.4.5",
|
||||
"fr.brouillard.oss.security.xhub" % "xhub4j-core" % "1.1.0",
|
||||
"io.github.java-diff-utils" % "java-diff-utils" % "4.16",
|
||||
"org.cache2k" % "cache2k-all" % "1.6.0.Final",
|
||||
"net.coobird" % "thumbnailator" % "0.4.20",
|
||||
"com.github.zafarkhaja" % "java-semver" % "0.10.2",
|
||||
"com.nimbusds" % "oauth2-oidc-sdk" % "11.29.1",
|
||||
"org.eclipse.jetty" % "jetty-webapp" % JettyVersion % "provided",
|
||||
"javax.servlet" % "javax.servlet-api" % "3.1.0" % "provided",
|
||||
"junit" % "junit" % "4.13.2" % "test",
|
||||
"org.scalatra" %% "scalatra-scalatest-javax" % ScalatraVersion % "test",
|
||||
"org.mockito" % "mockito-core" % "5.20.0" % "test",
|
||||
"com.dimafeng" %% "testcontainers-scala" % "0.43.0" % "test",
|
||||
"org.testcontainers" % "mysql" % "1.21.3" % "test",
|
||||
"org.testcontainers" % "postgresql" % "1.21.3" % "test",
|
||||
"net.i2p.crypto" % "eddsa" % "0.3.0",
|
||||
"is.tagomor.woothee" % "woothee-java" % "1.11.0",
|
||||
"org.ec4j.core" % "ec4j-core" % "1.1.1",
|
||||
"org.kohsuke" % "github-api" % "1.330" % "test"
|
||||
"org.apache.tika" % "tika-core" % "3.2.3",
|
||||
"com.github.takezoe" %% "blocking-slick" % "0.0.14",
|
||||
"com.novell.ldap" % "jldap" % "2009-10-07",
|
||||
"com.h2database" % "h2" % "2.4.240",
|
||||
"org.mariadb.jdbc" % "mariadb-java-client" % "2.7.13",
|
||||
"org.postgresql" % "postgresql" % "42.7.8",
|
||||
"ch.qos.logback" % "logback-classic" % "1.5.24",
|
||||
"com.zaxxer" % "HikariCP" % "7.0.2" exclude ("org.slf4j", "slf4j-api"),
|
||||
"com.typesafe" % "config" % "1.4.5",
|
||||
"fr.brouillard.oss.security.xhub" % "xhub4j-core" % "1.1.0",
|
||||
"io.github.java-diff-utils" % "java-diff-utils" % "4.16",
|
||||
"org.cache2k" % "cache2k-all" % "1.6.0.Final",
|
||||
"net.coobird" % "thumbnailator" % "0.4.21",
|
||||
"com.github.zafarkhaja" % "java-semver" % "0.10.2",
|
||||
"com.nimbusds" % "oauth2-oidc-sdk" % "11.31",
|
||||
"org.eclipse.jetty" % "jetty-webapp" % JettyVersion % "provided",
|
||||
"javax.servlet" % "javax.servlet-api" % "3.1.0" % "provided",
|
||||
"junit" % "junit" % "4.13.2" % "test",
|
||||
"org.scalatra" %% "scalatra-scalatest-javax" % ScalatraVersion % "test",
|
||||
"org.mockito" % "mockito-core" % "5.21.0" % "test",
|
||||
"org.testcontainers" % "testcontainers-mysql" % "2.0.3" % "test",
|
||||
"org.testcontainers" % "testcontainers-postgresql" % "2.0.3" % "test",
|
||||
"net.i2p.crypto" % "eddsa" % "0.3.0",
|
||||
"is.tagomor.woothee" % "woothee-java" % "1.11.0",
|
||||
"org.ec4j.core" % "ec4j-core" % "1.2.0",
|
||||
"org.kohsuke" % "github-api" % "1.330" % "test"
|
||||
)
|
||||
|
||||
// Compiler settings
|
||||
|
||||
@@ -38,7 +38,7 @@ Generate release files
|
||||
|
||||
For plug-in development, we have to publish the GitBucket jar file to the Maven central repository before release GitBucket itself.
|
||||
|
||||
First, start the sbt shell:
|
||||
First, stage artifacts on your machine:
|
||||
|
||||
```bash
|
||||
$ sbt publishSigned
|
||||
|
||||
@@ -1 +1 @@
|
||||
sbt.version=1.11.6
|
||||
sbt.version=1.12.0
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
scalacOptions ++= Seq("-unchecked", "-deprecation", "-feature")
|
||||
|
||||
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.5")
|
||||
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.6")
|
||||
addSbtPlugin("org.playframework.twirl" % "sbt-twirl" % "2.0.9")
|
||||
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "2.3.1")
|
||||
addSbtPlugin("org.scalatra.sbt" % "sbt-scalatra" % "1.0.4")
|
||||
addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.3.1")
|
||||
addSbtPlugin("com.github.sbt" % "sbt-license-report" % "1.8.0")
|
||||
addSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.3.1")
|
||||
addSbtPlugin("com.github.sbt" % "sbt-license-report" % "1.9.0")
|
||||
addSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.4.3")
|
||||
|
||||
addDependencyTreePlugin
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
notifications:1.11.0
|
||||
gist:4.23.0
|
||||
gist:4.24.0
|
||||
emoji:4.6.0
|
||||
pages:1.10.0
|
||||
|
||||
@@ -121,7 +121,8 @@ object GitBucketCoreModule
|
||||
new Version("4.42.0", new LiquibaseMigration("update/gitbucket-core_4.42.xml")),
|
||||
new Version("4.42.1"),
|
||||
new Version("4.43.0"),
|
||||
new Version("4.44.0", new LiquibaseMigration("update/gitbucket-core_4.44.xml"))
|
||||
new Version("4.44.0", new LiquibaseMigration("update/gitbucket-core_4.44.xml")),
|
||||
new Version("4.45.0")
|
||||
) {
|
||||
java.util.logging.Logger.getLogger("liquibase").setLevel(Level.SEVERE)
|
||||
}
|
||||
|
||||
@@ -351,7 +351,7 @@ case class Context(
|
||||
val path: String = settings.baseUrl.getOrElse(request.getContextPath)
|
||||
val currentPath: String = request.getRequestURI.substring(request.getContextPath.length)
|
||||
val baseUrl: String = settings.baseUrl(request)
|
||||
val host: String = new java.net.URL(baseUrl).getHost
|
||||
val host: String = new java.net.URI(baseUrl).toURL.getHost
|
||||
val platform: String = request.getHeader("User-Agent") match {
|
||||
case null => null
|
||||
case agent if agent.contains("Mac") => "mac"
|
||||
|
||||
@@ -13,8 +13,8 @@ import gitbucket.core.util.*
|
||||
import gitbucket.core.view.helpers.*
|
||||
import org.scalatra.Ok
|
||||
import org.scalatra.forms.*
|
||||
|
||||
import gitbucket.core.service.ActivityService.*
|
||||
import gitbucket.core.view.helpers
|
||||
|
||||
class IndexController
|
||||
extends IndexControllerBase
|
||||
@@ -92,6 +92,10 @@ trait IndexControllerBase extends ControllerBase {
|
||||
}
|
||||
}
|
||||
|
||||
get("/_is_renderable") {
|
||||
helpers.isRenderable(params("filename"))
|
||||
}
|
||||
|
||||
get("/signin") {
|
||||
if (context.loginAccount.nonEmpty) {
|
||||
redirect("/")
|
||||
@@ -247,13 +251,22 @@ trait IndexControllerBase extends ControllerBase {
|
||||
}
|
||||
}
|
||||
.map { t =>
|
||||
Map(
|
||||
"label" -> s"${avatar(t.userName, 16)}<b>@${StringUtil.escapeHtml(
|
||||
StringUtil.cutTail(t.userName, 25, "...")
|
||||
)}</b> ${StringUtil
|
||||
.escapeHtml(StringUtil.cutTail(t.fullName, 25, "..."))}",
|
||||
"value" -> t.userName
|
||||
)
|
||||
if (t.isGroupAccount) {
|
||||
Map(
|
||||
"label" -> s"${avatar(t.userName, 16)} <b>@${StringUtil.escapeHtml(
|
||||
StringUtil.cutTail(t.userName, 25, "...")
|
||||
)}</b>",
|
||||
"value" -> t.userName
|
||||
)
|
||||
} else {
|
||||
Map(
|
||||
"label" -> s"${avatar(t.userName, 16)} <b>@${StringUtil.escapeHtml(
|
||||
StringUtil.cutTail(t.userName, 25, "...")
|
||||
)}</b> (${StringUtil
|
||||
.escapeHtml(StringUtil.cutTail(t.fullName, 25, "..."))})",
|
||||
"value" -> t.userName
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
@@ -6,8 +6,7 @@ import gitbucket.core.service.IssuesService.*
|
||||
import gitbucket.core.service.*
|
||||
import gitbucket.core.util.Implicits.*
|
||||
import gitbucket.core.util.*
|
||||
import gitbucket.core.view
|
||||
import gitbucket.core.view.Markdown
|
||||
import gitbucket.core.view.helpers
|
||||
import org.scalatra.forms.*
|
||||
import org.scalatra.{BadRequest, Ok}
|
||||
|
||||
@@ -271,20 +270,24 @@ trait IssuesControllerBase extends ControllerBase {
|
||||
case t if t == "html" => html.editissue(x.content, x.issueId, repository)
|
||||
} getOrElse {
|
||||
contentType = formats("json")
|
||||
val content = helpers
|
||||
.renderMarkup(
|
||||
filePath = List("temporary.md"),
|
||||
fileContent = x.content getOrElse "No description given.",
|
||||
branch = repository.repository.defaultBranch,
|
||||
repository = repository,
|
||||
enableWikiLink = false,
|
||||
enableRefsLink = true,
|
||||
enableAnchor = true,
|
||||
enableLineBreaks = true,
|
||||
enableTaskList = true,
|
||||
hasWritePermission = true
|
||||
)
|
||||
.toString()
|
||||
org.json4s.jackson.Serialization.write(
|
||||
Map(
|
||||
"title" -> x.title,
|
||||
"content" -> Markdown.toHtml(
|
||||
markdown = x.content getOrElse "No description given.",
|
||||
repository = repository,
|
||||
branch = repository.repository.defaultBranch,
|
||||
enableWikiLink = false,
|
||||
enableRefsLink = true,
|
||||
enableAnchor = true,
|
||||
enableLineBreaks = true,
|
||||
enableTaskList = true,
|
||||
hasWritePermission = true
|
||||
)
|
||||
"content" -> content
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -301,19 +304,23 @@ trait IssuesControllerBase extends ControllerBase {
|
||||
case t if t == "html" => html.editcomment(x.content, x.commentId, repository)
|
||||
} getOrElse {
|
||||
contentType = formats("json")
|
||||
val content = helpers
|
||||
.renderMarkup(
|
||||
filePath = List("temporary.md"),
|
||||
fileContent = x.content,
|
||||
branch = repository.repository.defaultBranch,
|
||||
repository = repository,
|
||||
enableWikiLink = false,
|
||||
enableRefsLink = true,
|
||||
enableAnchor = true,
|
||||
enableLineBreaks = true,
|
||||
enableTaskList = true,
|
||||
hasWritePermission = true
|
||||
)
|
||||
.toString()
|
||||
org.json4s.jackson.Serialization.write(
|
||||
Map(
|
||||
"content" -> view.Markdown.toHtml(
|
||||
markdown = x.content,
|
||||
repository = repository,
|
||||
branch = repository.repository.defaultBranch,
|
||||
enableWikiLink = false,
|
||||
enableRefsLink = true,
|
||||
enableAnchor = true,
|
||||
enableLineBreaks = true,
|
||||
enableTaskList = true,
|
||||
hasWritePermission = true
|
||||
)
|
||||
"content" -> content
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -23,8 +23,7 @@ import org.apache.commons.compress.archivers.zip.{ZipArchiveEntry, ZipArchiveOut
|
||||
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream
|
||||
import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream
|
||||
import org.apache.commons.compress.compressors.xz.XZCompressorOutputStream
|
||||
import org.apache.commons.compress.utils.IOUtils
|
||||
import org.apache.commons.io.FileUtils
|
||||
import org.apache.commons.io.{FileUtils, IOUtils}
|
||||
import org.scalatra.forms.*
|
||||
import org.eclipse.jgit.api.{ArchiveCommand, Git}
|
||||
import org.eclipse.jgit.archive.{TgzFormat, ZipFormat}
|
||||
@@ -35,7 +34,7 @@ import org.eclipse.jgit.treewalk.TreeWalk.OperationType
|
||||
import org.eclipse.jgit.treewalk.filter.PathFilter
|
||||
import org.eclipse.jgit.util.io.EolStreamTypeUtil
|
||||
import org.json4s.jackson.Serialization
|
||||
import org.scalatra._
|
||||
import org.scalatra.*
|
||||
import org.scalatra.i18n.Messages
|
||||
|
||||
class RepositoryViewerController
|
||||
@@ -170,31 +169,19 @@ trait RepositoryViewerControllerBase extends ControllerBase {
|
||||
*/
|
||||
post("/:owner/:repository/_preview")(referrersOnly { repository =>
|
||||
contentType = "text/html"
|
||||
val filename = params.get("filename")
|
||||
filename match {
|
||||
case Some(f) =>
|
||||
helpers.renderMarkup(
|
||||
filePath = List(f),
|
||||
fileContent = params("content"),
|
||||
branch = repository.repository.defaultBranch,
|
||||
repository = repository,
|
||||
enableWikiLink = params("enableWikiLink").toBoolean,
|
||||
enableRefsLink = params("enableRefsLink").toBoolean,
|
||||
enableAnchor = false
|
||||
)
|
||||
case None =>
|
||||
helpers.markdown(
|
||||
markdown = params("content"),
|
||||
repository = repository,
|
||||
branch = repository.repository.defaultBranch,
|
||||
enableWikiLink = params("enableWikiLink").toBoolean,
|
||||
enableRefsLink = params("enableRefsLink").toBoolean,
|
||||
enableLineBreaks = params("enableLineBreaks").toBoolean,
|
||||
enableTaskList = params("enableTaskList").toBoolean,
|
||||
enableAnchor = false,
|
||||
hasWritePermission = hasDeveloperRole(repository.owner, repository.name, context.loginAccount)
|
||||
)
|
||||
}
|
||||
val filename = params.get("filename").getOrElse("temporary.md")
|
||||
helpers.renderMarkup(
|
||||
filePath = filename.split("/").toList,
|
||||
fileContent = params("content"),
|
||||
branch = repository.repository.defaultBranch,
|
||||
repository = repository,
|
||||
enableWikiLink = params("enableWikiLink").toBoolean,
|
||||
enableRefsLink = params("enableRefsLink").toBoolean,
|
||||
enableLineBreaks = params("enableLineBreaks").toBoolean,
|
||||
enableTaskList = params("enableTaskList").toBoolean,
|
||||
enableAnchor = false,
|
||||
hasWritePermission = hasDeveloperRole(repository.owner, repository.name, context.loginAccount)
|
||||
)
|
||||
})
|
||||
|
||||
/**
|
||||
@@ -897,19 +884,23 @@ trait RepositoryViewerControllerBase extends ControllerBase {
|
||||
case t if t == "html" => html.editcomment(x.content, x.commentId, repository)
|
||||
} getOrElse {
|
||||
contentType = formats("json")
|
||||
val content = helpers
|
||||
.renderMarkup(
|
||||
filePath = List("temporary.md"),
|
||||
fileContent = x.content,
|
||||
branch = repository.repository.defaultBranch,
|
||||
repository = repository,
|
||||
enableWikiLink = false,
|
||||
enableRefsLink = true,
|
||||
enableAnchor = true,
|
||||
enableLineBreaks = true,
|
||||
enableTaskList = true,
|
||||
hasWritePermission = true
|
||||
)
|
||||
.toString()
|
||||
org.json4s.jackson.Serialization.write(
|
||||
Map(
|
||||
"content" -> view.Markdown.toHtml(
|
||||
markdown = x.content,
|
||||
repository = repository,
|
||||
branch = repository.repository.defaultBranch,
|
||||
enableWikiLink = false,
|
||||
enableRefsLink = true,
|
||||
enableAnchor = true,
|
||||
enableLineBreaks = true,
|
||||
enableTaskList = true,
|
||||
hasWritePermission = true
|
||||
)
|
||||
"content" -> content
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -125,7 +125,8 @@ trait SystemSettingsControllerBase extends AccountManagementControllerBase {
|
||||
"maxDiffFiles" -> trim(label("Max diff files", number(required))),
|
||||
"maxDiffLines" -> trim(label("Max diff lines", number(required)))
|
||||
)(RepositoryViewerSettings.apply),
|
||||
"defaultBranch" -> trim(label("Default branch", text(required)))
|
||||
"defaultBranch" -> trim(label("Default branch", text(required))),
|
||||
"showFullName" -> trim(label("Show full name", boolean()))
|
||||
)(SystemSettings.apply).verifying { settings =>
|
||||
Vector(
|
||||
if (settings.ssh.enabled && settings.baseUrl.isEmpty) {
|
||||
|
||||
@@ -5,7 +5,7 @@ import gitbucket.core.service.{AccountService, ProtectedBranchService, Repositor
|
||||
import gitbucket.core.util.*
|
||||
import gitbucket.core.util.Directory.*
|
||||
import gitbucket.core.util.Implicits.*
|
||||
import gitbucket.core.util.JGitUtil.{getBranchesNoMergeInfo, processTree}
|
||||
import gitbucket.core.util.JGitUtil.getBranchesNoMergeInfo
|
||||
import org.eclipse.jgit.api.Git
|
||||
import org.scalatra.NoContent
|
||||
|
||||
|
||||
@@ -90,7 +90,17 @@ trait ApiRepositoryContentsControllerBase extends ControllerBase {
|
||||
path,
|
||||
"\" id=\"file\">",
|
||||
"<article>",
|
||||
renderMarkup(path.split("/").toList, new String(c), refStr, repository, false, false, true).body,
|
||||
renderMarkup(
|
||||
filePath = path.split("/").toList,
|
||||
fileContent = new String(c),
|
||||
branch = refStr,
|
||||
repository = repository,
|
||||
enableWikiLink = false,
|
||||
enableRefsLink = false,
|
||||
enableAnchor = false,
|
||||
enableLineBreaks = true,
|
||||
enableTaskList = true
|
||||
).body,
|
||||
"</article>",
|
||||
"</div>"
|
||||
).mkString
|
||||
|
||||
@@ -15,7 +15,7 @@ import gitbucket.core.service.RepositoryService.RepositoryInfo
|
||||
import gitbucket.core.service.SystemSettingsService
|
||||
import gitbucket.core.service.SystemSettingsService.SystemSettings
|
||||
import gitbucket.core.util.{ConfigUtil, DatabaseConfig}
|
||||
import gitbucket.core.util.Directory._
|
||||
import gitbucket.core.util.Directory.*
|
||||
import io.github.gitbucket.solidbase.Solidbase
|
||||
import io.github.gitbucket.solidbase.manager.JDBCVersionManager
|
||||
import io.github.gitbucket.solidbase.model.Module
|
||||
@@ -25,7 +25,7 @@ import org.apache.sshd.server.command.Command
|
||||
import org.slf4j.LoggerFactory
|
||||
import play.twirl.api.Html
|
||||
|
||||
import scala.jdk.CollectionConverters._
|
||||
import scala.jdk.CollectionConverters.*
|
||||
|
||||
class PluginRegistry {
|
||||
|
||||
@@ -233,29 +233,29 @@ object PluginRegistry {
|
||||
override def accept(dir: File, name: String): Boolean = name.endsWith(".jar")
|
||||
})
|
||||
.toSeq
|
||||
.sortBy(x => Version.valueOf(getPluginVersion(x.getName)))
|
||||
.sortBy(x => Version.parse(getPluginVersion(x.getName)))
|
||||
.reverse
|
||||
}
|
||||
|
||||
lazy val extraPluginDir: Option[String] = ConfigUtil.getConfigValue[String]("gitbucket.pluginDir")
|
||||
private lazy val extraPluginDir: Option[String] = ConfigUtil.getConfigValue[String]("gitbucket.pluginDir")
|
||||
|
||||
def getGitBucketVersion(pluginJarFileName: String): Option[String] = {
|
||||
val regex = ".+-gitbucket\\_(\\d+\\.\\d+\\.\\d+(-SNAPSHOT)?)-.+".r
|
||||
private def getGitBucketVersion(pluginJarFileName: String): Option[String] = {
|
||||
val regex = ".+-gitbucket_(\\d+\\.\\d+\\.\\d+(-SNAPSHOT)?)-.+".r
|
||||
pluginJarFileName match {
|
||||
case regex(all, _) => Some(all)
|
||||
case _ => None
|
||||
}
|
||||
}
|
||||
|
||||
def getPluginVersion(pluginJarFileName: String): String = {
|
||||
private def getPluginVersion(pluginJarFileName: String): String = {
|
||||
val regex = ".+-((\\d+)\\.(\\d+)(\\.(\\d+))?(-SNAPSHOT)?)\\.jar$".r
|
||||
pluginJarFileName match {
|
||||
case regex(all, major, minor, _, patch, modifier) => {
|
||||
if (patch != null) all
|
||||
else {
|
||||
case regex(all, major, minor, _, patch, modifier) =>
|
||||
if (patch != null) {
|
||||
all
|
||||
} else {
|
||||
s"${major}.${minor}.0" + (if (modifier == null) "" else modifier)
|
||||
}
|
||||
}
|
||||
case _ => "0.0.0"
|
||||
}
|
||||
}
|
||||
@@ -295,11 +295,10 @@ object PluginRegistry {
|
||||
|
||||
// Check duplication
|
||||
instance.getPlugins().find(_.pluginId == pluginId) match {
|
||||
case Some(x) => {
|
||||
case Some(x) =>
|
||||
logger.warn(s"Plugin ${pluginId} is duplicated. ${x.pluginJar.getName} is available.")
|
||||
classLoader.close()
|
||||
}
|
||||
case None => {
|
||||
case None =>
|
||||
// Migration
|
||||
val solidbase = new Solidbase()
|
||||
solidbase
|
||||
@@ -334,7 +333,6 @@ object PluginRegistry {
|
||||
classLoader = classLoader
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
case e: Throwable =>
|
||||
@@ -369,9 +367,8 @@ object PluginRegistry {
|
||||
extraWatcher = null
|
||||
}
|
||||
} catch {
|
||||
case e: Exception => {
|
||||
case e: Exception =>
|
||||
logger.error(s"Error during plugin shutdown: ${plugin.pluginJar.getName}", e)
|
||||
}
|
||||
} finally {
|
||||
plugin.classLoader.close()
|
||||
}
|
||||
@@ -437,7 +434,7 @@ class PluginWatchThread(context: ServletContext, dir: String) extends Thread wit
|
||||
logger.info("Start PluginWatchThread: " + path)
|
||||
|
||||
try {
|
||||
while (watchKey.isValid()) {
|
||||
while (watchKey.isValid) {
|
||||
val detectedWatchKey = watcher.take()
|
||||
val events = detectedWatchKey.pollEvents.asScala.filter { e =>
|
||||
e.context.toString != ".installed" && !e.context.toString.endsWith(".bak")
|
||||
|
||||
@@ -20,7 +20,7 @@ trait Renderer {
|
||||
|
||||
object MarkdownRenderer extends Renderer {
|
||||
override def render(request: RenderRequest): Html = {
|
||||
import request._
|
||||
import request.*
|
||||
Html(
|
||||
Markdown.toHtml(
|
||||
markdown = fileContent,
|
||||
@@ -29,9 +29,9 @@ object MarkdownRenderer extends Renderer {
|
||||
enableWikiLink = enableWikiLink,
|
||||
enableRefsLink = enableRefsLink,
|
||||
enableAnchor = enableAnchor,
|
||||
enableLineBreaks = false,
|
||||
enableTaskList = true,
|
||||
hasWritePermission = false
|
||||
enableLineBreaks = enableLineBreaks,
|
||||
enableTaskList = enableTaskList,
|
||||
hasWritePermission = hasWritePermission
|
||||
)(context)
|
||||
)
|
||||
}
|
||||
@@ -51,5 +51,8 @@ case class RenderRequest(
|
||||
enableWikiLink: Boolean,
|
||||
enableRefsLink: Boolean,
|
||||
enableAnchor: Boolean,
|
||||
enableLineBreaks: Boolean,
|
||||
enableTaskList: Boolean,
|
||||
hasWritePermission: Boolean,
|
||||
context: Context
|
||||
)
|
||||
|
||||
@@ -93,6 +93,7 @@ trait SystemSettingsService {
|
||||
props.setProperty(RepositoryViewerMaxDiffFiles, settings.repositoryViewer.maxDiffFiles.toString)
|
||||
props.setProperty(RepositoryViewerMaxDiffLines, settings.repositoryViewer.maxDiffLines.toString)
|
||||
props.setProperty(DefaultBranch, settings.defaultBranch)
|
||||
props.setProperty(ShowFullName, settings.showFullName.toString)
|
||||
|
||||
Using.resource(new java.io.FileOutputStream(GitBucketConf)) { out =>
|
||||
props.store(out, null)
|
||||
@@ -211,7 +212,8 @@ trait SystemSettingsService {
|
||||
getValue(props, RepositoryViewerMaxDiffFiles, 100),
|
||||
getValue(props, RepositoryViewerMaxDiffLines, 1000)
|
||||
),
|
||||
getValue(props, DefaultBranch, "main")
|
||||
getValue(props, DefaultBranch, "main"),
|
||||
getValue(props, ShowFullName, false)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -238,7 +240,8 @@ object SystemSettingsService {
|
||||
webHook: WebHook,
|
||||
upload: Upload,
|
||||
repositoryViewer: RepositoryViewerSettings,
|
||||
defaultBranch: String
|
||||
defaultBranch: String,
|
||||
showFullName: Boolean
|
||||
) {
|
||||
def baseUrl(request: HttpServletRequest): String =
|
||||
baseUrl.getOrElse(parseBaseUrl(request)).stripSuffix("/")
|
||||
@@ -457,6 +460,7 @@ object SystemSettingsService {
|
||||
private val RepositoryViewerMaxDiffFiles = "repository_viewer_max_diff_files"
|
||||
private val RepositoryViewerMaxDiffLines = "repository_viewer_max_diff_lines"
|
||||
private val DefaultBranch = "default_branch"
|
||||
private val ShowFullName = "show_full_name"
|
||||
|
||||
private def getValue[A: ClassTag](props: java.util.Properties, key: String, default: A): A = {
|
||||
getConfigValue(key).getOrElse {
|
||||
|
||||
@@ -265,7 +265,7 @@ trait WebHookService {
|
||||
}
|
||||
|
||||
private def validateTargetAddress(settings: SystemSettings, url: String): Boolean = {
|
||||
val host = new java.net.URL(url).getHost
|
||||
val host = new java.net.URI(url).toURL.getHost
|
||||
|
||||
!settings.webHook.blockPrivateAddress ||
|
||||
!HttpClientUtil.isPrivateAddress(host) ||
|
||||
|
||||
@@ -47,18 +47,28 @@ trait AvatarImageProvider { self: RequestCache =>
|
||||
}
|
||||
}
|
||||
|
||||
val displayName = if (!context.settings.showFullName) {
|
||||
s"@$userName"
|
||||
} else {
|
||||
if (mailAddress.isEmpty) {
|
||||
getAccountByUserNameFromCache(userName).map(_.fullName).getOrElse(s"@$userName")
|
||||
} else {
|
||||
getAccountByMailAddressFromCache(mailAddress).map(_.fullName).getOrElse(s"@$userName")
|
||||
}
|
||||
}
|
||||
|
||||
if (tooltip) {
|
||||
Html(
|
||||
s"""<img src="${src}" class="${if (size > 20) { "avatar" }
|
||||
else { "avatar-mini" }}" style="width: ${size}px; height: ${size}px;"
|
||||
| alt="@${StringUtil.escapeHtml(userName)}"
|
||||
| data-toggle="tooltip" title="${StringUtil.escapeHtml(userName)}" />""".stripMargin
|
||||
| alt="${StringUtil.escapeHtml(displayName)}"
|
||||
| data-toggle="tooltip" title="${StringUtil.escapeHtml(displayName)}" />""".stripMargin
|
||||
)
|
||||
} else {
|
||||
Html(
|
||||
s"""<img src="${src}" class="${if (size > 20) { "avatar" }
|
||||
else { "avatar-mini" }}" style="width: ${size}px; height: ${size}px;"
|
||||
| alt="@${StringUtil.escapeHtml(userName)}" />""".stripMargin
|
||||
| alt="${StringUtil.escapeHtml(displayName)}" />""".stripMargin
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import gitbucket.core.service.{RepositoryService, RequestCache}
|
||||
import gitbucket.core.util.StringUtil
|
||||
import io.github.gitbucket.markedj._
|
||||
import io.github.gitbucket.markedj.Utils._
|
||||
import gitbucket.core.service.WikiService
|
||||
|
||||
object Markdown {
|
||||
|
||||
@@ -75,7 +76,8 @@ object Markdown {
|
||||
)(implicit val context: Context)
|
||||
extends Renderer(options)
|
||||
with LinkConverter
|
||||
with RequestCache {
|
||||
with RequestCache
|
||||
with WikiService {
|
||||
|
||||
override def heading(text: String, level: Int, raw: String): String = {
|
||||
val id = generateAnchorName(text)
|
||||
@@ -192,7 +194,16 @@ object Markdown {
|
||||
.stripSuffix(".git") + "/blob/" + branch + "/" + urlWithRawParam
|
||||
}
|
||||
} else {
|
||||
repository.httpUrl.replaceFirst("/git/", "/").stripSuffix(".git") + "/wiki/_blob/" + url
|
||||
// URL is being modified to link to the image file on the repository, but users may want to link to the page if the page name is a link.
|
||||
// If the wiki page cannot be retrieved from the url, the blob address is returned; otherwise, the page address is returned.
|
||||
val pathElems = context.currentPath.split("/")
|
||||
val owner = pathElems(1)
|
||||
val repos = pathElems(2)
|
||||
if (getWikiPage(owner, repos, url, branch) == None) {
|
||||
repository.httpUrl.replaceFirst("/git/", "/").stripSuffix(".git") + "/wiki/_blob/" + url
|
||||
} else {
|
||||
repository.httpUrl.replaceFirst("/git/", "/").stripSuffix(".git") + "/wiki/" + url
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,6 +101,7 @@ object helpers extends AvatarImageProvider with LinkConverter with RequestCache
|
||||
/**
|
||||
* Converts Markdown of Wiki pages to HTML.
|
||||
*/
|
||||
@deprecated("This doesn't apply render plugins. Should use renderMarkup() instead.", "4.45.0")
|
||||
def markdown(
|
||||
markdown: String,
|
||||
repository: RepositoryService.RepositoryInfo,
|
||||
@@ -139,14 +140,29 @@ object helpers extends AvatarImageProvider with LinkConverter with RequestCache
|
||||
repository: RepositoryService.RepositoryInfo,
|
||||
enableWikiLink: Boolean,
|
||||
enableRefsLink: Boolean,
|
||||
enableAnchor: Boolean
|
||||
enableAnchor: Boolean,
|
||||
enableLineBreaks: Boolean,
|
||||
enableTaskList: Boolean,
|
||||
hasWritePermission: Boolean = false
|
||||
)(implicit context: Context): Html = {
|
||||
|
||||
val fileName = filePath.last.toLowerCase
|
||||
val extension = FileUtil.getExtension(fileName)
|
||||
val renderer = PluginRegistry().getRenderer(extension)
|
||||
renderer.render(
|
||||
RenderRequest(filePath, fileContent, branch, repository, enableWikiLink, enableRefsLink, enableAnchor, context)
|
||||
RenderRequest(
|
||||
filePath,
|
||||
fileContent,
|
||||
branch,
|
||||
repository,
|
||||
enableWikiLink,
|
||||
enableRefsLink,
|
||||
enableAnchor,
|
||||
enableLineBreaks,
|
||||
enableTaskList,
|
||||
hasWritePermission,
|
||||
context
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -316,12 +332,30 @@ object helpers extends AvatarImageProvider with LinkConverter with RequestCache
|
||||
*/
|
||||
def assets(path: String)(implicit context: Context): String = s"${context.path}/assets${path}?${hashQuery}"
|
||||
|
||||
def displayUserName(userName: String, mailAddress: String = "")(implicit context: Context): String = {
|
||||
val displayName = if (!context.settings.showFullName) {
|
||||
userName
|
||||
} else {
|
||||
if (mailAddress.isEmpty) {
|
||||
getAccountByUserNameFromCache(userName).map(_.fullName).getOrElse(userName)
|
||||
} else {
|
||||
getAccountByMailAddressFromCache(mailAddress).map(_.fullName).getOrElse(userName)
|
||||
}
|
||||
}
|
||||
if (userName == displayName) {
|
||||
userName
|
||||
} else {
|
||||
s"$userName ($displayName)"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates the text link to the account page.
|
||||
* If user does not exist or disabled, this method returns user name as text without link.
|
||||
*/
|
||||
def user(userName: String, mailAddress: String = "", styleClass: String = "")(implicit context: Context): Html =
|
||||
userWithContent(userName, mailAddress, styleClass)(Html(StringUtil.escapeHtml(userName)))
|
||||
userWithContent(userName, mailAddress, styleClass)(Html(StringUtil.escapeHtml(displayUserName(userName, mailAddress))))
|
||||
|
||||
/**
|
||||
* Generates the avatar link to the account page.
|
||||
@@ -511,6 +545,18 @@ object helpers extends AvatarImageProvider with LinkConverter with RequestCache
|
||||
Html(sb.toString())
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to enable checkboxes
|
||||
*/
|
||||
def enableCheckbox(html: Html, enable: Boolean): Html = {
|
||||
if (enable) {
|
||||
val re = "(<input\\s+[^<>]*type=\"checkbox\"\\s+[^<>]*)\\s+disabled[^<>]*>".r
|
||||
Html(re.replaceAllIn(html.toString(), "$1>"))
|
||||
} else {
|
||||
html
|
||||
}
|
||||
}
|
||||
|
||||
case class CommentDiffLine(newLine: Option[String], oldLine: Option[String], `type`: String, text: String)
|
||||
|
||||
def appendQueryString(baseUrl: String, queryString: String): String = {
|
||||
|
||||
@@ -56,16 +56,16 @@ $(function(){
|
||||
|
||||
$('#addMember').click(function(){
|
||||
$('#error-members').text('');
|
||||
var userName = $('#memberName').val();
|
||||
const userName = $('#memberName').val();
|
||||
|
||||
// check empty
|
||||
if($.trim(userName) == ''){
|
||||
if($.trim(userName) === ''){
|
||||
return false;
|
||||
}
|
||||
|
||||
// check duplication
|
||||
var exists = $('#member-list li').filter(function(){
|
||||
return $(this).data('name') == userName;
|
||||
const exists = $('#member-list li').filter(function(){
|
||||
return $(this).data('name') === userName;
|
||||
}).length > 0;
|
||||
if(exists){
|
||||
$('#error-members').text('User has been already added.');
|
||||
@@ -75,7 +75,7 @@ $(function(){
|
||||
// check existence
|
||||
$.post('@context.path/_user/existence', { 'userName': userName },
|
||||
function(data, status){
|
||||
if(data == 'user'){
|
||||
if(data === 'user'){
|
||||
addMemberHTML(userName, false);
|
||||
$('#memberName').val('');
|
||||
} else {
|
||||
@@ -90,7 +90,7 @@ $(function(){
|
||||
|
||||
// Don't submit form by ENTER key
|
||||
$('#memberName').keypress(function(e){
|
||||
return !(e.keyCode == 13);
|
||||
return !(e.keyCode === 13);
|
||||
});
|
||||
|
||||
$('#delete').click(function(){
|
||||
@@ -102,11 +102,11 @@ $(function(){
|
||||
}
|
||||
|
||||
function addMemberHTML(userName, isManager){
|
||||
var memberButton = $('<label class="btn btn-default btn-mini"><input type="radio" value="false" name="' + userName + '">Member</label>');
|
||||
const memberButton = $('<label class="btn btn-default btn-mini"><input type="radio" value="false" name="' + userName + '">Member</label>');
|
||||
if(!isManager){
|
||||
memberButton.addClass('active');
|
||||
}
|
||||
var managerButton = $('<label class="btn btn-default btn-mini"><input type="radio" value="true" name="' + userName + '">Manager</label>');
|
||||
const managerButton = $('<label class="btn btn-default btn-mini"><input type="radio" value="true" name="' + userName + '">Manager</label>');
|
||||
if(isManager){
|
||||
managerButton.addClass('active');
|
||||
}
|
||||
@@ -123,8 +123,8 @@ $(function(){
|
||||
}
|
||||
|
||||
function updateMembers(){
|
||||
var members = $('#member-list li').map(function(i, e){
|
||||
var userName = $(e).data('name');
|
||||
const members = $('#member-list li').map(function(i, e){
|
||||
const userName = $(e).data('name');
|
||||
return userName + ':' + $(e).find('label.active input[type=radio]').attr('value');
|
||||
}).get().join(',');
|
||||
$('#members').val(members);
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
</li>
|
||||
@gitbucket.core.plugin.PluginRegistry().getSystemSettingMenus.map { menu =>
|
||||
@menu(context).map { link =>
|
||||
<li@if(active==link.id){ class="active"}>
|
||||
<li class="menu-item-hover @if(active==link.id){active}">
|
||||
<a href="@context.path/@link.path">
|
||||
<i class="menu-icon octicon octicon-@link.icon.getOrElse("plug")"></i>
|
||||
<span>@link.label</span>
|
||||
|
||||
@@ -253,6 +253,21 @@
|
||||
<input type="radio" name="showMailAddress" value="false"@if(!context.settings.showMailAddress){ checked}>
|
||||
<span class="strong">Hide</span> <span class="normal">- Hide mail address in user's profile page.</span>
|
||||
</label>
|
||||
</fieldset>
|
||||
<!--====================================================================-->
|
||||
<!-- Show full name -->
|
||||
<!--====================================================================-->
|
||||
<hr>
|
||||
<label class="strong">Username display on UI</label>
|
||||
<fieldset>
|
||||
<label class="radio">
|
||||
<input type="radio" name="showFullName" value="false"@if(!context.settings.showFullName){ checked}>
|
||||
<span class="strong">User name</span> <span class="normal">- Username is primarily displayed on UI.</span>
|
||||
</label>
|
||||
<label class="radio">
|
||||
<input type="radio" name="showFullName" value="true"@if(context.settings.showFullName){ checked}>
|
||||
<span class="strong">Full name</span> <span class="normal">- Fullname is primarily displayed instead of username on UI.</span>
|
||||
</label>
|
||||
</fieldset>
|
||||
<!--====================================================================-->
|
||||
<!-- File upload -->
|
||||
|
||||
@@ -25,20 +25,23 @@
|
||||
<a href="@context.path/admin/users/@account.userName/_edituser">Edit</a>
|
||||
}
|
||||
</div>
|
||||
<div class="strong">
|
||||
@helpers.avatarLink(account.userName, 20)
|
||||
@if(account.isRemoved){
|
||||
@account.userName
|
||||
} else {
|
||||
<a href="@helpers.url(account.userName)">@account.userName</a>
|
||||
}
|
||||
@if(account.isGroupAccount){
|
||||
(Group)
|
||||
} else {
|
||||
@if(account.isAdmin){
|
||||
(Administrator)
|
||||
<div>
|
||||
<span class="strong">
|
||||
@helpers.avatarLink(account.userName, 20)
|
||||
@if(account.isRemoved){
|
||||
@account.userName
|
||||
} else {
|
||||
(Normal)
|
||||
<a href="@helpers.url(account.userName)">@account.userName</a>
|
||||
}
|
||||
</span>
|
||||
@if(account.isGroupAccount){
|
||||
- Group
|
||||
} else {
|
||||
(@account.fullName)
|
||||
@if(account.isAdmin){
|
||||
- Administrator
|
||||
} else {
|
||||
- Normal
|
||||
}
|
||||
}
|
||||
@if(account.isGroupAccount){
|
||||
@@ -50,10 +53,10 @@
|
||||
<div>
|
||||
<hr>
|
||||
@if(!account.isGroupAccount){
|
||||
<i class="octicon octicon-mail"></i> @account.mailAddress
|
||||
<i class="octicon octicon-mail"></i>@account.mailAddress
|
||||
}
|
||||
@account.url.map { url =>
|
||||
<i class="octicon octicon-home"></i> @url
|
||||
<i class="octicon octicon-home"></i>@url
|
||||
}
|
||||
</div>
|
||||
<div>
|
||||
|
||||
@@ -21,16 +21,18 @@
|
||||
</span>
|
||||
</div>
|
||||
<div class="commit-commentContent-@comment.commentId">
|
||||
@helpers.markdown(
|
||||
markdown = comment.content,
|
||||
repository = repository,
|
||||
branch = repository.repository.defaultBranch,
|
||||
enableWikiLink = false,
|
||||
enableRefsLink = true,
|
||||
enableLineBreaks = true,
|
||||
enableTaskList = true,
|
||||
hasWritePermission = hasWritePermission
|
||||
)
|
||||
@helpers.renderMarkup(
|
||||
filePath = List("temporary.md"),
|
||||
fileContent = comment.content,
|
||||
branch = repository.repository.defaultBranch,
|
||||
repository = repository,
|
||||
enableWikiLink = false,
|
||||
enableRefsLink = true,
|
||||
enableAnchor = true,
|
||||
enableLineBreaks = true,
|
||||
enableTaskList = true,
|
||||
hasWritePermission = hasWritePermission
|
||||
)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -57,6 +57,7 @@ $(function(){
|
||||
$('#preview@uid').click(function(){
|
||||
$('#preview-area@uid').html('<img src="@helpers.assets("/common/images/indicator.gif")"> Previewing...');
|
||||
$.post('@helpers.url(repository)/_preview', {
|
||||
filename : "temporary.md",
|
||||
content : $('#content@uid').val(),
|
||||
enableWikiLink : @enableWikiLink,
|
||||
enableRefsLink : @enableRefsLink,
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
</a>
|
||||
</span>
|
||||
@if(comment.action != "commit" && comment.action != "merge" && comment.action != "refer"
|
||||
&& (isManageable || context.loginAccount.map(_.userName == comment.commentedUserName).getOrElse(false))){
|
||||
&& (isManageable || context.loginAccount.exists(_.userName == comment.commentedUserName))){
|
||||
<span class="pull-right">
|
||||
<a href="#" data-comment-id="@comment.commentId"><i class="octicon octicon-pencil" aria-label="Edit"></i></a>
|
||||
<a href="#" data-comment-id="@comment.commentId"><i class="octicon octicon-x" aria-label="Remove"></i></a>
|
||||
@@ -32,12 +32,14 @@
|
||||
}
|
||||
</div>
|
||||
<div class="panel-body markdown-body" id="commentContent-@comment.commentId">
|
||||
@helpers.markdown(
|
||||
markdown = comment.content,
|
||||
repository = repository,
|
||||
@helpers.renderMarkup(
|
||||
filePath = List("temporary.md"),
|
||||
fileContent = comment.content,
|
||||
branch = repository.repository.defaultBranch,
|
||||
repository = repository,
|
||||
enableWikiLink = false,
|
||||
enableRefsLink = true,
|
||||
enableAnchor = true,
|
||||
enableLineBreaks = true,
|
||||
enableTaskList = true,
|
||||
hasWritePermission = isManageable
|
||||
@@ -52,18 +54,20 @@
|
||||
@helpers.user(issue.get.openedUserName, styleClass="username strong")
|
||||
<span class="muted">commented @gitbucket.core.helper.html.datetimeago(issue.get.registeredDate)</span>
|
||||
<span class="pull-right">
|
||||
@if(isManageable || context.loginAccount.map(_.userName == issue.get.openedUserName).getOrElse(false)){
|
||||
@if(isManageable || context.loginAccount.exists(_.userName == issue.get.openedUserName)){
|
||||
<a href="#" data-issue-id="@issue.get.issueId"><i class="octicon octicon-pencil" aria-label="Edit"></i></a>
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
<div class="panel-body markdown-body" id="issueContent">
|
||||
@helpers.markdown(
|
||||
markdown = issue.get.content getOrElse "No description provided.",
|
||||
repository = repository,
|
||||
@helpers.renderMarkup(
|
||||
filePath = List("temporary.md"),
|
||||
fileContent = issue.get.content getOrElse "No description provided.",
|
||||
branch = repository.repository.defaultBranch,
|
||||
repository = repository,
|
||||
enableWikiLink = false,
|
||||
enableRefsLink = true,
|
||||
enableAnchor = true,
|
||||
enableLineBreaks = true,
|
||||
enableTaskList = true,
|
||||
hasWritePermission = isManageable
|
||||
@@ -331,12 +335,14 @@
|
||||
}
|
||||
</div>
|
||||
<div class="panel-body markdown-body commit-commentContent-@comment.commentId">
|
||||
@helpers.markdown(
|
||||
markdown = comment.content,
|
||||
repository = repository,
|
||||
@helpers.renderMarkup(
|
||||
filePath = List("temporary.md"),
|
||||
fileContent = comment.content,
|
||||
branch = repository.repository.defaultBranch,
|
||||
repository = repository,
|
||||
enableWikiLink = false,
|
||||
enableRefsLink = true,
|
||||
enableAnchor = true,
|
||||
enableLineBreaks = true,
|
||||
enableTaskList = true,
|
||||
hasWritePermission = isManageable
|
||||
@@ -400,7 +406,7 @@ $(function(){
|
||||
// diff view
|
||||
const tr = comment.closest('.not-diff');
|
||||
if(tr.length > 0){
|
||||
if(tr.prev('.not-diff').length == 0){
|
||||
if(tr.prev('.not-diff').length === 0){
|
||||
tr.next('.not-diff:has(.reply-comment)').remove();
|
||||
}
|
||||
tr.remove();
|
||||
@@ -410,7 +416,7 @@ $(function(){
|
||||
const panel = comment.closest('div.panel:has(.commit-comment-box)');
|
||||
if(panel.length > 0){
|
||||
comment.parent('.commit-comment-box').remove();
|
||||
if(panel.has('.commit-comment-box').length == 0){
|
||||
if(panel.has('.commit-comment-box').length === 0){
|
||||
panel.remove();
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
@gitbucket.core.html.menu("issues", repository){
|
||||
<div>
|
||||
<div class="show-title pull-right">
|
||||
@if(isManageable || context.loginAccount.map(_.userName == issue.openedUserName).getOrElse(false)){
|
||||
@if(isManageable || context.loginAccount.exists(_.userName == issue.openedUserName)){
|
||||
<a class="btn btn-default" href="#" id="edit">Edit</a>
|
||||
}
|
||||
@if(isEditable){
|
||||
|
||||
@@ -131,7 +131,7 @@
|
||||
@collaborators.map { collaborator =>
|
||||
<li>
|
||||
<a href="javascript:void(0);" class="toggle-assign" data-name="@collaborator">
|
||||
@gitbucket.core.helper.html.checkicon(issueAssignees.exists(_.assigneeUserName == collaborator))@helpers.avatar(collaborator, 20) @collaborator
|
||||
@gitbucket.core.helper.html.checkicon(issueAssignees.exists(_.assigneeUserName == collaborator))@helpers.avatar(collaborator, 20) @helpers.displayUserName(collaborator)
|
||||
</a>
|
||||
</li>
|
||||
}
|
||||
|
||||
@@ -83,7 +83,18 @@
|
||||
@defining(helpers.isRenderable(pathList.last)){ isRenderable =>
|
||||
@if(!isBlame && isRenderable) {
|
||||
<div class="box-content-bottom @if(content.viewType == "text"){ markdown-body } " style="padding-left: 20px; padding-right: 20px;">
|
||||
@helpers.renderMarkup(pathList, content.content.getOrElse(""), branch, repository, false, false, true)
|
||||
@helpers.renderMarkup(
|
||||
filePath = pathList,
|
||||
fileContent = content.content.getOrElse(""),
|
||||
branch = branch,
|
||||
repository = repository,
|
||||
enableWikiLink = false,
|
||||
enableRefsLink = false,
|
||||
enableAnchor = true,
|
||||
enableLineBreaks = false,
|
||||
enableTaskList = true,
|
||||
hasWritePermission = hasWritePermission
|
||||
)
|
||||
</div>
|
||||
}else{
|
||||
@if(content.viewType == "text"){
|
||||
|
||||
@@ -208,29 +208,31 @@ $(function(){
|
||||
$('#preview').show();
|
||||
$('#btn-code').removeClass('active');
|
||||
|
||||
@if(fileName.map(helpers.isRenderable _).getOrElse(false)) {
|
||||
// update preview
|
||||
$('#preview').html('<img src="@helpers.assets("/common/images/indicator.gif")"> Previewing...');
|
||||
$.post('@helpers.url(repository)/_preview', {
|
||||
content : editor.getValue(),
|
||||
enableWikiLink : false,
|
||||
filename : $('#newFileName').val(),
|
||||
enableRefsLink : false,
|
||||
enableLineBreaks : false,
|
||||
enableTaskList : false
|
||||
}, function(data){
|
||||
$('#preview').empty().append(
|
||||
$('<div class="markdown-body" style="padding-left: 20px; padding-right: 20px;">').html(data));
|
||||
prettyPrint();
|
||||
});
|
||||
} else {
|
||||
// Show diff
|
||||
$('#preview').empty()
|
||||
.append($('<div id="diffText">'))
|
||||
.append($('<textarea id="newText" style="display: none;">').data('file-name',$("#newFileName").val()).data('val', editor.getValue()))
|
||||
.append($('<textarea id="oldText" style="display: none;">').data('file-name',$("#oldFileName").val()).data('val', $('#initial').val()));
|
||||
diffUsingJS('oldText', 'newText', 'diffText', 1);
|
||||
}
|
||||
$.get("@context.baseUrl/_is_renderable?filename=" + encodeURIComponent($('#newFileName').val()), function(data) {
|
||||
if (data === 'true') {
|
||||
// update preview
|
||||
$('#preview').html('<img src="@helpers.assets("/common/images/indicator.gif")"> Previewing...');
|
||||
$.post('@helpers.url(repository)/_preview', {
|
||||
content : editor.getValue(),
|
||||
enableWikiLink : false,
|
||||
filename : $('#path').val() + '/' + $('#newFileName').val(),
|
||||
enableRefsLink : false,
|
||||
enableLineBreaks : false,
|
||||
enableTaskList : false
|
||||
}, function(data){
|
||||
$('#preview').empty().append(
|
||||
$('<div class="markdown-body" style="padding-left: 20px; padding-right: 20px;">').html(data));
|
||||
prettyPrint();
|
||||
});
|
||||
} else {
|
||||
// Show diff
|
||||
$('#preview').empty()
|
||||
.append($('<div id="diffText">'))
|
||||
.append($('<textarea id="newText" style="display: none;">').data('file-name',$("#newFileName").val()).data('val', editor.getValue()))
|
||||
.append($('<textarea id="oldText" style="display: none;">').data('file-name',$("#oldFileName").val()).data('val', $('#initial').val()));
|
||||
diffUsingJS('oldText', 'newText', 'diffText', 1);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -220,7 +220,7 @@
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-content-bottom markdown-body" style="padding-left: 20px; padding-right: 20px;">@helpers.renderMarkup(filePath, content, branch, repository, false, false, true)</div>
|
||||
<div class="box-content-bottom markdown-body" style="padding-left: 20px; padding-right: 20px;">@helpers.renderMarkup(filePath, content, branch, repository, false, false, false, true, true)</div>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,25 +48,25 @@ $(function(){
|
||||
});
|
||||
|
||||
$('.add').click(function(){
|
||||
var id = $(this).attr('id') == 'addCollaborator' ? 'collaborator' : 'group';
|
||||
const id = $(this).attr('id') === 'addCollaborator' ? 'collaborator' : 'group';
|
||||
|
||||
$('#error-' + id).text('');
|
||||
var userName = $('#userName-' + id).val();
|
||||
const userName = $('#userName-' + id).val();
|
||||
|
||||
// check empty
|
||||
if($.trim(userName) == ''){
|
||||
if($.trim(userName) === ''){
|
||||
return false;
|
||||
}
|
||||
|
||||
// check owner
|
||||
var owner = '@repository.owner' == userName
|
||||
const owner = '@repository.owner' === userName
|
||||
if(owner){
|
||||
$('#error-' + id).text('User is owner of this repository.');
|
||||
return false;
|
||||
}
|
||||
// check duplication
|
||||
var exists = $('#' + id + '-list li').filter(function(){
|
||||
return $(this).data('name') == userName;
|
||||
const exists = $('#' + id + '-list li').filter(function(){
|
||||
return $(this).data('name') === userName;
|
||||
}).length > 0;
|
||||
if(exists){
|
||||
$('#error-' + id).text('User has been already added.');
|
||||
@@ -76,7 +76,7 @@ $(function(){
|
||||
// check existence
|
||||
$.post('@context.path/_user/existence', { 'userName': userName },
|
||||
function(data, status){
|
||||
if(data != ''){
|
||||
if(data !== ''){
|
||||
addListHTML(userName, '@Role.ADMIN.name', '#' + id + '-list');
|
||||
$('#userName-' + id).val('');
|
||||
} else {
|
||||
@@ -91,7 +91,7 @@ $(function(){
|
||||
|
||||
// Don't submit form by ENTER key
|
||||
$('#userName-collaborator, #userName-group').keypress(function(e){
|
||||
return !(e.keyCode == 13);
|
||||
return !(e.keyCode === 13);
|
||||
});
|
||||
|
||||
@collaborators.map { case (collaborator, isGroup) =>
|
||||
@@ -99,16 +99,16 @@ $(function(){
|
||||
}
|
||||
|
||||
function addListHTML(userName, role, id){
|
||||
var adminButton = $('<label class="btn btn-default btn-mini"><input type="radio" value="@Role.ADMIN.name" name="' + userName + '">Admin</label>');
|
||||
if(role == '@Role.ADMIN.name'){
|
||||
const adminButton = $('<label class="btn btn-default btn-mini"><input type="radio" value="@Role.ADMIN.name" name="' + userName + '">Admin</label>');
|
||||
if(role === '@Role.ADMIN.name'){
|
||||
adminButton.addClass('active');
|
||||
}
|
||||
var writeButton = $('<label class="btn btn-default btn-mini"><input type="radio" value="@Role.DEVELOPER.name" name="' + userName + '">Developer</label>');
|
||||
if(role == '@Role.DEVELOPER.name'){
|
||||
const writeButton = $('<label class="btn btn-default btn-mini"><input type="radio" value="@Role.DEVELOPER.name" name="' + userName + '">Developer</label>');
|
||||
if(role === '@Role.DEVELOPER.name'){
|
||||
writeButton.addClass('active');
|
||||
}
|
||||
var readButton = $('<label class="btn btn-default btn-mini"><input type="radio" value="@Role.GUEST.name" name="' + userName + '">Guest</label>');
|
||||
if(role == '@Role.GUEST.name'){
|
||||
const readButton = $('<label class="btn btn-default btn-mini"><input type="radio" value="@Role.GUEST.name" name="' + userName + '">Guest</label>');
|
||||
if(role === '@Role.GUEST.name'){
|
||||
readButton.addClass('active');
|
||||
}
|
||||
|
||||
@@ -124,13 +124,13 @@ $(function(){
|
||||
}
|
||||
|
||||
function updateValues(){
|
||||
var collaborators = $('#collaborator-list li').map(function(i, e){
|
||||
var userName = $(e).data('name');
|
||||
const collaborators = $('#collaborator-list li').map(function(i, e){
|
||||
const userName = $(e).data('name');
|
||||
return userName + ':' + $(e).find('label.active input[type=radio]').attr('value');
|
||||
}).get().join(',');
|
||||
|
||||
var groups = $('#group-list li').map(function(i, e){
|
||||
var userName = $(e).data('name');
|
||||
const groups = $('#group-list li').map(function(i, e){
|
||||
const userName = $(e).data('name');
|
||||
return userName + ':' + $(e).find('label.active input[type=radio]').attr('value');
|
||||
}).get().join(',');
|
||||
|
||||
|
||||
@@ -59,7 +59,17 @@
|
||||
@if(isEditable){
|
||||
<a href="@helpers.url(repository)/wiki/_Sidebar/_edit" style="text-decoration: none;"><span class="octicon octicon-pencil pull-right"></span></a>
|
||||
}
|
||||
@helpers.markdown(sidebarPage.content, repository, "master", true, false, false, false, pages)
|
||||
@helpers.renderMarkup(
|
||||
filePath = sidebarPage.name.split("/").toList,
|
||||
fileContent = sidebarPage.content,
|
||||
branch = "master",
|
||||
repository = repository,
|
||||
enableWikiLink = true,
|
||||
enableRefsLink = false,
|
||||
enableAnchor = false,
|
||||
enableLineBreaks = false,
|
||||
enableTaskList = false
|
||||
)
|
||||
</div>
|
||||
}.getOrElse{
|
||||
@if(isEditable){
|
||||
@@ -82,16 +92,16 @@
|
||||
</div>
|
||||
<div class="wiki-main">
|
||||
<div class="markdown-body">
|
||||
@helpers.markdown(
|
||||
markdown = page.content,
|
||||
repository = repository,
|
||||
@helpers.renderMarkup(
|
||||
filePath = page.name.split("/").toList,
|
||||
fileContent = page.content,
|
||||
branch = "master",
|
||||
repository = repository,
|
||||
enableWikiLink = true,
|
||||
enableRefsLink = false,
|
||||
enableAnchor = true,
|
||||
enableLineBreaks = false,
|
||||
enableTaskList = false,
|
||||
hasWritePermission = false,
|
||||
pages = pages
|
||||
enableTaskList = false
|
||||
)
|
||||
</div>
|
||||
@footer.map { footerPage =>
|
||||
@@ -99,15 +109,16 @@
|
||||
@if(isEditable){
|
||||
<a href="@helpers.url(repository)/wiki/_Footer/_edit" style="text-decoration: none;"><span class="octicon octicon-pencil pull-right"></span></a>
|
||||
}
|
||||
@helpers.markdown(
|
||||
markdown = footerPage.content,
|
||||
repository = repository,
|
||||
branch = "master",
|
||||
enableWikiLink = true,
|
||||
enableRefsLink = false,
|
||||
@helpers.renderMarkup(
|
||||
filePath = footerPage.name.split("/").toList,
|
||||
fileContent = footerPage.content,
|
||||
branch = "master",
|
||||
repository = repository,
|
||||
enableWikiLink = true,
|
||||
enableRefsLink = false,
|
||||
enableAnchor = false,
|
||||
enableLineBreaks = false,
|
||||
enableAnchor = false,
|
||||
pages = pages
|
||||
enableTaskList = false
|
||||
)
|
||||
</div>
|
||||
}.getOrElse{
|
||||
|
||||
@@ -1536,7 +1536,6 @@ div.markdown-body table th,
|
||||
div.markdown-body table td {
|
||||
padding: 8px;
|
||||
line-height: 20px;
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
border-top: 1px solid #dddddd;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
package gitbucket.core
|
||||
|
||||
import java.sql.DriverManager
|
||||
|
||||
import com.dimafeng.testcontainers.{MySQLContainer, PostgreSQLContainer}
|
||||
import io.github.gitbucket.solidbase.Solidbase
|
||||
import io.github.gitbucket.solidbase.model.Module
|
||||
import liquibase.database.core.{H2Database, MySQLDatabase, PostgresDatabase}
|
||||
import org.junit.runner.Description
|
||||
import org.scalatest.funsuite.AnyFunSuite
|
||||
import org.scalatest.Tag
|
||||
import org.testcontainers.postgresql.PostgreSQLContainer
|
||||
import org.testcontainers.mysql.MySQLContainer
|
||||
import org.testcontainers.utility.DockerImageName
|
||||
|
||||
object ExternalDBTest extends Tag("ExternalDBTest")
|
||||
@@ -26,24 +26,19 @@ class GitBucketCoreModuleSpec extends AnyFunSuite {
|
||||
|
||||
implicit private val suiteDescription: Description = Description.createSuiteDescription(getClass)
|
||||
|
||||
Seq("8.0", "5.7").foreach { tag =>
|
||||
Seq("8.4", "5.7").foreach { tag =>
|
||||
test(s"Migration MySQL $tag", ExternalDBTest) {
|
||||
val container = new MySQLContainer() {
|
||||
override val container: org.testcontainers.containers.MySQLContainer[?] =
|
||||
new org.testcontainers.containers.MySQLContainer(s"mysql:$tag") {
|
||||
override def getDriverClassName = "org.mariadb.jdbc.Driver"
|
||||
override def getJdbcUrl: String = super.getJdbcUrl + "?permitMysqlScheme"
|
||||
}
|
||||
// TODO https://jira.mariadb.org/browse/CONJ-663
|
||||
container.withCommand("mysqld --default-authentication-plugin=mysql_native_password")
|
||||
val container = new MySQLContainer(s"mysql:$tag") {
|
||||
override def getDriverClassName = "org.mariadb.jdbc.Driver"
|
||||
override def getJdbcUrl: String = super.getJdbcUrl + "?permitMysqlScheme"
|
||||
}
|
||||
container.start()
|
||||
try {
|
||||
new Solidbase().migrate(
|
||||
DriverManager.getConnection(
|
||||
container.jdbcUrl,
|
||||
container.username,
|
||||
container.password
|
||||
container.getJdbcUrl,
|
||||
container.getUsername,
|
||||
container.getPassword
|
||||
),
|
||||
Thread.currentThread().getContextClassLoader(),
|
||||
new MySQLDatabase(),
|
||||
@@ -57,12 +52,12 @@ class GitBucketCoreModuleSpec extends AnyFunSuite {
|
||||
|
||||
Seq("11", "10").foreach { tag =>
|
||||
test(s"Migration PostgreSQL $tag", ExternalDBTest) {
|
||||
val container = PostgreSQLContainer(DockerImageName.parse(s"postgres:$tag"))
|
||||
val container = new PostgreSQLContainer(DockerImageName.parse(s"postgres:$tag"))
|
||||
|
||||
container.start()
|
||||
try {
|
||||
new Solidbase().migrate(
|
||||
DriverManager.getConnection(container.jdbcUrl, container.username, container.password),
|
||||
DriverManager.getConnection(container.getJdbcUrl, container.getUsername, container.getPassword),
|
||||
Thread.currentThread().getContextClassLoader(),
|
||||
new PostgresDatabase(),
|
||||
new Module(GitBucketCoreModule.getModuleId, GitBucketCoreModule.getVersions)
|
||||
|
||||
@@ -85,7 +85,8 @@ trait ServiceSpecBase {
|
||||
maxDiffFiles = 100,
|
||||
maxDiffLines = 1000
|
||||
),
|
||||
defaultBranch = "main"
|
||||
defaultBranch = "main",
|
||||
showFullName = false
|
||||
)
|
||||
|
||||
def withTestDB[A](action: (Session) => A): A = {
|
||||
|
||||
@@ -107,7 +107,7 @@ class AvatarImageProviderSpec extends AnyFunSpec {
|
||||
provider.toHtml("user", 20, "hoge@hoge.com", true).toString ==
|
||||
"""<img src="/_unknown/_avatar" class="avatar-mini" style="width: 20px; height: 20px;"
|
||||
| alt="@user"
|
||||
| data-toggle="tooltip" title="user" />""".stripMargin
|
||||
| data-toggle="tooltip" title="@user" />""".stripMargin
|
||||
)
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ class AvatarImageProviderSpec extends AnyFunSpec {
|
||||
provider.toHtml("""<user>"<name>""", 20, "hoge@hoge.com", true).toString ==
|
||||
"""<img src="/_unknown/_avatar" class="avatar-mini" style="width: 20px; height: 20px;"
|
||||
| alt="@<user>"<name>"
|
||||
| data-toggle="tooltip" title="<user>"<name>" />""".stripMargin
|
||||
| data-toggle="tooltip" title="@<user>"<name>" />""".stripMargin
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -196,7 +196,8 @@ class AvatarImageProviderSpec extends AnyFunSpec {
|
||||
maxDiffFiles = 100,
|
||||
maxDiffLines = 1000
|
||||
),
|
||||
"main"
|
||||
defaultBranch = "main",
|
||||
showFullName = false
|
||||
)
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user