mirror of
https://github.com/gitbucket/gitbucket.git
synced 2025-11-09 23:15:49 +01:00
(refs #2)Implementing pull request list.
This commit is contained in:
@@ -32,26 +32,26 @@ trait DashboardControllerBase extends ControllerBase {
|
||||
else IssueSearchCondition(request)
|
||||
|
||||
session.put(sessionKey, condition)
|
||||
|
||||
|
||||
val userName = context.loginAccount.get.userName
|
||||
val repositories = getUserRepositories(userName, baseUrl).map(repo => repo.owner -> repo.name)
|
||||
val filterUser = Map(filter -> userName)
|
||||
val page = IssueSearchCondition.page(request)
|
||||
val page = IssueSearchCondition.page(request)
|
||||
//
|
||||
dashboard.html.issues(
|
||||
issues.html.listparts(
|
||||
searchIssue(condition, filterUser, (page - 1) * IssueLimit, IssueLimit, repositories: _*),
|
||||
searchIssue(condition, filterUser, false, (page - 1) * IssueLimit, IssueLimit, repositories: _*),
|
||||
page,
|
||||
countIssue(condition.copy(state = "open"), filterUser, repositories: _*),
|
||||
countIssue(condition.copy(state = "closed"), filterUser, repositories: _*),
|
||||
countIssue(condition.copy(state = "open"), filterUser, false, repositories: _*),
|
||||
countIssue(condition.copy(state = "closed"), filterUser, false, repositories: _*),
|
||||
condition),
|
||||
countIssue(condition, Map.empty, repositories: _*),
|
||||
countIssue(condition, Map("assigned" -> userName), repositories: _*),
|
||||
countIssue(condition, Map("created_by" -> userName), repositories: _*),
|
||||
countIssue(condition, Map.empty, false, repositories: _*),
|
||||
countIssue(condition, Map("assigned" -> userName), false, repositories: _*),
|
||||
countIssue(condition, Map("created_by" -> userName), false, repositories: _*),
|
||||
countIssueGroupByRepository(condition, filterUser, repositories: _*),
|
||||
condition,
|
||||
filter)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,16 +313,16 @@ trait IssuesControllerBase extends ControllerBase {
|
||||
session.put(sessionKey, condition)
|
||||
|
||||
issues.html.list(
|
||||
searchIssue(condition, filterUser, (page - 1) * IssueLimit, IssueLimit, owner -> repoName),
|
||||
searchIssue(condition, filterUser, false, (page - 1) * IssueLimit, IssueLimit, owner -> repoName),
|
||||
page,
|
||||
(getCollaborators(owner, repoName) :+ owner).sorted,
|
||||
getMilestones(owner, repoName),
|
||||
getLabels(owner, repoName),
|
||||
countIssue(condition.copy(state = "open"), filterUser, owner -> repoName),
|
||||
countIssue(condition.copy(state = "closed"), filterUser, owner -> repoName),
|
||||
countIssue(condition, Map.empty, owner -> repoName),
|
||||
context.loginAccount.map(x => countIssue(condition, Map("assigned" -> x.userName), owner -> repoName)),
|
||||
context.loginAccount.map(x => countIssue(condition, Map("created_by" -> x.userName), owner -> repoName)),
|
||||
countIssue(condition.copy(state = "open"), filterUser, false, owner -> repoName),
|
||||
countIssue(condition.copy(state = "closed"), filterUser, false, owner -> repoName),
|
||||
countIssue(condition, Map.empty, false, owner -> repoName),
|
||||
context.loginAccount.map(x => countIssue(condition, Map("assigned" -> x.userName), false, owner -> repoName)),
|
||||
context.loginAccount.map(x => countIssue(condition, Map("created_by" -> x.userName), false, owner -> repoName)),
|
||||
countIssueGroupByLabels(owner, repoName, condition, filterUser),
|
||||
condition,
|
||||
filter,
|
||||
|
||||
@@ -3,16 +3,19 @@ package app
|
||||
import util.{LockUtil, CollaboratorsAuthenticator, JGitUtil, ReferrerAuthenticator}
|
||||
import util.Directory._
|
||||
import util.Implicits._
|
||||
import util.JGitUtil.{DiffInfo, CommitInfo}
|
||||
import service._
|
||||
import org.eclipse.jgit.api.Git
|
||||
import jp.sf.amateras.scalatra.forms._
|
||||
import org.eclipse.jgit.transport.RefSpec
|
||||
import org.apache.commons.io.FileUtils
|
||||
import scala.collection.JavaConverters._
|
||||
import service.RepositoryService.RepositoryTreeNode
|
||||
import org.eclipse.jgit.lib.PersonIdent
|
||||
import org.eclipse.jgit.api.MergeCommand.FastForwardMode
|
||||
import service.IssuesService._
|
||||
import util.JGitUtil.DiffInfo
|
||||
import scala.Some
|
||||
import service.RepositoryService.RepositoryTreeNode
|
||||
import util.JGitUtil.CommitInfo
|
||||
|
||||
class PullRequestsController extends PullRequestsControllerBase
|
||||
with RepositoryService with AccountService with IssuesService with PullRequestService with MilestonesService with ActivityService
|
||||
@@ -50,10 +53,14 @@ trait PullRequestsControllerBase extends ControllerBase {
|
||||
case class MergeForm(message: String)
|
||||
|
||||
get("/:owner/:repository/pulls")(referrersOnly { repository =>
|
||||
pulls.html.list(repository)
|
||||
searchPullRequests(None, repository)
|
||||
})
|
||||
|
||||
get("/:owner/:repository/pulls/:id")(referrersOnly { repository =>
|
||||
get("/:owner/:repository/pulls/:userName")(referrersOnly { repository =>
|
||||
searchPullRequests(Some(params("userName")), repository)
|
||||
})
|
||||
|
||||
get("/:owner/:repository/pull/:id")(referrersOnly { repository =>
|
||||
val owner = repository.owner
|
||||
val name = repository.name
|
||||
val issueId = params("id").toInt
|
||||
@@ -86,7 +93,7 @@ trait PullRequestsControllerBase extends ControllerBase {
|
||||
} getOrElse NotFound
|
||||
})
|
||||
|
||||
post("/:owner/:repository/pulls/:id/merge", mergeForm)(collaboratorsOnly { (form, repository) =>
|
||||
post("/:owner/:repository/pull/:id/merge", mergeForm)(collaboratorsOnly { (form, repository) =>
|
||||
LockUtil.lock(s"${repository.owner}/${repository.name}/merge"){
|
||||
val issueId = params("id").toInt
|
||||
|
||||
@@ -143,7 +150,7 @@ trait PullRequestsControllerBase extends ControllerBase {
|
||||
}
|
||||
}
|
||||
|
||||
redirect(s"/${repository.owner}/${repository.name}/pulls/${issueId}")
|
||||
redirect(s"/${repository.owner}/${repository.name}/pull/${issueId}")
|
||||
|
||||
} finally {
|
||||
git.getRepository.close
|
||||
@@ -188,7 +195,7 @@ trait PullRequestsControllerBase extends ControllerBase {
|
||||
}
|
||||
}
|
||||
|
||||
get("/:owner/:repository/pulls/compare")(collaboratorsOnly { forkedRepository =>
|
||||
get("/:owner/:repository/compare")(collaboratorsOnly { forkedRepository =>
|
||||
(forkedRepository.repository.originUserName, forkedRepository.repository.originRepositoryName) match {
|
||||
case (Some(originUserName), Some(originRepositoryName)) => {
|
||||
getRepository(originUserName, originRepositoryName, baseUrl).map { originRepository =>
|
||||
@@ -199,20 +206,20 @@ trait PullRequestsControllerBase extends ControllerBase {
|
||||
val oldBranch = JGitUtil.getDefaultBranch(oldGit, originRepository).get._2
|
||||
val newBranch = JGitUtil.getDefaultBranch(newGit, forkedRepository).get._2
|
||||
|
||||
redirect(s"${context.path}/${forkedRepository.owner}/${forkedRepository.name}/pulls/compare/${originUserName}:${oldBranch}...${newBranch}")
|
||||
redirect(s"${context.path}/${forkedRepository.owner}/${forkedRepository.name}/compare/${originUserName}:${oldBranch}...${newBranch}")
|
||||
}
|
||||
} getOrElse NotFound
|
||||
}
|
||||
case _ => {
|
||||
JGitUtil.withGit(getRepositoryDir(forkedRepository.owner, forkedRepository.name)){ git =>
|
||||
val defaultBranch = JGitUtil.getDefaultBranch(git, forkedRepository).get._2
|
||||
redirect(s"${context.path}/${forkedRepository.owner}/${forkedRepository.name}/pulls/compare/${defaultBranch}...${defaultBranch}")
|
||||
redirect(s"${context.path}/${forkedRepository.owner}/${forkedRepository.name}/compare/${defaultBranch}...${defaultBranch}")
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
get("/:owner/:repository/pulls/compare/*...*")(collaboratorsOnly { repository =>
|
||||
get("/:owner/:repository/compare/*...*")(collaboratorsOnly { repository =>
|
||||
val Seq(origin, forked) = multiParams("splat")
|
||||
val (originOwner, tmpOriginBranch) = parseCompareIdentifie(origin, repository.owner)
|
||||
val (forkedOwner, tmpForkedBranch) = parseCompareIdentifie(forked, repository.owner)
|
||||
@@ -361,4 +368,29 @@ trait PullRequestsControllerBase extends ControllerBase {
|
||||
}
|
||||
}
|
||||
|
||||
private def searchPullRequests(userName: Option[String], repository: RepositoryService.RepositoryInfo) = {
|
||||
val owner = repository.owner
|
||||
val repoName = repository.name
|
||||
val filterUser = userName.map { x => Map("created_by" -> x) } getOrElse Map("all" -> "")
|
||||
val page = IssueSearchCondition.page(request)
|
||||
val sessionKey = s"${owner}/${repoName}/pulls"
|
||||
|
||||
// retrieve search condition
|
||||
val condition = if(request.getQueryString == null){
|
||||
session.get(sessionKey).getOrElse(IssueSearchCondition()).asInstanceOf[IssueSearchCondition]
|
||||
} else IssueSearchCondition(request)
|
||||
|
||||
session.put(sessionKey, condition)
|
||||
|
||||
pulls.html.list(
|
||||
searchIssue(condition, filterUser, true, (page - 1) * IssueLimit, IssueLimit, owner -> repoName),
|
||||
userName,
|
||||
page,
|
||||
countIssue(condition.copy(state = "open"), filterUser, true, owner -> repoName),
|
||||
countIssue(condition.copy(state = "closed"), filterUser, true, owner -> repoName),
|
||||
condition,
|
||||
repository,
|
||||
hasWritePermission(owner, repoName, context.loginAccount))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -44,14 +44,16 @@ trait IssuesService {
|
||||
*
|
||||
* @param condition the search condition
|
||||
* @param filterUser the filter user name (key is "all", "assigned" or "created_by", value is the user name)
|
||||
* @param onlyPullRequest if true then counts only pull request, false then counts both of issue and pull request.
|
||||
* @param repos Tuple of the repository owner and the repository name
|
||||
* @return the count of the search result
|
||||
*/
|
||||
def countIssue(condition: IssueSearchCondition, filterUser: Map[String, String], repos: (String, String)*): Int = {
|
||||
def countIssue(condition: IssueSearchCondition, filterUser: Map[String, String], onlyPullRequest: Boolean,
|
||||
repos: (String, String)*): Int = {
|
||||
// TODO It must be _.length instead of map (_.issueId) list).length.
|
||||
// But it does not work on Slick 1.0.1 (worked on Slick 1.0.0).
|
||||
// https://github.com/slick/slick/issues/170
|
||||
(searchIssueQuery(repos, condition, filterUser) map (_.issueId) list).length
|
||||
(searchIssueQuery(repos, condition, filterUser, onlyPullRequest) map (_.issueId) list).length
|
||||
}
|
||||
/**
|
||||
* Returns the Map which contains issue count for each labels.
|
||||
@@ -65,7 +67,7 @@ trait IssuesService {
|
||||
def countIssueGroupByLabels(owner: String, repository: String, condition: IssueSearchCondition,
|
||||
filterUser: Map[String, String]): Map[String, Int] = {
|
||||
|
||||
searchIssueQuery(Seq(owner -> repository), condition.copy(labels = Set.empty), filterUser)
|
||||
searchIssueQuery(Seq(owner -> repository), condition.copy(labels = Set.empty), filterUser, false)
|
||||
.innerJoin(IssueLabels).on { (t1, t2) =>
|
||||
t1.byIssue(t2.userName, t2.repositoryName, t2.issueId)
|
||||
}
|
||||
@@ -89,9 +91,9 @@ trait IssuesService {
|
||||
* @param repos Tuple of the repository owner and the repository name
|
||||
* @return list which contains issue count for each repository
|
||||
*/
|
||||
def countIssueGroupByRepository(condition: IssueSearchCondition, filterUser: Map[String, String],
|
||||
repos: (String, String)*): List[(String, String, Int)] = {
|
||||
searchIssueQuery(repos, condition.copy(repo = None), filterUser)
|
||||
def countIssueGroupByRepository(
|
||||
condition: IssueSearchCondition, filterUser: Map[String, String], repos: (String, String)*): List[(String, String, Int)] = {
|
||||
searchIssueQuery(repos, condition.copy(repo = None), filterUser, false)
|
||||
.groupBy { t =>
|
||||
t.userName ~ t.repositoryName
|
||||
}
|
||||
@@ -107,16 +109,17 @@ trait IssuesService {
|
||||
*
|
||||
* @param condition the search condition
|
||||
* @param filterUser the filter user name (key is "all", "assigned" or "created_by", value is the user name)
|
||||
* @param onlyPullRequest if true then returns only pull request, false then returns both of issue and pull request.
|
||||
* @param offset the offset for pagination
|
||||
* @param limit the limit for pagination
|
||||
* @param repos Tuple of the repository owner and the repository name
|
||||
* @return the search result (list of tuples which contain issue, labels and comment count)
|
||||
*/
|
||||
def searchIssue(condition: IssueSearchCondition, filterUser: Map[String, String],
|
||||
def searchIssue(condition: IssueSearchCondition, filterUser: Map[String, String], onlyPullRequest: Boolean,
|
||||
offset: Int, limit: Int, repos: (String, String)*): List[(Issue, List[Label], Int)] = {
|
||||
|
||||
// get issues and comment count and labels
|
||||
searchIssueQuery(repos, condition, filterUser)
|
||||
searchIssueQuery(repos, condition, filterUser, onlyPullRequest)
|
||||
.innerJoin(IssueOutline).on { (t1, t2) => t1.byIssue(t2.userName, t2.repositoryName, t2.issueId) }
|
||||
.leftJoin (IssueLabels) .on { case ((t1, t2), t3) => t1.byIssue(t3.userName, t3.repositoryName, t3.issueId) }
|
||||
.leftJoin (Labels) .on { case (((t1, t2), t3), t4) => t3.byLabel(t4.userName, t4.repositoryName, t4.labelId) }
|
||||
@@ -156,7 +159,8 @@ trait IssuesService {
|
||||
/**
|
||||
* Assembles query for conditional issue searching.
|
||||
*/
|
||||
private def searchIssueQuery(repos: Seq[(String, String)], condition: IssueSearchCondition, filterUser: Map[String, String]) =
|
||||
private def searchIssueQuery(repos: Seq[(String, String)], condition: IssueSearchCondition,
|
||||
filterUser: Map[String, String], onlyPullRequest: Boolean) =
|
||||
Query(Issues) filter { t1 =>
|
||||
condition.repo
|
||||
.map { _.split('/') match { case array => Seq(array(0) -> array(1)) } }
|
||||
@@ -168,6 +172,7 @@ trait IssuesService {
|
||||
(t1.milestoneId isNull, condition.milestoneId == Some(None)) &&
|
||||
(t1.assignedUserName is filterUser("assigned").bind, filterUser.get("assigned").isDefined) &&
|
||||
(t1.openedUserName is filterUser("created_by").bind, filterUser.get("created_by").isDefined) &&
|
||||
(t1.pullRequest is true.bind, onlyPullRequest) &&
|
||||
(IssueLabels filter { t2 =>
|
||||
(t2.byIssue(t1.userName, t1.repositoryName, t1.issueId)) &&
|
||||
(t2.labelId in
|
||||
|
||||
@@ -31,12 +31,4 @@ trait PullRequestService { self: IssuesService =>
|
||||
commitIdFrom,
|
||||
commitIdTo))
|
||||
|
||||
// def mergePullRequest(originUserName: String, originRepositoryName: String, issueId: Int,
|
||||
// mergeStartId: String, mergeEndId: String): Unit = {
|
||||
// Query(PullRequests)
|
||||
// .filter(_.byPrimaryKey(originUserName, originRepositoryName, issueId))
|
||||
// .map(t => t.mergeStartId ~ t.mergeEndId)
|
||||
// .update(mergeStartId, mergeEndId)
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ object helpers extends AvatarImageProvider with LinkConverter with RequestCache
|
||||
def activityMessage(message: String)(implicit context: app.Context): Html =
|
||||
Html(message
|
||||
.replaceAll("\\[issue:([^\\s]+?)/([^\\s]+?)#((\\d+))\\]" , s"""<a href="${context.path}/$$1/$$2/issues/$$3">$$1/$$2#$$3</a>""")
|
||||
.replaceAll("\\[pullreq:([^\\s]+?)/([^\\s]+?)#((\\d+))\\]" , s"""<a href="${context.path}/$$1/$$2/pulls/$$3">$$1/$$2#$$3</a>""")
|
||||
.replaceAll("\\[pullreq:([^\\s]+?)/([^\\s]+?)#((\\d+))\\]" , s"""<a href="${context.path}/$$1/$$2/pull/$$3">$$1/$$2#$$3</a>""")
|
||||
.replaceAll("\\[repo:([^\\s]+?)/([^\\s]+?)\\]" , s"""<a href="${context.path}/$$1/$$2\">$$1/$$2</a>""")
|
||||
.replaceAll("\\[branch:([^\\s]+?)/([^\\s]+?)#([^\\s]+?)\\]", s"""<a href="${context.path}/$$1/$$2/tree/$$3">$$3</a>""")
|
||||
.replaceAll("\\[tag:([^\\s]+?)/([^\\s]+?)#([^\\s]+?)\\]" , s"""<a href="${context.path}/$$1/$$2/tree/$$3">$$3</a>""")
|
||||
|
||||
Reference in New Issue
Block a user