diff --git a/src/main/scala/app/RepositoryViewerServlet.scala b/src/main/scala/app/RepositoryViewerServlet.scala
index 5e2cd3c..8e043c0 100644
--- a/src/main/scala/app/RepositoryViewerServlet.scala
+++ b/src/main/scala/app/RepositoryViewerServlet.scala
@@ -12,6 +12,7 @@
import org.eclipse.jgit.revwalk.RevCommit
import org.eclipse.jgit.diff.DiffEntry.ChangeType
import org.eclipse.jgit.errors.MissingObjectException
+import org.apache.commons.io.FilenameUtils
case class RepositoryInfo(owner: String, name: String, url: String, branchList: List[String], tags: List[String])
@@ -23,6 +24,8 @@
}
case class DiffInfo(changeType: ChangeType, oldPath: String, newPath: String, oldContent: Option[String], newContent: Option[String])
+
+case class ContentInfo(viewType: String, content: Option[String])
/**
* The repository viewer.
@@ -30,7 +33,7 @@
class RepositoryViewerServlet extends ServletBase {
/**
- * Shows user information.
+ * Displays user information.
*/
get("/:owner") {
val owner = params("owner")
@@ -38,7 +41,7 @@
}
/**
- * Shows the file list of the repository root and the default branch.
+ * Displays the file list of the repository root and the default branch.
*/
get("/:owner/:repository") {
val owner = params("owner")
@@ -48,7 +51,7 @@
}
/**
- * Shows the file list of the repository root and the specified branch.
+ * Displays the file list of the repository root and the specified branch.
*/
get("/:owner/:repository/tree/:branch") {
val owner = params("owner")
@@ -58,7 +61,7 @@
}
/**
- * Shows the file list of the specified path and branch.
+ * Displays the file list of the specified path and branch.
*/
get("/:owner/:repository/tree/:branch/*") {
val owner = params("owner")
@@ -68,7 +71,7 @@
}
/**
- * Shows the commit list of the specified branch.
+ * Displays the commit list of the specified branch.
*/
get("/:owner/:repository/commits/:branch"){
val owner = params("owner")
@@ -93,24 +96,35 @@
}
/**
- * Shows the file content of the specified branch or commit.
+ * Displays the file content of the specified branch or commit.
*/
get("/:owner/:repository/blob/:id/*"){
val owner = params("owner")
val repository = params("repository")
val id = params("id") // branch name or commit id
+ val raw = params.get("raw").getOrElse("false").toBoolean
val path = multiParams("splat").head.replaceFirst("^tree/.+?/", "")
val repositoryInfo = getRepositoryInfo(owner, repository)
if(repositoryInfo.branchList.contains(id)){
// id is branch name
- val dir = getBranchDir(owner, repository, id)
- val content = FileUtils.readFileToString(new File(dir, path), "UTF-8")
- val git = Git.open(dir)
- val rev = git.log.addPath(path).call.iterator.next
-
- html.blob(id, repositoryInfo, path.split("/").toList, content, new CommitInfo(rev))
-
+ val dir = getBranchDir(owner, repository, id)
+ val git = Git.open(dir)
+ val rev = git.log.addPath(path).call.iterator.next
+ val file = new File(dir, path)
+
+ if(raw){
+ // Download
+ contentType = "application/octet-stream"
+ file
+ } else {
+ // Viewer
+ val viewer = if(isImage(file.getName)) "image" else if(isLarge(file.length)) "large" else "text"
+ val content = ContentInfo(
+ viewer, if(viewer == "text") Some(FileUtils.readFileToString(file, "UTF-8")) else None
+ )
+ html.blob(id, repositoryInfo, path.split("/").toList, content, new CommitInfo(rev))
+ }
} else {
// id is commit id
val branch = getBranchNameFromCommitId(id, repositoryInfo)
@@ -119,24 +133,34 @@
val rev = git.log.add(ObjectId.fromString(id)).call.iterator.next
@scala.annotation.tailrec
- def getPathContent(path: String, walk: TreeWalk): Option[String] = {
- walk.next match{
- case true if(walk.getPathString == path) => getContent(git, walk.getObjectId(0))
- case true => getPathContent(path, walk)
- case false => None
- }
+ def getPathObjectId(path: String, walk: TreeWalk): ObjectId = walk.next match {
+ case true if(walk.getPathString == path) => walk.getObjectId(0)
+ case true => getPathObjectId(path, walk)
}
val walk = new TreeWalk(git.getRepository)
walk.addTree(rev.getTree)
- val content = getPathContent(path, walk).get
+ walk.setRecursive(true)
+ val objectId = getPathObjectId(path, walk)
- html.blob(branch, repositoryInfo, path.split("/").toList, content, new CommitInfo(rev))
+ if(raw){
+ // Download
+ contentType = "application/octet-stream"
+ getContent(git, objectId)
+
+ } else {
+ // Viewer
+ val large = isLarge(git.getRepository.getObjectDatabase.open(objectId).getSize)
+ val viewer = if(isImage(path)) "image" else if(large) "large" else "text"
+ val content = ContentInfo(viewer, if(viewer == "text") getContent(git, objectId).map(new String(_, "UTF-8")) else None)
+
+ html.blob(branch, repositoryInfo, path.split("/").toList, content, new CommitInfo(rev))
+ }
}
}
/**
- * Shows details of the specified commit.
+ * Displays details of the specified commit.
*/
get("/:owner/:repository/commit/:id"){
val owner = params("owner")
@@ -170,8 +194,8 @@
import scala.collection.JavaConverters._
git.diff.setNewTree(newTreeIter).setOldTree(oldTreeIter).call.asScala.map { diff =>
DiffInfo(diff.getChangeType, diff.getOldPath, diff.getNewPath,
- getContent(git, diff.getOldId.toObjectId),
- getContent(git, diff.getNewId.toObjectId))
+ getContent(git, diff.getOldId.toObjectId).map(new String(_, "UTF-8")),
+ getContent(git, diff.getNewId.toObjectId).map(new String(_, "UTF-8")))
}
} else {
// initial commit
@@ -179,7 +203,7 @@
walk.addTree(rev.getTree)
val buffer = new scala.collection.mutable.ListBuffer[DiffInfo]()
while(walk.next){
- buffer.append(DiffInfo(ChangeType.ADD, null, walk.getPathString, None, getContent(git, walk.getObjectId(0))))
+ buffer.append(DiffInfo(ChangeType.ADD, null, walk.getPathString, None, getContent(git, walk.getObjectId(0)).map(new String(_, "UTF-8"))))
}
buffer.toList
}
@@ -206,8 +230,8 @@
* @param id the object id
* @return the object or None if object does not exist
*/
- def getContent(git: Git, id: ObjectId): Option[String] = try {
- Some(new String(git.getRepository.getObjectDatabase.open(id).getBytes, "UTF-8"))
+ def getContent(git: Git, id: ObjectId): Option[Array[Byte]] = try {
+ Some(git.getRepository.getObjectDatabase.open(id).getBytes)
} catch {
case e: MissingObjectException => None
}
@@ -291,4 +315,11 @@
)
}
+ def isImage(name: String): Boolean = FilenameUtils.getExtension(name).toLowerCase match {
+ case "jpg"|"jpeg"|"bmp"|"gif"|"png" => true
+ case _ => false
+ }
+
+ def isLarge(size: Long): Boolean = (size > 1024 * 1000)
+
}
\ No newline at end of file
diff --git a/src/main/twirl/blob.scala.html b/src/main/twirl/blob.scala.html
index 4c61a5a..b5c89f8 100644
--- a/src/main/twirl/blob.scala.html
+++ b/src/main/twirl/blob.scala.html
@@ -1,4 +1,4 @@
-@(branch: String, repository: app.RepositoryInfo, pathList: List[String], content: String, latestCommit: app.CommitInfo)(implicit context: app.Context)
+@(branch: String, repository: app.RepositoryInfo, pathList: List[String], content: app.ContentInfo, latestCommit: app.CommitInfo)(implicit context: app.Context)
@import context._
@import view.helpers
@main(repository.owner+"/"+repository.name) {
@@ -24,14 +24,27 @@
@helpers.cut(latestCommit.message, 100)
@content
@content.content.get+ } + @if(content.viewType == "image"){ +