diff --git a/.travis.yml b/.travis.yml index ff18003..b901b6c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,8 @@ jdk: - oraclejdk8 - oraclejdk11 + - openjdk8 + - openjdk11 script: - sbt scalafmtSbtCheck scalafmtCheck test:scalafmtCheck test before_script: diff --git a/build.sbt b/build.sbt index ad28306..abd1554 100644 --- a/build.sbt +++ b/build.sbt @@ -5,7 +5,7 @@ val Name = "gitbucket" val GitBucketVersion = "4.30.0-SNAPSHOT" val ScalatraVersion = "2.6.3" -val JettyVersion = "9.4.11.v20180605" +val JettyVersion = "9.4.14.v20181114" val JgitVersion = "5.1.3.201810200350-r" lazy val root = (project in file(".")) @@ -36,14 +36,14 @@ "org.scalatra" %% "scalatra" % ScalatraVersion, "org.scalatra" %% "scalatra-json" % ScalatraVersion, "org.scalatra" %% "scalatra-forms" % ScalatraVersion, - "org.json4s" %% "json4s-jackson" % "3.5.4", + "org.json4s" %% "json4s-jackson" % "3.6.2", "commons-io" % "commons-io" % "2.6", - "io.github.gitbucket" % "solidbase" % "1.0.2", + "io.github.gitbucket" % "solidbase" % "1.0.3", "io.github.gitbucket" % "markedj" % "1.0.15", "org.apache.commons" % "commons-compress" % "1.18", "org.apache.commons" % "commons-email" % "1.5", "org.apache.httpcomponents" % "httpclient" % "4.5.6", - "org.apache.sshd" % "apache-sshd" % "1.7.0" exclude ("org.slf4j", "slf4j-jdk14"), + "org.apache.sshd" % "apache-sshd" % "2.1.0" exclude ("org.slf4j", "slf4j-jdk14") exclude ("org.apache.sshd", "sshd-mina") exclude ("org.apache.sshd", "sshd-netty"), "org.apache.tika" % "tika-core" % "1.19.1", "com.github.takezoe" %% "blocking-slick-32" % "0.0.11", "com.novell.ldap" % "jldap" % "2009-10-07", @@ -51,13 +51,13 @@ "org.mariadb.jdbc" % "mariadb-java-client" % "2.3.0", "org.postgresql" % "postgresql" % "42.2.5", "ch.qos.logback" % "logback-classic" % "1.2.3", - "com.zaxxer" % "HikariCP" % "2.7.9", + "com.zaxxer" % "HikariCP" % "3.2.0", "com.typesafe" % "config" % "1.3.3", - "com.typesafe.akka" %% "akka-actor" % "2.5.17", + "com.typesafe.akka" %% "akka-actor" % "2.5.18", "fr.brouillard.oss.security.xhub" % "xhub4j-core" % "1.0.0", "com.github.bkromhout" % "java-diff-utils" % "2.1.1", - "org.cache2k" % "cache2k-all" % "1.0.2.Final", - "com.enragedginger" %% "akka-quartz-scheduler" % "1.7.0-akka-2.5.x" exclude ("c3p0", "c3p0"), + "org.cache2k" % "cache2k-all" % "1.2.0.Final", + "com.enragedginger" %% "akka-quartz-scheduler" % "1.7.0-akka-2.5.x" exclude ("c3p0", "c3p0") exclude ("com.zaxxer", "HikariCP-java6"), "net.coobird" % "thumbnailator" % "0.4.8", "com.github.zafarkhaja" % "java-semver" % "0.9.0", "com.nimbusds" % "oauth2-oidc-sdk" % "5.64.4", @@ -65,12 +65,12 @@ "javax.servlet" % "javax.servlet-api" % "3.1.0" % "provided", "junit" % "junit" % "4.12" % "test", "org.scalatra" %% "scalatra-scalatest" % ScalatraVersion % "test", - "org.mockito" % "mockito-core" % "2.23.0" % "test", - "com.wix" % "wix-embedded-mysql" % "3.0.0" % "test", - "ru.yandex.qatools.embed" % "postgresql-embedded" % "2.9" % "test", + "org.mockito" % "mockito-core" % "2.23.4" % "test", + "com.wix" % "wix-embedded-mysql" % "4.2.0" % "test", + "ru.yandex.qatools.embed" % "postgresql-embedded" % "2.10" % "test", "net.i2p.crypto" % "eddsa" % "0.3.0", "is.tagomor.woothee" % "woothee-java" % "1.8.0", - "org.ec4j.core" % "ec4j-core" % "0.0.1" + "org.ec4j.core" % "ec4j-core" % "0.0.3" ) // Compiler settings diff --git a/project/plugins.sbt b/project/plugins.sbt index 6d6b112..11c1511 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -2,8 +2,9 @@ addSbtPlugin("com.geirsson" % "sbt-scalafmt" % "1.5.0") addSbtPlugin("com.typesafe.sbt" % "sbt-twirl" % "1.3.15") -addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.8") -addSbtPlugin("org.scalatra.sbt" % "sbt-scalatra" % "1.0.1") +addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.9") +addSbtPlugin("org.scalatra.sbt" % "sbt-scalatra" % "1.0.3") addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.2") addSbtCoursier -addSbtPlugin("com.typesafe.sbt" % "sbt-license-report" % "1.2.0") +addSbtPlugin("com.typesafe.sbt" % "sbt-license-report" % "1.2.0") +addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.9.2") diff --git a/src/main/scala/gitbucket/core/controller/AccountController.scala b/src/main/scala/gitbucket/core/controller/AccountController.scala index b04ce63..005aa8a 100644 --- a/src/main/scala/gitbucket/core/controller/AccountController.scala +++ b/src/main/scala/gitbucket/core/controller/AccountController.scala @@ -421,7 +421,7 @@ redirect(s"/${userName}/_application") }) - get("/:userName/_hooks")(oneselfOnly { + get("/:userName/_hooks")(managersOnly { val userName = params("userName") getAccountByUserName(userName).map { account => gitbucket.core.account.html.hooks(account, getAccountWebHooks(account.userName), flash.get("info")) @@ -431,7 +431,7 @@ /** * Display the account web hook edit page. */ - get("/:userName/_hooks/new")(oneselfOnly { + get("/:userName/_hooks/new")(managersOnly { val userName = params("userName") getAccountByUserName(userName).map { account => val webhook = AccountWebHook(userName, "", WebHookContentType.FORM, None) @@ -442,7 +442,7 @@ /** * Add the account web hook URL. */ - post("/:userName/_hooks/new", accountWebHookForm(false))(oneselfOnly { form => + post("/:userName/_hooks/new", accountWebHookForm(false))(managersOnly { form => val userName = params("userName") addAccountWebHook(userName, form.url, form.events, form.ctype, form.token) flash += "info" -> s"Webhook ${form.url} created" @@ -452,7 +452,7 @@ /** * Delete the account web hook URL. */ - get("/:userName/_hooks/delete")(oneselfOnly { + get("/:userName/_hooks/delete")(managersOnly { val userName = params("userName") deleteAccountWebHook(userName, params("url")) flash += "info" -> s"Webhook ${params("url")} deleted" @@ -462,7 +462,7 @@ /** * Display the account web hook edit page. */ - get("/:userName/_hooks/edit")(oneselfOnly { + get("/:userName/_hooks/edit")(managersOnly { val userName = params("userName") getAccountByUserName(userName).flatMap { account => getAccountWebHook(userName, params("url")).map { @@ -475,7 +475,7 @@ /** * Update account web hook settings. */ - post("/:userName/_hooks/edit", accountWebHookForm(true))(oneselfOnly { form => + post("/:userName/_hooks/edit", accountWebHookForm(true))(managersOnly { form => val userName = params("userName") updateAccountWebHook(userName, form.url, form.events, form.ctype, form.token) flash += "info" -> s"webhook ${form.url} updated" @@ -485,7 +485,7 @@ /** * Send the test request to registered account web hook URLs. */ - ajaxPost("/:userName/_hooks/test")(oneselfOnly { + ajaxPost("/:userName/_hooks/test")(managersOnly { // TODO Is it possible to merge with [[RepositorySettingsController.ajaxPost]]? import scala.concurrent.duration._ import scala.concurrent._ diff --git a/src/main/scala/gitbucket/core/controller/IssuesController.scala b/src/main/scala/gitbucket/core/controller/IssuesController.scala index 514564a..2c2fa68 100644 --- a/src/main/scala/gitbucket/core/controller/IssuesController.scala +++ b/src/main/scala/gitbucket/core/controller/IssuesController.scala @@ -257,6 +257,7 @@ "content" -> Markdown.toHtml( markdown = x.content getOrElse "No description given.", repository = repository, + branch = repository.repository.defaultBranch, enableWikiLink = false, enableRefsLink = true, enableAnchor = true, @@ -284,6 +285,7 @@ "content" -> view.Markdown.toHtml( markdown = x.content, repository = repository, + branch = repository.repository.defaultBranch, enableWikiLink = false, enableRefsLink = true, enableAnchor = true, diff --git a/src/main/scala/gitbucket/core/controller/PreProcessController.scala b/src/main/scala/gitbucket/core/controller/PreProcessController.scala index 50023c4..9e21ecc 100644 --- a/src/main/scala/gitbucket/core/controller/PreProcessController.scala +++ b/src/main/scala/gitbucket/core/controller/PreProcessController.scala @@ -1,5 +1,6 @@ package gitbucket.core.controller +import gitbucket.core.plugin.PluginRegistry import org.scalatra.MovedPermanently class PreProcessController extends PreProcessControllerBase @@ -30,7 +31,10 @@ */ get(!context.settings.allowAnonymousAccess, context.loginAccount.isEmpty) { if (!context.currentPath.startsWith("/assets") && !context.currentPath.startsWith("/signin") && - !context.currentPath.startsWith("/register") && !context.currentPath.endsWith("/info/refs")) { + !context.currentPath.startsWith("/register") && !context.currentPath.endsWith("/info/refs") && + !PluginRegistry().getAnonymousAccessiblePaths().exists { path => + context.currentPath.startsWith(path) + }) { Unauthorized() } else { pass() diff --git a/src/main/scala/gitbucket/core/controller/RepositorySettingsController.scala b/src/main/scala/gitbucket/core/controller/RepositorySettingsController.scala index 521a10a..4dc1dc0 100644 --- a/src/main/scala/gitbucket/core/controller/RepositorySettingsController.scala +++ b/src/main/scala/gitbucket/core/controller/RepositorySettingsController.scala @@ -512,10 +512,10 @@ private def mergeOptions = new ValueType[Seq[String]] { override def convert(name: String, params: Map[String, Seq[String]], messages: Messages): Seq[String] = { - params.get("mergeOptions").getOrElse(Nil) + params.getOrElse("mergeOptions", Nil) } override def validate(name: String, params: Map[String, Seq[String]], messages: Messages): Seq[(String, String)] = { - val mergeOptions = params.get("mergeOptions").getOrElse(Nil) + val mergeOptions = params.getOrElse("mergeOptions", Nil) if (mergeOptions.isEmpty) { Seq("mergeOptions" -> "At least one option must be enabled.") } else if (!mergeOptions.forall(x => Seq("merge-commit", "squash", "rebase").contains(x))) { diff --git a/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala b/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala index 49cecce..e8b9288 100644 --- a/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala +++ b/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala @@ -174,7 +174,7 @@ helpers.renderMarkup( filePath = List(f), fileContent = params("content"), - branch = "master", + branch = repository.repository.defaultBranch, repository = repository, enableWikiLink = params("enableWikiLink").toBoolean, enableRefsLink = params("enableRefsLink").toBoolean, @@ -184,6 +184,7 @@ helpers.markdown( markdown = params("content"), repository = repository, + branch = repository.repository.defaultBranch, enableWikiLink = params("enableWikiLink").toBoolean, enableRefsLink = params("enableRefsLink").toBoolean, enableLineBreaks = params("enableLineBreaks").toBoolean, @@ -679,6 +680,7 @@ "content" -> view.Markdown.toHtml( markdown = x.content, repository = repository, + branch = repository.repository.defaultBranch, enableWikiLink = false, enableRefsLink = true, enableAnchor = true, @@ -943,18 +945,19 @@ path: String ) = { def archive(revision: String, archiveFormat: String, archive: ArchiveOutputStream)( - entryCreator: (String, Long, Int) => ArchiveEntry + entryCreator: (String, Long, java.util.Date, Int) => ArchiveEntry ): Unit = { using(Git.open(getRepositoryDir(repository.owner, repository.name))) { git => val oid = git.getRepository.resolve(revision) - val revCommit = JGitUtil.getRevCommitFromId(git, oid) + val commit = JGitUtil.getRevCommitFromId(git, oid) + val date = commit.getCommitterIdent.getWhen val sha1 = oid.getName() val repositorySuffix = (if (sha1.startsWith(revision)) sha1 else revision).replace('/', '-') val pathSuffix = if (path.isEmpty) "" else '-' + path.replace('/', '-') val baseName = repository.name + "-" + repositorySuffix + pathSuffix using(new TreeWalk(git.getRepository)) { treeWalk => - treeWalk.addTree(revCommit.getTree) + treeWalk.addTree(commit.getTree) treeWalk.setRecursive(true) if (!path.isEmpty) { treeWalk.setFilter(PathFilter.create(path)) @@ -966,8 +969,8 @@ else path.split("/").last + treeWalk.getPathString.substring(path.length) val size = JGitUtil.getFileSize(git, repository, treeWalk) val mode = treeWalk.getFileMode.getBits - val entry: ArchiveEntry = entryCreator(entryPath, size, mode) - JGitUtil.openFile(git, repository, revCommit.getTree, treeWalk.getPathString) { in => + val entry: ArchiveEntry = entryCreator(entryPath, size, date, mode) + JGitUtil.openFile(git, repository, commit.getTree, treeWalk.getPathString) { in => archive.putArchiveEntry(entry) IOUtils.copy(in, archive) archive.closeArchiveEntry() @@ -992,10 +995,11 @@ contentType = "application/octet-stream" response.setBufferSize(1024 * 1024) using(new ZipArchiveOutputStream(response.getOutputStream)) { zip => - archive(revision, ".zip", zip) { (path, size, mode) => + archive(revision, ".zip", zip) { (path, size, date, mode) => val entry = new ZipArchiveEntry(path) entry.setSize(size) entry.setUnixMode(mode) + entry.setTime(date.getTime) entry } } @@ -1016,9 +1020,10 @@ tar.setBigNumberMode(TarArchiveOutputStream.BIGNUMBER_STAR) tar.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU) tar.setAddPaxHeadersForNonAsciiNames(true) - archive(revision, ".tar.gz", tar) { (path, size, mode) => + archive(revision, ".tar.gz", tar) { (path, size, date, mode) => val entry = new TarArchiveEntry(path) entry.setSize(size) + entry.setModTime(date) entry.setMode(mode) entry } diff --git a/src/main/scala/gitbucket/core/plugin/Plugin.scala b/src/main/scala/gitbucket/core/plugin/Plugin.scala index 92a51ea..e5ccb59 100644 --- a/src/main/scala/gitbucket/core/plugin/Plugin.scala +++ b/src/main/scala/gitbucket/core/plugin/Plugin.scala @@ -8,7 +8,7 @@ import gitbucket.core.service.SystemSettingsService.SystemSettings import gitbucket.core.util.SyntaxSugars._ import io.github.gitbucket.solidbase.model.Version -import org.apache.sshd.server.Command +import org.apache.sshd.server.command.Command import play.twirl.api.Html /** @@ -48,6 +48,20 @@ ): Seq[(String, ControllerBase)] = Nil /** + * Override to declare this plug-in provides anonymous accessible paths. + */ + val anonymousAccessiblePaths: Seq[String] = Nil + + /** + * Override to declare this plug-in provides anonymous accessible paths. + */ + def anonymousAccessiblePaths( + registry: PluginRegistry, + context: ServletContext, + settings: SystemSettings + ): Seq[String] = Nil + + /** * Override to declare this plug-in provides JavaScript. */ val javaScripts: Seq[(String, String)] = Nil @@ -333,6 +347,10 @@ case (path, controller) => registry.addController(path, controller) } + (anonymousAccessiblePaths ++ anonymousAccessiblePaths(registry, context, settings)).foreach { + case (path) => + registry.addAnonymousAccessiblePath(path) + } (javaScripts ++ javaScripts(registry, context, settings)).foreach { case (path, script) => registry.addJavaScript(path, script) diff --git a/src/main/scala/gitbucket/core/plugin/PluginRegistry.scala b/src/main/scala/gitbucket/core/plugin/PluginRegistry.scala index 6964732..a68a9b3 100644 --- a/src/main/scala/gitbucket/core/plugin/PluginRegistry.scala +++ b/src/main/scala/gitbucket/core/plugin/PluginRegistry.scala @@ -1,6 +1,6 @@ package gitbucket.core.plugin -import java.io.{File, FilenameFilter, InputStream} +import java.io.{File, FilenameFilter} import java.net.URLClassLoader import java.nio.file.{Files, Paths, StandardWatchEventKinds} import java.util.Base64 @@ -15,7 +15,6 @@ import gitbucket.core.service.RepositoryService.RepositoryInfo import gitbucket.core.service.SystemSettingsService import gitbucket.core.service.SystemSettingsService.SystemSettings -import gitbucket.core.util.SyntaxSugars._ import gitbucket.core.util.DatabaseConfig import gitbucket.core.util.Directory._ import gitbucket.core.util.HttpClientUtil._ @@ -24,7 +23,7 @@ import io.github.gitbucket.solidbase.model.Module import org.apache.commons.io.FileUtils import org.apache.http.client.methods.HttpGet -import org.apache.sshd.server.Command +import org.apache.sshd.server.command.Command import org.slf4j.LoggerFactory import play.twirl.api.Html @@ -35,6 +34,7 @@ private val plugins = new ConcurrentLinkedQueue[PluginInfo] private val javaScripts = new ConcurrentLinkedQueue[(String, String)] private val controllers = new ConcurrentLinkedQueue[(ControllerBase, String)] + private val anonymousAccessiblePaths = new ConcurrentLinkedQueue[String] private val images = new ConcurrentHashMap[String, String] private val renderers = new ConcurrentHashMap[String, Renderer] renderers.put("md", MarkdownRenderer) @@ -70,25 +70,16 @@ images.put(id, encoded) } - @deprecated("Use addImage(id: String, bytes: Array[Byte]) instead", "3.4.0") - def addImage(id: String, in: InputStream): Unit = { - val bytes = using(in) { in => - val bytes = new Array[Byte](in.available) - in.read(bytes) - bytes - } - addImage(id, bytes) - } - def getImage(id: String): String = images.get(id) def addController(path: String, controller: ControllerBase): Unit = controllers.add((controller, path)) - @deprecated("Use addController(path: String, controller: ControllerBase) instead", "3.4.0") - def addController(controller: ControllerBase, path: String): Unit = addController(path, controller) - def getControllers(): Seq[(ControllerBase, String)] = controllers.asScala.toSeq + def addAnonymousAccessiblePath(path: String): Unit = anonymousAccessiblePaths.add(path) + + def getAnonymousAccessiblePaths(): Seq[String] = anonymousAccessiblePaths.asScala.toSeq + def addJavaScript(path: String, script: String): Unit = javaScripts.add((path, script)) //javaScripts += ((path, script)) diff --git a/src/main/scala/gitbucket/core/plugin/Renderer.scala b/src/main/scala/gitbucket/core/plugin/Renderer.scala index 6c4037b..5a78705 100644 --- a/src/main/scala/gitbucket/core/plugin/Renderer.scala +++ b/src/main/scala/gitbucket/core/plugin/Renderer.scala @@ -25,6 +25,7 @@ Markdown.toHtml( markdown = fileContent, repository = repository, + branch = branch, enableWikiLink = enableWikiLink, enableRefsLink = enableRefsLink, enableAnchor = enableAnchor, diff --git a/src/main/scala/gitbucket/core/ssh/GitCommand.scala b/src/main/scala/gitbucket/core/ssh/GitCommand.scala index 19dcdbf..8e8cfe5 100644 --- a/src/main/scala/gitbucket/core/ssh/GitCommand.scala +++ b/src/main/scala/gitbucket/core/ssh/GitCommand.scala @@ -6,7 +6,7 @@ import gitbucket.core.servlet.{CommitLogHook, Database} import gitbucket.core.util.{SyntaxSugars, Directory} import org.apache.sshd.server.{Environment, ExitCallback, SessionAware} -import org.apache.sshd.server.{Command, CommandFactory} +import org.apache.sshd.server.command.{Command, CommandFactory} import org.apache.sshd.server.session.ServerSession import org.slf4j.LoggerFactory import java.io.{File, InputStream, OutputStream} @@ -16,7 +16,7 @@ import Directory._ import gitbucket.core.ssh.PublicKeyAuthenticator.AuthType import org.eclipse.jgit.transport.{ReceivePack, UploadPack} -import org.apache.sshd.server.scp.UnknownCommand +import org.apache.sshd.server.shell.UnknownCommand import org.eclipse.jgit.errors.RepositoryNotFoundException object GitCommand { diff --git a/src/main/scala/gitbucket/core/ssh/NoShell.scala b/src/main/scala/gitbucket/core/ssh/NoShell.scala index 35f276a..b350e26 100644 --- a/src/main/scala/gitbucket/core/ssh/NoShell.scala +++ b/src/main/scala/gitbucket/core/ssh/NoShell.scala @@ -3,7 +3,7 @@ import gitbucket.core.service.SystemSettingsService.SshAddress import org.apache.sshd.common.Factory import org.apache.sshd.server.{Environment, ExitCallback} -import org.apache.sshd.server.Command +import org.apache.sshd.server.command.Command import java.io.{OutputStream, InputStream} import org.eclipse.jgit.lib.Constants diff --git a/src/main/scala/gitbucket/core/util/Authenticator.scala b/src/main/scala/gitbucket/core/util/Authenticator.scala index 7dd8fd5..b226509 100644 --- a/src/main/scala/gitbucket/core/util/Authenticator.scala +++ b/src/main/scala/gitbucket/core/util/Authenticator.scala @@ -161,6 +161,8 @@ private def authenticate(action: => Any) = { context.loginAccount match { + case Some(x) if x.isAdmin => action + case Some(x) if x.userName == request.paths(0) => action case Some(x) if (getGroupMembers(request.paths(0)).exists { member => member.userName == x.userName && member.isManager }) => diff --git a/src/main/scala/gitbucket/core/util/SyntaxSugars.scala b/src/main/scala/gitbucket/core/util/SyntaxSugars.scala index 2ede323..cc3ad41 100644 --- a/src/main/scala/gitbucket/core/util/SyntaxSugars.scala +++ b/src/main/scala/gitbucket/core/util/SyntaxSugars.scala @@ -65,7 +65,7 @@ implicit class HeadValueAccessibleMap(map: Map[String, Seq[String]]) { def value(key: String): String = map(key).head def optionValue(key: String): Option[String] = map.get(key).flatMap(_.headOption) - def values(key: String): Seq[String] = map.get(key).getOrElse(Seq.empty) + def values(key: String): Seq[String] = map.getOrElse(key, Seq.empty) } } diff --git a/src/main/scala/gitbucket/core/view/Markdown.scala b/src/main/scala/gitbucket/core/view/Markdown.scala index 4eac137..989a668 100644 --- a/src/main/scala/gitbucket/core/view/Markdown.scala +++ b/src/main/scala/gitbucket/core/view/Markdown.scala @@ -16,6 +16,7 @@ * Converts Markdown of Wiki pages to HTML. * * @param repository the repository which contains the markdown + * @param branch the target branch * @param enableWikiLink if true then wiki style link is available in markdown * @param enableRefsLink if true then issue reference (e.g. #123) is rendered as link * @param enableAnchor if true then anchor for headline is generated @@ -27,6 +28,7 @@ def toHtml( markdown: String, repository: RepositoryService.RepositoryInfo, + branch: String, enableWikiLink: Boolean, enableRefsLink: Boolean, enableAnchor: Boolean, @@ -45,6 +47,7 @@ val renderer = new GitBucketMarkedRenderer( options, repository, + branch, enableWikiLink, enableRefsLink, enableAnchor, @@ -62,6 +65,7 @@ class GitBucketMarkedRenderer( options: Options, repository: RepositoryService.RepositoryInfo, + branch: String, enableWikiLink: Boolean, enableRefsLink: Boolean, enableAnchor: Boolean, @@ -131,11 +135,11 @@ } override def link(href: String, title: String, text: String): String = { - super.link(fixUrl(href, false), title, text) + super.link(fixUrl(href, branch, false), title, text) } override def image(href: String, title: String, text: String): String = { - super.image(fixUrl(href, true), title, text) + super.image(fixUrl(href, branch, true), title, text) } override def nolink(text: String): String = { @@ -162,7 +166,7 @@ } } - private def fixUrl(url: String, isImage: Boolean = false): String = { + private def fixUrl(url: String, branch: String, isImage: Boolean = false): String = { lazy val urlWithRawParam: String = url + (if (isImage && !url.endsWith("?raw=true")) "?raw=true" else "") if (url.startsWith("http://") || url.startsWith("https://") || url.startsWith("mailto:") || url.startsWith("/")) { @@ -172,13 +176,7 @@ } else if (!enableWikiLink) { if (context.currentPath.contains("/blob/")) { urlWithRawParam - } else if (context.currentPath.contains("/tree/")) { - val paths = context.currentPath.split("/") - val branch = if (paths.length > 3) paths.drop(4).mkString("/") else repository.repository.defaultBranch - repository.httpUrl.replaceFirst("/git/", "/").stripSuffix(".git") + "/blob/" + branch + "/" + urlWithRawParam } else { - val paths = context.currentPath.split("/") - val branch = if (paths.length > 3) paths.last else repository.repository.defaultBranch repository.httpUrl.replaceFirst("/git/", "/").stripSuffix(".git") + "/blob/" + branch + "/" + urlWithRawParam } } else { diff --git a/src/main/scala/gitbucket/core/view/helpers.scala b/src/main/scala/gitbucket/core/view/helpers.scala index ab7d5bd..5fa80ed 100644 --- a/src/main/scala/gitbucket/core/view/helpers.scala +++ b/src/main/scala/gitbucket/core/view/helpers.scala @@ -102,6 +102,7 @@ def markdown( markdown: String, repository: RepositoryService.RepositoryInfo, + branch: String, enableWikiLink: Boolean, enableRefsLink: Boolean, enableLineBreaks: Boolean, @@ -114,6 +115,7 @@ Markdown.toHtml( markdown = markdown, repository = repository, + branch = branch, enableWikiLink = enableWikiLink, enableRefsLink = enableRefsLink, enableAnchor = enableAnchor, diff --git a/src/main/twirl/gitbucket/core/helper/commitcomment.scala.html b/src/main/twirl/gitbucket/core/helper/commitcomment.scala.html index 63f099b..0a45e8e 100644 --- a/src/main/twirl/gitbucket/core/helper/commitcomment.scala.html +++ b/src/main/twirl/gitbucket/core/helper/commitcomment.scala.html @@ -22,12 +22,13 @@