Merge branch 'master' into fork-and-pullreq

Conflicts:
	src/main/scala/app/CreateRepositoryController.scala
	src/main/scala/util/JGitUtil.scala
This commit is contained in:
takezoe
2013-07-26 18:22:14 +09:00
16 changed files with 413 additions and 252 deletions

View File

@@ -7,7 +7,7 @@ import Q.interpolation
import model._
import util.Implicits._
import util.StringUtil
import util.StringUtil._
trait IssuesService {
import IssuesService._
@@ -99,47 +99,38 @@ trait IssuesService {
def searchIssue(owner: String, repository: String, condition: IssueSearchCondition,
filter: String, userName: Option[String], offset: Int, limit: Int): List[(Issue, List[Label], Int)] = {
// get issues and comment count
val issues = searchIssueQuery(owner, repository, condition, filter, userName)
.leftJoin(Query(IssueComments)
.filter { t =>
(t.byRepository(owner, repository)) &&
(t.action inSetBind Seq("comment", "close_comment", "reopen_comment"))
// get issues and comment count and labels
searchIssueQuery(owner, repository, condition, filter, userName)
.innerJoin(IssueOutline).on { (t1, t2) => t1.byIssue(t2.userName, t2.repositoryName, t2.issueId) }
.leftJoin (IssueLabels) .on { case ((t1, t2), t3) => t1.byIssue(t3.userName, t3.repositoryName, t3.issueId) }
.leftJoin (Labels) .on { case (((t1, t2), t3), t4) => t3.byLabel(t4.userName, t4.repositoryName, t4.labelId) }
.map { case (((t1, t2), t3), t4) =>
(t1, t2.commentCount, t4.labelId.?, t4.labelName.?, t4.color.?)
}
.groupBy { _.issueId }
.map { case (issueId, t) => issueId ~ t.length }).on((t1, t2) => t1.issueId is t2._1)
.sortBy { case (t1, t2) =>
(condition.sort match {
case "created" => t1.registeredDate
case "comments" => t2._2
case "updated" => t1.updatedDate
}) match {
case sort => condition.direction match {
case "asc" => sort asc
case "desc" => sort desc
.sortBy(_._4) // labelName
.sortBy { case (t1, commentCount, _,_,_) =>
(condition.sort match {
case "created" => t1.registeredDate
case "comments" => commentCount
case "updated" => t1.updatedDate
}) match {
case sort => condition.direction match {
case "asc" => sort asc
case "desc" => sort desc
}
}
}
}
.map { case (t1, t2) => (t1, t2._2.ifNull(0)) }
.drop(offset).take(limit)
.list
// get labels
val labels = Query(IssueLabels)
.innerJoin(Labels).on { (t1, t2) =>
t1.byLabel(t2.userName, t2.repositoryName, t2.labelId)
}
.filter { case (t1, t2) =>
(t1.byRepository(owner, repository)) &&
(t1.issueId inSetBind (issues.map(_._1.issueId)))
}
.sortBy { case (t1, t2) => t1.issueId ~ t2.labelName }
.map { case (t1, t2) => (t1.issueId, t2) }
.list
issues.map { case (issue, commentCount) =>
(issue, labels.collect { case (issueId, labels) if(issueId == issue.issueId) => labels }, commentCount)
}
.drop(offset).take(limit)
.list
.splitWith(_._1.issueId == _._1.issueId)
.map { issues => issues.head match {
case (issue, commentCount, _,_,_) =>
(issue,
issues.flatMap { t => t._3.map (
Label(issue.userName, issue.repositoryName, _, t._4.get, t._5.get)
)} toList,
commentCount)
}} toList
}
/**
@@ -247,42 +238,47 @@ trait IssuesService {
*/
def searchIssuesByKeyword(owner: String, repository: String, query: String): List[(Issue, Int, String)] = {
import scala.slick.driver.H2Driver.likeEncode
val keywords = StringUtil.splitWords(query.toLowerCase)
val keywords = splitWords(query.toLowerCase)
// Search Issue
val issues = Query(Issues).filter { t =>
keywords.map { keyword =>
(t.title.toLowerCase like (s"%${likeEncode(keyword)}%", '^')) ||
(t.content.toLowerCase like (s"%${likeEncode(keyword)}%", '^'))
} .reduceLeft(_ && _)
}.map { t => (t, 0, t.content.?) }
val issues = Issues
.innerJoin(IssueOutline).on { case (t1, t2) =>
t1.byIssue(t2.userName, t2.repositoryName, t2.issueId)
}
.filter { case (t1, t2) =>
keywords.map { keyword =>
(t1.title.toLowerCase like (s"%${likeEncode(keyword)}%", '^')) ||
(t1.content.toLowerCase like (s"%${likeEncode(keyword)}%", '^'))
} .reduceLeft(_ && _)
}
.map { case (t1, t2) =>
(t1, 0, t1.content.?, t2.commentCount)
}
// Search IssueComment
val comments = Query(IssueComments).innerJoin(Issues).on { case (t1, t2) =>
t1.byIssue(t2.userName, t2.repositoryName, t2.issueId)
}.filter { case (t1, t2) =>
keywords.map { query =>
t1.content.toLowerCase like (s"%${likeEncode(query)}%", '^')
}.reduceLeft(_ && _)
}.map { case (t1, t2) => (t2, t1.commentId, t1.content.?) }
val comments = IssueComments
.innerJoin(Issues).on { case (t1, t2) =>
t1.byIssue(t2.userName, t2.repositoryName, t2.issueId)
}
.innerJoin(IssueOutline).on { case ((t1, t2), t3) =>
t2.byIssue(t3.userName, t3.repositoryName, t3.issueId)
}
.filter { case ((t1, t2), t3) =>
keywords.map { query =>
t1.content.toLowerCase like (s"%${likeEncode(query)}%", '^')
}.reduceLeft(_ && _)
}
.map { case ((t1, t2), t3) =>
(t2, t1.commentId, t1.content.?, t3.commentCount)
}
def getCommentCount(issue: Issue): Int = {
Query(IssueComments)
.filter { t =>
t.byIssue(issue.userName, issue.repositoryName, issue.issueId) &&
(t.action inSetBind Seq("comment", "close_comment", "reopen_comment"))
}
.map(_.issueId)
.list.length
}
issues.union(comments).sortBy { case (issue, commentId, _) =>
issues.union(comments).sortBy { case (issue, commentId, _, _) =>
issue.issueId ~ commentId
}.list.splitWith { case ((issue1, _, _), (issue2, _, _)) =>
}.list.splitWith { case ((issue1, _, _, _), (issue2, _, _, _)) =>
issue1.issueId == issue2.issueId
}.map { result =>
val (issue, _, content) = result.head
(issue, getCommentCount(issue) , content.getOrElse(""))
}.map { _.head match {
case (issue, _, content, commentCount) => (issue, commentCount, content.getOrElse(""))
}
}.toList
}
@@ -290,13 +286,13 @@ trait IssuesService {
object IssuesService {
import javax.servlet.http.HttpServletRequest
import util.StringUtil._
val IssueLimit = 30
case class IssueSearchCondition(
labels: Set[String] = Set.empty,
milestoneId: Option[Option[Int]] = None,
repo: Option[String] = None,
state: String = "open",
sort: String = "created",
direction: String = "desc"){
@@ -308,6 +304,7 @@ object IssuesService {
case Some(x) => x.toString
case None => "none"
})},
repo.map("for=" + urlEncode(_)),
Some("state=" + urlEncode(state)),
Some("sort=" + urlEncode(sort)),
Some("direction=" + urlEncode(direction))).flatten.mkString("&")
@@ -328,6 +325,7 @@ object IssuesService {
case "none" => None
case x => Some(x.toInt)
}),
param(request, "for"),
param(request, "state", Seq("open", "closed")).getOrElse("open"),
param(request, "sort", Seq("created", "comments", "updated")).getOrElse("created"),
param(request, "direction", Seq("asc", "desc")).getOrElse("desc"))

View File

@@ -29,20 +29,24 @@ trait RepositorySearchService { self: IssuesService =>
def countFiles(owner: String, repository: String, query: String): Int =
JGitUtil.withGit(getRepositoryDir(owner, repository)){ git =>
searchRepositoryFiles(git, query).length
if(JGitUtil.isEmpty(git)) 0 else searchRepositoryFiles(git, query).length
}
def searchFiles(owner: String, repository: String, query: String): List[FileSearchResult] =
JGitUtil.withGit(getRepositoryDir(owner, repository)){ git =>
val files = searchRepositoryFiles(git, query)
val commits = JGitUtil.getLatestCommitFromPaths(git, files.toList.map(_._1), "HEAD")
files.map { case (path, text) =>
val (highlightText, lineNumber) = getHighlightText(text, query)
FileSearchResult(
path,
commits(path).getCommitterIdent.getWhen,
highlightText,
lineNumber)
if(JGitUtil.isEmpty(git)){
Nil
} else {
val files = searchRepositoryFiles(git, query)
val commits = JGitUtil.getLatestCommitFromPaths(git, files.toList.map(_._1), "HEAD")
files.map { case (path, text) =>
val (highlightText, lineNumber) = getHighlightText(text, query)
FileSearchResult(
path,
commits(path).getCommitterIdent.getWhen,
highlightText,
lineNumber)
}
}
}
@@ -118,4 +122,4 @@ object RepositorySearchService {
highlightText: String,
highlightLineNumber: Int)
}
}

View File

@@ -53,14 +53,11 @@ trait WikiService {
*/
def getWikiPage(owner: String, repository: String, pageName: String): Option[WikiPageInfo] = {
JGitUtil.withGit(Directory.getWikiRepositoryDir(owner, repository)){ git =>
try {
if(!JGitUtil.isEmpty(git)){
JGitUtil.getFileList(git, "master", ".").find(_.name == pageName + ".md").map { file =>
WikiPageInfo(file.name, new String(git.getRepository.open(file.id).getBytes, "UTF-8"), file.committer, file.time)
}
} catch {
// TODO no commit, but it should not judge by exception.
case e: NullPointerException => None
}
} else None
}
}
@@ -69,7 +66,7 @@ trait WikiService {
*/
def getFileContent(owner: String, repository: String, path: String): Option[Array[Byte]] = {
JGitUtil.withGit(Directory.getWikiRepositoryDir(owner, repository)){ git =>
try {
if(!JGitUtil.isEmpty(git)){
val index = path.lastIndexOf('/')
val parentPath = if(index < 0) "." else path.substring(0, index)
val fileName = if(index < 0) path else path.substring(index + 1)
@@ -77,10 +74,7 @@ trait WikiService {
JGitUtil.getFileList(git, "master", parentPath).find(_.name == fileName).map { file =>
git.getRepository.open(file.id).getBytes
}
} catch {
// TODO no commit, but it should not judge by exception.
case e: NullPointerException => None
}
} else None
}
}