Newer
Older
gitbucket_jkp / src / main / scala / app / IndexController.scala
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 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

    html.index(getRecentActivities(),
      getAccessibleRepositories(loginAccount, baseUrl),
      loadSystemSettings(),
      loginAccount.map{ account => getRepositoryNamesOfUser(account.userName) }.getOrElse(Nil)
    )
  }

  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)