mirror of
https://github.com/gitbucket/gitbucket.git
synced 2025-11-06 21:45:50 +01:00
Merge pull request #2164 from kounoike/pr-call-hook-moveto-service
Move Plugin/Web Hook call to service layer
This commit is contained in:
@@ -360,13 +360,7 @@ trait AccountControllerBase extends AccountManagementControllerBase {
|
|||||||
// FileUtils.deleteDirectory(getWikiRepositoryDir(userName, repositoryName))
|
// FileUtils.deleteDirectory(getWikiRepositoryDir(userName, repositoryName))
|
||||||
// FileUtils.deleteDirectory(getTemporaryDir(userName, repositoryName))
|
// FileUtils.deleteDirectory(getTemporaryDir(userName, repositoryName))
|
||||||
// }
|
// }
|
||||||
// Remove from GROUP_MEMBER and COLLABORATOR
|
suspendAccount(account)
|
||||||
removeUserRelatedData(userName)
|
|
||||||
updateAccount(account.copy(isRemoved = true))
|
|
||||||
|
|
||||||
// call hooks
|
|
||||||
PluginRegistry().getAccountHooks.foreach(_.deleted(userName))
|
|
||||||
|
|
||||||
session.invalidate
|
session.invalidate
|
||||||
redirect("/")
|
redirect("/")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ class ApiController
|
|||||||
with WebHookService
|
with WebHookService
|
||||||
with WebHookPullRequestService
|
with WebHookPullRequestService
|
||||||
with WebHookIssueCommentService
|
with WebHookIssueCommentService
|
||||||
|
with WebHookPullRequestReviewCommentService
|
||||||
with WikiService
|
with WikiService
|
||||||
with ActivityService
|
with ActivityService
|
||||||
with PrioritiesService
|
with PrioritiesService
|
||||||
|
|||||||
@@ -12,9 +12,13 @@ class DashboardController
|
|||||||
with PullRequestService
|
with PullRequestService
|
||||||
with RepositoryService
|
with RepositoryService
|
||||||
with AccountService
|
with AccountService
|
||||||
|
with ActivityService
|
||||||
with CommitsService
|
with CommitsService
|
||||||
with LabelsService
|
with LabelsService
|
||||||
with PrioritiesService
|
with PrioritiesService
|
||||||
|
with WebHookService
|
||||||
|
with WebHookPullRequestService
|
||||||
|
with WebHookPullRequestReviewCommentService
|
||||||
with MilestonesService
|
with MilestonesService
|
||||||
with UsersAuthenticator
|
with UsersAuthenticator
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ class IssuesController
|
|||||||
with WritableUsersAuthenticator
|
with WritableUsersAuthenticator
|
||||||
with PullRequestService
|
with PullRequestService
|
||||||
with WebHookIssueCommentService
|
with WebHookIssueCommentService
|
||||||
|
with WebHookPullRequestReviewCommentService
|
||||||
with CommitsService
|
with CommitsService
|
||||||
with PrioritiesService
|
with PrioritiesService
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ class PullRequestsController
|
|||||||
with CommitsService
|
with CommitsService
|
||||||
with ActivityService
|
with ActivityService
|
||||||
with WebHookPullRequestService
|
with WebHookPullRequestService
|
||||||
|
with WebHookPullRequestReviewCommentService
|
||||||
with ReadableUsersAuthenticator
|
with ReadableUsersAuthenticator
|
||||||
with ReferrerAuthenticator
|
with ReferrerAuthenticator
|
||||||
with WritableUsersAuthenticator
|
with WritableUsersAuthenticator
|
||||||
@@ -294,11 +295,12 @@ trait PullRequestsControllerBase extends ControllerBase {
|
|||||||
issueId <- params("id").toIntOpt
|
issueId <- params("id").toIntOpt
|
||||||
loginAccount <- context.loginAccount
|
loginAccount <- context.loginAccount
|
||||||
(issue, pullreq) <- getPullRequest(baseRepository.owner, baseRepository.name, issueId)
|
(issue, pullreq) <- getPullRequest(baseRepository.owner, baseRepository.name, issueId)
|
||||||
|
repository <- getRepository(pullreq.requestUserName, pullreq.requestRepositoryName)
|
||||||
|
remoteRepository <- getRepository(pullreq.userName, pullreq.repositoryName)
|
||||||
owner = pullreq.requestUserName
|
owner = pullreq.requestUserName
|
||||||
name = pullreq.requestRepositoryName
|
name = pullreq.requestRepositoryName
|
||||||
if hasDeveloperRole(owner, name, context.loginAccount)
|
if hasDeveloperRole(owner, name, context.loginAccount)
|
||||||
} yield {
|
} yield {
|
||||||
val repository = getRepository(owner, name).get
|
|
||||||
val branchProtection = getProtectedBranchInfo(owner, name, pullreq.requestBranch)
|
val branchProtection = getProtectedBranchInfo(owner, name, pullreq.requestBranch)
|
||||||
if (branchProtection.needStatusCheck(loginAccount.userName)) {
|
if (branchProtection.needStatusCheck(loginAccount.userName)) {
|
||||||
flash += "error" -> s"branch ${pullreq.requestBranch} is protected need status check."
|
flash += "error" -> s"branch ${pullreq.requestBranch} is protected need status check."
|
||||||
@@ -314,83 +316,19 @@ trait PullRequestsControllerBase extends ControllerBase {
|
|||||||
JGitUtil.getAllCommitIds(git)
|
JGitUtil.getAllCommitIds(git)
|
||||||
}.toSet
|
}.toSet
|
||||||
pullRemote(
|
pullRemote(
|
||||||
owner,
|
repository,
|
||||||
name,
|
|
||||||
pullreq.requestBranch,
|
pullreq.requestBranch,
|
||||||
pullreq.userName,
|
remoteRepository,
|
||||||
pullreq.repositoryName,
|
|
||||||
pullreq.branch,
|
pullreq.branch,
|
||||||
loginAccount,
|
loginAccount,
|
||||||
s"Merge branch '${alias}' into ${pullreq.requestBranch}"
|
s"Merge branch '${alias}' into ${pullreq.requestBranch}",
|
||||||
|
Some(pullreq)
|
||||||
) match {
|
) match {
|
||||||
case None => // conflict
|
case None => // conflict
|
||||||
flash += "error" -> s"Can't automatic merging branch '${alias}' into ${pullreq.requestBranch}."
|
flash += "error" -> s"Can't automatic merging branch '${alias}' into ${pullreq.requestBranch}."
|
||||||
case Some(oldId) =>
|
case Some(oldId) =>
|
||||||
// update pull request
|
// update pull request
|
||||||
updatePullRequests(owner, name, pullreq.requestBranch)
|
updatePullRequests(owner, name, pullreq.requestBranch, loginAccount, "synchronize")
|
||||||
|
|
||||||
using(Git.open(Directory.getRepositoryDir(owner, name))) {
|
|
||||||
git =>
|
|
||||||
// after update branch
|
|
||||||
val newCommitId = git.getRepository.resolve(s"refs/heads/${pullreq.requestBranch}")
|
|
||||||
val commits = git.log
|
|
||||||
.addRange(oldId, newCommitId)
|
|
||||||
.call
|
|
||||||
.iterator
|
|
||||||
.asScala
|
|
||||||
.map(c => new JGitUtil.CommitInfo(c))
|
|
||||||
.toList
|
|
||||||
|
|
||||||
commits.foreach { commit =>
|
|
||||||
if (!existIds.contains(commit.id)) {
|
|
||||||
createIssueComment(owner, name, commit)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// record activity
|
|
||||||
recordPushActivity(owner, name, loginAccount.userName, pullreq.branch, commits)
|
|
||||||
|
|
||||||
// close issue by commit message
|
|
||||||
if (pullreq.requestBranch == repository.repository.defaultBranch) {
|
|
||||||
commits.foreach { commit =>
|
|
||||||
closeIssuesFromMessage(commit.fullMessage, loginAccount.userName, owner, name).foreach {
|
|
||||||
issueId =>
|
|
||||||
getIssue(repository.owner, repository.name, issueId.toString).foreach { issue =>
|
|
||||||
callIssuesWebHook("closed", repository, issue, baseUrl, loginAccount)
|
|
||||||
PluginRegistry().getIssueHooks
|
|
||||||
.foreach(
|
|
||||||
_.closedByCommitComment(issue, repository, commit.fullMessage, loginAccount)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// call web hook
|
|
||||||
callPullRequestWebHookByRequestBranch(
|
|
||||||
"synchronize",
|
|
||||||
repository,
|
|
||||||
pullreq.requestBranch,
|
|
||||||
baseUrl,
|
|
||||||
loginAccount
|
|
||||||
)
|
|
||||||
callWebHookOf(owner, name, WebHook.Push) {
|
|
||||||
for {
|
|
||||||
ownerAccount <- getAccountByUserName(owner)
|
|
||||||
} yield {
|
|
||||||
WebHookService.WebHookPushPayload(
|
|
||||||
git,
|
|
||||||
loginAccount,
|
|
||||||
pullreq.requestBranch,
|
|
||||||
repository,
|
|
||||||
commits,
|
|
||||||
ownerAccount,
|
|
||||||
oldId = oldId,
|
|
||||||
newId = newCommitId
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
flash += "info" -> s"Merge branch '${alias}' into ${pullreq.requestBranch}"
|
flash += "info" -> s"Merge branch '${alias}' into ${pullreq.requestBranch}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -401,119 +339,14 @@ trait PullRequestsControllerBase extends ControllerBase {
|
|||||||
})
|
})
|
||||||
|
|
||||||
post("/:owner/:repository/pull/:id/merge", mergeForm)(writableUsersOnly { (form, repository) =>
|
post("/:owner/:repository/pull/:id/merge", mergeForm)(writableUsersOnly { (form, repository) =>
|
||||||
params("id").toIntOpt.flatMap {
|
params("id").toIntOpt.flatMap { issueId =>
|
||||||
issueId =>
|
val owner = repository.owner
|
||||||
val owner = repository.owner
|
val name = repository.name
|
||||||
val name = repository.name
|
|
||||||
if (repository.repository.options.mergeOptions.split(",").contains(form.strategy)) {
|
|
||||||
LockUtil.lock(s"${owner}/${name}") {
|
|
||||||
getPullRequest(owner, name, issueId).map {
|
|
||||||
case (issue, pullreq) =>
|
|
||||||
using(Git.open(getRepositoryDir(owner, name))) {
|
|
||||||
git =>
|
|
||||||
// mark issue as merged and close.
|
|
||||||
val loginAccount = context.loginAccount.get
|
|
||||||
val commentId = createComment(owner, name, loginAccount.userName, issueId, form.message, "merge")
|
|
||||||
createComment(owner, name, loginAccount.userName, issueId, "Close", "close")
|
|
||||||
updateClosed(owner, name, issueId, true)
|
|
||||||
|
|
||||||
// record activity
|
mergePullRequest(repository, issueId, context.loginAccount.get, form.message, form.strategy) match {
|
||||||
recordMergeActivity(owner, name, loginAccount.userName, issueId, form.message)
|
case Right(objectId) => redirect(s"/${owner}/${name}/pull/${issueId}")
|
||||||
|
case Left(message) => Some(BadRequest())
|
||||||
val (commits, _) = getRequestCompareInfo(
|
}
|
||||||
owner,
|
|
||||||
name,
|
|
||||||
pullreq.commitIdFrom,
|
|
||||||
pullreq.requestUserName,
|
|
||||||
pullreq.requestRepositoryName,
|
|
||||||
pullreq.commitIdTo
|
|
||||||
)
|
|
||||||
|
|
||||||
val revCommits = using(new RevWalk(git.getRepository)) { revWalk =>
|
|
||||||
commits.flatten.map { commit =>
|
|
||||||
revWalk.parseCommit(git.getRepository.resolve(commit.id))
|
|
||||||
}
|
|
||||||
}.reverse
|
|
||||||
|
|
||||||
// merge git repository
|
|
||||||
form.strategy match {
|
|
||||||
case "merge-commit" =>
|
|
||||||
mergePullRequest(
|
|
||||||
git,
|
|
||||||
pullreq.branch,
|
|
||||||
issueId,
|
|
||||||
s"Merge pull request #${issueId} from ${pullreq.requestUserName}/${pullreq.requestBranch}\n\n" + form.message,
|
|
||||||
new PersonIdent(loginAccount.fullName, loginAccount.mailAddress)
|
|
||||||
)
|
|
||||||
case "rebase" =>
|
|
||||||
rebasePullRequest(
|
|
||||||
git,
|
|
||||||
pullreq.branch,
|
|
||||||
issueId,
|
|
||||||
revCommits,
|
|
||||||
new PersonIdent(loginAccount.fullName, loginAccount.mailAddress)
|
|
||||||
)
|
|
||||||
case "squash" =>
|
|
||||||
squashPullRequest(
|
|
||||||
git,
|
|
||||||
pullreq.branch,
|
|
||||||
issueId,
|
|
||||||
s"${issue.title} (#${issueId})\n\n" + form.message,
|
|
||||||
new PersonIdent(loginAccount.fullName, loginAccount.mailAddress)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// close issue by content of pull request
|
|
||||||
val defaultBranch = getRepository(owner, name).get.repository.defaultBranch
|
|
||||||
if (pullreq.branch == defaultBranch) {
|
|
||||||
commits.flatten.foreach { commit =>
|
|
||||||
closeIssuesFromMessage(commit.fullMessage, loginAccount.userName, owner, name).foreach {
|
|
||||||
issueId =>
|
|
||||||
getIssue(owner, name, issueId.toString).foreach { issue =>
|
|
||||||
callIssuesWebHook("closed", repository, issue, baseUrl, loginAccount)
|
|
||||||
PluginRegistry().getIssueHooks
|
|
||||||
.foreach(_.closedByCommitComment(issue, repository, commit.fullMessage, loginAccount))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val issueContent = issue.title + " " + issue.content.getOrElse("")
|
|
||||||
closeIssuesFromMessage(
|
|
||||||
issueContent,
|
|
||||||
loginAccount.userName,
|
|
||||||
owner,
|
|
||||||
name
|
|
||||||
).foreach { issueId =>
|
|
||||||
getIssue(owner, name, issueId.toString).foreach { issue =>
|
|
||||||
callIssuesWebHook("closed", repository, issue, baseUrl, loginAccount)
|
|
||||||
PluginRegistry().getIssueHooks
|
|
||||||
.foreach(_.closedByCommitComment(issue, repository, issueContent, loginAccount))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
closeIssuesFromMessage(form.message, loginAccount.userName, owner, name).foreach { issueId =>
|
|
||||||
getIssue(owner, name, issueId.toString).foreach { issue =>
|
|
||||||
callIssuesWebHook("closed", repository, issue, baseUrl, loginAccount)
|
|
||||||
PluginRegistry().getIssueHooks
|
|
||||||
.foreach(_.closedByCommitComment(issue, repository, issueContent, loginAccount))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
updatePullRequests(owner, name, pullreq.branch)
|
|
||||||
|
|
||||||
// call web hook
|
|
||||||
callPullRequestWebHook("closed", repository, issueId, context.baseUrl, context.loginAccount.get)
|
|
||||||
|
|
||||||
// call hooks
|
|
||||||
PluginRegistry().getPullRequestHooks.foreach { h =>
|
|
||||||
h.addedComment(commentId, form.message, issue, repository)
|
|
||||||
h.merged(issue, repository)
|
|
||||||
}
|
|
||||||
|
|
||||||
redirect(s"/${owner}/${name}/pull/${issueId}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else Some(BadRequest())
|
|
||||||
} getOrElse NotFound()
|
} getOrElse NotFound()
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -760,7 +593,7 @@ trait PullRequestsControllerBase extends ControllerBase {
|
|||||||
recordPullRequestActivity(owner, name, loginUserName, issueId, form.title)
|
recordPullRequestActivity(owner, name, loginUserName, issueId, form.title)
|
||||||
|
|
||||||
// call web hook
|
// call web hook
|
||||||
callPullRequestWebHook("opened", repository, issueId, context.baseUrl, context.loginAccount.get)
|
callPullRequestWebHook("opened", repository, issueId, context.loginAccount.get)
|
||||||
|
|
||||||
getIssue(owner, name, issueId.toString) foreach { issue =>
|
getIssue(owner, name, issueId.toString) foreach { issue =>
|
||||||
// extract references and create refer comment
|
// extract references and create refer comment
|
||||||
|
|||||||
@@ -13,13 +13,11 @@ import gitbucket.core.util.SyntaxSugars._
|
|||||||
import gitbucket.core.util.Implicits._
|
import gitbucket.core.util.Implicits._
|
||||||
import gitbucket.core.util.Directory._
|
import gitbucket.core.util.Directory._
|
||||||
import org.scalatra.forms._
|
import org.scalatra.forms._
|
||||||
import org.apache.commons.io.FileUtils
|
|
||||||
import org.scalatra.i18n.Messages
|
import org.scalatra.i18n.Messages
|
||||||
import org.eclipse.jgit.api.Git
|
import org.eclipse.jgit.api.Git
|
||||||
import org.eclipse.jgit.lib.Constants
|
import org.eclipse.jgit.lib.Constants
|
||||||
import org.eclipse.jgit.lib.ObjectId
|
import org.eclipse.jgit.lib.ObjectId
|
||||||
import gitbucket.core.model.WebHookContentType
|
import gitbucket.core.model.WebHookContentType
|
||||||
import gitbucket.core.plugin.PluginRegistry
|
|
||||||
|
|
||||||
class RepositorySettingsController
|
class RepositorySettingsController
|
||||||
extends RepositorySettingsControllerBase
|
extends RepositorySettingsControllerBase
|
||||||
@@ -148,29 +146,6 @@ trait RepositorySettingsControllerBase extends ControllerBase {
|
|||||||
if (repository.name != form.repositoryName) {
|
if (repository.name != form.repositoryName) {
|
||||||
// Update database
|
// Update database
|
||||||
renameRepository(repository.owner, repository.name, repository.owner, form.repositoryName)
|
renameRepository(repository.owner, repository.name, repository.owner, form.repositoryName)
|
||||||
// Move git repository
|
|
||||||
defining(getRepositoryDir(repository.owner, repository.name)) { dir =>
|
|
||||||
if (dir.isDirectory) {
|
|
||||||
FileUtils.moveDirectory(dir, getRepositoryDir(repository.owner, form.repositoryName))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Move wiki repository
|
|
||||||
defining(getWikiRepositoryDir(repository.owner, repository.name)) { dir =>
|
|
||||||
if (dir.isDirectory) {
|
|
||||||
FileUtils.moveDirectory(dir, getWikiRepositoryDir(repository.owner, form.repositoryName))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Move files directory
|
|
||||||
defining(getRepositoryFilesDir(repository.owner, repository.name)) { dir =>
|
|
||||||
if (dir.isDirectory) {
|
|
||||||
FileUtils.moveDirectory(dir, getRepositoryFilesDir(repository.owner, form.repositoryName))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Delete parent directory
|
|
||||||
FileUtil.deleteDirectoryIfEmpty(getRepositoryFilesDir(repository.owner, repository.name))
|
|
||||||
|
|
||||||
// Call hooks
|
|
||||||
PluginRegistry().getRepositoryHooks.foreach(_.renamed(repository.owner, repository.name, form.repositoryName))
|
|
||||||
}
|
}
|
||||||
flash += "info" -> "Repository settings has been updated."
|
flash += "info" -> "Repository settings has been updated."
|
||||||
redirect(s"/${repository.owner}/${form.repositoryName}/settings/options")
|
redirect(s"/${repository.owner}/${form.repositoryName}/settings/options")
|
||||||
@@ -392,31 +367,7 @@ trait RepositorySettingsControllerBase extends ControllerBase {
|
|||||||
post("/:owner/:repository/settings/transfer", transferForm)(ownerOnly { (form, repository) =>
|
post("/:owner/:repository/settings/transfer", transferForm)(ownerOnly { (form, repository) =>
|
||||||
// Change repository owner
|
// Change repository owner
|
||||||
if (repository.owner != form.newOwner) {
|
if (repository.owner != form.newOwner) {
|
||||||
LockUtil.lock(s"${repository.owner}/${repository.name}") {
|
renameRepository(repository.owner, repository.name, form.newOwner, repository.name)
|
||||||
// Update database
|
|
||||||
renameRepository(repository.owner, repository.name, form.newOwner, repository.name)
|
|
||||||
// Move git repository
|
|
||||||
defining(getRepositoryDir(repository.owner, repository.name)) { dir =>
|
|
||||||
if (dir.isDirectory) {
|
|
||||||
FileUtils.moveDirectory(dir, getRepositoryDir(form.newOwner, repository.name))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Move wiki repository
|
|
||||||
defining(getWikiRepositoryDir(repository.owner, repository.name)) { dir =>
|
|
||||||
if (dir.isDirectory) {
|
|
||||||
FileUtils.moveDirectory(dir, getWikiRepositoryDir(form.newOwner, repository.name))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Move files directory
|
|
||||||
defining(getRepositoryFilesDir(repository.owner, repository.name)) { dir =>
|
|
||||||
if (dir.isDirectory) {
|
|
||||||
FileUtils.moveDirectory(dir, getRepositoryFilesDir(form.newOwner, repository.name))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call hooks
|
|
||||||
PluginRegistry().getRepositoryHooks.foreach(_.transferred(repository.owner, form.newOwner, repository.name))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
redirect(s"/${form.newOwner}/${repository.name}")
|
redirect(s"/${form.newOwner}/${repository.name}")
|
||||||
})
|
})
|
||||||
@@ -425,19 +376,8 @@ trait RepositorySettingsControllerBase extends ControllerBase {
|
|||||||
* Delete the repository.
|
* Delete the repository.
|
||||||
*/
|
*/
|
||||||
post("/:owner/:repository/settings/delete")(ownerOnly { repository =>
|
post("/:owner/:repository/settings/delete")(ownerOnly { repository =>
|
||||||
LockUtil.lock(s"${repository.owner}/${repository.name}") {
|
// Delete the repository and related files
|
||||||
// Delete the repository and related files
|
deleteRepository(repository.repository)
|
||||||
deleteRepository(repository.owner, repository.name)
|
|
||||||
|
|
||||||
FileUtils.deleteDirectory(getRepositoryDir(repository.owner, repository.name))
|
|
||||||
FileUtils.deleteDirectory(getWikiRepositoryDir(repository.owner, repository.name))
|
|
||||||
FileUtils.deleteDirectory(getTemporaryDir(repository.owner, repository.name))
|
|
||||||
FileUtils.deleteDirectory(getRepositoryFilesDir(repository.owner, repository.name))
|
|
||||||
|
|
||||||
// Call hooks
|
|
||||||
PluginRegistry().getRepositoryHooks.foreach(_.deleted(repository.owner, repository.name))
|
|
||||||
}
|
|
||||||
|
|
||||||
redirect(s"/${repository.owner}")
|
redirect(s"/${repository.owner}")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -7,14 +7,13 @@ import gitbucket.core.plugin.PluginRegistry
|
|||||||
import gitbucket.core.repo.html
|
import gitbucket.core.repo.html
|
||||||
import gitbucket.core.helper
|
import gitbucket.core.helper
|
||||||
import gitbucket.core.service._
|
import gitbucket.core.service._
|
||||||
|
import gitbucket.core.service.RepositoryCommitFileService.CommitFile
|
||||||
import gitbucket.core.util._
|
import gitbucket.core.util._
|
||||||
import gitbucket.core.util.JGitUtil._
|
|
||||||
import gitbucket.core.util.StringUtil._
|
import gitbucket.core.util.StringUtil._
|
||||||
import gitbucket.core.util.SyntaxSugars._
|
import gitbucket.core.util.SyntaxSugars._
|
||||||
import gitbucket.core.util.Implicits._
|
import gitbucket.core.util.Implicits._
|
||||||
import gitbucket.core.util.Directory._
|
import gitbucket.core.util.Directory._
|
||||||
import gitbucket.core.model.{Account, CommitState, CommitStatus, WebHook}
|
import gitbucket.core.model.{Account, CommitState, CommitStatus}
|
||||||
import gitbucket.core.service.WebHookService._
|
|
||||||
import gitbucket.core.view
|
import gitbucket.core.view
|
||||||
import gitbucket.core.view.helpers
|
import gitbucket.core.view.helpers
|
||||||
import org.apache.commons.compress.archivers.{ArchiveEntry, ArchiveOutputStream}
|
import org.apache.commons.compress.archivers.{ArchiveEntry, ArchiveOutputStream}
|
||||||
@@ -24,15 +23,12 @@ import org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream
|
|||||||
import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream
|
import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream
|
||||||
import org.apache.commons.compress.compressors.xz.XZCompressorOutputStream
|
import org.apache.commons.compress.compressors.xz.XZCompressorOutputStream
|
||||||
import org.apache.commons.compress.utils.IOUtils
|
import org.apache.commons.compress.utils.IOUtils
|
||||||
import org.scalatra.forms._
|
|
||||||
import org.apache.commons.io.FileUtils
|
import org.apache.commons.io.FileUtils
|
||||||
import org.ec4j.core.model.PropertyType
|
import org.scalatra.forms._
|
||||||
import org.eclipse.jgit.api.{ArchiveCommand, Git}
|
import org.eclipse.jgit.api.{ArchiveCommand, Git}
|
||||||
import org.eclipse.jgit.archive.{TgzFormat, ZipFormat}
|
import org.eclipse.jgit.archive.{TgzFormat, ZipFormat}
|
||||||
import org.eclipse.jgit.dircache.{DirCache, DirCacheBuilder}
|
|
||||||
import org.eclipse.jgit.errors.MissingObjectException
|
import org.eclipse.jgit.errors.MissingObjectException
|
||||||
import org.eclipse.jgit.lib._
|
import org.eclipse.jgit.lib._
|
||||||
import org.eclipse.jgit.transport.{ReceiveCommand, ReceivePack}
|
|
||||||
import org.eclipse.jgit.treewalk.TreeWalk
|
import org.eclipse.jgit.treewalk.TreeWalk
|
||||||
import org.eclipse.jgit.treewalk.filter.PathFilter
|
import org.eclipse.jgit.treewalk.filter.PathFilter
|
||||||
import org.json4s.jackson.Serialization
|
import org.json4s.jackson.Serialization
|
||||||
@@ -42,6 +38,7 @@ import org.scalatra.i18n.Messages
|
|||||||
class RepositoryViewerController
|
class RepositoryViewerController
|
||||||
extends RepositoryViewerControllerBase
|
extends RepositoryViewerControllerBase
|
||||||
with RepositoryService
|
with RepositoryService
|
||||||
|
with RepositoryCommitFileService
|
||||||
with AccountService
|
with AccountService
|
||||||
with ActivityService
|
with ActivityService
|
||||||
with IssuesService
|
with IssuesService
|
||||||
@@ -64,6 +61,7 @@ class RepositoryViewerController
|
|||||||
*/
|
*/
|
||||||
trait RepositoryViewerControllerBase extends ControllerBase {
|
trait RepositoryViewerControllerBase extends ControllerBase {
|
||||||
self: RepositoryService
|
self: RepositoryService
|
||||||
|
with RepositoryCommitFileService
|
||||||
with AccountService
|
with AccountService
|
||||||
with ActivityService
|
with ActivityService
|
||||||
with IssuesService
|
with IssuesService
|
||||||
@@ -319,13 +317,34 @@ trait RepositoryViewerControllerBase extends ControllerBase {
|
|||||||
CommitFile(line.substring(0, i).trim, line.substring(i + 1).trim)
|
CommitFile(line.substring(0, i).trim, line.substring(i + 1).trim)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val newFiles = files.map { file =>
|
||||||
|
file.copy(name = if (form.path.length == 0) file.name else s"${form.path}/${file.name}")
|
||||||
|
}
|
||||||
|
|
||||||
commitFiles(
|
commitFiles(
|
||||||
repository = repository,
|
repository = repository,
|
||||||
branch = form.branch,
|
branch = form.branch,
|
||||||
path = form.path,
|
path = form.path,
|
||||||
files = files,
|
files = files,
|
||||||
message = form.message.getOrElse("Add files via upload")
|
message = form.message.getOrElse("Add files via upload"),
|
||||||
)
|
loginAccount = context.loginAccount.get
|
||||||
|
) {
|
||||||
|
case (git, headTip, builder, inserter) =>
|
||||||
|
JGitUtil.processTree(git, headTip) { (path, tree) =>
|
||||||
|
if (!newFiles.exists(_.name.contains(path))) {
|
||||||
|
builder.add(JGitUtil.createDirCacheEntry(path, tree.getEntryFileMode, tree.getEntryObjectId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newFiles.foreach { file =>
|
||||||
|
val bytes =
|
||||||
|
FileUtils.readFileToByteArray(new File(getTemporaryDir(session.getId), FileUtil.checkFilename(file.id)))
|
||||||
|
builder.add(
|
||||||
|
JGitUtil.createDirCacheEntry(file.name, FileMode.REGULAR_FILE, inserter.insert(Constants.OBJ_BLOB, bytes))
|
||||||
|
)
|
||||||
|
builder.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (form.path.length == 0) {
|
if (form.path.length == 0) {
|
||||||
redirect(s"/${repository.owner}/${repository.name}/tree/${form.branch}")
|
redirect(s"/${repository.owner}/${repository.name}/tree/${form.branch}")
|
||||||
@@ -394,7 +413,8 @@ trait RepositoryViewerControllerBase extends ControllerBase {
|
|||||||
content = appendNewLine(convertLineSeparator(form.content, form.lineSeparator), form.lineSeparator),
|
content = appendNewLine(convertLineSeparator(form.content, form.lineSeparator), form.lineSeparator),
|
||||||
charset = form.charset,
|
charset = form.charset,
|
||||||
message = form.message.getOrElse(s"Create ${form.newFileName}"),
|
message = form.message.getOrElse(s"Create ${form.newFileName}"),
|
||||||
commit = form.commit
|
commit = form.commit,
|
||||||
|
loginAccount = context.loginAccount.get
|
||||||
)
|
)
|
||||||
|
|
||||||
redirect(
|
redirect(
|
||||||
@@ -417,7 +437,8 @@ trait RepositoryViewerControllerBase extends ControllerBase {
|
|||||||
} else {
|
} else {
|
||||||
form.message.getOrElse(s"Rename ${form.oldFileName.get} to ${form.newFileName}")
|
form.message.getOrElse(s"Rename ${form.oldFileName.get} to ${form.newFileName}")
|
||||||
},
|
},
|
||||||
commit = form.commit
|
commit = form.commit,
|
||||||
|
loginAccount = context.loginAccount.get
|
||||||
)
|
)
|
||||||
|
|
||||||
redirect(
|
redirect(
|
||||||
@@ -436,7 +457,8 @@ trait RepositoryViewerControllerBase extends ControllerBase {
|
|||||||
content = "",
|
content = "",
|
||||||
charset = "",
|
charset = "",
|
||||||
message = form.message.getOrElse(s"Delete ${form.fileName}"),
|
message = form.message.getOrElse(s"Delete ${form.fileName}"),
|
||||||
commit = form.commit
|
commit = form.commit,
|
||||||
|
loginAccount = context.loginAccount.get
|
||||||
)
|
)
|
||||||
|
|
||||||
println(form.path)
|
println(form.path)
|
||||||
@@ -593,50 +615,17 @@ trait RepositoryViewerControllerBase extends ControllerBase {
|
|||||||
post("/:owner/:repository/commit/:id/comment/new", commentForm)(readableUsersOnly { (form, repository) =>
|
post("/:owner/:repository/commit/:id/comment/new", commentForm)(readableUsersOnly { (form, repository) =>
|
||||||
val id = params("id")
|
val id = params("id")
|
||||||
createCommitComment(
|
createCommitComment(
|
||||||
repository.owner,
|
repository,
|
||||||
repository.name,
|
|
||||||
id,
|
id,
|
||||||
context.loginAccount.get.userName,
|
context.loginAccount.get,
|
||||||
form.content,
|
form.content,
|
||||||
form.fileName,
|
form.fileName,
|
||||||
form.oldLineNumber,
|
form.oldLineNumber,
|
||||||
form.newLineNumber,
|
form.newLineNumber,
|
||||||
|
form.diff,
|
||||||
form.issueId
|
form.issueId
|
||||||
)
|
)
|
||||||
|
|
||||||
for {
|
|
||||||
fileName <- form.fileName
|
|
||||||
diff <- form.diff
|
|
||||||
} {
|
|
||||||
saveCommitCommentDiff(
|
|
||||||
repository.owner,
|
|
||||||
repository.name,
|
|
||||||
id,
|
|
||||||
fileName,
|
|
||||||
form.oldLineNumber,
|
|
||||||
form.newLineNumber,
|
|
||||||
diff
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
form.issueId match {
|
|
||||||
case Some(issueId) =>
|
|
||||||
recordCommentPullRequestActivity(
|
|
||||||
repository.owner,
|
|
||||||
repository.name,
|
|
||||||
context.loginAccount.get.userName,
|
|
||||||
issueId,
|
|
||||||
form.content
|
|
||||||
)
|
|
||||||
case None =>
|
|
||||||
recordCommentCommitActivity(
|
|
||||||
repository.owner,
|
|
||||||
repository.name,
|
|
||||||
context.loginAccount.get.userName,
|
|
||||||
id,
|
|
||||||
form.content
|
|
||||||
)
|
|
||||||
}
|
|
||||||
redirect(s"/${repository.owner}/${repository.name}/commit/${id}")
|
redirect(s"/${repository.owner}/${repository.name}/commit/${id}")
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -661,64 +650,18 @@ trait RepositoryViewerControllerBase extends ControllerBase {
|
|||||||
ajaxPost("/:owner/:repository/commit/:id/comment/_data/new", commentForm)(readableUsersOnly { (form, repository) =>
|
ajaxPost("/:owner/:repository/commit/:id/comment/_data/new", commentForm)(readableUsersOnly { (form, repository) =>
|
||||||
val id = params("id")
|
val id = params("id")
|
||||||
val commentId = createCommitComment(
|
val commentId = createCommitComment(
|
||||||
repository.owner,
|
repository,
|
||||||
repository.name,
|
|
||||||
id,
|
id,
|
||||||
context.loginAccount.get.userName,
|
context.loginAccount.get,
|
||||||
form.content,
|
form.content,
|
||||||
form.fileName,
|
form.fileName,
|
||||||
form.oldLineNumber,
|
form.oldLineNumber,
|
||||||
form.newLineNumber,
|
form.newLineNumber,
|
||||||
|
form.diff,
|
||||||
form.issueId
|
form.issueId
|
||||||
)
|
)
|
||||||
|
|
||||||
for {
|
|
||||||
fileName <- form.fileName
|
|
||||||
diff <- form.diff
|
|
||||||
} {
|
|
||||||
saveCommitCommentDiff(
|
|
||||||
repository.owner,
|
|
||||||
repository.name,
|
|
||||||
id,
|
|
||||||
fileName,
|
|
||||||
form.oldLineNumber,
|
|
||||||
form.newLineNumber,
|
|
||||||
diff
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val comment = getCommitComment(repository.owner, repository.name, commentId.toString).get
|
val comment = getCommitComment(repository.owner, repository.name, commentId.toString).get
|
||||||
form.issueId match {
|
|
||||||
case Some(issueId) =>
|
|
||||||
getPullRequest(repository.owner, repository.name, issueId).foreach {
|
|
||||||
case (issue, pullRequest) =>
|
|
||||||
recordCommentPullRequestActivity(
|
|
||||||
repository.owner,
|
|
||||||
repository.name,
|
|
||||||
context.loginAccount.get.userName,
|
|
||||||
issueId,
|
|
||||||
form.content
|
|
||||||
)
|
|
||||||
PluginRegistry().getPullRequestHooks.foreach(_.addedComment(commentId, form.content, issue, repository))
|
|
||||||
callPullRequestReviewCommentWebHook(
|
|
||||||
"create",
|
|
||||||
comment,
|
|
||||||
repository,
|
|
||||||
issue,
|
|
||||||
pullRequest,
|
|
||||||
context.baseUrl,
|
|
||||||
context.loginAccount.get
|
|
||||||
)
|
|
||||||
}
|
|
||||||
case None =>
|
|
||||||
recordCommentCommitActivity(
|
|
||||||
repository.owner,
|
|
||||||
repository.name,
|
|
||||||
context.loginAccount.get.userName,
|
|
||||||
id,
|
|
||||||
form.content
|
|
||||||
)
|
|
||||||
}
|
|
||||||
helper.html
|
helper.html
|
||||||
.commitcomment(comment, hasDeveloperRole(repository.owner, repository.name, context.loginAccount), repository)
|
.commitcomment(comment, hasDeveloperRole(repository.owner, repository.name, context.loginAccount), repository)
|
||||||
})
|
})
|
||||||
@@ -930,185 +873,6 @@ trait RepositoryViewerControllerBase extends ControllerBase {
|
|||||||
lazy val isValid: Boolean = fileIds.nonEmpty
|
lazy val isValid: Boolean = fileIds.nonEmpty
|
||||||
}
|
}
|
||||||
|
|
||||||
case class CommitFile(id: String, name: String)
|
|
||||||
|
|
||||||
private def commitFiles(
|
|
||||||
repository: RepositoryService.RepositoryInfo,
|
|
||||||
files: Seq[CommitFile],
|
|
||||||
branch: String,
|
|
||||||
path: String,
|
|
||||||
message: String
|
|
||||||
) = {
|
|
||||||
// prepend path to the filename
|
|
||||||
val newFiles = files.map { file =>
|
|
||||||
file.copy(name = if (path.length == 0) file.name else s"${path}/${file.name}")
|
|
||||||
}
|
|
||||||
|
|
||||||
_commitFile(repository, branch, message) {
|
|
||||||
case (git, headTip, builder, inserter) =>
|
|
||||||
JGitUtil.processTree(git, headTip) { (path, tree) =>
|
|
||||||
if (!newFiles.exists(_.name.contains(path))) {
|
|
||||||
builder.add(JGitUtil.createDirCacheEntry(path, tree.getEntryFileMode, tree.getEntryObjectId))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
newFiles.foreach { file =>
|
|
||||||
val bytes =
|
|
||||||
FileUtils.readFileToByteArray(new File(getTemporaryDir(session.getId), FileUtil.checkFilename(file.id)))
|
|
||||||
builder.add(
|
|
||||||
JGitUtil.createDirCacheEntry(file.name, FileMode.REGULAR_FILE, inserter.insert(Constants.OBJ_BLOB, bytes))
|
|
||||||
)
|
|
||||||
builder.finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private def commitFile(
|
|
||||||
repository: RepositoryService.RepositoryInfo,
|
|
||||||
branch: String,
|
|
||||||
path: String,
|
|
||||||
newFileName: Option[String],
|
|
||||||
oldFileName: Option[String],
|
|
||||||
content: String,
|
|
||||||
charset: String,
|
|
||||||
message: String,
|
|
||||||
commit: String
|
|
||||||
) = {
|
|
||||||
|
|
||||||
val newPath = newFileName.map { newFileName =>
|
|
||||||
if (path.length == 0) newFileName else s"${path}/${newFileName}"
|
|
||||||
}
|
|
||||||
val oldPath = oldFileName.map { oldFileName =>
|
|
||||||
if (path.length == 0) oldFileName else s"${path}/${oldFileName}"
|
|
||||||
}
|
|
||||||
|
|
||||||
_commitFile(repository, branch, message) {
|
|
||||||
case (git, headTip, builder, inserter) =>
|
|
||||||
if (headTip.getName == commit) {
|
|
||||||
val permission = JGitUtil
|
|
||||||
.processTree(git, headTip) { (path, tree) =>
|
|
||||||
// Add all entries except the editing file
|
|
||||||
if (!newPath.contains(path) && !oldPath.contains(path)) {
|
|
||||||
builder.add(JGitUtil.createDirCacheEntry(path, tree.getEntryFileMode, tree.getEntryObjectId))
|
|
||||||
}
|
|
||||||
// Retrieve permission if file exists to keep it
|
|
||||||
oldPath.collect { case x if x == path => tree.getEntryFileMode.getBits }
|
|
||||||
}
|
|
||||||
.flatten
|
|
||||||
.headOption
|
|
||||||
|
|
||||||
newPath.foreach { newPath =>
|
|
||||||
builder.add(JGitUtil.createDirCacheEntry(newPath, permission.map { bits =>
|
|
||||||
FileMode.fromBits(bits)
|
|
||||||
} getOrElse FileMode.REGULAR_FILE, inserter.insert(Constants.OBJ_BLOB, content.getBytes(charset))))
|
|
||||||
}
|
|
||||||
builder.finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private def _commitFile(repository: RepositoryService.RepositoryInfo, branch: String, message: String)(
|
|
||||||
f: (Git, ObjectId, DirCacheBuilder, ObjectInserter) => Unit
|
|
||||||
) = {
|
|
||||||
|
|
||||||
LockUtil.lock(s"${repository.owner}/${repository.name}") {
|
|
||||||
using(Git.open(getRepositoryDir(repository.owner, repository.name))) { git =>
|
|
||||||
val loginAccount = context.loginAccount.get
|
|
||||||
val builder = DirCache.newInCore.builder()
|
|
||||||
val inserter = git.getRepository.newObjectInserter()
|
|
||||||
val headName = s"refs/heads/${branch}"
|
|
||||||
val headTip = git.getRepository.resolve(headName)
|
|
||||||
|
|
||||||
f(git, headTip, builder, inserter)
|
|
||||||
|
|
||||||
val commitId = JGitUtil.createNewCommit(
|
|
||||||
git,
|
|
||||||
inserter,
|
|
||||||
headTip,
|
|
||||||
builder.getDirCache.writeTree(inserter),
|
|
||||||
headName,
|
|
||||||
loginAccount.fullName,
|
|
||||||
loginAccount.mailAddress,
|
|
||||||
message
|
|
||||||
)
|
|
||||||
|
|
||||||
inserter.flush()
|
|
||||||
inserter.close()
|
|
||||||
|
|
||||||
val receivePack = new ReceivePack(git.getRepository)
|
|
||||||
val receiveCommand = new ReceiveCommand(headTip, commitId, headName)
|
|
||||||
|
|
||||||
// call post commit hook
|
|
||||||
val error = PluginRegistry().getReceiveHooks.flatMap { hook =>
|
|
||||||
hook.preReceive(repository.owner, repository.name, receivePack, receiveCommand, loginAccount.userName)
|
|
||||||
}.headOption
|
|
||||||
|
|
||||||
error match {
|
|
||||||
case Some(error) =>
|
|
||||||
// commit is rejected
|
|
||||||
// TODO Notify commit failure to edited user
|
|
||||||
val refUpdate = git.getRepository.updateRef(headName)
|
|
||||||
refUpdate.setNewObjectId(headTip)
|
|
||||||
refUpdate.setForceUpdate(true)
|
|
||||||
refUpdate.update()
|
|
||||||
|
|
||||||
case None =>
|
|
||||||
// update refs
|
|
||||||
val refUpdate = git.getRepository.updateRef(headName)
|
|
||||||
refUpdate.setNewObjectId(commitId)
|
|
||||||
refUpdate.setForceUpdate(false)
|
|
||||||
refUpdate.setRefLogIdent(new PersonIdent(loginAccount.fullName, loginAccount.mailAddress))
|
|
||||||
refUpdate.update()
|
|
||||||
|
|
||||||
// update pull request
|
|
||||||
updatePullRequests(repository.owner, repository.name, branch)
|
|
||||||
|
|
||||||
// record activity
|
|
||||||
val commitInfo = new CommitInfo(JGitUtil.getRevCommitFromId(git, commitId))
|
|
||||||
recordPushActivity(repository.owner, repository.name, loginAccount.userName, branch, List(commitInfo))
|
|
||||||
|
|
||||||
// create issue comment by commit message
|
|
||||||
createIssueComment(repository.owner, repository.name, commitInfo)
|
|
||||||
|
|
||||||
// close issue by commit message
|
|
||||||
if (branch == repository.repository.defaultBranch) {
|
|
||||||
closeIssuesFromMessage(message, loginAccount.userName, repository.owner, repository.name).foreach {
|
|
||||||
issueId =>
|
|
||||||
getIssue(repository.owner, repository.name, issueId.toString).foreach { issue =>
|
|
||||||
callIssuesWebHook("closed", repository, issue, baseUrl, loginAccount)
|
|
||||||
PluginRegistry().getIssueHooks
|
|
||||||
.foreach(_.closedByCommitComment(issue, repository, message, loginAccount))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// call post commit hook
|
|
||||||
PluginRegistry().getReceiveHooks.foreach { hook =>
|
|
||||||
hook.postReceive(repository.owner, repository.name, receivePack, receiveCommand, loginAccount.userName)
|
|
||||||
}
|
|
||||||
|
|
||||||
//call web hook
|
|
||||||
callPullRequestWebHookByRequestBranch("synchronize", repository, branch, context.baseUrl, loginAccount)
|
|
||||||
val commit = new JGitUtil.CommitInfo(JGitUtil.getRevCommitFromId(git, commitId))
|
|
||||||
callWebHookOf(repository.owner, repository.name, WebHook.Push) {
|
|
||||||
getAccountByUserName(repository.owner).map { ownerAccount =>
|
|
||||||
WebHookPushPayload(
|
|
||||||
git,
|
|
||||||
loginAccount,
|
|
||||||
headName,
|
|
||||||
repository,
|
|
||||||
List(commit),
|
|
||||||
ownerAccount,
|
|
||||||
oldId = headTip,
|
|
||||||
newId = commitId
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val readmeFiles = PluginRegistry().renderableExtensions.map { extension =>
|
private val readmeFiles = PluginRegistry().renderableExtensions.map { extension =>
|
||||||
s"readme.${extension}"
|
s"readme.${extension}"
|
||||||
} ++ Seq("readme.txt", "readme")
|
} ++ Seq("readme.txt", "readme")
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import gitbucket.core.model.Profile.profile.blockingApi._
|
|||||||
import gitbucket.core.model.Profile.dateColumnType
|
import gitbucket.core.model.Profile.dateColumnType
|
||||||
import gitbucket.core.util.{LDAPUtil, StringUtil}
|
import gitbucket.core.util.{LDAPUtil, StringUtil}
|
||||||
import StringUtil._
|
import StringUtil._
|
||||||
|
import gitbucket.core.plugin.PluginRegistry
|
||||||
import gitbucket.core.service.SystemSettingsService.SystemSettings
|
import gitbucket.core.service.SystemSettingsService.SystemSettings
|
||||||
|
|
||||||
trait AccountService {
|
trait AccountService {
|
||||||
@@ -180,6 +181,15 @@ trait AccountService {
|
|||||||
description = description
|
description = description
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def suspendAccount(account: Account)(implicit s: Session): Unit = {
|
||||||
|
// Remove from GROUP_MEMBER and COLLABORATOR
|
||||||
|
removeUserRelatedData(account.userName)
|
||||||
|
updateAccount(account.copy(isRemoved = true))
|
||||||
|
|
||||||
|
// call hooks
|
||||||
|
PluginRegistry().getAccountHooks.foreach(_.deleted(account.userName))
|
||||||
|
}
|
||||||
|
|
||||||
def updateAccount(account: Account)(implicit s: Session): Unit =
|
def updateAccount(account: Account)(implicit s: Session): Unit =
|
||||||
Accounts
|
Accounts
|
||||||
.filter { a =>
|
.filter { a =>
|
||||||
@@ -278,6 +288,15 @@ trait AccountService {
|
|||||||
Collaborators.filter(_.collaboratorName === userName.bind).delete
|
Collaborators.filter(_.collaboratorName === userName.bind).delete
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def removeUser(account: Account)(implicit s: Session): Unit = {
|
||||||
|
// Remove from GROUP_MEMBER and COLLABORATOR
|
||||||
|
removeUserRelatedData(account.userName)
|
||||||
|
updateAccount(account.copy(isRemoved = true))
|
||||||
|
|
||||||
|
// call hooks
|
||||||
|
PluginRegistry().getAccountHooks.foreach(_.deleted(account.userName))
|
||||||
|
}
|
||||||
|
|
||||||
def getGroupNames(userName: String)(implicit s: Session): List[String] = {
|
def getGroupNames(userName: String)(implicit s: Session): List[String] = {
|
||||||
List(userName) ++
|
List(userName) ++
|
||||||
Collaborators.filter(_.collaboratorName === userName.bind).sortBy(_.userName).map(_.userName).list.distinct
|
Collaborators.filter(_.collaboratorName === userName.bind).sortBy(_.userName).map(_.userName).list.distinct
|
||||||
|
|||||||
@@ -2,15 +2,20 @@ package gitbucket.core.service
|
|||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
import gitbucket.core.model.CommitComment
|
import gitbucket.core.api.JsonFormat
|
||||||
|
import gitbucket.core.controller.Context
|
||||||
|
import gitbucket.core.model.{Account, CommitComment}
|
||||||
import gitbucket.core.model.Profile._
|
import gitbucket.core.model.Profile._
|
||||||
import gitbucket.core.model.Profile.profile.blockingApi._
|
import gitbucket.core.model.Profile.profile.blockingApi._
|
||||||
import gitbucket.core.model.Profile.dateColumnType
|
import gitbucket.core.model.Profile.dateColumnType
|
||||||
|
import gitbucket.core.plugin.PluginRegistry
|
||||||
|
import gitbucket.core.service.RepositoryService.RepositoryInfo
|
||||||
import gitbucket.core.util.Directory._
|
import gitbucket.core.util.Directory._
|
||||||
import gitbucket.core.util.{FileUtil, StringUtil}
|
import gitbucket.core.util.{FileUtil, StringUtil}
|
||||||
import org.apache.commons.io.FileUtils
|
import org.apache.commons.io.FileUtils
|
||||||
|
|
||||||
trait CommitsService {
|
trait CommitsService {
|
||||||
|
self: ActivityService with PullRequestService with WebHookPullRequestReviewCommentService =>
|
||||||
|
|
||||||
def getCommitComments(owner: String, repository: String, commitId: String, includePullRequest: Boolean)(
|
def getCommitComments(owner: String, repository: String, commitId: String, includePullRequest: Boolean)(
|
||||||
implicit s: Session
|
implicit s: Session
|
||||||
@@ -28,21 +33,21 @@ trait CommitsService {
|
|||||||
None
|
None
|
||||||
|
|
||||||
def createCommitComment(
|
def createCommitComment(
|
||||||
owner: String,
|
repository: RepositoryInfo,
|
||||||
repository: String,
|
|
||||||
commitId: String,
|
commitId: String,
|
||||||
loginUser: String,
|
loginAccount: Account,
|
||||||
content: String,
|
content: String,
|
||||||
fileName: Option[String],
|
fileName: Option[String],
|
||||||
oldLine: Option[Int],
|
oldLine: Option[Int],
|
||||||
newLine: Option[Int],
|
newLine: Option[Int],
|
||||||
|
diff: Option[String],
|
||||||
issueId: Option[Int]
|
issueId: Option[Int]
|
||||||
)(implicit s: Session): Int =
|
)(implicit s: Session, c: JsonFormat.Context, context: Context): Int = {
|
||||||
CommitComments returning CommitComments.map(_.commentId) insert CommitComment(
|
val commentId = CommitComments returning CommitComments.map(_.commentId) insert CommitComment(
|
||||||
userName = owner,
|
userName = repository.owner,
|
||||||
repositoryName = repository,
|
repositoryName = repository.name,
|
||||||
commitId = commitId,
|
commitId = commitId,
|
||||||
commentedUserName = loginUser,
|
commentedUserName = loginAccount.userName,
|
||||||
content = content,
|
content = content,
|
||||||
fileName = fileName,
|
fileName = fileName,
|
||||||
oldLine = oldLine,
|
oldLine = oldLine,
|
||||||
@@ -55,6 +60,56 @@ trait CommitsService {
|
|||||||
originalNewLine = newLine
|
originalNewLine = newLine
|
||||||
)
|
)
|
||||||
|
|
||||||
|
for {
|
||||||
|
fileName <- fileName
|
||||||
|
diff <- diff
|
||||||
|
} {
|
||||||
|
saveCommitCommentDiff(
|
||||||
|
repository.owner,
|
||||||
|
repository.name,
|
||||||
|
commitId,
|
||||||
|
fileName,
|
||||||
|
oldLine,
|
||||||
|
newLine,
|
||||||
|
diff
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val comment = getCommitComment(repository.owner, repository.name, commentId.toString).get
|
||||||
|
issueId match {
|
||||||
|
case Some(issueId) =>
|
||||||
|
getPullRequest(repository.owner, repository.name, issueId).foreach {
|
||||||
|
case (issue, pullRequest) =>
|
||||||
|
recordCommentPullRequestActivity(
|
||||||
|
repository.owner,
|
||||||
|
repository.name,
|
||||||
|
loginAccount.userName,
|
||||||
|
issueId,
|
||||||
|
content
|
||||||
|
)
|
||||||
|
PluginRegistry().getPullRequestHooks.foreach(_.addedComment(commentId, content, issue, repository))
|
||||||
|
callPullRequestReviewCommentWebHook(
|
||||||
|
"create",
|
||||||
|
comment,
|
||||||
|
repository,
|
||||||
|
issue,
|
||||||
|
pullRequest,
|
||||||
|
loginAccount
|
||||||
|
)
|
||||||
|
}
|
||||||
|
case None =>
|
||||||
|
recordCommentCommitActivity(
|
||||||
|
repository.owner,
|
||||||
|
repository.name,
|
||||||
|
loginAccount.userName,
|
||||||
|
commitId,
|
||||||
|
content
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
commentId
|
||||||
|
}
|
||||||
|
|
||||||
def updateCommitCommentPosition(commentId: Int, commitId: String, oldLine: Option[Int], newLine: Option[Int])(
|
def updateCommitCommentPosition(commentId: Int, commitId: String, oldLine: Option[Int], newLine: Option[Int])(
|
||||||
implicit s: Session
|
implicit s: Session
|
||||||
): Unit =
|
): Unit =
|
||||||
|
|||||||
@@ -87,9 +87,9 @@ trait HandleCommentService {
|
|||||||
case "reopen" => "reopened"
|
case "reopen" => "reopened"
|
||||||
}
|
}
|
||||||
if (issue.isPullRequest)
|
if (issue.isPullRequest)
|
||||||
callPullRequestWebHook(webHookAction, repository, issue.issueId, context.baseUrl, loginAccount)
|
callPullRequestWebHook(webHookAction, repository, issue.issueId, loginAccount)
|
||||||
else
|
else
|
||||||
callIssuesWebHook(webHookAction, repository, issue, context.baseUrl, loginAccount)
|
callIssuesWebHook(webHookAction, repository, issue, loginAccount)
|
||||||
}
|
}
|
||||||
|
|
||||||
// call hooks
|
// call hooks
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ trait IssueCreationService {
|
|||||||
createReferComment(owner, name, issue, title + " " + body.getOrElse(""), loginAccount)
|
createReferComment(owner, name, issue, title + " " + body.getOrElse(""), loginAccount)
|
||||||
|
|
||||||
// call web hooks
|
// call web hooks
|
||||||
callIssuesWebHook("opened", repository, issue, context.baseUrl, loginAccount)
|
callIssuesWebHook("opened", repository, issue, loginAccount)
|
||||||
|
|
||||||
// call hooks
|
// call hooks
|
||||||
PluginRegistry().getIssueHooks.foreach(_.created(issue, repository))
|
PluginRegistry().getIssueHooks.foreach(_.created(issue, repository))
|
||||||
|
|||||||
@@ -1,8 +1,16 @@
|
|||||||
package gitbucket.core.service
|
package gitbucket.core.service
|
||||||
|
|
||||||
import gitbucket.core.model.Account
|
import gitbucket.core.api.JsonFormat
|
||||||
|
import gitbucket.core.controller.Context
|
||||||
|
import gitbucket.core.model.{Account, PullRequest, WebHook}
|
||||||
|
import gitbucket.core.plugin.PluginRegistry
|
||||||
|
import gitbucket.core.service.RepositoryService.RepositoryInfo
|
||||||
import gitbucket.core.util.Directory._
|
import gitbucket.core.util.Directory._
|
||||||
|
import gitbucket.core.util.{JGitUtil, LockUtil}
|
||||||
import gitbucket.core.util.SyntaxSugars._
|
import gitbucket.core.util.SyntaxSugars._
|
||||||
|
import gitbucket.core.model.Profile._
|
||||||
|
import gitbucket.core.model.Profile.profile._
|
||||||
|
import gitbucket.core.model.Profile.profile.blockingApi._
|
||||||
import org.eclipse.jgit.merge.{MergeStrategy, Merger, RecursiveMerger}
|
import org.eclipse.jgit.merge.{MergeStrategy, Merger, RecursiveMerger}
|
||||||
import org.eclipse.jgit.api.Git
|
import org.eclipse.jgit.api.Git
|
||||||
import org.eclipse.jgit.transport.RefSpec
|
import org.eclipse.jgit.transport.RefSpec
|
||||||
@@ -13,6 +21,13 @@ import org.eclipse.jgit.revwalk.{RevCommit, RevWalk}
|
|||||||
import scala.collection.JavaConverters._
|
import scala.collection.JavaConverters._
|
||||||
|
|
||||||
trait MergeService {
|
trait MergeService {
|
||||||
|
self: AccountService
|
||||||
|
with ActivityService
|
||||||
|
with IssuesService
|
||||||
|
with RepositoryService
|
||||||
|
with PullRequestService
|
||||||
|
with WebHookPullRequestService =>
|
||||||
|
|
||||||
import MergeService._
|
import MergeService._
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -43,7 +58,13 @@ trait MergeService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** merge the pull request with a merge commit */
|
/** merge the pull request with a merge commit */
|
||||||
def mergePullRequest(git: Git, branch: String, issueId: Int, message: String, committer: PersonIdent): Unit = {
|
def mergePullRequest(
|
||||||
|
git: Git,
|
||||||
|
branch: String,
|
||||||
|
issueId: Int,
|
||||||
|
message: String,
|
||||||
|
committer: PersonIdent
|
||||||
|
): ObjectId = {
|
||||||
new MergeCacheInfo(git, branch, issueId).merge(message, committer)
|
new MergeCacheInfo(git, branch, issueId).merge(message, committer)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,12 +75,18 @@ trait MergeService {
|
|||||||
issueId: Int,
|
issueId: Int,
|
||||||
commits: Seq[RevCommit],
|
commits: Seq[RevCommit],
|
||||||
committer: PersonIdent
|
committer: PersonIdent
|
||||||
): Unit = {
|
): ObjectId = {
|
||||||
new MergeCacheInfo(git, branch, issueId).rebase(committer, commits)
|
new MergeCacheInfo(git, branch, issueId).rebase(committer, commits)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** squash commits in the pull request and append it */
|
/** squash commits in the pull request and append it */
|
||||||
def squashPullRequest(git: Git, branch: String, issueId: Int, message: String, committer: PersonIdent): Unit = {
|
def squashPullRequest(
|
||||||
|
git: Git,
|
||||||
|
branch: String,
|
||||||
|
issueId: Int,
|
||||||
|
message: String,
|
||||||
|
committer: PersonIdent
|
||||||
|
): ObjectId = {
|
||||||
new MergeCacheInfo(git, branch, issueId).squash(message, committer)
|
new MergeCacheInfo(git, branch, issueId).squash(message, committer)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,27 +163,223 @@ trait MergeService {
|
|||||||
tryMergeRemote(userName, repositoryName, branch, requestUserName, requestRepositoryName, requestBranch).left.toOption
|
tryMergeRemote(userName, repositoryName, branch, requestUserName, requestRepositoryName, requestBranch).left.toOption
|
||||||
|
|
||||||
def pullRemote(
|
def pullRemote(
|
||||||
localUserName: String,
|
localRepository: RepositoryInfo,
|
||||||
localRepositoryName: String,
|
|
||||||
localBranch: String,
|
localBranch: String,
|
||||||
remoteUserName: String,
|
remoteRepository: RepositoryInfo,
|
||||||
remoteRepositoryName: String,
|
|
||||||
remoteBranch: String,
|
remoteBranch: String,
|
||||||
loginAccount: Account,
|
loginAccount: Account,
|
||||||
message: String
|
message: String,
|
||||||
): Option[ObjectId] = {
|
pullreq: Option[PullRequest]
|
||||||
|
)(implicit s: Session, c: JsonFormat.Context): Option[ObjectId] = {
|
||||||
|
val localUserName = localRepository.owner
|
||||||
|
val localRepositoryName = localRepository.name
|
||||||
|
val remoteUserName = remoteRepository.owner
|
||||||
|
val remoteRepositoryName = remoteRepository.name
|
||||||
tryMergeRemote(localUserName, localRepositoryName, localBranch, remoteUserName, remoteRepositoryName, remoteBranch).map {
|
tryMergeRemote(localUserName, localRepositoryName, localBranch, remoteUserName, remoteRepositoryName, remoteBranch).map {
|
||||||
case (newTreeId, oldBaseId, oldHeadId) =>
|
case (newTreeId, oldBaseId, oldHeadId) =>
|
||||||
using(Git.open(getRepositoryDir(localUserName, localRepositoryName))) { git =>
|
using(Git.open(getRepositoryDir(localUserName, localRepositoryName))) { git =>
|
||||||
|
val existIds = JGitUtil.getAllCommitIds(git).toSet
|
||||||
|
|
||||||
val committer = new PersonIdent(loginAccount.fullName, loginAccount.mailAddress)
|
val committer = new PersonIdent(loginAccount.fullName, loginAccount.mailAddress)
|
||||||
val newCommit =
|
val newCommit =
|
||||||
Util.createMergeCommit(git.getRepository, newTreeId, committer, message, Seq(oldBaseId, oldHeadId))
|
Util.createMergeCommit(git.getRepository, newTreeId, committer, message, Seq(oldBaseId, oldHeadId))
|
||||||
Util.updateRefs(git.getRepository, s"refs/heads/${localBranch}", newCommit, false, committer, Some("merge"))
|
Util.updateRefs(git.getRepository, s"refs/heads/${localBranch}", newCommit, false, committer, Some("merge"))
|
||||||
|
|
||||||
|
val commits = git.log
|
||||||
|
.addRange(oldBaseId, newCommit)
|
||||||
|
.call
|
||||||
|
.iterator
|
||||||
|
.asScala
|
||||||
|
.map(c => new JGitUtil.CommitInfo(c))
|
||||||
|
.toList
|
||||||
|
|
||||||
|
commits.foreach { commit =>
|
||||||
|
if (!existIds.contains(commit.id)) {
|
||||||
|
createIssueComment(localUserName, localRepositoryName, commit)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// record activity
|
||||||
|
recordPushActivity(
|
||||||
|
localUserName,
|
||||||
|
localRepositoryName,
|
||||||
|
loginAccount.userName,
|
||||||
|
localBranch,
|
||||||
|
commits
|
||||||
|
)
|
||||||
|
|
||||||
|
// close issue by commit message
|
||||||
|
if (localBranch == localRepository.repository.defaultBranch) {
|
||||||
|
commits.foreach { commit =>
|
||||||
|
closeIssuesFromMessage(commit.fullMessage, loginAccount.userName, localUserName, localRepositoryName)
|
||||||
|
.foreach { issueId =>
|
||||||
|
getIssue(localRepository.owner, localRepository.name, issueId.toString).foreach { issue =>
|
||||||
|
callIssuesWebHook("closed", localRepository, issue, loginAccount)
|
||||||
|
PluginRegistry().getIssueHooks
|
||||||
|
.foreach(
|
||||||
|
_.closedByCommitComment(issue, localRepository, commit.fullMessage, loginAccount)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pullreq.foreach { pullreq =>
|
||||||
|
callWebHookOf(localRepository.owner, localRepository.name, WebHook.Push) {
|
||||||
|
for {
|
||||||
|
ownerAccount <- getAccountByUserName(localRepository.owner)
|
||||||
|
} yield {
|
||||||
|
WebHookService.WebHookPushPayload(
|
||||||
|
git,
|
||||||
|
loginAccount,
|
||||||
|
pullreq.requestBranch,
|
||||||
|
localRepository,
|
||||||
|
commits,
|
||||||
|
ownerAccount,
|
||||||
|
oldId = oldBaseId,
|
||||||
|
newId = newCommit
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
oldBaseId
|
oldBaseId
|
||||||
}.toOption
|
}.toOption
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def mergePullRequest(
|
||||||
|
repository: RepositoryInfo,
|
||||||
|
issueId: Int,
|
||||||
|
loginAccount: Account,
|
||||||
|
message: String,
|
||||||
|
strategy: String
|
||||||
|
)(implicit s: Session, c: JsonFormat.Context, context: Context): Either[String, ObjectId] = {
|
||||||
|
if (repository.repository.options.mergeOptions.split(",").contains(strategy)) {
|
||||||
|
LockUtil.lock(s"${repository.owner}/${repository.name}") {
|
||||||
|
getPullRequest(repository.owner, repository.name, issueId)
|
||||||
|
.map {
|
||||||
|
case (issue, pullreq) =>
|
||||||
|
using(Git.open(getRepositoryDir(repository.owner, repository.name))) { git =>
|
||||||
|
// mark issue as merged and close.
|
||||||
|
val commentId =
|
||||||
|
createComment(repository.owner, repository.name, loginAccount.userName, issueId, message, "merge")
|
||||||
|
createComment(repository.owner, repository.name, loginAccount.userName, issueId, "Close", "close")
|
||||||
|
updateClosed(repository.owner, repository.name, issueId, true)
|
||||||
|
|
||||||
|
// record activity
|
||||||
|
recordMergeActivity(repository.owner, repository.name, loginAccount.userName, issueId, message)
|
||||||
|
|
||||||
|
val (commits, _) = getRequestCompareInfo(
|
||||||
|
repository.owner,
|
||||||
|
repository.name,
|
||||||
|
pullreq.commitIdFrom,
|
||||||
|
pullreq.requestUserName,
|
||||||
|
pullreq.requestRepositoryName,
|
||||||
|
pullreq.commitIdTo
|
||||||
|
)
|
||||||
|
|
||||||
|
val revCommits = using(new RevWalk(git.getRepository)) { revWalk =>
|
||||||
|
commits.flatten.map { commit =>
|
||||||
|
revWalk.parseCommit(git.getRepository.resolve(commit.id))
|
||||||
|
}
|
||||||
|
}.reverse
|
||||||
|
|
||||||
|
// merge git repository
|
||||||
|
(strategy match {
|
||||||
|
case "merge-commit" =>
|
||||||
|
Some(
|
||||||
|
mergePullRequest(
|
||||||
|
git,
|
||||||
|
pullreq.branch,
|
||||||
|
issueId,
|
||||||
|
s"Merge pull request #${issueId} from ${pullreq.requestUserName}/${pullreq.requestBranch}\n\n" + message,
|
||||||
|
new PersonIdent(loginAccount.fullName, loginAccount.mailAddress)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
case "rebase" =>
|
||||||
|
Some(
|
||||||
|
rebasePullRequest(
|
||||||
|
git,
|
||||||
|
pullreq.branch,
|
||||||
|
issueId,
|
||||||
|
revCommits,
|
||||||
|
new PersonIdent(loginAccount.fullName, loginAccount.mailAddress)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
case "squash" =>
|
||||||
|
Some(
|
||||||
|
squashPullRequest(
|
||||||
|
git,
|
||||||
|
pullreq.branch,
|
||||||
|
issueId,
|
||||||
|
s"${issue.title} (#${issueId})\n\n" + message,
|
||||||
|
new PersonIdent(loginAccount.fullName, loginAccount.mailAddress)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
case _ =>
|
||||||
|
None
|
||||||
|
}) match {
|
||||||
|
case Some(newCommitId) =>
|
||||||
|
// close issue by content of pull request
|
||||||
|
val defaultBranch = getRepository(repository.owner, repository.name).get.repository.defaultBranch
|
||||||
|
if (pullreq.branch == defaultBranch) {
|
||||||
|
commits.flatten.foreach { commit =>
|
||||||
|
closeIssuesFromMessage(
|
||||||
|
commit.fullMessage,
|
||||||
|
loginAccount.userName,
|
||||||
|
repository.owner,
|
||||||
|
repository.name
|
||||||
|
).foreach { issueId =>
|
||||||
|
getIssue(repository.owner, repository.name, issueId.toString).foreach { issue =>
|
||||||
|
callIssuesWebHook("closed", repository, issue, loginAccount)
|
||||||
|
PluginRegistry().getIssueHooks
|
||||||
|
.foreach(_.closedByCommitComment(issue, repository, commit.fullMessage, loginAccount))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val issueContent = issue.title + " " + issue.content.getOrElse("")
|
||||||
|
closeIssuesFromMessage(
|
||||||
|
issueContent,
|
||||||
|
loginAccount.userName,
|
||||||
|
repository.owner,
|
||||||
|
repository.name
|
||||||
|
).foreach { issueId =>
|
||||||
|
getIssue(repository.owner, repository.name, issueId.toString).foreach { issue =>
|
||||||
|
callIssuesWebHook("closed", repository, issue, loginAccount)
|
||||||
|
PluginRegistry().getIssueHooks
|
||||||
|
.foreach(_.closedByCommitComment(issue, repository, issueContent, loginAccount))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closeIssuesFromMessage(message, loginAccount.userName, repository.owner, repository.name)
|
||||||
|
.foreach { issueId =>
|
||||||
|
getIssue(repository.owner, repository.name, issueId.toString).foreach { issue =>
|
||||||
|
callIssuesWebHook("closed", repository, issue, loginAccount)
|
||||||
|
PluginRegistry().getIssueHooks
|
||||||
|
.foreach(_.closedByCommitComment(issue, repository, issueContent, loginAccount))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updatePullRequests(repository.owner, repository.name, pullreq.branch, loginAccount, "closed")
|
||||||
|
|
||||||
|
// call hooks
|
||||||
|
PluginRegistry().getPullRequestHooks.foreach { h =>
|
||||||
|
h.addedComment(commentId, message, issue, repository)
|
||||||
|
h.merged(issue, repository)
|
||||||
|
}
|
||||||
|
|
||||||
|
Right(newCommitId)
|
||||||
|
case None =>
|
||||||
|
Left("Unknown strategy")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case _ => Left("Unknown error")
|
||||||
|
}
|
||||||
|
.getOrElse(Left("Pull request not found"))
|
||||||
|
}
|
||||||
|
} else Left("Strategy not allowed")
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object MergeService {
|
object MergeService {
|
||||||
@@ -191,13 +414,15 @@ object MergeService {
|
|||||||
force: Boolean,
|
force: Boolean,
|
||||||
committer: PersonIdent,
|
committer: PersonIdent,
|
||||||
refLogMessage: Option[String] = None
|
refLogMessage: Option[String] = None
|
||||||
): Unit = {
|
): ObjectId = {
|
||||||
val refUpdate = repository.updateRef(ref)
|
val refUpdate = repository.updateRef(ref)
|
||||||
refUpdate.setNewObjectId(newObjectId)
|
refUpdate.setNewObjectId(newObjectId)
|
||||||
refUpdate.setForceUpdate(force)
|
refUpdate.setForceUpdate(force)
|
||||||
refUpdate.setRefLogIdent(committer)
|
refUpdate.setRefLogIdent(committer)
|
||||||
refLogMessage.foreach(refUpdate.setRefLogMessage(_, true))
|
refLogMessage.foreach(refUpdate.setRefLogMessage(_, true))
|
||||||
refUpdate.update()
|
refUpdate.update()
|
||||||
|
|
||||||
|
newObjectId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,7 +490,7 @@ object MergeService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// update branch from cache
|
// update branch from cache
|
||||||
def merge(message: String, committer: PersonIdent) = {
|
def merge(message: String, committer: PersonIdent): ObjectId = {
|
||||||
if (checkConflict().isDefined) {
|
if (checkConflict().isDefined) {
|
||||||
throw new RuntimeException("This pull request can't merge automatically.")
|
throw new RuntimeException("This pull request can't merge automatically.")
|
||||||
}
|
}
|
||||||
@@ -278,7 +503,7 @@ object MergeService {
|
|||||||
Util.updateRefs(repository, s"refs/heads/${branch}", mergeCommitId, false, committer, Some("merged"))
|
Util.updateRefs(repository, s"refs/heads/${branch}", mergeCommitId, false, committer, Some("merged"))
|
||||||
}
|
}
|
||||||
|
|
||||||
def rebase(committer: PersonIdent, commits: Seq[RevCommit]): Unit = {
|
def rebase(committer: PersonIdent, commits: Seq[RevCommit]): ObjectId = {
|
||||||
if (checkConflict().isDefined) {
|
if (checkConflict().isDefined) {
|
||||||
throw new RuntimeException("This pull request can't merge automatically.")
|
throw new RuntimeException("This pull request can't merge automatically.")
|
||||||
}
|
}
|
||||||
@@ -310,7 +535,7 @@ object MergeService {
|
|||||||
Util.updateRefs(repository, s"refs/heads/${branch}", previousId, false, committer, Some("rebased"))
|
Util.updateRefs(repository, s"refs/heads/${branch}", previousId, false, committer, Some("rebased"))
|
||||||
}
|
}
|
||||||
|
|
||||||
def squash(message: String, committer: PersonIdent): Unit = {
|
def squash(message: String, committer: PersonIdent): ObjectId = {
|
||||||
if (checkConflict().isDefined) {
|
if (checkConflict().isDefined) {
|
||||||
throw new RuntimeException("This pull request can't merge automatically.")
|
throw new RuntimeException("This pull request can't merge automatically.")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import gitbucket.core.model.{CommitComments => _, Session => _, _}
|
|||||||
import gitbucket.core.model.Profile._
|
import gitbucket.core.model.Profile._
|
||||||
import gitbucket.core.model.Profile.profile.blockingApi._
|
import gitbucket.core.model.Profile.profile.blockingApi._
|
||||||
import difflib.{Delta, DiffUtils}
|
import difflib.{Delta, DiffUtils}
|
||||||
|
import gitbucket.core.api.JsonFormat
|
||||||
import gitbucket.core.util.SyntaxSugars._
|
import gitbucket.core.util.SyntaxSugars._
|
||||||
import gitbucket.core.util.Directory._
|
import gitbucket.core.util.Directory._
|
||||||
import gitbucket.core.util.Implicits._
|
import gitbucket.core.util.Implicits._
|
||||||
@@ -15,7 +16,8 @@ import org.eclipse.jgit.api.Git
|
|||||||
|
|
||||||
import scala.collection.JavaConverters._
|
import scala.collection.JavaConverters._
|
||||||
|
|
||||||
trait PullRequestService { self: IssuesService with CommitsService =>
|
trait PullRequestService {
|
||||||
|
self: IssuesService with CommitsService with WebHookService with WebHookPullRequestService with RepositoryService =>
|
||||||
import PullRequestService._
|
import PullRequestService._
|
||||||
|
|
||||||
def getPullRequest(owner: String, repository: String, issueId: Int)(
|
def getPullRequest(owner: String, repository: String, issueId: Int)(
|
||||||
@@ -164,7 +166,10 @@ trait PullRequestService { self: IssuesService with CommitsService =>
|
|||||||
/**
|
/**
|
||||||
* Fetch pull request contents into refs/pull/${issueId}/head and update pull request table.
|
* Fetch pull request contents into refs/pull/${issueId}/head and update pull request table.
|
||||||
*/
|
*/
|
||||||
def updatePullRequests(owner: String, repository: String, branch: String)(implicit s: Session): Unit =
|
def updatePullRequests(owner: String, repository: String, branch: String, loginAccount: Account, action: String)(
|
||||||
|
implicit s: Session,
|
||||||
|
c: JsonFormat.Context
|
||||||
|
): Unit = {
|
||||||
getPullRequestsByRequest(owner, repository, branch, Some(false)).foreach { pullreq =>
|
getPullRequestsByRequest(owner, repository, branch, Some(false)).foreach { pullreq =>
|
||||||
if (Repositories.filter(_.byRepository(pullreq.userName, pullreq.repositoryName)).exists.run) {
|
if (Repositories.filter(_.byRepository(pullreq.userName, pullreq.repositoryName)).exists.run) {
|
||||||
// Update the git repository
|
// Update the git repository
|
||||||
@@ -204,8 +209,17 @@ trait PullRequestService { self: IssuesService with CommitsService =>
|
|||||||
|
|
||||||
// Update commit id in the PULL_REQUEST table
|
// Update commit id in the PULL_REQUEST table
|
||||||
updateCommitId(pullreq.userName, pullreq.repositoryName, pullreq.issueId, commitIdTo, commitIdFrom)
|
updateCommitId(pullreq.userName, pullreq.repositoryName, pullreq.issueId, commitIdTo, commitIdFrom)
|
||||||
|
|
||||||
|
// call web hook
|
||||||
|
callPullRequestWebHookByRequestBranch(
|
||||||
|
action,
|
||||||
|
getRepository(owner, repository).get,
|
||||||
|
pullreq.requestBranch,
|
||||||
|
loginAccount
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def getPullRequestByRequestCommit(
|
def getPullRequestByRequestCommit(
|
||||||
userName: String,
|
userName: String,
|
||||||
|
|||||||
@@ -0,0 +1,188 @@
|
|||||||
|
package gitbucket.core.service
|
||||||
|
import gitbucket.core.api.JsonFormat
|
||||||
|
import gitbucket.core.model.{Account, WebHook}
|
||||||
|
import gitbucket.core.model.Profile._
|
||||||
|
import gitbucket.core.model.Profile.profile.blockingApi._
|
||||||
|
import gitbucket.core.plugin.PluginRegistry
|
||||||
|
import gitbucket.core.service.WebHookService.WebHookPushPayload
|
||||||
|
import gitbucket.core.util.Directory.getRepositoryDir
|
||||||
|
import gitbucket.core.util.JGitUtil.CommitInfo
|
||||||
|
import gitbucket.core.util.{JGitUtil, LockUtil}
|
||||||
|
import gitbucket.core.util.SyntaxSugars.using
|
||||||
|
import org.eclipse.jgit.api.Git
|
||||||
|
import org.eclipse.jgit.dircache.{DirCache, DirCacheBuilder}
|
||||||
|
import org.eclipse.jgit.lib._
|
||||||
|
import org.eclipse.jgit.transport.{ReceiveCommand, ReceivePack}
|
||||||
|
|
||||||
|
trait RepositoryCommitFileService {
|
||||||
|
self: AccountService with ActivityService with IssuesService with PullRequestService with WebHookPullRequestService =>
|
||||||
|
import RepositoryCommitFileService._
|
||||||
|
|
||||||
|
def commitFiles(
|
||||||
|
repository: RepositoryService.RepositoryInfo,
|
||||||
|
files: Seq[CommitFile],
|
||||||
|
branch: String,
|
||||||
|
path: String,
|
||||||
|
message: String,
|
||||||
|
loginAccount: Account
|
||||||
|
)(
|
||||||
|
f: (Git, ObjectId, DirCacheBuilder, ObjectInserter) => Unit
|
||||||
|
)(implicit s: Session, c: JsonFormat.Context) = {
|
||||||
|
// prepend path to the filename
|
||||||
|
_commitFile(repository, branch, message, loginAccount)(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
def commitFile(
|
||||||
|
repository: RepositoryService.RepositoryInfo,
|
||||||
|
branch: String,
|
||||||
|
path: String,
|
||||||
|
newFileName: Option[String],
|
||||||
|
oldFileName: Option[String],
|
||||||
|
content: String,
|
||||||
|
charset: String,
|
||||||
|
message: String,
|
||||||
|
commit: String,
|
||||||
|
loginAccount: Account
|
||||||
|
)(implicit s: Session, c: JsonFormat.Context) = {
|
||||||
|
|
||||||
|
val newPath = newFileName.map { newFileName =>
|
||||||
|
if (path.length == 0) newFileName else s"${path}/${newFileName}"
|
||||||
|
}
|
||||||
|
val oldPath = oldFileName.map { oldFileName =>
|
||||||
|
if (path.length == 0) oldFileName else s"${path}/${oldFileName}"
|
||||||
|
}
|
||||||
|
|
||||||
|
_commitFile(repository, branch, message, loginAccount) {
|
||||||
|
case (git, headTip, builder, inserter) =>
|
||||||
|
if (headTip.getName == commit) {
|
||||||
|
val permission = JGitUtil
|
||||||
|
.processTree(git, headTip) { (path, tree) =>
|
||||||
|
// Add all entries except the editing file
|
||||||
|
if (!newPath.contains(path) && !oldPath.contains(path)) {
|
||||||
|
builder.add(JGitUtil.createDirCacheEntry(path, tree.getEntryFileMode, tree.getEntryObjectId))
|
||||||
|
}
|
||||||
|
// Retrieve permission if file exists to keep it
|
||||||
|
oldPath.collect { case x if x == path => tree.getEntryFileMode.getBits }
|
||||||
|
}
|
||||||
|
.flatten
|
||||||
|
.headOption
|
||||||
|
|
||||||
|
newPath.foreach { newPath =>
|
||||||
|
builder.add(JGitUtil.createDirCacheEntry(newPath, permission.map { bits =>
|
||||||
|
FileMode.fromBits(bits)
|
||||||
|
} getOrElse FileMode.REGULAR_FILE, inserter.insert(Constants.OBJ_BLOB, content.getBytes(charset))))
|
||||||
|
}
|
||||||
|
builder.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private def _commitFile(
|
||||||
|
repository: RepositoryService.RepositoryInfo,
|
||||||
|
branch: String,
|
||||||
|
message: String,
|
||||||
|
loginAccount: Account
|
||||||
|
)(
|
||||||
|
f: (Git, ObjectId, DirCacheBuilder, ObjectInserter) => Unit
|
||||||
|
)(implicit s: Session, c: JsonFormat.Context) = {
|
||||||
|
|
||||||
|
LockUtil.lock(s"${repository.owner}/${repository.name}") {
|
||||||
|
using(Git.open(getRepositoryDir(repository.owner, repository.name))) { git =>
|
||||||
|
val builder = DirCache.newInCore.builder()
|
||||||
|
val inserter = git.getRepository.newObjectInserter()
|
||||||
|
val headName = s"refs/heads/${branch}"
|
||||||
|
val headTip = git.getRepository.resolve(headName)
|
||||||
|
|
||||||
|
f(git, headTip, builder, inserter)
|
||||||
|
|
||||||
|
val commitId = JGitUtil.createNewCommit(
|
||||||
|
git,
|
||||||
|
inserter,
|
||||||
|
headTip,
|
||||||
|
builder.getDirCache.writeTree(inserter),
|
||||||
|
headName,
|
||||||
|
loginAccount.fullName,
|
||||||
|
loginAccount.mailAddress,
|
||||||
|
message
|
||||||
|
)
|
||||||
|
|
||||||
|
inserter.flush()
|
||||||
|
inserter.close()
|
||||||
|
|
||||||
|
val receivePack = new ReceivePack(git.getRepository)
|
||||||
|
val receiveCommand = new ReceiveCommand(headTip, commitId, headName)
|
||||||
|
|
||||||
|
// call post commit hook
|
||||||
|
val error = PluginRegistry().getReceiveHooks.flatMap { hook =>
|
||||||
|
hook.preReceive(repository.owner, repository.name, receivePack, receiveCommand, loginAccount.userName)
|
||||||
|
}.headOption
|
||||||
|
|
||||||
|
error match {
|
||||||
|
case Some(error) =>
|
||||||
|
// commit is rejected
|
||||||
|
// TODO Notify commit failure to edited user
|
||||||
|
val refUpdate = git.getRepository.updateRef(headName)
|
||||||
|
refUpdate.setNewObjectId(headTip)
|
||||||
|
refUpdate.setForceUpdate(true)
|
||||||
|
refUpdate.update()
|
||||||
|
|
||||||
|
case None =>
|
||||||
|
// update refs
|
||||||
|
val refUpdate = git.getRepository.updateRef(headName)
|
||||||
|
refUpdate.setNewObjectId(commitId)
|
||||||
|
refUpdate.setForceUpdate(false)
|
||||||
|
refUpdate.setRefLogIdent(new PersonIdent(loginAccount.fullName, loginAccount.mailAddress))
|
||||||
|
refUpdate.update()
|
||||||
|
|
||||||
|
// update pull request
|
||||||
|
updatePullRequests(repository.owner, repository.name, branch, loginAccount, "synchronize")
|
||||||
|
|
||||||
|
// record activity
|
||||||
|
val commitInfo = new CommitInfo(JGitUtil.getRevCommitFromId(git, commitId))
|
||||||
|
recordPushActivity(repository.owner, repository.name, loginAccount.userName, branch, List(commitInfo))
|
||||||
|
|
||||||
|
// create issue comment by commit message
|
||||||
|
createIssueComment(repository.owner, repository.name, commitInfo)
|
||||||
|
|
||||||
|
// close issue by commit message
|
||||||
|
if (branch == repository.repository.defaultBranch) {
|
||||||
|
closeIssuesFromMessage(message, loginAccount.userName, repository.owner, repository.name).foreach {
|
||||||
|
issueId =>
|
||||||
|
getIssue(repository.owner, repository.name, issueId.toString).foreach { issue =>
|
||||||
|
callIssuesWebHook("closed", repository, issue, loginAccount)
|
||||||
|
PluginRegistry().getIssueHooks
|
||||||
|
.foreach(_.closedByCommitComment(issue, repository, message, loginAccount))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// call post commit hook
|
||||||
|
PluginRegistry().getReceiveHooks.foreach { hook =>
|
||||||
|
hook.postReceive(repository.owner, repository.name, receivePack, receiveCommand, loginAccount.userName)
|
||||||
|
}
|
||||||
|
|
||||||
|
val commit = new JGitUtil.CommitInfo(JGitUtil.getRevCommitFromId(git, commitId))
|
||||||
|
callWebHookOf(repository.owner, repository.name, WebHook.Push) {
|
||||||
|
getAccountByUserName(repository.owner).map { ownerAccount =>
|
||||||
|
WebHookPushPayload(
|
||||||
|
git,
|
||||||
|
loginAccount,
|
||||||
|
headName,
|
||||||
|
repository,
|
||||||
|
List(commit),
|
||||||
|
ownerAccount,
|
||||||
|
oldId = headTip,
|
||||||
|
newId = commitId
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
object RepositoryCommitFileService {
|
||||||
|
case class CommitFile(id: String, name: String)
|
||||||
|
}
|
||||||
@@ -1,16 +1,25 @@
|
|||||||
package gitbucket.core.service
|
package gitbucket.core.service
|
||||||
|
|
||||||
|
import gitbucket.core.api.JsonFormat
|
||||||
import gitbucket.core.controller.Context
|
import gitbucket.core.controller.Context
|
||||||
import gitbucket.core.util._
|
import gitbucket.core.util._
|
||||||
import gitbucket.core.util.SyntaxSugars._
|
import gitbucket.core.util.SyntaxSugars._
|
||||||
import gitbucket.core.model.{Account, Collaborator, Repository, RepositoryOptions, Role, ReleaseTag}
|
import gitbucket.core.model.{CommitComments => _, Session => _, _}
|
||||||
import gitbucket.core.model.Profile._
|
import gitbucket.core.model.Profile._
|
||||||
import gitbucket.core.model.Profile.profile.blockingApi._
|
import gitbucket.core.model.Profile.profile.blockingApi._
|
||||||
import gitbucket.core.model.Profile.dateColumnType
|
import gitbucket.core.model.Profile.dateColumnType
|
||||||
import gitbucket.core.util.JGitUtil.FileInfo
|
import gitbucket.core.plugin.PluginRegistry
|
||||||
|
import gitbucket.core.service.WebHookService.WebHookPushPayload
|
||||||
|
import gitbucket.core.util.Directory.{getRepositoryDir, getRepositoryFilesDir, getTemporaryDir, getWikiRepositoryDir}
|
||||||
|
import gitbucket.core.util.JGitUtil.{CommitInfo, FileInfo}
|
||||||
|
import org.apache.commons.io.FileUtils
|
||||||
import org.eclipse.jgit.api.Git
|
import org.eclipse.jgit.api.Git
|
||||||
|
import org.eclipse.jgit.dircache.{DirCache, DirCacheBuilder}
|
||||||
|
import org.eclipse.jgit.lib.{Repository => _, _}
|
||||||
|
import org.eclipse.jgit.transport.{ReceiveCommand, ReceivePack}
|
||||||
|
|
||||||
trait RepositoryService { self: AccountService =>
|
trait RepositoryService {
|
||||||
|
self: AccountService =>
|
||||||
import RepositoryService._
|
import RepositoryService._
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -68,181 +77,232 @@ trait RepositoryService { self: AccountService =>
|
|||||||
(Repositories filter { t =>
|
(Repositories filter { t =>
|
||||||
t.byRepository(oldUserName, oldRepositoryName)
|
t.byRepository(oldUserName, oldRepositoryName)
|
||||||
} firstOption).foreach { repository =>
|
} firstOption).foreach { repository =>
|
||||||
Repositories insert repository.copy(userName = newUserName, repositoryName = newRepositoryName)
|
LockUtil.lock(s"${repository.userName}/${repository.repositoryName}") {
|
||||||
|
Repositories insert repository.copy(userName = newUserName, repositoryName = newRepositoryName)
|
||||||
|
|
||||||
val webHooks = RepositoryWebHooks.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
val webHooks = RepositoryWebHooks.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
||||||
val webHookEvents = RepositoryWebHookEvents.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
val webHookEvents = RepositoryWebHookEvents.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
||||||
val milestones = Milestones.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
val milestones = Milestones.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
||||||
val issueId = IssueId.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
val issueId = IssueId.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
||||||
val issues = Issues.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
val issues = Issues.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
||||||
val pullRequests = PullRequests.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
val pullRequests = PullRequests.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
||||||
val labels = Labels.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
val labels = Labels.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
||||||
val priorities = Priorities.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
val priorities = Priorities.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
||||||
val issueComments = IssueComments.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
val issueComments = IssueComments.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
||||||
val issueLabels = IssueLabels.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
val issueLabels = IssueLabels.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
||||||
val commitComments = CommitComments.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
val commitComments = CommitComments.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
||||||
val commitStatuses = CommitStatuses.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
val commitStatuses = CommitStatuses.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
||||||
val collaborators = Collaborators.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
val collaborators = Collaborators.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
||||||
val protectedBranches = ProtectedBranches.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
val protectedBranches = ProtectedBranches.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
||||||
val protectedBranchContexts =
|
val protectedBranchContexts =
|
||||||
ProtectedBranchContexts.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
ProtectedBranchContexts.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
||||||
val deployKeys = DeployKeys.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
val deployKeys = DeployKeys.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
||||||
val releases = ReleaseTags.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
val releases = ReleaseTags.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
||||||
val releaseAssets = ReleaseAssets.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
val releaseAssets = ReleaseAssets.filter(_.byRepository(oldUserName, oldRepositoryName)).list
|
||||||
|
|
||||||
Repositories
|
Repositories
|
||||||
.filter { t =>
|
.filter { t =>
|
||||||
(t.originUserName === oldUserName.bind) && (t.originRepositoryName === oldRepositoryName.bind)
|
(t.originUserName === oldUserName.bind) && (t.originRepositoryName === oldRepositoryName.bind)
|
||||||
}
|
|
||||||
.map { t =>
|
|
||||||
t.originUserName -> t.originRepositoryName
|
|
||||||
}
|
|
||||||
.update(newUserName, newRepositoryName)
|
|
||||||
|
|
||||||
Repositories
|
|
||||||
.filter { t =>
|
|
||||||
(t.parentUserName === oldUserName.bind) && (t.parentRepositoryName === oldRepositoryName.bind)
|
|
||||||
}
|
|
||||||
.map { t =>
|
|
||||||
t.parentUserName -> t.parentRepositoryName
|
|
||||||
}
|
|
||||||
.update(newUserName, newRepositoryName)
|
|
||||||
|
|
||||||
// Updates activity fk before deleting repository because activity is sorted by activityId
|
|
||||||
// and it can't be changed by deleting-and-inserting record.
|
|
||||||
Activities.filter(_.byRepository(oldUserName, oldRepositoryName)).list.foreach { activity =>
|
|
||||||
Activities
|
|
||||||
.filter(_.activityId === activity.activityId.bind)
|
|
||||||
.map(x => (x.userName, x.repositoryName))
|
|
||||||
.update(newUserName, newRepositoryName)
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteRepository(oldUserName, oldRepositoryName)
|
|
||||||
|
|
||||||
RepositoryWebHooks.insertAll(
|
|
||||||
webHooks.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _*
|
|
||||||
)
|
|
||||||
RepositoryWebHookEvents.insertAll(
|
|
||||||
webHookEvents.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _*
|
|
||||||
)
|
|
||||||
Milestones.insertAll(milestones.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _*)
|
|
||||||
Priorities.insertAll(priorities.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _*)
|
|
||||||
IssueId.insertAll(issueId.map(_.copy(_1 = newUserName, _2 = newRepositoryName)): _*)
|
|
||||||
|
|
||||||
val newMilestones = Milestones.filter(_.byRepository(newUserName, newRepositoryName)).list
|
|
||||||
val newPriorities = Priorities.filter(_.byRepository(newUserName, newRepositoryName)).list
|
|
||||||
Issues.insertAll(issues.map { x =>
|
|
||||||
x.copy(
|
|
||||||
userName = newUserName,
|
|
||||||
repositoryName = newRepositoryName,
|
|
||||||
milestoneId = x.milestoneId.map { id =>
|
|
||||||
newMilestones.find(_.title == milestones.find(_.milestoneId == id).get.title).get.milestoneId
|
|
||||||
},
|
|
||||||
priorityId = x.priorityId.map { id =>
|
|
||||||
newPriorities.find(_.priorityName == priorities.find(_.priorityId == id).get.priorityName).get.priorityId
|
|
||||||
}
|
}
|
||||||
|
.map { t =>
|
||||||
|
t.originUserName -> t.originRepositoryName
|
||||||
|
}
|
||||||
|
.update(newUserName, newRepositoryName)
|
||||||
|
|
||||||
|
Repositories
|
||||||
|
.filter { t =>
|
||||||
|
(t.parentUserName === oldUserName.bind) && (t.parentRepositoryName === oldRepositoryName.bind)
|
||||||
|
}
|
||||||
|
.map { t =>
|
||||||
|
t.parentUserName -> t.parentRepositoryName
|
||||||
|
}
|
||||||
|
.update(newUserName, newRepositoryName)
|
||||||
|
|
||||||
|
// Updates activity fk before deleting repository because activity is sorted by activityId
|
||||||
|
// and it can't be changed by deleting-and-inserting record.
|
||||||
|
Activities.filter(_.byRepository(oldUserName, oldRepositoryName)).list.foreach { activity =>
|
||||||
|
Activities
|
||||||
|
.filter(_.activityId === activity.activityId.bind)
|
||||||
|
.map(x => (x.userName, x.repositoryName))
|
||||||
|
.update(newUserName, newRepositoryName)
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteRepositoryOnModel(oldUserName, oldRepositoryName)
|
||||||
|
|
||||||
|
RepositoryWebHooks.insertAll(
|
||||||
|
webHooks.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _*
|
||||||
)
|
)
|
||||||
}: _*)
|
RepositoryWebHookEvents.insertAll(
|
||||||
|
webHookEvents.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _*
|
||||||
|
)
|
||||||
|
Milestones.insertAll(milestones.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _*)
|
||||||
|
Priorities.insertAll(priorities.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _*)
|
||||||
|
IssueId.insertAll(issueId.map(_.copy(_1 = newUserName, _2 = newRepositoryName)): _*)
|
||||||
|
|
||||||
PullRequests.insertAll(pullRequests.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _*)
|
val newMilestones = Milestones.filter(_.byRepository(newUserName, newRepositoryName)).list
|
||||||
IssueComments.insertAll(
|
val newPriorities = Priorities.filter(_.byRepository(newUserName, newRepositoryName)).list
|
||||||
issueComments.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _*
|
Issues.insertAll(issues.map { x =>
|
||||||
)
|
x.copy(
|
||||||
Labels.insertAll(labels.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _*)
|
userName = newUserName,
|
||||||
CommitComments.insertAll(
|
repositoryName = newRepositoryName,
|
||||||
commitComments.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _*
|
milestoneId = x.milestoneId.map { id =>
|
||||||
)
|
newMilestones.find(_.title == milestones.find(_.milestoneId == id).get.title).get.milestoneId
|
||||||
CommitStatuses.insertAll(
|
},
|
||||||
commitStatuses.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _*
|
priorityId = x.priorityId.map { id =>
|
||||||
)
|
newPriorities
|
||||||
ProtectedBranches.insertAll(
|
.find(_.priorityName == priorities.find(_.priorityId == id).get.priorityName)
|
||||||
protectedBranches.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _*
|
.get
|
||||||
)
|
.priorityId
|
||||||
ProtectedBranchContexts.insertAll(
|
}
|
||||||
protectedBranchContexts.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _*
|
|
||||||
)
|
|
||||||
DeployKeys.insertAll(deployKeys.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _*)
|
|
||||||
ReleaseTags.insertAll(releases.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _*)
|
|
||||||
ReleaseAssets.insertAll(
|
|
||||||
releaseAssets.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _*
|
|
||||||
)
|
|
||||||
|
|
||||||
// Update source repository of pull requests
|
|
||||||
PullRequests
|
|
||||||
.filter { t =>
|
|
||||||
(t.requestUserName === oldUserName.bind) && (t.requestRepositoryName === oldRepositoryName.bind)
|
|
||||||
}
|
|
||||||
.map { t =>
|
|
||||||
t.requestUserName -> t.requestRepositoryName
|
|
||||||
}
|
|
||||||
.update(newUserName, newRepositoryName)
|
|
||||||
|
|
||||||
// Convert labelId
|
|
||||||
val oldLabelMap = labels.map(x => (x.labelId, x.labelName)).toMap
|
|
||||||
val newLabelMap =
|
|
||||||
Labels.filter(_.byRepository(newUserName, newRepositoryName)).map(x => (x.labelName, x.labelId)).list.toMap
|
|
||||||
IssueLabels.insertAll(
|
|
||||||
issueLabels.map(
|
|
||||||
x =>
|
|
||||||
x.copy(
|
|
||||||
labelId = newLabelMap(oldLabelMap(x.labelId)),
|
|
||||||
userName = newUserName,
|
|
||||||
repositoryName = newRepositoryName
|
|
||||||
)
|
)
|
||||||
): _*
|
}: _*)
|
||||||
)
|
|
||||||
|
|
||||||
// TODO Drop transferred owner from collaborators?
|
PullRequests.insertAll(
|
||||||
Collaborators.insertAll(
|
pullRequests.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _*
|
||||||
collaborators.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _*
|
)
|
||||||
)
|
IssueComments.insertAll(
|
||||||
|
issueComments.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _*
|
||||||
|
)
|
||||||
|
Labels.insertAll(labels.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _*)
|
||||||
|
CommitComments.insertAll(
|
||||||
|
commitComments.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _*
|
||||||
|
)
|
||||||
|
CommitStatuses.insertAll(
|
||||||
|
commitStatuses.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _*
|
||||||
|
)
|
||||||
|
ProtectedBranches.insertAll(
|
||||||
|
protectedBranches.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _*
|
||||||
|
)
|
||||||
|
ProtectedBranchContexts.insertAll(
|
||||||
|
protectedBranchContexts.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _*
|
||||||
|
)
|
||||||
|
DeployKeys.insertAll(deployKeys.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _*)
|
||||||
|
ReleaseTags.insertAll(releases.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _*)
|
||||||
|
ReleaseAssets.insertAll(
|
||||||
|
releaseAssets.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _*
|
||||||
|
)
|
||||||
|
|
||||||
// Update activity messages
|
// Update source repository of pull requests
|
||||||
Activities
|
PullRequests
|
||||||
.filter { t =>
|
.filter { t =>
|
||||||
(t.message like s"%:${oldUserName}/${oldRepositoryName}]%") ||
|
(t.requestUserName === oldUserName.bind) && (t.requestRepositoryName === oldRepositoryName.bind)
|
||||||
(t.message like s"%:${oldUserName}/${oldRepositoryName}#%") ||
|
}
|
||||||
(t.message like s"%:${oldUserName}/${oldRepositoryName}@%")
|
.map { t =>
|
||||||
|
t.requestUserName -> t.requestRepositoryName
|
||||||
|
}
|
||||||
|
.update(newUserName, newRepositoryName)
|
||||||
|
|
||||||
|
// Convert labelId
|
||||||
|
val oldLabelMap = labels.map(x => (x.labelId, x.labelName)).toMap
|
||||||
|
val newLabelMap =
|
||||||
|
Labels.filter(_.byRepository(newUserName, newRepositoryName)).map(x => (x.labelName, x.labelId)).list.toMap
|
||||||
|
IssueLabels.insertAll(
|
||||||
|
issueLabels.map(
|
||||||
|
x =>
|
||||||
|
x.copy(
|
||||||
|
labelId = newLabelMap(oldLabelMap(x.labelId)),
|
||||||
|
userName = newUserName,
|
||||||
|
repositoryName = newRepositoryName
|
||||||
|
)
|
||||||
|
): _*
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO Drop transferred owner from collaborators?
|
||||||
|
Collaborators.insertAll(
|
||||||
|
collaborators.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _*
|
||||||
|
)
|
||||||
|
|
||||||
|
// Update activity messages
|
||||||
|
Activities
|
||||||
|
.filter { t =>
|
||||||
|
(t.message like s"%:${oldUserName}/${oldRepositoryName}]%") ||
|
||||||
|
(t.message like s"%:${oldUserName}/${oldRepositoryName}#%") ||
|
||||||
|
(t.message like s"%:${oldUserName}/${oldRepositoryName}@%")
|
||||||
|
}
|
||||||
|
.map { t =>
|
||||||
|
t.activityId -> t.message
|
||||||
|
}
|
||||||
|
.list
|
||||||
|
.foreach {
|
||||||
|
case (activityId, message) =>
|
||||||
|
Activities
|
||||||
|
.filter(_.activityId === activityId.bind)
|
||||||
|
.map(_.message)
|
||||||
|
.update(
|
||||||
|
message
|
||||||
|
.replace(
|
||||||
|
s"[repo:${oldUserName}/${oldRepositoryName}]",
|
||||||
|
s"[repo:${newUserName}/${newRepositoryName}]"
|
||||||
|
)
|
||||||
|
.replace(
|
||||||
|
s"[branch:${oldUserName}/${oldRepositoryName}#",
|
||||||
|
s"[branch:${newUserName}/${newRepositoryName}#"
|
||||||
|
)
|
||||||
|
.replace(
|
||||||
|
s"[tag:${oldUserName}/${oldRepositoryName}#",
|
||||||
|
s"[tag:${newUserName}/${newRepositoryName}#"
|
||||||
|
)
|
||||||
|
.replace(
|
||||||
|
s"[pullreq:${oldUserName}/${oldRepositoryName}#",
|
||||||
|
s"[pullreq:${newUserName}/${newRepositoryName}#"
|
||||||
|
)
|
||||||
|
.replace(
|
||||||
|
s"[issue:${oldUserName}/${oldRepositoryName}#",
|
||||||
|
s"[issue:${newUserName}/${newRepositoryName}#"
|
||||||
|
)
|
||||||
|
.replace(
|
||||||
|
s"[commit:${oldUserName}/${oldRepositoryName}@",
|
||||||
|
s"[commit:${newUserName}/${newRepositoryName}@"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// Move git repository
|
||||||
|
defining(getRepositoryDir(oldUserName, oldRepositoryName)) { dir =>
|
||||||
|
if (dir.isDirectory) {
|
||||||
|
FileUtils.moveDirectory(dir, getRepositoryDir(newUserName, newRepositoryName))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.map { t =>
|
// Move wiki repository
|
||||||
t.activityId -> t.message
|
defining(getWikiRepositoryDir(oldUserName, oldRepositoryName)) { dir =>
|
||||||
|
if (dir.isDirectory) {
|
||||||
|
FileUtils.moveDirectory(dir, getWikiRepositoryDir(newUserName, newRepositoryName))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.list
|
// Move files directory
|
||||||
.foreach {
|
defining(getRepositoryFilesDir(oldUserName, oldRepositoryName)) { dir =>
|
||||||
case (activityId, message) =>
|
if (dir.isDirectory) {
|
||||||
Activities
|
FileUtils.moveDirectory(dir, getRepositoryFilesDir(newUserName, newRepositoryName))
|
||||||
.filter(_.activityId === activityId.bind)
|
}
|
||||||
.map(_.message)
|
|
||||||
.update(
|
|
||||||
message
|
|
||||||
.replace(
|
|
||||||
s"[repo:${oldUserName}/${oldRepositoryName}]",
|
|
||||||
s"[repo:${newUserName}/${newRepositoryName}]"
|
|
||||||
)
|
|
||||||
.replace(
|
|
||||||
s"[branch:${oldUserName}/${oldRepositoryName}#",
|
|
||||||
s"[branch:${newUserName}/${newRepositoryName}#"
|
|
||||||
)
|
|
||||||
.replace(s"[tag:${oldUserName}/${oldRepositoryName}#", s"[tag:${newUserName}/${newRepositoryName}#")
|
|
||||||
.replace(
|
|
||||||
s"[pullreq:${oldUserName}/${oldRepositoryName}#",
|
|
||||||
s"[pullreq:${newUserName}/${newRepositoryName}#"
|
|
||||||
)
|
|
||||||
.replace(
|
|
||||||
s"[issue:${oldUserName}/${oldRepositoryName}#",
|
|
||||||
s"[issue:${newUserName}/${newRepositoryName}#"
|
|
||||||
)
|
|
||||||
.replace(
|
|
||||||
s"[commit:${oldUserName}/${oldRepositoryName}@",
|
|
||||||
s"[commit:${newUserName}/${newRepositoryName}@"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
// Delete parent directory
|
||||||
|
FileUtil.deleteDirectoryIfEmpty(getRepositoryFilesDir(oldUserName, oldRepositoryName))
|
||||||
|
|
||||||
|
// Call hooks
|
||||||
|
if (oldUserName == newUserName) {
|
||||||
|
PluginRegistry().getRepositoryHooks.foreach(_.renamed(oldUserName, oldRepositoryName, newRepositoryName))
|
||||||
|
} else {
|
||||||
|
PluginRegistry().getRepositoryHooks.foreach(_.transferred(oldUserName, newUserName, newRepositoryName))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def deleteRepository(userName: String, repositoryName: String)(implicit s: Session): Unit = {
|
def deleteRepository(repository: Repository)(implicit s: Session): Unit = {
|
||||||
|
LockUtil.lock(s"${repository.userName}/${repository.repositoryName}") {
|
||||||
|
deleteRepositoryOnModel(repository.userName, repository.repositoryName)
|
||||||
|
|
||||||
|
FileUtils.deleteDirectory(getRepositoryDir(repository.userName, repository.repositoryName))
|
||||||
|
FileUtils.deleteDirectory(getWikiRepositoryDir(repository.userName, repository.repositoryName))
|
||||||
|
FileUtils.deleteDirectory(getTemporaryDir(repository.userName, repository.repositoryName))
|
||||||
|
FileUtils.deleteDirectory(getRepositoryFilesDir(repository.userName, repository.repositoryName))
|
||||||
|
|
||||||
|
// Call hooks
|
||||||
|
PluginRegistry().getRepositoryHooks.foreach(_.deleted(repository.userName, repository.repositoryName))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private def deleteRepositoryOnModel(userName: String, repositoryName: String)(implicit s: Session): Unit = {
|
||||||
Activities.filter(_.byRepository(userName, repositoryName)).delete
|
Activities.filter(_.byRepository(userName, repositoryName)).delete
|
||||||
Collaborators.filter(_.byRepository(userName, repositoryName)).delete
|
Collaborators.filter(_.byRepository(userName, repositoryName)).delete
|
||||||
CommitComments.filter(_.byRepository(userName, repositoryName)).delete
|
CommitComments.filter(_.byRepository(userName, repositoryName)).delete
|
||||||
@@ -710,7 +770,6 @@ trait RepositoryService { self: AccountService =>
|
|||||||
}
|
}
|
||||||
|
|
||||||
object RepositoryService {
|
object RepositoryService {
|
||||||
|
|
||||||
case class RepositoryInfo(
|
case class RepositoryInfo(
|
||||||
owner: String,
|
owner: String,
|
||||||
name: String,
|
name: String,
|
||||||
|
|||||||
@@ -311,7 +311,6 @@ trait WebHookPullRequestService extends WebHookService {
|
|||||||
action: String,
|
action: String,
|
||||||
repository: RepositoryService.RepositoryInfo,
|
repository: RepositoryService.RepositoryInfo,
|
||||||
issue: Issue,
|
issue: Issue,
|
||||||
baseUrl: String,
|
|
||||||
sender: Account
|
sender: Account
|
||||||
)(implicit s: Session, context: JsonFormat.Context): Unit = {
|
)(implicit s: Session, context: JsonFormat.Context): Unit = {
|
||||||
callWebHookOf(repository.owner, repository.name, WebHook.Issues) {
|
callWebHookOf(repository.owner, repository.name, WebHook.Issues) {
|
||||||
@@ -341,7 +340,6 @@ trait WebHookPullRequestService extends WebHookService {
|
|||||||
action: String,
|
action: String,
|
||||||
repository: RepositoryService.RepositoryInfo,
|
repository: RepositoryService.RepositoryInfo,
|
||||||
issueId: Int,
|
issueId: Int,
|
||||||
baseUrl: String,
|
|
||||||
sender: Account
|
sender: Account
|
||||||
)(implicit s: Session, c: JsonFormat.Context): Unit = {
|
)(implicit s: Session, c: JsonFormat.Context): Unit = {
|
||||||
import WebHookService._
|
import WebHookService._
|
||||||
@@ -404,7 +402,6 @@ trait WebHookPullRequestService extends WebHookService {
|
|||||||
action: String,
|
action: String,
|
||||||
requestRepository: RepositoryService.RepositoryInfo,
|
requestRepository: RepositoryService.RepositoryInfo,
|
||||||
requestBranch: String,
|
requestBranch: String,
|
||||||
baseUrl: String,
|
|
||||||
sender: Account
|
sender: Account
|
||||||
)(implicit s: Session, c: JsonFormat.Context): Unit = {
|
)(implicit s: Session, c: JsonFormat.Context): Unit = {
|
||||||
import WebHookService._
|
import WebHookService._
|
||||||
@@ -450,7 +447,6 @@ trait WebHookPullRequestReviewCommentService extends WebHookService {
|
|||||||
repository: RepositoryService.RepositoryInfo,
|
repository: RepositoryService.RepositoryInfo,
|
||||||
issue: Issue,
|
issue: Issue,
|
||||||
pullRequest: PullRequest,
|
pullRequest: PullRequest,
|
||||||
baseUrl: String,
|
|
||||||
sender: Account
|
sender: Account
|
||||||
)(implicit s: Session, c: JsonFormat.Context): Unit = {
|
)(implicit s: Session, c: JsonFormat.Context): Unit = {
|
||||||
import WebHookService._
|
import WebHookService._
|
||||||
|
|||||||
@@ -221,6 +221,7 @@ class CommitLogHook(owner: String, repository: String, pusher: String, baseUrl:
|
|||||||
with PrioritiesService
|
with PrioritiesService
|
||||||
with MilestonesService
|
with MilestonesService
|
||||||
with WebHookPullRequestService
|
with WebHookPullRequestService
|
||||||
|
with WebHookPullRequestReviewCommentService
|
||||||
with CommitsService {
|
with CommitsService {
|
||||||
|
|
||||||
private val logger = LoggerFactory.getLogger(classOf[CommitLogHook])
|
private val logger = LoggerFactory.getLogger(classOf[CommitLogHook])
|
||||||
@@ -299,7 +300,7 @@ class CommitLogHook(owner: String, repository: String, pusher: String, baseUrl:
|
|||||||
getAccountByUserName(pusher).foreach { pusherAccount =>
|
getAccountByUserName(pusher).foreach { pusherAccount =>
|
||||||
closeIssuesFromMessage(commit.fullMessage, pusher, owner, repository).foreach { issueId =>
|
closeIssuesFromMessage(commit.fullMessage, pusher, owner, repository).foreach { issueId =>
|
||||||
getIssue(owner, repository, issueId.toString).foreach { issue =>
|
getIssue(owner, repository, issueId.toString).foreach { issue =>
|
||||||
callIssuesWebHook("closed", repositoryInfo, issue, baseUrl, pusherAccount)
|
callIssuesWebHook("closed", repositoryInfo, issue, pusherAccount)
|
||||||
PluginRegistry().getIssueHooks
|
PluginRegistry().getIssueHooks
|
||||||
.foreach(_.closedByCommitComment(issue, repositoryInfo, commit.fullMessage, pusherAccount))
|
.foreach(_.closedByCommitComment(issue, repositoryInfo, commit.fullMessage, pusherAccount))
|
||||||
}
|
}
|
||||||
@@ -319,7 +320,7 @@ class CommitLogHook(owner: String, repository: String, pusher: String, baseUrl:
|
|||||||
}.isDefined) {
|
}.isDefined) {
|
||||||
markMergeAndClosePullRequest(pusher, owner, repository, pull)
|
markMergeAndClosePullRequest(pusher, owner, repository, pull)
|
||||||
getAccountByUserName(pusher).foreach { pusherAccount =>
|
getAccountByUserName(pusher).foreach { pusherAccount =>
|
||||||
callPullRequestWebHook("closed", repositoryInfo, pull.issueId, baseUrl, pusherAccount)
|
callPullRequestWebHook("closed", repositoryInfo, pull.issueId, pusherAccount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -346,15 +347,8 @@ class CommitLogHook(owner: String, repository: String, pusher: String, baseUrl:
|
|||||||
command.getType match {
|
command.getType match {
|
||||||
case ReceiveCommand.Type.CREATE | ReceiveCommand.Type.UPDATE |
|
case ReceiveCommand.Type.CREATE | ReceiveCommand.Type.UPDATE |
|
||||||
ReceiveCommand.Type.UPDATE_NONFASTFORWARD =>
|
ReceiveCommand.Type.UPDATE_NONFASTFORWARD =>
|
||||||
updatePullRequests(owner, repository, branchName)
|
|
||||||
getAccountByUserName(pusher).foreach { pusherAccount =>
|
getAccountByUserName(pusher).foreach { pusherAccount =>
|
||||||
callPullRequestWebHookByRequestBranch(
|
updatePullRequests(owner, repository, branchName, pusherAccount, "synchronize")
|
||||||
"synchronize",
|
|
||||||
repositoryInfo,
|
|
||||||
branchName,
|
|
||||||
baseUrl,
|
|
||||||
pusherAccount
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
case _ =>
|
case _ =>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ import org.scalatest.FunSpec
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class MergeServiceSpec extends FunSpec {
|
class MergeServiceSpec extends FunSpec {
|
||||||
val service = new MergeService {}
|
val service = new MergeService with AccountService with ActivityService with IssuesService with LabelsService
|
||||||
|
with MilestonesService with RepositoryService with PrioritiesService with PullRequestService with CommitsService
|
||||||
|
with WebHookPullRequestService with WebHookPullRequestReviewCommentService {}
|
||||||
val branch = "master"
|
val branch = "master"
|
||||||
val issueId = 10
|
val issueId = 10
|
||||||
def initRepository(owner: String, name: String): File = {
|
def initRepository(owner: String, name: String): File = {
|
||||||
|
|||||||
@@ -9,11 +9,15 @@ class PullRequestServiceSpec
|
|||||||
with PullRequestService
|
with PullRequestService
|
||||||
with IssuesService
|
with IssuesService
|
||||||
with AccountService
|
with AccountService
|
||||||
|
with ActivityService
|
||||||
with RepositoryService
|
with RepositoryService
|
||||||
with CommitsService
|
with CommitsService
|
||||||
with LabelsService
|
with LabelsService
|
||||||
with MilestonesService
|
with MilestonesService
|
||||||
with PrioritiesService {
|
with PrioritiesService
|
||||||
|
with WebHookService
|
||||||
|
with WebHookPullRequestService
|
||||||
|
with WebHookPullRequestReviewCommentService {
|
||||||
|
|
||||||
def swap(r: (Issue, PullRequest)) = (r._2 -> r._1)
|
def swap(r: (Issue, PullRequest)) = (r._2 -> r._1)
|
||||||
|
|
||||||
|
|||||||
@@ -43,8 +43,10 @@ trait ServiceSpecBase {
|
|||||||
|
|
||||||
def user(name: String)(implicit s: Session): Account = AccountService.getAccountByUserName(name).get
|
def user(name: String)(implicit s: Session): Account = AccountService.getAccountByUserName(name).get
|
||||||
|
|
||||||
lazy val dummyService = new RepositoryService with AccountService with IssuesService with PullRequestService
|
lazy val dummyService = new RepositoryService with AccountService with ActivityService with IssuesService
|
||||||
with CommitsService with CommitStatusService with LabelsService with MilestonesService with PrioritiesService() {}
|
with PullRequestService with CommitsService with CommitStatusService with LabelsService with MilestonesService
|
||||||
|
with PrioritiesService with WebHookService with WebHookPullRequestService
|
||||||
|
with WebHookPullRequestReviewCommentService {}
|
||||||
|
|
||||||
def generateNewUserWithDBRepository(userName: String, repositoryName: String)(implicit s: Session): Account = {
|
def generateNewUserWithDBRepository(userName: String, repositoryName: String)(implicit s: Session): Account = {
|
||||||
val ac = AccountService.getAccountByUserName(userName).getOrElse(generateNewAccount(userName))
|
val ac = AccountService.getAccountByUserName(userName).getOrElse(generateNewAccount(userName))
|
||||||
|
|||||||
@@ -5,8 +5,9 @@ import org.scalatest.FunSuite
|
|||||||
import gitbucket.core.model.WebHookContentType
|
import gitbucket.core.model.WebHookContentType
|
||||||
|
|
||||||
class WebHookServiceSpec extends FunSuite with ServiceSpecBase {
|
class WebHookServiceSpec extends FunSuite with ServiceSpecBase {
|
||||||
lazy val service = new WebHookPullRequestService with AccountService with RepositoryService with PullRequestService
|
lazy val service = new WebHookPullRequestService with AccountService with ActivityService with RepositoryService
|
||||||
with IssuesService with CommitsService with LabelsService with MilestonesService with PrioritiesService
|
with PullRequestService with IssuesService with CommitsService with LabelsService with MilestonesService
|
||||||
|
with PrioritiesService with WebHookPullRequestReviewCommentService
|
||||||
|
|
||||||
test("WebHookPullRequestService.getPullRequestsByRequestForWebhook") {
|
test("WebHookPullRequestService.getPullRequestsByRequestForWebhook") {
|
||||||
withTestDB { implicit session =>
|
withTestDB { implicit session =>
|
||||||
|
|||||||
Reference in New Issue
Block a user