mirror of
https://github.com/gitbucket/gitbucket.git
synced 2025-11-08 14:35:52 +01:00
(refs #508)Basic filter box implementation
This commit is contained in:
@@ -9,7 +9,6 @@ import util.Implicits._
|
|||||||
import util.ControlUtil._
|
import util.ControlUtil._
|
||||||
import org.scalatra.Ok
|
import org.scalatra.Ok
|
||||||
import model.Issue
|
import model.Issue
|
||||||
import plugin.PluginSystem
|
|
||||||
|
|
||||||
class IssuesController extends IssuesControllerBase
|
class IssuesController extends IssuesControllerBase
|
||||||
with IssuesService with RepositoryService with AccountService with LabelsService with MilestonesService with ActivityService
|
with IssuesService with RepositoryService with AccountService with LabelsService with MilestonesService with ActivityService
|
||||||
@@ -50,7 +49,12 @@ trait IssuesControllerBase extends ControllerBase {
|
|||||||
)(IssueStateForm.apply)
|
)(IssueStateForm.apply)
|
||||||
|
|
||||||
get("/:owner/:repository/issues")(referrersOnly { repository =>
|
get("/:owner/:repository/issues")(referrersOnly { repository =>
|
||||||
searchIssues(repository)
|
val q = request.getParameter("q")
|
||||||
|
if(Option(q).exists(_.contains("is:pr"))){
|
||||||
|
redirect(s"/${repository.owner}/${repository.name}/pulls?q=" + StringUtil.urlEncode(q))
|
||||||
|
} else {
|
||||||
|
searchIssues(repository)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
get("/:owner/:repository/issues/:id")(referrersOnly { repository =>
|
get("/:owner/:repository/issues/:id")(referrersOnly { repository =>
|
||||||
@@ -390,7 +394,14 @@ trait IssuesControllerBase extends ControllerBase {
|
|||||||
|
|
||||||
// retrieve search condition
|
// retrieve search condition
|
||||||
val condition = session.putAndGet(sessionKey,
|
val condition = session.putAndGet(sessionKey,
|
||||||
if(request.hasQueryString) IssueSearchCondition(request)
|
if(request.hasQueryString){
|
||||||
|
val q = request.getParameter("q")
|
||||||
|
if(q == null){
|
||||||
|
IssueSearchCondition(request)
|
||||||
|
} else {
|
||||||
|
IssueSearchCondition(q, getMilestones(owner, repoName).map(x => (x.title, x.milestoneId)).toMap)
|
||||||
|
}
|
||||||
|
}
|
||||||
else session.getAs[IssueSearchCondition](sessionKey).getOrElse(IssueSearchCondition())
|
else session.getAs[IssueSearchCondition](sessionKey).getOrElse(IssueSearchCondition())
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,475 +1,483 @@
|
|||||||
package app
|
package app
|
||||||
|
|
||||||
import util.{LockUtil, CollaboratorsAuthenticator, JGitUtil, ReferrerAuthenticator, Notifier, Keys}
|
import util._
|
||||||
import util.Directory._
|
import util.Directory._
|
||||||
import util.Implicits._
|
import util.Implicits._
|
||||||
import util.ControlUtil._
|
import util.ControlUtil._
|
||||||
import service._
|
import service._
|
||||||
import org.eclipse.jgit.api.Git
|
import org.eclipse.jgit.api.Git
|
||||||
import jp.sf.amateras.scalatra.forms._
|
import jp.sf.amateras.scalatra.forms._
|
||||||
import org.eclipse.jgit.transport.RefSpec
|
import org.eclipse.jgit.transport.RefSpec
|
||||||
import scala.collection.JavaConverters._
|
import scala.collection.JavaConverters._
|
||||||
import org.eclipse.jgit.lib.{ObjectId, CommitBuilder, PersonIdent}
|
import org.eclipse.jgit.lib.{ObjectId, CommitBuilder, PersonIdent}
|
||||||
import service.IssuesService._
|
import service.IssuesService._
|
||||||
import service.PullRequestService._
|
import service.PullRequestService._
|
||||||
import util.JGitUtil.DiffInfo
|
import util.JGitUtil.DiffInfo
|
||||||
import util.JGitUtil.CommitInfo
|
import util.JGitUtil.CommitInfo
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import org.eclipse.jgit.merge.MergeStrategy
|
import org.eclipse.jgit.merge.MergeStrategy
|
||||||
import org.eclipse.jgit.errors.NoMergeBaseException
|
import org.eclipse.jgit.errors.NoMergeBaseException
|
||||||
import service.WebHookService.WebHookPayload
|
import service.WebHookService.WebHookPayload
|
||||||
|
import util.JGitUtil.DiffInfo
|
||||||
class PullRequestsController extends PullRequestsControllerBase
|
import scala.Some
|
||||||
with RepositoryService with AccountService with IssuesService with PullRequestService with MilestonesService with LabelsService
|
import util.JGitUtil.CommitInfo
|
||||||
with ActivityService with WebHookService with ReferrerAuthenticator with CollaboratorsAuthenticator
|
|
||||||
|
class PullRequestsController extends PullRequestsControllerBase
|
||||||
trait PullRequestsControllerBase extends ControllerBase {
|
with RepositoryService with AccountService with IssuesService with PullRequestService with MilestonesService with LabelsService
|
||||||
self: RepositoryService with AccountService with IssuesService with MilestonesService with LabelsService
|
with ActivityService with WebHookService with ReferrerAuthenticator with CollaboratorsAuthenticator
|
||||||
with ActivityService with PullRequestService with WebHookService with ReferrerAuthenticator with CollaboratorsAuthenticator =>
|
|
||||||
|
trait PullRequestsControllerBase extends ControllerBase {
|
||||||
private val logger = LoggerFactory.getLogger(classOf[PullRequestsControllerBase])
|
self: RepositoryService with AccountService with IssuesService with MilestonesService with LabelsService
|
||||||
|
with ActivityService with PullRequestService with WebHookService with ReferrerAuthenticator with CollaboratorsAuthenticator =>
|
||||||
val pullRequestForm = mapping(
|
|
||||||
"title" -> trim(label("Title" , text(required, maxlength(100)))),
|
private val logger = LoggerFactory.getLogger(classOf[PullRequestsControllerBase])
|
||||||
"content" -> trim(label("Content", optional(text()))),
|
|
||||||
"targetUserName" -> trim(text(required, maxlength(100))),
|
val pullRequestForm = mapping(
|
||||||
"targetBranch" -> trim(text(required, maxlength(100))),
|
"title" -> trim(label("Title" , text(required, maxlength(100)))),
|
||||||
"requestUserName" -> trim(text(required, maxlength(100))),
|
"content" -> trim(label("Content", optional(text()))),
|
||||||
"requestRepositoryName" -> trim(text(required, maxlength(100))),
|
"targetUserName" -> trim(text(required, maxlength(100))),
|
||||||
"requestBranch" -> trim(text(required, maxlength(100))),
|
"targetBranch" -> trim(text(required, maxlength(100))),
|
||||||
"commitIdFrom" -> trim(text(required, maxlength(40))),
|
"requestUserName" -> trim(text(required, maxlength(100))),
|
||||||
"commitIdTo" -> trim(text(required, maxlength(40)))
|
"requestRepositoryName" -> trim(text(required, maxlength(100))),
|
||||||
)(PullRequestForm.apply)
|
"requestBranch" -> trim(text(required, maxlength(100))),
|
||||||
|
"commitIdFrom" -> trim(text(required, maxlength(40))),
|
||||||
val mergeForm = mapping(
|
"commitIdTo" -> trim(text(required, maxlength(40)))
|
||||||
"message" -> trim(label("Message", text(required)))
|
)(PullRequestForm.apply)
|
||||||
)(MergeForm.apply)
|
|
||||||
|
val mergeForm = mapping(
|
||||||
case class PullRequestForm(
|
"message" -> trim(label("Message", text(required)))
|
||||||
title: String,
|
)(MergeForm.apply)
|
||||||
content: Option[String],
|
|
||||||
targetUserName: String,
|
case class PullRequestForm(
|
||||||
targetBranch: String,
|
title: String,
|
||||||
requestUserName: String,
|
content: Option[String],
|
||||||
requestRepositoryName: String,
|
targetUserName: String,
|
||||||
requestBranch: String,
|
targetBranch: String,
|
||||||
commitIdFrom: String,
|
requestUserName: String,
|
||||||
commitIdTo: String)
|
requestRepositoryName: String,
|
||||||
|
requestBranch: String,
|
||||||
case class MergeForm(message: String)
|
commitIdFrom: String,
|
||||||
|
commitIdTo: String)
|
||||||
get("/:owner/:repository/pulls")(referrersOnly { repository =>
|
|
||||||
searchPullRequests(None, repository)
|
case class MergeForm(message: String)
|
||||||
})
|
|
||||||
|
get("/:owner/:repository/pulls")(referrersOnly { repository =>
|
||||||
get("/:owner/:repository/pull/:id")(referrersOnly { repository =>
|
val q = request.getParameter("q")
|
||||||
params("id").toIntOpt.flatMap{ issueId =>
|
if(Option(q).exists(_.contains("is:issue"))){
|
||||||
val owner = repository.owner
|
redirect(s"/${repository.owner}/${repository.name}/issues?q=" + StringUtil.urlEncode(q))
|
||||||
val name = repository.name
|
} else {
|
||||||
getPullRequest(owner, name, issueId) map { case(issue, pullreq) =>
|
searchPullRequests(None, repository)
|
||||||
using(Git.open(getRepositoryDir(owner, name))){ git =>
|
}
|
||||||
val (commits, diffs) =
|
})
|
||||||
getRequestCompareInfo(owner, name, pullreq.commitIdFrom, owner, name, pullreq.commitIdTo)
|
|
||||||
|
get("/:owner/:repository/pull/:id")(referrersOnly { repository =>
|
||||||
pulls.html.pullreq(
|
params("id").toIntOpt.flatMap{ issueId =>
|
||||||
issue, pullreq,
|
val owner = repository.owner
|
||||||
getComments(owner, name, issueId),
|
val name = repository.name
|
||||||
getIssueLabels(owner, name, issueId),
|
getPullRequest(owner, name, issueId) map { case(issue, pullreq) =>
|
||||||
(getCollaborators(owner, name) ::: (if(getAccountByUserName(owner).get.isGroupAccount) Nil else List(owner))).sorted,
|
using(Git.open(getRepositoryDir(owner, name))){ git =>
|
||||||
getMilestonesWithIssueCount(owner, name),
|
val (commits, diffs) =
|
||||||
getLabels(owner, name),
|
getRequestCompareInfo(owner, name, pullreq.commitIdFrom, owner, name, pullreq.commitIdTo)
|
||||||
commits,
|
|
||||||
diffs,
|
pulls.html.pullreq(
|
||||||
hasWritePermission(owner, name, context.loginAccount),
|
issue, pullreq,
|
||||||
repository)
|
getComments(owner, name, issueId),
|
||||||
}
|
getIssueLabels(owner, name, issueId),
|
||||||
}
|
(getCollaborators(owner, name) ::: (if(getAccountByUserName(owner).get.isGroupAccount) Nil else List(owner))).sorted,
|
||||||
} getOrElse NotFound
|
getMilestonesWithIssueCount(owner, name),
|
||||||
})
|
getLabels(owner, name),
|
||||||
|
commits,
|
||||||
ajaxGet("/:owner/:repository/pull/:id/mergeguide")(collaboratorsOnly { repository =>
|
diffs,
|
||||||
params("id").toIntOpt.flatMap{ issueId =>
|
hasWritePermission(owner, name, context.loginAccount),
|
||||||
val owner = repository.owner
|
repository)
|
||||||
val name = repository.name
|
}
|
||||||
getPullRequest(owner, name, issueId) map { case(issue, pullreq) =>
|
}
|
||||||
pulls.html.mergeguide(
|
} getOrElse NotFound
|
||||||
checkConflictInPullRequest(owner, name, pullreq.branch, pullreq.requestUserName, name, pullreq.requestBranch, issueId),
|
})
|
||||||
pullreq,
|
|
||||||
s"${context.baseUrl}/git/${pullreq.requestUserName}/${pullreq.requestRepositoryName}.git")
|
ajaxGet("/:owner/:repository/pull/:id/mergeguide")(collaboratorsOnly { repository =>
|
||||||
}
|
params("id").toIntOpt.flatMap{ issueId =>
|
||||||
} getOrElse NotFound
|
val owner = repository.owner
|
||||||
})
|
val name = repository.name
|
||||||
|
getPullRequest(owner, name, issueId) map { case(issue, pullreq) =>
|
||||||
get("/:owner/:repository/pull/:id/delete/*")(collaboratorsOnly { repository =>
|
pulls.html.mergeguide(
|
||||||
params("id").toIntOpt.map { issueId =>
|
checkConflictInPullRequest(owner, name, pullreq.branch, pullreq.requestUserName, name, pullreq.requestBranch, issueId),
|
||||||
val branchName = multiParams("splat").head
|
pullreq,
|
||||||
val userName = context.loginAccount.get.userName
|
s"${context.baseUrl}/git/${pullreq.requestUserName}/${pullreq.requestRepositoryName}.git")
|
||||||
if(repository.repository.defaultBranch != branchName){
|
}
|
||||||
using(Git.open(getRepositoryDir(repository.owner, repository.name))){ git =>
|
} getOrElse NotFound
|
||||||
git.branchDelete().setForce(true).setBranchNames(branchName).call()
|
})
|
||||||
recordDeleteBranchActivity(repository.owner, repository.name, userName, branchName)
|
|
||||||
}
|
get("/:owner/:repository/pull/:id/delete/*")(collaboratorsOnly { repository =>
|
||||||
}
|
params("id").toIntOpt.map { issueId =>
|
||||||
createComment(repository.owner, repository.name, userName, issueId, branchName, "delete_branch")
|
val branchName = multiParams("splat").head
|
||||||
redirect(s"/${repository.owner}/${repository.name}/pull/${issueId}")
|
val userName = context.loginAccount.get.userName
|
||||||
} getOrElse NotFound
|
if(repository.repository.defaultBranch != branchName){
|
||||||
})
|
using(Git.open(getRepositoryDir(repository.owner, repository.name))){ git =>
|
||||||
|
git.branchDelete().setForce(true).setBranchNames(branchName).call()
|
||||||
post("/:owner/:repository/pull/:id/merge", mergeForm)(collaboratorsOnly { (form, repository) =>
|
recordDeleteBranchActivity(repository.owner, repository.name, userName, branchName)
|
||||||
params("id").toIntOpt.flatMap { issueId =>
|
}
|
||||||
val owner = repository.owner
|
}
|
||||||
val name = repository.name
|
createComment(repository.owner, repository.name, userName, issueId, branchName, "delete_branch")
|
||||||
LockUtil.lock(s"${owner}/${name}"){
|
redirect(s"/${repository.owner}/${repository.name}/pull/${issueId}")
|
||||||
getPullRequest(owner, name, issueId).map { case (issue, pullreq) =>
|
} getOrElse NotFound
|
||||||
using(Git.open(getRepositoryDir(owner, name))) { git =>
|
})
|
||||||
// mark issue as merged and close.
|
|
||||||
val loginAccount = context.loginAccount.get
|
post("/:owner/:repository/pull/:id/merge", mergeForm)(collaboratorsOnly { (form, repository) =>
|
||||||
createComment(owner, name, loginAccount.userName, issueId, form.message, "merge")
|
params("id").toIntOpt.flatMap { issueId =>
|
||||||
createComment(owner, name, loginAccount.userName, issueId, "Close", "close")
|
val owner = repository.owner
|
||||||
updateClosed(owner, name, issueId, true)
|
val name = repository.name
|
||||||
|
LockUtil.lock(s"${owner}/${name}"){
|
||||||
// record activity
|
getPullRequest(owner, name, issueId).map { case (issue, pullreq) =>
|
||||||
recordMergeActivity(owner, name, loginAccount.userName, issueId, form.message)
|
using(Git.open(getRepositoryDir(owner, name))) { git =>
|
||||||
|
// mark issue as merged and close.
|
||||||
// merge
|
val loginAccount = context.loginAccount.get
|
||||||
val mergeBaseRefName = s"refs/heads/${pullreq.branch}"
|
createComment(owner, name, loginAccount.userName, issueId, form.message, "merge")
|
||||||
val merger = MergeStrategy.RECURSIVE.newMerger(git.getRepository, true)
|
createComment(owner, name, loginAccount.userName, issueId, "Close", "close")
|
||||||
val mergeBaseTip = git.getRepository.resolve(mergeBaseRefName)
|
updateClosed(owner, name, issueId, true)
|
||||||
val mergeTip = git.getRepository.resolve(s"refs/pull/${issueId}/head")
|
|
||||||
val conflicted = try {
|
// record activity
|
||||||
!merger.merge(mergeBaseTip, mergeTip)
|
recordMergeActivity(owner, name, loginAccount.userName, issueId, form.message)
|
||||||
} catch {
|
|
||||||
case e: NoMergeBaseException => true
|
// merge
|
||||||
}
|
val mergeBaseRefName = s"refs/heads/${pullreq.branch}"
|
||||||
if (conflicted) {
|
val merger = MergeStrategy.RECURSIVE.newMerger(git.getRepository, true)
|
||||||
throw new RuntimeException("This pull request can't merge automatically.")
|
val mergeBaseTip = git.getRepository.resolve(mergeBaseRefName)
|
||||||
}
|
val mergeTip = git.getRepository.resolve(s"refs/pull/${issueId}/head")
|
||||||
|
val conflicted = try {
|
||||||
// creates merge commit
|
!merger.merge(mergeBaseTip, mergeTip)
|
||||||
val mergeCommit = new CommitBuilder()
|
} catch {
|
||||||
mergeCommit.setTreeId(merger.getResultTreeId)
|
case e: NoMergeBaseException => true
|
||||||
mergeCommit.setParentIds(Array[ObjectId](mergeBaseTip, mergeTip): _*)
|
}
|
||||||
val personIdent = new PersonIdent(loginAccount.fullName, loginAccount.mailAddress)
|
if (conflicted) {
|
||||||
mergeCommit.setAuthor(personIdent)
|
throw new RuntimeException("This pull request can't merge automatically.")
|
||||||
mergeCommit.setCommitter(personIdent)
|
}
|
||||||
mergeCommit.setMessage(s"Merge pull request #${issueId} from ${pullreq.requestUserName}/${pullreq.requestBranch}\n\n" +
|
|
||||||
form.message)
|
// creates merge commit
|
||||||
|
val mergeCommit = new CommitBuilder()
|
||||||
// insertObject and got mergeCommit Object Id
|
mergeCommit.setTreeId(merger.getResultTreeId)
|
||||||
val inserter = git.getRepository.newObjectInserter
|
mergeCommit.setParentIds(Array[ObjectId](mergeBaseTip, mergeTip): _*)
|
||||||
val mergeCommitId = inserter.insert(mergeCommit)
|
val personIdent = new PersonIdent(loginAccount.fullName, loginAccount.mailAddress)
|
||||||
inserter.flush()
|
mergeCommit.setAuthor(personIdent)
|
||||||
inserter.release()
|
mergeCommit.setCommitter(personIdent)
|
||||||
|
mergeCommit.setMessage(s"Merge pull request #${issueId} from ${pullreq.requestUserName}/${pullreq.requestBranch}\n\n" +
|
||||||
// update refs
|
form.message)
|
||||||
val refUpdate = git.getRepository.updateRef(mergeBaseRefName)
|
|
||||||
refUpdate.setNewObjectId(mergeCommitId)
|
// insertObject and got mergeCommit Object Id
|
||||||
refUpdate.setForceUpdate(false)
|
val inserter = git.getRepository.newObjectInserter
|
||||||
refUpdate.setRefLogIdent(personIdent)
|
val mergeCommitId = inserter.insert(mergeCommit)
|
||||||
refUpdate.setRefLogMessage("merged", true)
|
inserter.flush()
|
||||||
refUpdate.update()
|
inserter.release()
|
||||||
|
|
||||||
val (commits, _) = getRequestCompareInfo(owner, name, pullreq.commitIdFrom,
|
// update refs
|
||||||
pullreq.requestUserName, pullreq.requestRepositoryName, pullreq.commitIdTo)
|
val refUpdate = git.getRepository.updateRef(mergeBaseRefName)
|
||||||
|
refUpdate.setNewObjectId(mergeCommitId)
|
||||||
// close issue by content of pull request
|
refUpdate.setForceUpdate(false)
|
||||||
val defaultBranch = getRepository(owner, name, context.baseUrl).get.repository.defaultBranch
|
refUpdate.setRefLogIdent(personIdent)
|
||||||
if(pullreq.branch == defaultBranch){
|
refUpdate.setRefLogMessage("merged", true)
|
||||||
commits.flatten.foreach { commit =>
|
refUpdate.update()
|
||||||
closeIssuesFromMessage(commit.fullMessage, loginAccount.userName, owner, name)
|
|
||||||
}
|
val (commits, _) = getRequestCompareInfo(owner, name, pullreq.commitIdFrom,
|
||||||
issue.content match {
|
pullreq.requestUserName, pullreq.requestRepositoryName, pullreq.commitIdTo)
|
||||||
case Some(content) => closeIssuesFromMessage(content, loginAccount.userName, owner, name)
|
|
||||||
case _ =>
|
// close issue by content of pull request
|
||||||
}
|
val defaultBranch = getRepository(owner, name, context.baseUrl).get.repository.defaultBranch
|
||||||
closeIssuesFromMessage(form.message, loginAccount.userName, owner, name)
|
if(pullreq.branch == defaultBranch){
|
||||||
}
|
commits.flatten.foreach { commit =>
|
||||||
// call web hook
|
closeIssuesFromMessage(commit.fullMessage, loginAccount.userName, owner, name)
|
||||||
getWebHookURLs(owner, name) match {
|
}
|
||||||
case webHookURLs if(webHookURLs.nonEmpty) =>
|
issue.content match {
|
||||||
for(ownerAccount <- getAccountByUserName(owner)){
|
case Some(content) => closeIssuesFromMessage(content, loginAccount.userName, owner, name)
|
||||||
callWebHook(owner, name, webHookURLs,
|
case _ =>
|
||||||
WebHookPayload(git, loginAccount, mergeBaseRefName, repository, commits.flatten.toList, ownerAccount))
|
}
|
||||||
}
|
closeIssuesFromMessage(form.message, loginAccount.userName, owner, name)
|
||||||
case _ =>
|
}
|
||||||
}
|
// call web hook
|
||||||
|
getWebHookURLs(owner, name) match {
|
||||||
// notifications
|
case webHookURLs if(webHookURLs.nonEmpty) =>
|
||||||
Notifier().toNotify(repository, issueId, "merge"){
|
for(ownerAccount <- getAccountByUserName(owner)){
|
||||||
Notifier.msgStatus(s"${context.baseUrl}/${owner}/${name}/pull/${issueId}")
|
callWebHook(owner, name, webHookURLs,
|
||||||
}
|
WebHookPayload(git, loginAccount, mergeBaseRefName, repository, commits.flatten.toList, ownerAccount))
|
||||||
|
}
|
||||||
redirect(s"/${owner}/${name}/pull/${issueId}")
|
case _ =>
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
// notifications
|
||||||
} getOrElse NotFound
|
Notifier().toNotify(repository, issueId, "merge"){
|
||||||
})
|
Notifier.msgStatus(s"${context.baseUrl}/${owner}/${name}/pull/${issueId}")
|
||||||
|
}
|
||||||
get("/:owner/:repository/compare")(referrersOnly { forkedRepository =>
|
|
||||||
(forkedRepository.repository.originUserName, forkedRepository.repository.originRepositoryName) match {
|
redirect(s"/${owner}/${name}/pull/${issueId}")
|
||||||
case (Some(originUserName), Some(originRepositoryName)) => {
|
}
|
||||||
getRepository(originUserName, originRepositoryName, context.baseUrl).map { originRepository =>
|
}
|
||||||
using(
|
}
|
||||||
Git.open(getRepositoryDir(originUserName, originRepositoryName)),
|
} getOrElse NotFound
|
||||||
Git.open(getRepositoryDir(forkedRepository.owner, forkedRepository.name))
|
})
|
||||||
){ (oldGit, newGit) =>
|
|
||||||
val oldBranch = JGitUtil.getDefaultBranch(oldGit, originRepository).get._2
|
get("/:owner/:repository/compare")(referrersOnly { forkedRepository =>
|
||||||
val newBranch = JGitUtil.getDefaultBranch(newGit, forkedRepository).get._2
|
(forkedRepository.repository.originUserName, forkedRepository.repository.originRepositoryName) match {
|
||||||
|
case (Some(originUserName), Some(originRepositoryName)) => {
|
||||||
redirect(s"/${forkedRepository.owner}/${forkedRepository.name}/compare/${originUserName}:${oldBranch}...${newBranch}")
|
getRepository(originUserName, originRepositoryName, context.baseUrl).map { originRepository =>
|
||||||
}
|
using(
|
||||||
} getOrElse NotFound
|
Git.open(getRepositoryDir(originUserName, originRepositoryName)),
|
||||||
}
|
Git.open(getRepositoryDir(forkedRepository.owner, forkedRepository.name))
|
||||||
case _ => {
|
){ (oldGit, newGit) =>
|
||||||
using(Git.open(getRepositoryDir(forkedRepository.owner, forkedRepository.name))){ git =>
|
val oldBranch = JGitUtil.getDefaultBranch(oldGit, originRepository).get._2
|
||||||
JGitUtil.getDefaultBranch(git, forkedRepository).map { case (_, defaultBranch) =>
|
val newBranch = JGitUtil.getDefaultBranch(newGit, forkedRepository).get._2
|
||||||
redirect(s"/${forkedRepository.owner}/${forkedRepository.name}/compare/${defaultBranch}...${defaultBranch}")
|
|
||||||
} getOrElse {
|
redirect(s"/${forkedRepository.owner}/${forkedRepository.name}/compare/${originUserName}:${oldBranch}...${newBranch}")
|
||||||
redirect(s"/${forkedRepository.owner}/${forkedRepository.name}")
|
}
|
||||||
}
|
} getOrElse NotFound
|
||||||
}
|
}
|
||||||
}
|
case _ => {
|
||||||
}
|
using(Git.open(getRepositoryDir(forkedRepository.owner, forkedRepository.name))){ git =>
|
||||||
})
|
JGitUtil.getDefaultBranch(git, forkedRepository).map { case (_, defaultBranch) =>
|
||||||
|
redirect(s"/${forkedRepository.owner}/${forkedRepository.name}/compare/${defaultBranch}...${defaultBranch}")
|
||||||
get("/:owner/:repository/compare/*...*")(referrersOnly { forkedRepository =>
|
} getOrElse {
|
||||||
val Seq(origin, forked) = multiParams("splat")
|
redirect(s"/${forkedRepository.owner}/${forkedRepository.name}")
|
||||||
val (originOwner, tmpOriginBranch) = parseCompareIdentifie(origin, forkedRepository.owner)
|
}
|
||||||
val (forkedOwner, tmpForkedBranch) = parseCompareIdentifie(forked, forkedRepository.owner)
|
}
|
||||||
|
}
|
||||||
(for(
|
}
|
||||||
originRepositoryName <- if(originOwner == forkedOwner){
|
})
|
||||||
Some(forkedRepository.name)
|
|
||||||
} else {
|
get("/:owner/:repository/compare/*...*")(referrersOnly { forkedRepository =>
|
||||||
forkedRepository.repository.originRepositoryName.orElse {
|
val Seq(origin, forked) = multiParams("splat")
|
||||||
getForkedRepositories(forkedRepository.owner, forkedRepository.name).find(_._1 == originOwner).map(_._2)
|
val (originOwner, tmpOriginBranch) = parseCompareIdentifie(origin, forkedRepository.owner)
|
||||||
}
|
val (forkedOwner, tmpForkedBranch) = parseCompareIdentifie(forked, forkedRepository.owner)
|
||||||
};
|
|
||||||
originRepository <- getRepository(originOwner, originRepositoryName, context.baseUrl)
|
(for(
|
||||||
) yield {
|
originRepositoryName <- if(originOwner == forkedOwner){
|
||||||
using(
|
Some(forkedRepository.name)
|
||||||
Git.open(getRepositoryDir(originRepository.owner, originRepository.name)),
|
} else {
|
||||||
Git.open(getRepositoryDir(forkedRepository.owner, forkedRepository.name))
|
forkedRepository.repository.originRepositoryName.orElse {
|
||||||
){ case (oldGit, newGit) =>
|
getForkedRepositories(forkedRepository.owner, forkedRepository.name).find(_._1 == originOwner).map(_._2)
|
||||||
val originBranch = JGitUtil.getDefaultBranch(oldGit, originRepository, tmpOriginBranch).get._2
|
}
|
||||||
val forkedBranch = JGitUtil.getDefaultBranch(newGit, forkedRepository, tmpForkedBranch).get._2
|
};
|
||||||
|
originRepository <- getRepository(originOwner, originRepositoryName, context.baseUrl)
|
||||||
val forkedId = JGitUtil.getForkedCommitId(oldGit, newGit,
|
) yield {
|
||||||
originRepository.owner, originRepository.name, originBranch,
|
using(
|
||||||
forkedRepository.owner, forkedRepository.name, forkedBranch)
|
Git.open(getRepositoryDir(originRepository.owner, originRepository.name)),
|
||||||
|
Git.open(getRepositoryDir(forkedRepository.owner, forkedRepository.name))
|
||||||
val oldId = oldGit.getRepository.resolve(forkedId)
|
){ case (oldGit, newGit) =>
|
||||||
val newId = newGit.getRepository.resolve(forkedBranch)
|
val originBranch = JGitUtil.getDefaultBranch(oldGit, originRepository, tmpOriginBranch).get._2
|
||||||
|
val forkedBranch = JGitUtil.getDefaultBranch(newGit, forkedRepository, tmpForkedBranch).get._2
|
||||||
val (commits, diffs) = getRequestCompareInfo(
|
|
||||||
originRepository.owner, originRepository.name, oldId.getName,
|
val forkedId = JGitUtil.getForkedCommitId(oldGit, newGit,
|
||||||
forkedRepository.owner, forkedRepository.name, newId.getName)
|
originRepository.owner, originRepository.name, originBranch,
|
||||||
|
forkedRepository.owner, forkedRepository.name, forkedBranch)
|
||||||
pulls.html.compare(
|
|
||||||
commits,
|
val oldId = oldGit.getRepository.resolve(forkedId)
|
||||||
diffs,
|
val newId = newGit.getRepository.resolve(forkedBranch)
|
||||||
(forkedRepository.repository.originUserName, forkedRepository.repository.originRepositoryName) match {
|
|
||||||
case (Some(userName), Some(repositoryName)) => (userName, repositoryName) :: getForkedRepositories(userName, repositoryName)
|
val (commits, diffs) = getRequestCompareInfo(
|
||||||
case _ => (forkedRepository.owner, forkedRepository.name) :: getForkedRepositories(forkedRepository.owner, forkedRepository.name)
|
originRepository.owner, originRepository.name, oldId.getName,
|
||||||
},
|
forkedRepository.owner, forkedRepository.name, newId.getName)
|
||||||
originBranch,
|
|
||||||
forkedBranch,
|
pulls.html.compare(
|
||||||
oldId.getName,
|
commits,
|
||||||
newId.getName,
|
diffs,
|
||||||
forkedRepository,
|
(forkedRepository.repository.originUserName, forkedRepository.repository.originRepositoryName) match {
|
||||||
originRepository,
|
case (Some(userName), Some(repositoryName)) => (userName, repositoryName) :: getForkedRepositories(userName, repositoryName)
|
||||||
forkedRepository,
|
case _ => (forkedRepository.owner, forkedRepository.name) :: getForkedRepositories(forkedRepository.owner, forkedRepository.name)
|
||||||
hasWritePermission(forkedRepository.owner, forkedRepository.name, context.loginAccount))
|
},
|
||||||
}
|
originBranch,
|
||||||
}) getOrElse NotFound
|
forkedBranch,
|
||||||
})
|
oldId.getName,
|
||||||
|
newId.getName,
|
||||||
ajaxGet("/:owner/:repository/compare/*...*/mergecheck")(collaboratorsOnly { forkedRepository =>
|
forkedRepository,
|
||||||
val Seq(origin, forked) = multiParams("splat")
|
originRepository,
|
||||||
val (originOwner, tmpOriginBranch) = parseCompareIdentifie(origin, forkedRepository.owner)
|
forkedRepository,
|
||||||
val (forkedOwner, tmpForkedBranch) = parseCompareIdentifie(forked, forkedRepository.owner)
|
hasWritePermission(forkedRepository.owner, forkedRepository.name, context.loginAccount))
|
||||||
|
}
|
||||||
(for(
|
}) getOrElse NotFound
|
||||||
originRepositoryName <- if(originOwner == forkedOwner){
|
})
|
||||||
Some(forkedRepository.name)
|
|
||||||
} else {
|
ajaxGet("/:owner/:repository/compare/*...*/mergecheck")(collaboratorsOnly { forkedRepository =>
|
||||||
forkedRepository.repository.originRepositoryName.orElse {
|
val Seq(origin, forked) = multiParams("splat")
|
||||||
getForkedRepositories(forkedRepository.owner, forkedRepository.name).find(_._1 == originOwner).map(_._2)
|
val (originOwner, tmpOriginBranch) = parseCompareIdentifie(origin, forkedRepository.owner)
|
||||||
}
|
val (forkedOwner, tmpForkedBranch) = parseCompareIdentifie(forked, forkedRepository.owner)
|
||||||
};
|
|
||||||
originRepository <- getRepository(originOwner, originRepositoryName, context.baseUrl)
|
(for(
|
||||||
) yield {
|
originRepositoryName <- if(originOwner == forkedOwner){
|
||||||
using(
|
Some(forkedRepository.name)
|
||||||
Git.open(getRepositoryDir(originRepository.owner, originRepository.name)),
|
} else {
|
||||||
Git.open(getRepositoryDir(forkedRepository.owner, forkedRepository.name))
|
forkedRepository.repository.originRepositoryName.orElse {
|
||||||
){ case (oldGit, newGit) =>
|
getForkedRepositories(forkedRepository.owner, forkedRepository.name).find(_._1 == originOwner).map(_._2)
|
||||||
val originBranch = JGitUtil.getDefaultBranch(oldGit, originRepository, tmpOriginBranch).get._2
|
}
|
||||||
val forkedBranch = JGitUtil.getDefaultBranch(newGit, forkedRepository, tmpForkedBranch).get._2
|
};
|
||||||
|
originRepository <- getRepository(originOwner, originRepositoryName, context.baseUrl)
|
||||||
pulls.html.mergecheck(
|
) yield {
|
||||||
checkConflict(originRepository.owner, originRepository.name, originBranch,
|
using(
|
||||||
forkedRepository.owner, forkedRepository.name, forkedBranch))
|
Git.open(getRepositoryDir(originRepository.owner, originRepository.name)),
|
||||||
}
|
Git.open(getRepositoryDir(forkedRepository.owner, forkedRepository.name))
|
||||||
}) getOrElse NotFound
|
){ case (oldGit, newGit) =>
|
||||||
})
|
val originBranch = JGitUtil.getDefaultBranch(oldGit, originRepository, tmpOriginBranch).get._2
|
||||||
|
val forkedBranch = JGitUtil.getDefaultBranch(newGit, forkedRepository, tmpForkedBranch).get._2
|
||||||
post("/:owner/:repository/pulls/new", pullRequestForm)(referrersOnly { (form, repository) =>
|
|
||||||
val loginUserName = context.loginAccount.get.userName
|
pulls.html.mergecheck(
|
||||||
|
checkConflict(originRepository.owner, originRepository.name, originBranch,
|
||||||
val issueId = createIssue(
|
forkedRepository.owner, forkedRepository.name, forkedBranch))
|
||||||
owner = repository.owner,
|
}
|
||||||
repository = repository.name,
|
}) getOrElse NotFound
|
||||||
loginUser = loginUserName,
|
})
|
||||||
title = form.title,
|
|
||||||
content = form.content,
|
post("/:owner/:repository/pulls/new", pullRequestForm)(referrersOnly { (form, repository) =>
|
||||||
assignedUserName = None,
|
val loginUserName = context.loginAccount.get.userName
|
||||||
milestoneId = None,
|
|
||||||
isPullRequest = true)
|
val issueId = createIssue(
|
||||||
|
owner = repository.owner,
|
||||||
createPullRequest(
|
repository = repository.name,
|
||||||
originUserName = repository.owner,
|
loginUser = loginUserName,
|
||||||
originRepositoryName = repository.name,
|
title = form.title,
|
||||||
issueId = issueId,
|
content = form.content,
|
||||||
originBranch = form.targetBranch,
|
assignedUserName = None,
|
||||||
requestUserName = form.requestUserName,
|
milestoneId = None,
|
||||||
requestRepositoryName = form.requestRepositoryName,
|
isPullRequest = true)
|
||||||
requestBranch = form.requestBranch,
|
|
||||||
commitIdFrom = form.commitIdFrom,
|
createPullRequest(
|
||||||
commitIdTo = form.commitIdTo)
|
originUserName = repository.owner,
|
||||||
|
originRepositoryName = repository.name,
|
||||||
// fetch requested branch
|
issueId = issueId,
|
||||||
using(Git.open(getRepositoryDir(repository.owner, repository.name))){ git =>
|
originBranch = form.targetBranch,
|
||||||
git.fetch
|
requestUserName = form.requestUserName,
|
||||||
.setRemote(getRepositoryDir(form.requestUserName, form.requestRepositoryName).toURI.toString)
|
requestRepositoryName = form.requestRepositoryName,
|
||||||
.setRefSpecs(new RefSpec(s"refs/heads/${form.requestBranch}:refs/pull/${issueId}/head"))
|
requestBranch = form.requestBranch,
|
||||||
.call
|
commitIdFrom = form.commitIdFrom,
|
||||||
}
|
commitIdTo = form.commitIdTo)
|
||||||
|
|
||||||
// record activity
|
// fetch requested branch
|
||||||
recordPullRequestActivity(repository.owner, repository.name, loginUserName, issueId, form.title)
|
using(Git.open(getRepositoryDir(repository.owner, repository.name))){ git =>
|
||||||
|
git.fetch
|
||||||
// notifications
|
.setRemote(getRepositoryDir(form.requestUserName, form.requestRepositoryName).toURI.toString)
|
||||||
Notifier().toNotify(repository, issueId, form.content.getOrElse("")){
|
.setRefSpecs(new RefSpec(s"refs/heads/${form.requestBranch}:refs/pull/${issueId}/head"))
|
||||||
Notifier.msgPullRequest(s"${context.baseUrl}/${repository.owner}/${repository.name}/pull/${issueId}")
|
.call
|
||||||
}
|
}
|
||||||
|
|
||||||
redirect(s"/${repository.owner}/${repository.name}/pull/${issueId}")
|
// record activity
|
||||||
})
|
recordPullRequestActivity(repository.owner, repository.name, loginUserName, issueId, form.title)
|
||||||
|
|
||||||
/**
|
// notifications
|
||||||
* Checks whether conflict will be caused in merging. Returns true if conflict will be caused.
|
Notifier().toNotify(repository, issueId, form.content.getOrElse("")){
|
||||||
*/
|
Notifier.msgPullRequest(s"${context.baseUrl}/${repository.owner}/${repository.name}/pull/${issueId}")
|
||||||
private def checkConflict(userName: String, repositoryName: String, branch: String,
|
}
|
||||||
requestUserName: String, requestRepositoryName: String, requestBranch: String): Boolean = {
|
|
||||||
LockUtil.lock(s"${userName}/${repositoryName}"){
|
redirect(s"/${repository.owner}/${repository.name}/pull/${issueId}")
|
||||||
using(Git.open(getRepositoryDir(requestUserName, requestRepositoryName))) { git =>
|
})
|
||||||
val remoteRefName = s"refs/heads/${branch}"
|
|
||||||
val tmpRefName = s"refs/merge-check/${userName}/${branch}"
|
/**
|
||||||
val refSpec = new RefSpec(s"${remoteRefName}:${tmpRefName}").setForceUpdate(true)
|
* Checks whether conflict will be caused in merging. Returns true if conflict will be caused.
|
||||||
try {
|
*/
|
||||||
// fetch objects from origin repository branch
|
private def checkConflict(userName: String, repositoryName: String, branch: String,
|
||||||
git.fetch
|
requestUserName: String, requestRepositoryName: String, requestBranch: String): Boolean = {
|
||||||
.setRemote(getRepositoryDir(userName, repositoryName).toURI.toString)
|
LockUtil.lock(s"${userName}/${repositoryName}"){
|
||||||
.setRefSpecs(refSpec)
|
using(Git.open(getRepositoryDir(requestUserName, requestRepositoryName))) { git =>
|
||||||
.call
|
val remoteRefName = s"refs/heads/${branch}"
|
||||||
|
val tmpRefName = s"refs/merge-check/${userName}/${branch}"
|
||||||
// merge conflict check
|
val refSpec = new RefSpec(s"${remoteRefName}:${tmpRefName}").setForceUpdate(true)
|
||||||
val merger = MergeStrategy.RECURSIVE.newMerger(git.getRepository, true)
|
try {
|
||||||
val mergeBaseTip = git.getRepository.resolve(s"refs/heads/${requestBranch}")
|
// fetch objects from origin repository branch
|
||||||
val mergeTip = git.getRepository.resolve(tmpRefName)
|
git.fetch
|
||||||
try {
|
.setRemote(getRepositoryDir(userName, repositoryName).toURI.toString)
|
||||||
!merger.merge(mergeBaseTip, mergeTip)
|
.setRefSpecs(refSpec)
|
||||||
} catch {
|
.call
|
||||||
case e: NoMergeBaseException => true
|
|
||||||
}
|
// merge conflict check
|
||||||
} finally {
|
val merger = MergeStrategy.RECURSIVE.newMerger(git.getRepository, true)
|
||||||
val refUpdate = git.getRepository.updateRef(refSpec.getDestination)
|
val mergeBaseTip = git.getRepository.resolve(s"refs/heads/${requestBranch}")
|
||||||
refUpdate.setForceUpdate(true)
|
val mergeTip = git.getRepository.resolve(tmpRefName)
|
||||||
refUpdate.delete()
|
try {
|
||||||
}
|
!merger.merge(mergeBaseTip, mergeTip)
|
||||||
}
|
} catch {
|
||||||
}
|
case e: NoMergeBaseException => true
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
/**
|
val refUpdate = git.getRepository.updateRef(refSpec.getDestination)
|
||||||
* Checks whether conflict will be caused in merging within pull request. Returns true if conflict will be caused.
|
refUpdate.setForceUpdate(true)
|
||||||
*/
|
refUpdate.delete()
|
||||||
private def checkConflictInPullRequest(userName: String, repositoryName: String, branch: String,
|
}
|
||||||
requestUserName: String, requestRepositoryName: String, requestBranch: String,
|
}
|
||||||
issueId: Int): Boolean = {
|
}
|
||||||
LockUtil.lock(s"${userName}/${repositoryName}") {
|
}
|
||||||
using(Git.open(getRepositoryDir(userName, repositoryName))) { git =>
|
|
||||||
// merge
|
/**
|
||||||
val merger = MergeStrategy.RECURSIVE.newMerger(git.getRepository, true)
|
* Checks whether conflict will be caused in merging within pull request. Returns true if conflict will be caused.
|
||||||
val mergeBaseTip = git.getRepository.resolve(s"refs/heads/${branch}")
|
*/
|
||||||
val mergeTip = git.getRepository.resolve(s"refs/pull/${issueId}/head")
|
private def checkConflictInPullRequest(userName: String, repositoryName: String, branch: String,
|
||||||
try {
|
requestUserName: String, requestRepositoryName: String, requestBranch: String,
|
||||||
!merger.merge(mergeBaseTip, mergeTip)
|
issueId: Int): Boolean = {
|
||||||
} catch {
|
LockUtil.lock(s"${userName}/${repositoryName}") {
|
||||||
case e: NoMergeBaseException => true
|
using(Git.open(getRepositoryDir(userName, repositoryName))) { git =>
|
||||||
}
|
// merge
|
||||||
}
|
val merger = MergeStrategy.RECURSIVE.newMerger(git.getRepository, true)
|
||||||
}
|
val mergeBaseTip = git.getRepository.resolve(s"refs/heads/${branch}")
|
||||||
}
|
val mergeTip = git.getRepository.resolve(s"refs/pull/${issueId}/head")
|
||||||
|
try {
|
||||||
/**
|
!merger.merge(mergeBaseTip, mergeTip)
|
||||||
* Parses branch identifier and extracts owner and branch name as tuple.
|
} catch {
|
||||||
*
|
case e: NoMergeBaseException => true
|
||||||
* - "owner:branch" to ("owner", "branch")
|
}
|
||||||
* - "branch" to ("defaultOwner", "branch")
|
}
|
||||||
*/
|
}
|
||||||
private def parseCompareIdentifie(value: String, defaultOwner: String): (String, String) =
|
}
|
||||||
if(value.contains(':')){
|
|
||||||
val array = value.split(":")
|
/**
|
||||||
(array(0), array(1))
|
* Parses branch identifier and extracts owner and branch name as tuple.
|
||||||
} else {
|
*
|
||||||
(defaultOwner, value)
|
* - "owner:branch" to ("owner", "branch")
|
||||||
}
|
* - "branch" to ("defaultOwner", "branch")
|
||||||
|
*/
|
||||||
private def getRequestCompareInfo(userName: String, repositoryName: String, branch: String,
|
private def parseCompareIdentifie(value: String, defaultOwner: String): (String, String) =
|
||||||
requestUserName: String, requestRepositoryName: String, requestCommitId: String): (Seq[Seq[CommitInfo]], Seq[DiffInfo]) =
|
if(value.contains(':')){
|
||||||
using(
|
val array = value.split(":")
|
||||||
Git.open(getRepositoryDir(userName, repositoryName)),
|
(array(0), array(1))
|
||||||
Git.open(getRepositoryDir(requestUserName, requestRepositoryName))
|
} else {
|
||||||
){ (oldGit, newGit) =>
|
(defaultOwner, value)
|
||||||
val oldId = oldGit.getRepository.resolve(branch)
|
}
|
||||||
val newId = newGit.getRepository.resolve(requestCommitId)
|
|
||||||
|
private def getRequestCompareInfo(userName: String, repositoryName: String, branch: String,
|
||||||
val commits = newGit.log.addRange(oldId, newId).call.iterator.asScala.map { revCommit =>
|
requestUserName: String, requestRepositoryName: String, requestCommitId: String): (Seq[Seq[CommitInfo]], Seq[DiffInfo]) =
|
||||||
new CommitInfo(revCommit)
|
using(
|
||||||
}.toList.splitWith { (commit1, commit2) =>
|
Git.open(getRepositoryDir(userName, repositoryName)),
|
||||||
view.helpers.date(commit1.commitTime) == view.helpers.date(commit2.commitTime)
|
Git.open(getRepositoryDir(requestUserName, requestRepositoryName))
|
||||||
}
|
){ (oldGit, newGit) =>
|
||||||
|
val oldId = oldGit.getRepository.resolve(branch)
|
||||||
val diffs = JGitUtil.getDiffs(newGit, oldId.getName, newId.getName, true)
|
val newId = newGit.getRepository.resolve(requestCommitId)
|
||||||
|
|
||||||
(commits, diffs)
|
val commits = newGit.log.addRange(oldId, newId).call.iterator.asScala.map { revCommit =>
|
||||||
}
|
new CommitInfo(revCommit)
|
||||||
|
}.toList.splitWith { (commit1, commit2) =>
|
||||||
private def searchPullRequests(userName: Option[String], repository: RepositoryService.RepositoryInfo) =
|
view.helpers.date(commit1.commitTime) == view.helpers.date(commit2.commitTime)
|
||||||
defining(repository.owner, repository.name){ case (owner, repoName) =>
|
}
|
||||||
val page = IssueSearchCondition.page(request)
|
|
||||||
val sessionKey = Keys.Session.Pulls(owner, repoName)
|
val diffs = JGitUtil.getDiffs(newGit, oldId.getName, newId.getName, true)
|
||||||
|
|
||||||
// retrieve search condition
|
(commits, diffs)
|
||||||
val condition = session.putAndGet(sessionKey,
|
}
|
||||||
if(request.hasQueryString) IssueSearchCondition(request)
|
|
||||||
else session.getAs[IssueSearchCondition](sessionKey).getOrElse(IssueSearchCondition())
|
private def searchPullRequests(userName: Option[String], repository: RepositoryService.RepositoryInfo) =
|
||||||
)
|
defining(repository.owner, repository.name){ case (owner, repoName) =>
|
||||||
|
val page = IssueSearchCondition.page(request)
|
||||||
issues.html.list(
|
val sessionKey = Keys.Session.Pulls(owner, repoName)
|
||||||
"pulls",
|
|
||||||
searchIssue(condition, Map.empty, true, (page - 1) * PullRequestLimit, PullRequestLimit, owner -> repoName),
|
// retrieve search condition
|
||||||
page,
|
val condition = session.putAndGet(sessionKey,
|
||||||
(getCollaborators(owner, repoName) :+ owner).sorted,
|
if(request.hasQueryString) IssueSearchCondition(request)
|
||||||
getMilestones(owner, repoName),
|
else session.getAs[IssueSearchCondition](sessionKey).getOrElse(IssueSearchCondition())
|
||||||
getLabels(owner, repoName),
|
)
|
||||||
countIssue(condition.copy(state = "open" ), Map.empty, true, owner -> repoName),
|
|
||||||
countIssue(condition.copy(state = "closed"), Map.empty, true, owner -> repoName),
|
issues.html.list(
|
||||||
condition,
|
"pulls",
|
||||||
repository,
|
searchIssue(condition, Map.empty, true, (page - 1) * PullRequestLimit, PullRequestLimit, owner -> repoName),
|
||||||
hasWritePermission(owner, repoName, context.loginAccount))
|
page,
|
||||||
}
|
(getCollaborators(owner, repoName) :+ owner).sorted,
|
||||||
|
getMilestones(owner, repoName),
|
||||||
}
|
getLabels(owner, repoName),
|
||||||
|
countIssue(condition.copy(state = "open" ), Map.empty, true, owner -> repoName),
|
||||||
|
countIssue(condition.copy(state = "closed"), Map.empty, true, owner -> repoName),
|
||||||
|
condition,
|
||||||
|
repository,
|
||||||
|
hasWritePermission(owner, repoName, context.loginAccount))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -415,6 +415,47 @@ object IssuesService {
|
|||||||
if(value == null || value.isEmpty || (allow.nonEmpty && !allow.contains(value))) None else Some(value)
|
if(value == null || value.isEmpty || (allow.nonEmpty && !allow.contains(value))) None else Some(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restores IssueSearchCondition instance from filter query.
|
||||||
|
*/
|
||||||
|
def apply(filter: String, milestones: Map[String, Int]): IssueSearchCondition = {
|
||||||
|
val conditions = filter.split("[ \t]+").map { x =>
|
||||||
|
val dim = x.split(":")
|
||||||
|
dim(0) -> dim(1)
|
||||||
|
}.groupBy(_._1).map { case (key, values) =>
|
||||||
|
key -> values.map(_._2).toSeq
|
||||||
|
}
|
||||||
|
|
||||||
|
val (sort, direction) = conditions.get("sort").flatMap(_.headOption).getOrElse("created-desc") match {
|
||||||
|
case "created-asc" => ("created" , "asc" )
|
||||||
|
case "comments-desc" => ("comments", "desc")
|
||||||
|
case "comments-asc" => ("comments", "asc" )
|
||||||
|
case "updated-desc" => ("comments", "desc")
|
||||||
|
case "updated-asc" => ("comments", "asc" )
|
||||||
|
case _ => ("created" , "desc")
|
||||||
|
}
|
||||||
|
|
||||||
|
IssueSearchCondition(
|
||||||
|
conditions.get("label").map(_.toSet).getOrElse(Set.empty),
|
||||||
|
conditions.get("milestone").flatMap(_.headOption) match {
|
||||||
|
case None => None
|
||||||
|
case Some("none") => Some(None)
|
||||||
|
case Some(x) => Some(milestones.get(x))
|
||||||
|
},
|
||||||
|
conditions.get("author").flatMap(_.headOption),
|
||||||
|
conditions.get("assignee").flatMap(_.headOption),
|
||||||
|
None, // TODO??
|
||||||
|
conditions.get("is").getOrElse(Seq.empty).filter(x => x == "open" || x == "closed").headOption.getOrElse("open"),
|
||||||
|
sort,
|
||||||
|
direction,
|
||||||
|
None, // TODO??
|
||||||
|
Set.empty // TODO??
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restores IssueSearchCondition instance from request parameters.
|
||||||
|
*/
|
||||||
def apply(request: HttpServletRequest): IssueSearchCondition =
|
def apply(request: HttpServletRequest): IssueSearchCondition =
|
||||||
IssueSearchCondition(
|
IssueSearchCondition(
|
||||||
param(request, "labels").map(_.split(",").toSet).getOrElse(Set.empty),
|
param(request, "labels").map(_.split(",").toSet).getOrElse(Set.empty),
|
||||||
|
|||||||
@@ -11,22 +11,24 @@
|
|||||||
<li class="@if(active == "milestones"){active} last"><a href="@url(repository)/issues/milestones">Milestones</a></li>
|
<li class="@if(active == "milestones"){active} last"><a href="@url(repository)/issues/milestones">Milestones</a></li>
|
||||||
<li class="pull-right">
|
<li class="pull-right">
|
||||||
@condition.map { condition =>
|
@condition.map { condition =>
|
||||||
<div class="input-prepend" style="margin-bottom: 0px;">
|
<form method="GET" id="search-filter-form">
|
||||||
<div class="btn-group">
|
<div class="input-prepend" style="margin-bottom: 0px;">
|
||||||
<button class="btn dropdown-toggle" data-toggle="dropdown" style="height: 34px;">
|
<div class="btn-group">
|
||||||
Filter
|
<button type="button" class="btn dropdown-toggle" data-toggle="dropdown" style="height: 34px;">
|
||||||
<span class="caret"></span>
|
Filter
|
||||||
</button>
|
<span class="caret"></span>
|
||||||
<ul class="dropdown-menu">
|
</button>
|
||||||
<li><a href="#">Open issues and pull requests</a></li>
|
<ul class="dropdown-menu">
|
||||||
<li><a href="#">Your issues</a></li>
|
<li><a href="#">Open issues and pull requests</a></li>
|
||||||
<li><a href="#">Your pull requests</a></li>
|
<li><a href="#">Your issues</a></li>
|
||||||
<li><a href="#">Everything assigned to you</a></li>
|
<li><a href="#">Your pull requests</a></li>
|
||||||
<li><a href="#">Everything mentioning you</a></li>
|
<li><a href="#">Everything assigned to you</a></li>
|
||||||
</ul>
|
<li><a href="#">Everything mentioning you</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<input type="text" id="search-filter-box" class="input-xlarge" name="q" style="height: 24px;" value="is:@{if(active == "issues") "issue" else "pr"} @condition.toFilterString"/>
|
||||||
</div>
|
</div>
|
||||||
<input type="text" class="input-xlarge" style="height: 24px;" value="@condition.toFilterString"/>
|
</form>
|
||||||
</div>
|
|
||||||
}
|
}
|
||||||
@if(loginAccount.isDefined){
|
@if(loginAccount.isDefined){
|
||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
|
|||||||
Reference in New Issue
Block a user