Permalink
Browse files

Initial Import.

  • Loading branch information...
1 parent 986a1f9 commit 257f8c01b63b5bbf6934b05e92526698bd76adbb @takezoe takezoe committed Apr 10, 2013
Showing with 20,054 additions and 0 deletions.
  1. +2 −0 command.bat
  2. +36 −0 project/build.scala
  3. +7 −0 project/plugins.sbt
  4. BIN sbt-launch-0.12.3.jar
  5. +2 −0 sbt.bat
  6. +10 −0 src/main/scala/ScalatraBootstrap.scala
  7. +51 −0 src/main/scala/app/CreateRepositoryServlet.scala
  8. +196 −0 src/main/scala/app/RepositoryViewerServlet.scala
  9. +10 −0 src/main/scala/app/ServletBase.scala
  10. +21 −0 src/main/scala/util/Directory.scala
  11. +22 −0 src/main/scala/util/Implicits.scala
  12. +23 −0 src/main/scala/view/helpers.scala
  13. +53 −0 src/main/twirl/blob.scala.html
  14. +37 −0 src/main/twirl/commits.scala.html
  15. +53 −0 src/main/twirl/files.scala.html
  16. +14 −0 src/main/twirl/header.scala.html
  17. +43 −0 src/main/twirl/main.scala.html
  18. +22 −0 src/main/twirl/navtab.scala.html
  19. +16 −0 src/main/twirl/newrepo.scala.html
  20. +35 −0 src/main/twirl/user.scala.html
  21. +34 −0 src/main/webapp/WEB-INF/web.xml
  22. +1,109 −0 src/main/webapp/assets/bootstrap/css/bootstrap-responsive.css
  23. +9 −0 src/main/webapp/assets/bootstrap/css/bootstrap-responsive.min.css
  24. +6,158 −0 src/main/webapp/assets/bootstrap/css/bootstrap.css
  25. +9 −0 src/main/webapp/assets/bootstrap/css/bootstrap.min.css
  26. BIN src/main/webapp/assets/bootstrap/img/glyphicons-halflings-white.png
  27. BIN src/main/webapp/assets/bootstrap/img/glyphicons-halflings.png
  28. +2,276 −0 src/main/webapp/assets/bootstrap/js/bootstrap.js
  29. +6 −0 src/main/webapp/assets/bootstrap/js/bootstrap.min.js
  30. +58 −0 src/main/webapp/assets/common/css/gitbucket.css
  31. BIN src/main/webapp/assets/common/images/file.png
  32. BIN src/main/webapp/assets/common/images/folder.png
  33. +9,597 −0 src/main/webapp/assets/common/js/jquery-1.9.1.js
  34. +2 −0 src/main/webapp/assets/google-code-prettify/lang-apollo.js
  35. +3 −0 src/main/webapp/assets/google-code-prettify/lang-basic.js
  36. +18 −0 src/main/webapp/assets/google-code-prettify/lang-clj.js
  37. +2 −0 src/main/webapp/assets/google-code-prettify/lang-css.js
  38. +3 −0 src/main/webapp/assets/google-code-prettify/lang-dart.js
  39. +2 −0 src/main/webapp/assets/google-code-prettify/lang-erlang.js
  40. +1 −0 src/main/webapp/assets/google-code-prettify/lang-go.js
  41. +2 −0 src/main/webapp/assets/google-code-prettify/lang-hs.js
  42. +3 −0 src/main/webapp/assets/google-code-prettify/lang-lisp.js
  43. +1 −0 src/main/webapp/assets/google-code-prettify/lang-llvm.js
  44. +2 −0 src/main/webapp/assets/google-code-prettify/lang-lua.js
  45. +6 −0 src/main/webapp/assets/google-code-prettify/lang-matlab.js
  46. +2 −0 src/main/webapp/assets/google-code-prettify/lang-ml.js
  47. +2 −0 src/main/webapp/assets/google-code-prettify/lang-mumps.js
  48. +4 −0 src/main/webapp/assets/google-code-prettify/lang-n.js
  49. +3 −0 src/main/webapp/assets/google-code-prettify/lang-pascal.js
  50. +1 −0 src/main/webapp/assets/google-code-prettify/lang-proto.js
  51. +2 −0 src/main/webapp/assets/google-code-prettify/lang-r.js
  52. +1 −0 src/main/webapp/assets/google-code-prettify/lang-rd.js
  53. +2 −0 src/main/webapp/assets/google-code-prettify/lang-scala.js
  54. +2 −0 src/main/webapp/assets/google-code-prettify/lang-sql.js
  55. +3 −0 src/main/webapp/assets/google-code-prettify/lang-tcl.js
  56. +1 −0 src/main/webapp/assets/google-code-prettify/lang-tex.js
  57. +2 −0 src/main/webapp/assets/google-code-prettify/lang-vb.js
  58. +3 −0 src/main/webapp/assets/google-code-prettify/lang-vhdl.js
  59. +2 −0 src/main/webapp/assets/google-code-prettify/lang-wiki.js
  60. +3 −0 src/main/webapp/assets/google-code-prettify/lang-xq.js
  61. +2 −0 src/main/webapp/assets/google-code-prettify/lang-yaml.js
  62. +1 −0 src/main/webapp/assets/google-code-prettify/prettify.css
  63. +30 −0 src/main/webapp/assets/google-code-prettify/prettify.js
  64. +34 −0 src/main/webapp/assets/google-code-prettify/run_prettify.js
View
@@ -0,0 +1,2 @@
+%~d0
+cmd /k cd %~p0
View
@@ -0,0 +1,36 @@
+import sbt._
+import Keys._
+import org.scalatra.sbt._
+import org.scalatra.sbt.PluginKeys._
+import twirl.sbt.TwirlPlugin._
+import com.typesafe.sbteclipse.plugin.EclipsePlugin.EclipseKeys
+
+object MyBuild extends Build {
+ val Organization = "jp.sf.amateras"
+ val Name = "gitbucket"
+ val Version = "0.0.1"
+ val ScalaVersion = "2.10.1"
+ val ScalatraVersion = "2.2.0"
+
+ lazy val project = Project (
+ "gitbucket",
+ file("."),
+ settings = Defaults.defaultSettings ++ ScalatraPlugin.scalatraWithJRebel ++ Seq(
+ organization := Organization,
+ name := Name,
+ version := Version,
+ scalaVersion := ScalaVersion,
+ resolvers += Classpaths.typesafeReleases,
+ libraryDependencies ++= Seq(
+ "org.eclipse.jgit" % "org.eclipse.jgit.http.server" % "2.3.1.201302201838-r",
+ "org.apache.commons" % "commons-io" % "1.3.2",
+ "org.scalatra" %% "scalatra" % ScalatraVersion,
+ "org.scalatra" %% "scalatra-specs2" % ScalatraVersion % "test",
+ "ch.qos.logback" % "logback-classic" % "1.0.6" % "runtime",
+ "org.eclipse.jetty" % "jetty-webapp" % "8.1.8.v20121106" % "container",
+ "org.eclipse.jetty.orbit" % "javax.servlet" % "3.0.0.v201112011016" % "container;provided;test" artifacts (Artifact("javax.servlet", "jar", "jar"))
+ ),
+ EclipseKeys.withSource := true
+ ) ++ seq(Twirl.settings: _*)
+ )
+}
View
@@ -0,0 +1,7 @@
+addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.1.2")
+
+addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.2.0")
+
+addSbtPlugin("org.scalatra.sbt" % "scalatra-sbt" % "0.2.0")
+
+addSbtPlugin("io.spray" % "sbt-twirl" % "0.6.1")
View
Binary file not shown.
View
@@ -0,0 +1,2 @@
+set SCRIPT_DIR=%~dp0
+java -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=256m -Xmx512M -Xss2M -jar "%SCRIPT_DIR%\sbt-launch-0.12.3.jar" %*
@@ -0,0 +1,10 @@
+import app._
+import org.scalatra._
+import javax.servlet.ServletContext
+
+class ScalatraBootstrap extends LifeCycle {
+ override def init(context: ServletContext) {
+ context.mount(new CreateRepositoryServlet, "/new")
+ context.mount(new RepositoryViewerServlet, "/*")
+ }
+}
@@ -0,0 +1,51 @@
+package app
+
+import util.Directory._
+
+import org.scalatra._
+import java.io.File
+import org.eclipse.jgit.api.Git
+import org.eclipse.jgit.lib._
+import org.apache.commons.io.FileUtils
+
+/**
+ * Creates new repository.
+ */
+class CreateRepositoryServlet extends ScalatraServlet with ServletBase {
+
+ /**
+ * Show the new repository form.
+ */
+ get("/new") {
+ html.newrepo.render()
+ }
+
+ /**
+ * Create new repository.
+ */
+ post("/new") {
+ val repositoryName = params("name")
+ val description = params("description")
+
+ val dir = new File(getRepositoryDir(LoginUser, repositoryName), ".git")
+ val repository = new RepositoryBuilder()
+ .setGitDir(dir)
+ .build()
+
+ repository.create
+
+ if(description.nonEmpty){
+ // Create README.md
+ val readme = new File(dir.getParentFile, "README.md")
+ FileUtils.writeStringToFile(readme,
+ repositoryName + "\n===============\n\n" + description, "UTF-8")
+
+ val git = new Git(repository)
+ git.add.addFilepattern("README.md").call
+ git.commit.setMessage("Initial commit").call
+ }
+
+ // redirect to the repository
+ redirect("/%s/%s".format(LoginUser, repositoryName))
+ }
+}
@@ -0,0 +1,196 @@
+package app
+
+import util.Directory._
+import util.Implicits._
+import org.scalatra._
+import java.io.File
+import java.util.Date
+import org.eclipse.jgit.api.Git
+import org.eclipse.jgit.lib._
+import org.apache.commons.io.FileUtils
+
+case class RepositoryInfo(owner: String, name: String, url: String, branchList: List[String], tags: List[String])
+
+case class FileInfo(isDirectory: Boolean, name: String, time: Date, message: String, committer: String)
+
+case class CommitInfo(id: String, time: Date, committer: String, message: String)
+
+/**
+ * The repository viewer.
+ */
+class RepositoryViewerServlet extends ScalatraServlet with ServletBase {
+
+ get("/:owner") {
+ val owner = params("owner")
+ html.user.render(owner, getRepositories(owner).map(getRepositoryInfo(owner, _)))
+ }
+
+ /**
+ * Shows the file list of the repository root and the default branch.
+ */
+ get("/:owner/:repository") {
+ val owner = params("owner")
+ val repository = params("repository")
+ updateAllBranches(owner, repository)
+
+ fileList(owner, repository)
+ }
+
+ /**
+ * Shows the file list of the repository root and the specified branch.
+ */
+ get("/:owner/:repository/tree/:branch") {
+ val owner = params("owner")
+ val repository = params("repository")
+ updateAllBranches(owner, repository)
+
+ fileList(owner, repository, params("branch"))
+ }
+
+ /**
+ * Shows the file list of the specified path and branch.
+ */
+ get("/:owner/:repository/tree/:branch/*") {
+ val owner = params("owner")
+ val repository = params("repository")
+ updateAllBranches(owner, repository)
+
+ fileList(owner, repository, params("branch"), multiParams("splat").head)
+ }
+
+ /**
+ * Shows the commit list of the specified branch.
+ */
+ get("/:owner/:repository/commits/:branch"){
+ val owner = params("owner")
+ val repository = params("repository")
+ updateAllBranches(owner, repository)
+
+ val branchName = params("branch")
+ val page = params.getOrElse("page", "1").toInt
+ val dir = getBranchDir(owner, repository, branchName)
+
+ val git = Git.open(dir)
+ val i = git.log.call.iterator
+ val listBuffer = scala.collection.mutable.ListBuffer[CommitInfo]()
+ var count = 0
+ while(i.hasNext && listBuffer.size < 30){
+ count = count + 1
+ val ref = i.next
+ if((page - 1) * 30 < count){
+ listBuffer.append(CommitInfo(ref.getName, ref.getCommitterIdent.getWhen, ref.getCommitterIdent.getName, ref.getShortMessage))
+ }
+ }
+
+ html.commits.render(branchName, getRepositoryInfo(owner, repository),
+ listBuffer.toSeq.splitWith{ (commit1, commit2) =>
+ view.helpers.date(commit1.time) == view.helpers.date(commit2.time)
+ }, page, i.hasNext)
+ }
+
+ /**
+ * Shows the file content of the specified branch.
+ */
+ get("/:owner/:repository/blob/:branch/*"){
+ val owner = params("owner")
+ val repository = params("repository")
+ updateAllBranches(owner, repository)
+
+ val branchName = params("branch")
+ val path = multiParams("splat").head.replaceFirst("^tree/.+?/", "")
+
+ val dir = getBranchDir(owner, repository, branchName)
+ val content = FileUtils.readFileToString(new File(dir, path), "UTF-8")
+
+ val git = Git.open(dir)
+ val latestRev = git.log.addPath(path).call.iterator.next
+
+ html.blob.render(branchName, getRepositoryInfo(owner, repository), path.split("/").toList, content,
+ CommitInfo(latestRev.getName, latestRev.getCommitterIdent.getWhen, latestRev.getCommitterIdent.getName, latestRev.getShortMessage))
+ }
+
+ def getRepositoryInfo(owner: String, repository: String) = {
+ val git = Git.open(getRepositoryDir(owner, repository))
+ RepositoryInfo(
+ owner, repository, "https://github.com/takezoe/%s.git".format(repository),
+ // branches
+ git.branchList.call.toArray.map { ref =>
+ ref.asInstanceOf[Ref].getName.replaceFirst("^refs/heads/", "")
+ }.toList,
+ // tags
+ git.tagList.call.toArray.map { ref =>
+ ref.asInstanceOf[Ref].getName
+ }.toList
+ )
+ }
+
+ /**
+ * Setup all branches for the repository viewer.
+ * This method copies the repository and checkout branches.
+ */
+ def updateAllBranches(owner: String, repository: String) = {
+ val dir = getRepositoryDir(owner, repository)
+ val git = Git.open(dir)
+
+ val branchList = git.branchList.call.toArray.map { ref =>
+ ref.asInstanceOf[Ref].getName.replaceFirst("^refs/heads/", "")
+ }.toList
+
+ branchList.foreach { branch =>
+ val branchdir = getBranchDir(owner, repository, branch)
+ if(!branchdir.exists){
+ FileUtils.copyDirectory(dir, branchdir)
+ Git.open(branchdir).checkout.setName(branch).call
+ }
+ // TODO コピー元のリポジトリからpullする?
+ }
+ }
+
+ /**
+ * Provides the file list of the specified branch and path.
+ */
+ def fileList(owner: String, repository: String, branch: String = "", path: String = ".") = {
+ val branchName = if(branch.isEmpty){
+ Git.open(getRepositoryDir(owner, repository)).getRepository.getBranch
+ } else {
+ branch
+ }
+
+ val dir = getBranchDir(owner, repository, branchName)
+ val git = Git.open(dir)
+ val latestRev = {if(path == ".") git.log else git.log.addPath(path)}.call.iterator.next
+
+ html.files.render(
+ // current branch
+ branchName,
+ // repository
+ getRepositoryInfo(owner, repository),
+ // current path
+ if(path == ".") Nil else path.split("/").toList,
+ // latest commit
+ CommitInfo(latestRev.getName, latestRev.getCommitterIdent.getWhen, latestRev.getCommitterIdent.getName, latestRev.getShortMessage),
+ // file list
+ new File(dir, path).listFiles()
+ .filterNot{ file => file.getName == ".git" }
+ .sortWith { (file1, file2) =>
+ if(file1.isDirectory && !file2.isDirectory){
+ true
+ } else if(!file1.isDirectory && file2.isDirectory){
+ false
+ } else {
+ file1.getName.compareTo(file2.getName) < 0
+ }
+ }
+ .map { file =>
+ val rev = Git.open(dir).log.addPath(if(path == ".") file.getName else path + "/" + file.getName).call.iterator.next
+ if(rev == null){
+ None
+ } else {
+ Some(FileInfo(file.isDirectory, file.getName, latestRev.getCommitterIdent.getWhen, rev.getShortMessage, rev.getCommitterIdent.getName))
+ }
+ }
+ .flatten.toList
+ )
+ }
+
+}
@@ -0,0 +1,10 @@
+package app
+
+/**
+ * Provides generic features for ScalatraServlet implementations.
+ */
+trait ServletBase {
+
+ val LoginUser = "takezoe"
+
+}
@@ -0,0 +1,21 @@
+package util
+
+import java.io.File
+
+object Directory {
+
+ val GitBucketHome = "C:/Users/takez_000/gitbucket"
+
+ def getRepositories(owner: String): List[String] =
+ new File("%s/%s".format(GitBucketHome, owner)).listFiles.filter(_.isDirectory).map(_.getName).toList
+
+ def getRepositoryDir(owner: String, repository: String): File =
+ new File("%s/%s/%s/repository".format(GitBucketHome, owner, repository))
+
+ def getBranchDir(owner: String, repository: String, branch: String): File =
+ new File("%s/%s/%s/branch/%s".format(GitBucketHome, owner, repository, branch))
+
+ def getTagDir(owner: String, repository: String, tag: String): File =
+ new File("%s/%s/%s/tags/%s".format(GitBucketHome, owner, repository, tag))
+
+}
@@ -0,0 +1,22 @@
+package util
+
+object Implicits {
+ implicit def extendsSeq[A](seq: Seq[A]) = new {
+
+ def splitWith(condition: (A, A) => Boolean): Seq[Seq[A]] = split(seq)(condition)
+
+ @scala.annotation.tailrec
+ private def split[A](list: Seq[A], result: Seq[Seq[A]] = Nil)(condition: (A, A) => Boolean): Seq[Seq[A]] = {
+ list match {
+ case x :: xs => {
+ xs.span(condition(x, _)) match {
+ case (matched, remained) => split(remained, result :+ (x :: matched))(condition)
+ }
+ }
+ case Nil => result
+ }
+ }
+
+ }
+
+}
@@ -0,0 +1,23 @@
+package view
+import java.util.Date
+import java.text.SimpleDateFormat
+
+object helpers {
+
+ def datetime(date: Date): String = {
+ new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(date)
+ }
+
+ def date(date: Date): String = {
+ new SimpleDateFormat("yyyy/MM/dd").format(date)
+ }
+
+ def cut(message: String, length: Int): String = {
+ if(message.length > length){
+ message.substring(0, length) + "..."
+ } else {
+ message
+ }
+ }
+
+}
Oops, something went wrong.

0 comments on commit 257f8c0

Please sign in to comment.