diff --git a/README.md b/README.md index 4e11726..913a08a 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ - Gravatar support - Plug-in system -If you want to try the development version of GitBucket, see the documentation for developers at [Wiki](https://github.com/gitbucket/gitbucket/wiki). +If you want to try the development version of GitBucket, see [Developer's Guide](https://github.com/gitbucket/gitbucket/blob/master/doc/how_to_run.md). Installation -------- @@ -41,35 +41,7 @@ To upgrade GitBucket, only replace gitbucket.war after stop GitBucket. All GitBucket data is stored in HOME/.gitbucket. So if you want to back up GitBucket data, copy this directory to the other disk. -For Installation on Windows Server with IIS see [this wiki page](https://github.com/gitbucket/gitbucket/wiki/Installation-on-IIS-and-Helicontech-Zoo) - -### Mac OS X -#### Installing Via Homebrew - -``` -$ brew install gitbucket -==> Downloading https://github.com/takezoe/gitbucket/releases/download/1.10/gitbucket.war -######################################################################## 100.0% -==> Caveats -Note: When using launchctl the port will be 8080. - -To have launchd start gitbucket at login: - ln -sfv /usr/local/opt/gitbucket/*.plist ~/Library/LaunchAgents -Then to load gitbucket now: - launchctl load ~/Library/LaunchAgents/homebrew.mxcl.gitbucket.plist -Or, if you don't want/need launchctl, you can just run: - java -jar /usr/local/opt/gitbucket/libexec/gitbucket.war -==> Summary -/usr/local/Cellar/gitbucket/1.10: 3 files, 42M, built in 11 seconds -``` - -#### Manual Installation -On OS X, generate `gitbucket.plist` by [this script](https://raw.githubusercontent.com/gitbucket/gitbucket/master/contrib/macosx/makePlist) and copy it to `~/Library/LaunchAgents/` - -Run the following commands in `Terminal` to - -- start gitbucket: `launchctl load ~/Library/LaunchAgents/gitbucket.plist` -- stop gitbucket: `launchctl unload ~/Library/LaunchAgents/gitbucket.plist` +About installation on Mac or Windows Server (with IIS), configuration of Apache or Nginx and also integration with other tools or services such as Jenkins or Slack, see [Wiki](https://github.com/gitbucket/gitbucket/wiki). Plug-ins -------- diff --git a/doc/jrebel.md b/doc/jrebel.md new file mode 100644 index 0000000..9ea1f68 --- /dev/null +++ b/doc/jrebel.md @@ -0,0 +1,148 @@ +JRebel integration (optional) +============================= + +[JRebel](http://zeroturnaround.com/software/jrebel/) is a JVM plugin that makes developing web apps much faster. +JRebel is generally able to eliminate the need for the following slow "app restart" in sbt following a code change: + +``` +> jetty:start +``` + +While JRebel is not open source, it does reload your code faster than the `~;copy-resources;aux-compile` way of doing things using `sbt`. + +It's only used during development, and doesn't change your deployed app in any way. + +JRebel used to be free for Scala developers, but that changed recently, and now there's a cost associated with usage for Scala. There are trial plans and free non-commercial licenses available if you just want to try it out. + +---- + +## 1. Get a JRebel license + +Sign up for a [usage plan](https://my.jrebel.com/). You will need to create an account. + +## 2. Download JRebel + +Download the most recent ["nosetup" JRebel zip](http://zeroturnaround.com/software/jrebel/download/prev-releases/). +Next, unzip the downloaded file. + +## 3. Activate + +Follow the [instructions on the JRebel website](http://zeroturnaround.com/software/jrebel/download/prev-releases/) to activate your downloaded JRebel. + +You can use the default settings for all the configurations. + +You don't need to integrate with your IDE, since we're using sbt to do the servlet deployment. + +## 4. Tell jvm where JRebel is + +Fortunately, the gitbucket project is already set up to use JRebel. +You only need to tell jvm where to find the jrebel jar. + +To do so, edit your shell resource file (usually `~/.bash_profile` on Mac, and `~/.bashrc` on Linux), and add the following line: + +```bash +export JREBEL=/path/to/jrebel/jrebel.jar +``` + +For example, if you unzipped your JRebel download in your home directory, you whould use: + +```bash +export JREBEL=~/jrebel/jrebel.jar +``` + +Now reload your shell: + +``` +$ source ~/.bash_profile # on Mac +$ source ~/.bashrc # on Linux +``` + +## 5. See it in action! + +Now you're ready to use JRebel with the gitbucket. +When you run sbt as normal, you will see a long message from JRebel, indicating it has loaded. +Here's an abbreviated version of what you will see: + +``` +$ ./sbt +[info] Loading project definition from /git/gitbucket/project +[info] Set current project to gitbucket (in build file:/git/gitbucket/) +> +``` + +You will start the servlet container slightly differently now that you're using sbt. + +``` +> jetty:start +: +[info] starting server ... +[success] Total time: 3 s, completed Jan 3, 2016 9:47:55 PM +2016-01-03 21:47:57 JRebel: +2016-01-03 21:47:57 JRebel: A newer version '6.3.1' is available for download +2016-01-03 21:47:57 JRebel: from http://zeroturnaround.com/software/jrebel/download/ +2016-01-03 21:47:57 JRebel: +2016-01-03 21:47:58 JRebel: Contacting myJRebel server .. +2016-01-03 21:47:59 JRebel: Directory '/git/gitbucket/target/scala-2.11/classes' will be monitored for changes. +2016-01-03 21:47:59 JRebel: Directory '/git/gitbucket/target/scala-2.11/test-classes' will be monitored for changes. +2016-01-03 21:47:59 JRebel: Directory '/git/gitbucket/target/webapp' will be monitored for changes. +2016-01-03 21:48:00 JRebel: +2016-01-03 21:48:00 JRebel: ############################################################# +2016-01-03 21:48:00 JRebel: +2016-01-03 21:48:00 JRebel: JRebel Legacy Agent 6.2.5 (201509291538) +2016-01-03 21:48:00 JRebel: (c) Copyright ZeroTurnaround AS, Estonia, Tartu. +2016-01-03 21:48:00 JRebel: +2016-01-03 21:48:00 JRebel: Over the last 30 days JRebel prevented +2016-01-03 21:48:00 JRebel: at least 182 redeploys/restarts saving you about 7.4 hours. +2016-01-03 21:48:00 JRebel: +2016-01-03 21:48:00 JRebel: Over the last 324 days JRebel prevented +2016-01-03 21:48:00 JRebel: at least 1538 redeploys/restarts saving you about 62.4 hours. +2016-01-03 21:48:00 JRebel: +2016-01-03 21:48:00 JRebel: Licensed to nazo king (using myJRebel). +2016-01-03 21:48:00 JRebel: +2016-01-03 21:48:00 JRebel: +2016-01-03 21:48:00 JRebel: ############################################################# +2016-01-03 21:48:00 JRebel: +: + +> ~ copy-resources +[success] Total time: 0 s, completed Jan 3, 2016 9:13:54 PM +1. Waiting for source changes... (press enter to interrupt) +``` + +Finally, change your code. +For example, you can change the title on `src/main/twirl/gitbucket/core/main.scala.html` like this: + +```html +: + + GitBucket + @defining(AutoUpdate.getCurrentVersion){ version => + @version.majorVersion.@version.minorVersion + } + change code !!!!!!!!!!!!!!!! + +: +``` + +If JRebel is doing is correctly installed you will see a notice for you: + +``` +1. Waiting for source changes... (press enter to interrupt) +2016-01-03 21:48:42 JRebel: Reloading class 'gitbucket.core.html.main$'. +[info] Wrote rebel.xml to /git/gitbucket/target/scala-2.11/resource_managed/main/rebel.xml +[info] Compiling 1 Scala source to /git/gitbucket/target/scala-2.11/classes... +[success] Total time: 3 s, completed Jan 3, 2016 9:48:55 PM +2. Waiting for source changes... (press enter to interrupt) +``` + +And you reload browser, JRebel give notice of that it has reloaded classes: + +``` +[success] Total time: 3 s, completed Jan 3, 2016 9:48:55 PM +2. Waiting for source changes... (press enter to interrupt) +2016-01-03 21:49:13 JRebel: Reloading class 'gitbucket.core.html.main$'. +``` + +## 6. Limitations + +JRebel is nearly always able to eliminate the need to explicitly reload your container after a code change. However, if you change any of your routes patterns, there is nothing JRebel can do, you will have to run `jetty:start`. diff --git a/doc/readme.md b/doc/readme.md index d4e3c58..f8b23de 100644 --- a/doc/readme.md +++ b/doc/readme.md @@ -9,3 +9,4 @@ * [Notification Email](notification.md) * [Automatic Schema Updating](auto_update.md) * [Release Operation](release.md) + * [JRebel integration (optional)](jrebel.md) diff --git a/project/build.scala b/project/build.scala index 84822c9..493c620 100644 --- a/project/build.scala +++ b/project/build.scala @@ -5,6 +5,8 @@ import sbtassembly.AssemblyKeys._ import sbtassembly._ import JettyPlugin.autoImport._ +import fi.gekkio.sbtplugins.jrebel.JRebelPlugin._ +import com.earldouglas.xwp.WebappPlugin.autoImport.webappPrepare object MyBuild extends Build { val Organization = "gitbucket" @@ -78,5 +80,10 @@ testOptions in Test += Tests.Setup( () => new java.io.File("target/gitbucket_home_for_test").mkdir() ), fork in Test := true, packageOptions += Package.MainClass("JettyLauncher") + ).settings(jrebelSettings: _*).settings( + jrebel.webLinks += (target in webappPrepare).value, + jrebel.enabled := System.getenv().get("JREBEL") != null, + javaOptions in Jetty ++= Option(System.getenv().get("JREBEL")).toSeq.flatMap(path => + Seq("-noverify", "-XX:+UseConcMarkSweepGC", "-XX:+CMSClassUnloadingEnabled", s"-javaagent:${path}")) ).enablePlugins(SbtTwirl, JettyPlugin) } diff --git a/project/plugins.sbt b/project/plugins.sbt index 5ed803b..fe0d1bd 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -2,4 +2,5 @@ addSbtPlugin("com.typesafe.sbt" % "sbt-twirl" % "1.0.4") addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.12.0") -addSbtPlugin("com.earldouglas" % "xsbt-web-plugin" % "2.1.0") \ No newline at end of file +addSbtPlugin("com.earldouglas" % "xsbt-web-plugin" % "2.1.0") +addSbtPlugin("fi.gekkio.sbtplugins" % "sbt-jrebel-plugin" % "0.10.0") diff --git a/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala b/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala index 2e63b17..155204b 100644 --- a/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala +++ b/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala @@ -111,6 +111,7 @@ enableRefsLink = params("enableRefsLink").toBoolean, enableLineBreaks = params("enableLineBreaks").toBoolean, enableTaskList = params("enableTaskList").toBoolean, + enableAnchor = false, hasWritePermission = hasWritePermission(repository.owner, repository.name, context.loginAccount) ) }) diff --git a/src/main/scala/gitbucket/core/view/Markdown.scala b/src/main/scala/gitbucket/core/view/Markdown.scala index 2d78546..5acaa1d 100644 --- a/src/main/scala/gitbucket/core/view/Markdown.scala +++ b/src/main/scala/gitbucket/core/view/Markdown.scala @@ -33,28 +33,30 @@ enableTaskList: Boolean = false, hasWritePermission: Boolean = false, pages: List[String] = Nil)(implicit context: Context): String = { - // escape issue id - val s = if(enableRefsLink){ - markdown.replaceAll("(?<=(\\W|^))#(\\d+)(?=(\\W|$))", "issue:$2") - } else markdown // escape task list - val source = if(enableTaskList){ - escapeTaskList(s) - } else s + val source = if(enableTaskList) escapeTaskList(markdown) else markdown val options = new Options() options.setSanitize(true) options.setBreaks(enableLineBreaks) - val renderer = new GitBucketMarkedRenderer(options, repository, enableWikiLink, enableRefsLink, enableAnchor, enableTaskList, hasWritePermission, pages) + + val renderer = new GitBucketMarkedRenderer(options, repository, + enableWikiLink, enableRefsLink, enableAnchor, enableTaskList, hasWritePermission, pages) + Marked.marked(source, options, renderer) } /** * Extends markedj Renderer for GitBucket */ - class GitBucketMarkedRenderer(options: Options, repository: RepositoryService.RepositoryInfo, - enableWikiLink: Boolean, enableRefsLink: Boolean, enableAnchor: Boolean, enableTaskList: Boolean, hasWritePermission: Boolean, + class GitBucketMarkedRenderer(options: Options, + repository: RepositoryService.RepositoryInfo, + enableWikiLink: Boolean, + enableRefsLink: Boolean, + enableAnchor: Boolean, + enableTaskList: Boolean, + hasWritePermission: Boolean, pages: List[String]) (implicit val context: Context) extends Renderer(options) with LinkConverter with RequestCache { @@ -62,11 +64,14 @@ val id = generateAnchorName(text) val out = new StringBuilder() - out.append("") + out.append("") out.append("") out.append("") + } else { + out.append(">") } out.append(text) @@ -83,28 +88,27 @@ var listType: String = null if (ordered) { listType = "ol" - } - else { + } else { listType = "ul" } if(body.contains("""class="task-list-item-checkbox"""")){ - return "<" + listType + " class=\"task-list\">\n" + body + "\n" + "<" + listType + " class=\"task-list\">\n" + body + "\n" } else { - return "<" + listType + ">\n" + body + "\n" + "<" + listType + ">\n" + body + "\n" } } override def listitem(text: String): String = { if(text.contains("""class="task-list-item-checkbox" """)){ - return "
  • " + text + "
  • \n" + "
  • " + text + "
  • \n" } else { - return "
  • " + text + "
  • \n" + "
  • " + text + "
  • \n" } } override def text(text: String): String = { // convert commit id and username to link. - val t1 = if(enableRefsLink) convertRefsLinks(text, repository, "issue:", false) else text + val t1 = if(enableRefsLink) convertRefsLinks(text, repository, "#", false) else text // convert task list to checkbox. val t2 = if(enableTaskList) convertCheckBox(t1, hasWritePermission) else t1 diff --git a/src/main/scala/gitbucket/core/view/helpers.scala b/src/main/scala/gitbucket/core/view/helpers.scala index 69418fc..a09edcb 100644 --- a/src/main/scala/gitbucket/core/view/helpers.scala +++ b/src/main/scala/gitbucket/core/view/helpers.scala @@ -89,6 +89,7 @@ enableWikiLink: Boolean, enableRefsLink: Boolean, enableLineBreaks: Boolean, + enableAnchor: Boolean = true, enableTaskList: Boolean = false, hasWritePermission: Boolean = false, pages: List[String] = Nil)(implicit context: Context): Html = @@ -97,7 +98,7 @@ repository = repository, enableWikiLink = enableWikiLink, enableRefsLink = enableRefsLink, - enableAnchor = true, + enableAnchor = enableAnchor, enableLineBreaks = enableLineBreaks, enableTaskList = enableTaskList, hasWritePermission = hasWritePermission, diff --git a/src/main/twirl/gitbucket/core/repo/editor.scala.html b/src/main/twirl/gitbucket/core/repo/editor.scala.html index 8639ae8..b1079bd 100644 --- a/src/main/twirl/gitbucket/core/repo/editor.scala.html +++ b/src/main/twirl/gitbucket/core/repo/editor.scala.html @@ -122,16 +122,17 @@ $('#editor').hide(); $('#preview').show(); $('#btn-code').removeClass('active'); - $('#btn-preview').appendClass('active'); + $('#btn-preview').addClass('active'); @if(fileName.map(isRenderable _).getOrElse(false)) { // update preview $('#preview').html(' Previewing...'); $.post('@url(repository)/_preview', { - content : editor.getValue(), - enableWikiLink : false, - enableRefsLink : false, - enableTaskList : false + content : editor.getValue(), + enableWikiLink : false, + enableRefsLink : false, + enableLineBreaks : false, + enableTaskList : false }, function(data){ $('#preview').empty().append( $('
    ').html(data)); diff --git a/src/main/twirl/gitbucket/core/repo/files.scala.html b/src/main/twirl/gitbucket/core/repo/files.scala.html index f8b0885..b272a3b 100644 --- a/src/main/twirl/gitbucket/core/repo/files.scala.html +++ b/src/main/twirl/gitbucket/core/repo/files.scala.html @@ -106,25 +106,25 @@ } - @if(file.isDirectory){ - @if(file.linkUrl.isDefined){ - - @file.name.split("/").toList.init match { - case Nil => {} - case list => {@list.mkString("", "/", "/")} - }@file.name.split("/").toList.last - + @if(file.isDirectory){ + @if(file.linkUrl.isDefined){ + + @file.name.split("/").toList.init match { + case Nil => {} + case list => {@list.mkString("", "/", "/")} + }@file.name.split("/").toList.last + + } else { + + @file.name.split("/").toList.init match { + case Nil => {} + case list => {@list.mkString("", "/", "/")} + }@file.name.split("/").toList.last + + } } else { - - @file.name.split("/").toList.init match { - case Nil => {} - case list => {@list.mkString("", "/", "/")} - }@file.name.split("/").toList.last - + @file.name } - } else { - @file.name - } @link(file.message, repository) diff --git a/src/main/webapp/assets/common/css/gitbucket.css b/src/main/webapp/assets/common/css/gitbucket.css index 5b13ac1..fe72462 100644 --- a/src/main/webapp/assets/common/css/gitbucket.css +++ b/src/main/webapp/assets/common/css/gitbucket.css @@ -829,6 +829,9 @@ table.table-file-list .content-name { max-width: 180px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } table.table-file-list .commit-message { @@ -1715,28 +1718,39 @@ border-bottom: 1px solid #ddd; font-size: 2.5em; font-weight: bold; + line-height: 1.7; } div.markdown-body h2 { border-bottom: 1px solid #eee; font-size: 2em; + font-weight: bold; + line-height: 1.7; } div.markdown-body h3 { font-size: 1.5em; + font-weight: bold; + line-height: 1.7; } div.markdown-body h4 { font-size: 1.2em; + font-weight: bold; + line-height: 1.7; } div.markdown-body h5 { font-size: 1em; + font-weight: bold; + line-height: 1.7; } div.markdown-body h6 { color:#777; font-size: 1em; + font-weight: bold; + line-height: 1.7; } div.markdown-body li { @@ -1902,7 +1916,6 @@ .markdown-head { position: relative; - line-height: 1.7; } a.markdown-anchor-link {