Merge branch 'repository-search-cache' into #3_repository-search

This commit is contained in:
takezoe
2013-07-19 18:04:28 +09:00
4 changed files with 70 additions and 30 deletions

View File

@@ -8,6 +8,7 @@ import org.eclipse.jgit.treewalk.TreeWalk
import org.eclipse.jgit.revwalk.RevWalk import org.eclipse.jgit.revwalk.RevWalk
import scala.collection.mutable.ListBuffer import scala.collection.mutable.ListBuffer
import org.eclipse.jgit.lib.FileMode import org.eclipse.jgit.lib.FileMode
import model.Issue
class IndexController extends IndexControllerBase class IndexController extends IndexControllerBase
with RepositoryService with AccountService with SystemSettingsService with ActivityService with IssuesService with RepositoryService with AccountService with SystemSettingsService with ActivityService with IssuesService
@@ -40,11 +41,18 @@ trait IndexControllerBase extends ControllerBase { self: RepositoryService
} }
get("/:owner/:repository/search")(referrersOnly { repository => get("/:owner/:repository/search")(referrersOnly { repository =>
import RepositorySearch._
val query = params("q").trim val query = params("q").trim
val target = params.getOrElse("type", "code") val target = params.getOrElse("type", "code")
val page = try {
val i = params.getOrElse("page", "1").toInt
if(i <= 0) 1 else i
} catch {
case e: NumberFormatException => 1
}
val issues = if(query.isEmpty) Nil else searchIssuesByKeyword(repository.owner, repository.name, query)
val files = if(query.isEmpty) Nil else searchRepositoryFiles(repository.owner, repository.name, query) val SearchResult(files, issues) = searchRepository(repository.owner, repository.name, query)
target.toLowerCase match { target.toLowerCase match {
case "issue" => case "issue" =>
@@ -56,19 +64,34 @@ trait IndexControllerBase extends ControllerBase { self: RepositoryService
issue.registeredDate, issue.registeredDate,
commentCount, commentCount,
getHighlightText(content, query)._1) getHighlightText(content, query)._1)
}, files.size, query, repository) }, files.size, query, page, repository)
case _ => case _ =>
JGitUtil.withGit(getRepositoryDir(repository.owner, repository.name)){ git => JGitUtil.withGit(getRepositoryDir(repository.owner, repository.name)){ git =>
val commits = JGitUtil.getLatestCommitFromPaths(git, files.toList.map(_._1), "HEAD") val commits = JGitUtil.getLatestCommitFromPaths(git, files.toList.map(_._1), "HEAD")
search.html.code(files.toList.map { case (path, text) => search.html.code(files.toList.map { case (path, text) =>
val (highlightText, lineNumber) = getHighlightText(text, query) val (highlightText, lineNumber) = getHighlightText(text, query)
FileSearchResult(path, commits(path).getCommitterIdent.getWhen, highlightText, lineNumber) FileSearchResult(
}, issues.size, query, repository) path,
commits(path).getCommitterIdent.getWhen,
highlightText,
lineNumber)
}, issues.size, query, page, repository)
} }
} }
}) })
case class SearchResult(
files: List[(String, String)],
issues: List[(Issue, Int, String)]
)
def searchRepository(owner: String, repository: String, query: String): SearchResult = {
val issues = if(query.isEmpty) Nil else searchIssuesByKeyword(owner, repository, query)
val files = if(query.isEmpty) Nil else searchRepositoryFiles(owner, repository, query)
SearchResult(files, issues)
}
private def searchRepositoryFiles(owner: String, repository: String, query: String): List[(String, String)] = { private def searchRepositoryFiles(owner: String, repository: String, query: String): List[(String, String)] = {
JGitUtil.withGit(getRepositoryDir(owner, repository)){ git => JGitUtil.withGit(getRepositoryDir(owner, repository)){ git =>
val revWalk = new RevWalk(git.getRepository) val revWalk = new RevWalk(git.getRepository)
@@ -102,6 +125,7 @@ trait IndexControllerBase extends ControllerBase { self: RepositoryService
} }
} }
private def getHighlightText(content: String, query: String): (String, Int) = { private def getHighlightText(content: String, query: String): (String, Int) = {
val keywords = StringUtil.splitWords(query.toLowerCase) val keywords = StringUtil.splitWords(query.toLowerCase)
val lowerText = content.toLowerCase val lowerText = content.toLowerCase
@@ -120,7 +144,6 @@ trait IndexControllerBase extends ControllerBase { self: RepositoryService
} }
case class IssueSearchResult( case class IssueSearchResult(
issueId: Int, issueId: Int,
title: String, title: String,
@@ -133,4 +156,9 @@ case class FileSearchResult(
path: String, path: String,
lastModified: java.util.Date, lastModified: java.util.Date,
highlightText: String, highlightText: String,
highlightLineNumber: Int) highlightLineNumber: Int)
object RepositorySearch extends IssuesService {
val CodeLimit = 10
val IssueLimit = 10
}

View File

@@ -1,32 +1,32 @@
@(page: Int, count: Int, limit: Int, width: Int, baseURL: String) @(page: Int, count: Int, limit: Int, width: Int, baseURL: String)
@defining(view.Pagination(page, count, service.IssuesService.IssueLimit, width)){ p => @defining(view.Pagination(page, count, limit, width)){ p =>
@if(p.count > p.limit){ @if(p.count > p.limit){
<div class="pagination"> <div class="pagination">
<ul> <ul>
@if(page == 1){ @if(page == 1){
<li class="disabled"><span>&#9664;</span></li> <li class="disabled"><span>&#9664;</span></li>
} else { } else {
<li><a href="@baseURL&page=@(page - 1)">&#9664;</a></li> <li><a href="@baseURL&page=@(page - 1)">&#9664;</a></li>
} }
@for(i <- 1 to p.max){ @for(i <- 1 to p.max){
@if(i == p.max && p.omitRight){ @if(i == p.max && p.omitRight){
<li><span>&hellip;</span></li> <li><span>&hellip;</span></li>
} }
@if(i == page){ @if(i == page){
<li class="active"><span>@i</span></li> <li class="active"><span>@i</span></li>
} else { } else {
@if(p.visibleFor(i)){ @if(p.visibleFor(i)){
<li><a href="@baseURL&page=@i">@i</a></li> <li><a href="@baseURL&page=@i">@i</a></li>
} }
} }
@if(i == 1 && p.omitLeft){ @if(i == 1 && p.omitLeft){
<li><span>&hellip;</span></li> <li><span>&hellip;</span></li>
} }
} }
@if(page == p.max){ @if(page == p.max){
<li class="disabled"><span>&#9654;</span></li> <li class="disabled"><span>&#9654;</span></li>
} else { } else {
<li><a href="@baseURL&page=@(page + 1)">&#9654;</a></li> <li><a href="@baseURL&page=@(page + 1)">&#9654;</a></li>
} }
</ul> </ul>
</div> </div>

View File

@@ -1,4 +1,8 @@
@(files: List[app.FileSearchResult], issueCount: Int, query: String, repository: service.RepositoryService.RepositoryInfo)(implicit context: app.Context) @(files: List[app.FileSearchResult],
issueCount: Int,
query: String,
page: Int,
repository: service.RepositoryService.RepositoryInfo)(implicit context: app.Context)
@import context._ @import context._
@import view.helpers._ @import view.helpers._
@html.main("Search Results", Some(repository)){ @html.main("Search Results", Some(repository)){
@@ -8,12 +12,14 @@
} else { } else {
<h4>We've found @files.size code @plural(files.size, "result")</h4> <h4>We've found @files.size code @plural(files.size, "result")</h4>
} }
@files.map { file => @files.drop((page - 1) * app.RepositorySearch.CodeLimit).take(app.RepositorySearch.CodeLimit).map { file =>
<div> <div>
<h5><a href="@url(repository)/blob/@repository.repository.defaultBranch/@file.path">@file.path</a></h5> <h5><a href="@url(repository)/blob/@repository.repository.defaultBranch/@file.path">@file.path</a></h5>
<div class="small muted">Latest commit at @datetime(file.lastModified)</div> <div class="small muted">Latest commit at @datetime(file.lastModified)</div>
<pre class="prettyprint linenums:@file.highlightLineNumber" style="padding-left: 25px;">@Html(file.highlightText)</pre> <pre class="prettyprint linenums:@file.highlightLineNumber" style="padding-left: 25px;">@Html(file.highlightText)</pre>
</div> </div>
} }
@helper.html.paginator(page, files.size, app.RepositorySearch.CodeLimit, 10,
s"${url(repository)}/search?q=${urlEncode(query)}&type=code")
} }
} }

View File

@@ -1,4 +1,8 @@
@(issues: List[app.IssueSearchResult], fileCount: Int, query: String, repository: service.RepositoryService.RepositoryInfo)(implicit context: app.Context) @(issues: List[app.IssueSearchResult],
fileCount: Int,
query: String,
page: Int,
repository: service.RepositoryService.RepositoryInfo)(implicit context: app.Context)
@import context._ @import context._
@import view.helpers._ @import view.helpers._
@html.main("Search Results", Some(repository)){ @html.main("Search Results", Some(repository)){
@@ -8,10 +12,10 @@
} else { } else {
<h4>We've found @issues.size code @plural(issues.size, "result")</h4> <h4>We've found @issues.size code @plural(issues.size, "result")</h4>
} }
@issues.map { issue => @issues.drop((page - 1) * app.RepositorySearch.IssueLimit).take(app.RepositorySearch.IssueLimit).map { issue =>
<div class="block"> <div class="block">
<div class="pull-right muted">#@issue.issueId</div> <div class="pull-right muted">#@issue.issueId</div>
<h4><a href="@url(repository)/issues/@issue.issueId">@issue.title</a></h4> <h4 style="margin-top: 0px;"><a href="@url(repository)/issues/@issue.issueId">@issue.title</a></h4>
<pre>@Html(issue.highlightText)</pre> <pre>@Html(issue.highlightText)</pre>
<div class="small muted"> <div class="small muted">
Opened by <a href="@url(issue.openedUserName)" class="username">@issue.openedUserName</a> Opened by <a href="@url(issue.openedUserName)" class="username">@issue.openedUserName</a>
@@ -22,5 +26,7 @@
</div> </div>
</div> </div>
} }
@helper.html.paginator(page, issues.size, app.RepositorySearch.IssueLimit, 10,
s"${url(repository)}/search?q=${urlEncode(query)}&type=issue")
} }
} }