mirror of
https://github.com/gitbucket/gitbucket.git
synced 2025-11-06 21:45:50 +01:00
(refs #3)Start work for repository search.
This commit is contained in:
@@ -1,13 +1,28 @@
|
|||||||
package app
|
package app
|
||||||
|
|
||||||
|
import util._
|
||||||
|
import util.Directory._
|
||||||
import service._
|
import service._
|
||||||
|
import jp.sf.amateras.scalatra.forms._
|
||||||
|
import org.eclipse.jgit.api.Git
|
||||||
|
import org.apache.commons.io.FileUtils
|
||||||
|
|
||||||
class IndexController extends IndexControllerBase
|
class IndexController extends IndexControllerBase
|
||||||
with RepositoryService with AccountService with SystemSettingsService with ActivityService
|
with RepositoryService with AccountService with SystemSettingsService with ActivityService
|
||||||
|
with ReferrerAuthenticator
|
||||||
|
|
||||||
trait IndexControllerBase extends ControllerBase { self: RepositoryService
|
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("/"){
|
get("/"){
|
||||||
val loginAccount = context.loginAccount
|
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>
|
<script src="@assets/zclip/ZeroClipboard.min.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<form action="@path/search" method="GET">
|
<form id="search" action="@path/search" method="POST">
|
||||||
<div class="navbar">
|
<div class="navbar">
|
||||||
<div class="navbar-inner">
|
<div class="navbar-inner">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
@@ -41,7 +41,13 @@
|
|||||||
<a class="brand" href="@path/">GitBucket</a>
|
<a class="brand" href="@path/">GitBucket</a>
|
||||||
<div class="nav-collapse collapse pull-right">
|
<div class="nav-collapse collapse pull-right">
|
||||||
@repository.map { repository =>
|
@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){
|
@if(loginAccount.isDefined){
|
||||||
<a href="@url(loginAccount.get.userName)" class="username menu">@avatar(loginAccount.get.userName, 20) @loginAccount.get.userName</a>
|
<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">
|
<div class="container body">
|
||||||
@body
|
@body
|
||||||
</div>
|
</div>
|
||||||
|
<script>
|
||||||
|
$(function(){
|
||||||
|
$('#search').submit(function(){
|
||||||
|
return $.trim($(this).find('input[name=query]').val()) != '';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</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