Merge pull request #2164 from kounoike/pr-call-hook-moveto-service

Move Plugin/Web Hook call to service layer
This commit is contained in:
Naoki Takezoe
2018-10-14 23:03:16 +09:00
committed by GitHub
21 changed files with 837 additions and 741 deletions

View File

@@ -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("/")
} }

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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}") {
// Update database
renameRepository(repository.owner, repository.name, form.newOwner, repository.name) 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.owner, repository.name) deleteRepository(repository.repository)
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}")
}) })

View File

@@ -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")

View File

@@ -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

View File

@@ -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 =

View File

@@ -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

View File

@@ -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))

View File

@@ -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.")
} }

View File

@@ -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,6 +209,15 @@ 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
)
}
} }
} }

View File

@@ -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)
}

View File

@@ -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,6 +77,7 @@ trait RepositoryService { self: AccountService =>
(Repositories filter { t => (Repositories filter { t =>
t.byRepository(oldUserName, oldRepositoryName) t.byRepository(oldUserName, oldRepositoryName)
} firstOption).foreach { repository => } firstOption).foreach { repository =>
LockUtil.lock(s"${repository.userName}/${repository.repositoryName}") {
Repositories insert repository.copy(userName = newUserName, repositoryName = newRepositoryName) Repositories insert repository.copy(userName = newUserName, repositoryName = newRepositoryName)
val webHooks = RepositoryWebHooks.filter(_.byRepository(oldUserName, oldRepositoryName)).list val webHooks = RepositoryWebHooks.filter(_.byRepository(oldUserName, oldRepositoryName)).list
@@ -117,7 +127,7 @@ trait RepositoryService { self: AccountService =>
.update(newUserName, newRepositoryName) .update(newUserName, newRepositoryName)
} }
deleteRepository(oldUserName, oldRepositoryName) deleteRepositoryOnModel(oldUserName, oldRepositoryName)
RepositoryWebHooks.insertAll( RepositoryWebHooks.insertAll(
webHooks.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _* webHooks.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _*
@@ -139,12 +149,17 @@ trait RepositoryService { self: AccountService =>
newMilestones.find(_.title == milestones.find(_.milestoneId == id).get.title).get.milestoneId newMilestones.find(_.title == milestones.find(_.milestoneId == id).get.title).get.milestoneId
}, },
priorityId = x.priorityId.map { id => priorityId = x.priorityId.map { id =>
newPriorities.find(_.priorityName == priorities.find(_.priorityId == id).get.priorityName).get.priorityId newPriorities
.find(_.priorityName == priorities.find(_.priorityId == id).get.priorityName)
.get
.priorityId
} }
) )
}: _*) }: _*)
PullRequests.insertAll(pullRequests.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _*) PullRequests.insertAll(
pullRequests.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _*
)
IssueComments.insertAll( IssueComments.insertAll(
issueComments.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _* issueComments.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)): _*
) )
@@ -223,7 +238,10 @@ trait RepositoryService { self: AccountService =>
s"[branch:${oldUserName}/${oldRepositoryName}#", s"[branch:${oldUserName}/${oldRepositoryName}#",
s"[branch:${newUserName}/${newRepositoryName}#" s"[branch:${newUserName}/${newRepositoryName}#"
) )
.replace(s"[tag:${oldUserName}/${oldRepositoryName}#", s"[tag:${newUserName}/${newRepositoryName}#") .replace(
s"[tag:${oldUserName}/${oldRepositoryName}#",
s"[tag:${newUserName}/${newRepositoryName}#"
)
.replace( .replace(
s"[pullreq:${oldUserName}/${oldRepositoryName}#", s"[pullreq:${oldUserName}/${oldRepositoryName}#",
s"[pullreq:${newUserName}/${newRepositoryName}#" s"[pullreq:${newUserName}/${newRepositoryName}#"
@@ -238,11 +256,53 @@ trait RepositoryService { self: AccountService =>
) )
) )
} }
// Move git repository
defining(getRepositoryDir(oldUserName, oldRepositoryName)) { dir =>
if (dir.isDirectory) {
FileUtils.moveDirectory(dir, getRepositoryDir(newUserName, newRepositoryName))
}
}
// Move wiki repository
defining(getWikiRepositoryDir(oldUserName, oldRepositoryName)) { dir =>
if (dir.isDirectory) {
FileUtils.moveDirectory(dir, getWikiRepositoryDir(newUserName, newRepositoryName))
}
}
// Move files directory
defining(getRepositoryFilesDir(oldUserName, oldRepositoryName)) { dir =>
if (dir.isDirectory) {
FileUtils.moveDirectory(dir, getRepositoryFilesDir(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,

View File

@@ -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._

View File

@@ -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 _ =>
} }

View File

@@ -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 = {

View 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)

View File

@@ -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))

View File

@@ -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 =>