mirror of
https://github.com/gitbucket/gitbucket.git
synced 2025-11-07 14:05:52 +01:00
(refs #3)Start work for repository search.
This commit is contained in:
@@ -1,12 +1,27 @@
|
||||
package app
|
||||
|
||||
import util._
|
||||
import util.Directory._
|
||||
import service._
|
||||
import jp.sf.amateras.scalatra.forms._
|
||||
import org.eclipse.jgit.api.Git
|
||||
import org.apache.commons.io.FileUtils
|
||||
|
||||
class IndexController extends IndexControllerBase
|
||||
with RepositoryService with AccountService with SystemSettingsService with ActivityService
|
||||
with ReferrerAuthenticator
|
||||
|
||||
trait IndexControllerBase extends ControllerBase { self: RepositoryService
|
||||
with SystemSettingsService with ActivityService =>
|
||||
with SystemSettingsService with ActivityService
|
||||
with ReferrerAuthenticator =>
|
||||
|
||||
val searchForm = mapping(
|
||||
"query" -> trim(text(required)), // TODO optional?
|
||||
"owner" -> trim(text(required)),
|
||||
"repository" -> trim(text(required))
|
||||
)(SearchForm.apply)
|
||||
|
||||
case class SearchForm(query: String, owner: String, repository: String)
|
||||
|
||||
get("/"){
|
||||
val loginAccount = context.loginAccount
|
||||
@@ -18,4 +33,60 @@ trait IndexControllerBase extends ControllerBase { self: RepositoryService
|
||||
)
|
||||
}
|
||||
|
||||
post("/search", searchForm){ form =>
|
||||
redirect(s"${form.owner}/${form.repository}/search?q=${StringUtil.urlEncode(form.query)}")
|
||||
}
|
||||
|
||||
// TODO readable only
|
||||
get("/:owner/:repository/search")(referrersOnly { repository =>
|
||||
val owner = params("owner")
|
||||
val name = params("repository")
|
||||
val query = params("q")
|
||||
val target = params.getOrElse("type", "Code")
|
||||
|
||||
target.toLowerCase match {
|
||||
case "issue" => {
|
||||
// TODO search issue
|
||||
}
|
||||
case _ => {
|
||||
JGitUtil.withGit(getRepositoryDir(owner, name)){ git =>
|
||||
// TODO search code
|
||||
val dir = new java.io.File(getTemporaryDir(owner, name), "search")
|
||||
if(!dir.exists){
|
||||
val git = Git
|
||||
.cloneRepository.setDirectory(dir)
|
||||
.setURI(getRepositoryDir(owner, name).toURI.toString)
|
||||
.setBranch(repository.repository.defaultBranch)
|
||||
.call
|
||||
git.getRepository.close
|
||||
} else {
|
||||
val git = Git.open(dir)
|
||||
git.pull.call
|
||||
if(git.getRepository.getBranch != repository.repository.defaultBranch){
|
||||
git.checkout.setName(repository.repository.defaultBranch).call
|
||||
}
|
||||
git.getRepository.close
|
||||
}
|
||||
|
||||
search.html.code(searchDirectory(query, dir).map { file =>
|
||||
FileSearchResult(
|
||||
file.getAbsolutePath.substring(dir.getAbsolutePath.length + 1).replace('\\', '/'),
|
||||
new java.util.Date(file.lastModified)
|
||||
)
|
||||
}, query, repository)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
private def searchDirectory(query: String, dir: java.io.File, matched: List[java.io.File] = Nil): List[java.io.File] = {
|
||||
dir.listFiles.toList.flatMap {
|
||||
case file if(file.isDirectory && file.getName != ".git") => searchDirectory(query, file, matched)
|
||||
case file if(file.isFile && FileUtils.readFileToString(file).contains(query)) => matched :+ file
|
||||
case _ => matched
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
case class FileSearchResult(path: String, lastModified: java.util.Date)
|
||||
@@ -29,7 +29,7 @@
|
||||
<script src="@assets/zclip/ZeroClipboard.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<form action="@path/search" method="GET">
|
||||
<form id="search" action="@path/search" method="POST">
|
||||
<div class="navbar">
|
||||
<div class="navbar-inner">
|
||||
<div class="container">
|
||||
@@ -41,7 +41,13 @@
|
||||
<a class="brand" href="@path/">GitBucket</a>
|
||||
<div class="nav-collapse collapse pull-right">
|
||||
@repository.map { repository =>
|
||||
<input type="text" name="query" style="width: 300px;margin-top: 5px; margin-bottom: 0px;" placeholder="Search this repository"/>
|
||||
@if(loginAccount.isDefined){
|
||||
<input type="text" name="query" style="width: 300px; margin-top: 0px; margin-bottom: 0px;" placeholder="Search this repository"/>
|
||||
} else {
|
||||
<input type="text" name="query" style="width: 300px; margin-top: 5px; margin-bottom: 0px;" placeholder="Search this repository"/>
|
||||
}
|
||||
<input type="hidden" name="owner" value="@repository.owner"/>
|
||||
<input type="hidden" name="repository" value="@repository.name"/>
|
||||
}
|
||||
@if(loginAccount.isDefined){
|
||||
<a href="@url(loginAccount.get.userName)" class="username menu">@avatar(loginAccount.get.userName, 20) @loginAccount.get.userName</a>
|
||||
@@ -65,5 +71,12 @@
|
||||
<div class="container body">
|
||||
@body
|
||||
</div>
|
||||
<script>
|
||||
$(function(){
|
||||
$('#search').submit(function(){
|
||||
return $.trim($(this).find('input[name=query]').val()) != '';
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
16
src/main/twirl/search/code.scala.html
Normal file
16
src/main/twirl/search/code.scala.html
Normal file
@@ -0,0 +1,16 @@
|
||||
@(files: List[app.FileSearchResult], query: String, repository: service.RepositoryService.RepositoryInfo)(implicit context: app.Context)
|
||||
@import context._
|
||||
@import view.helpers._
|
||||
@html.main("Search Results", Some(repository)){
|
||||
@if(files.isEmpty){
|
||||
<h4>We couldn't find any code matching '@query'</h4>
|
||||
} else {
|
||||
<h4>We've found @files.size code @plural(files.size, "result")</h4>
|
||||
}
|
||||
@files.map { file =>
|
||||
<div>
|
||||
<div><a href="@url(repository)/blob/@repository.repository.defaultBranch/@file.path">@file.path</a></div>
|
||||
<div class="muted">@datetime(file.lastModified)</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user