From b5992198529cae0c5595e4a0edc29633d60eff03 Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Sun, 17 Jan 2016 01:38:11 +0900 Subject: [PATCH] Add commit hook extension point for plugins --- .../core/api/ApiBranchProtection.scala | 4 +-- .../controller/PullRequestsController.scala | 4 +-- .../RepositorySettingsController.scala | 6 ++-- .../RepositoryViewerController.scala | 4 +-- .../gitbucket/core/plugin/CommitHook.scala | 12 +++++++ .../core/plugin/PluginRegistory.scala | 9 +++++ ...ice.scala => ProtectedBranchService.scala} | 34 +++++++++++-------- .../core/service/PullRequestService.scala | 2 +- .../core/servlet/GitRepositoryServlet.scala | 9 ++--- 9 files changed, 55 insertions(+), 29 deletions(-) create mode 100644 src/main/scala/gitbucket/core/plugin/CommitHook.scala rename src/main/scala/gitbucket/core/service/{ProtectedBrancheService.scala => ProtectedBranchService.scala} (85%) diff --git a/src/main/scala/gitbucket/core/api/ApiBranchProtection.scala b/src/main/scala/gitbucket/core/api/ApiBranchProtection.scala index 2af86f2bf..6554e0812 100644 --- a/src/main/scala/gitbucket/core/api/ApiBranchProtection.scala +++ b/src/main/scala/gitbucket/core/api/ApiBranchProtection.scala @@ -1,6 +1,6 @@ package gitbucket.core.api -import gitbucket.core.service.ProtectedBrancheService +import gitbucket.core.service.ProtectedBranchService import org.json4s._ /** https://developer.github.com/v3/repos/#enabling-and-disabling-branch-protection */ @@ -12,7 +12,7 @@ object ApiBranchProtection{ /** form for enabling-and-disabling-branch-protection */ case class EnablingAndDisabling(protection: ApiBranchProtection) - def apply(info: ProtectedBrancheService.ProtectedBranchInfo): ApiBranchProtection = ApiBranchProtection( + def apply(info: ProtectedBranchService.ProtectedBranchInfo): ApiBranchProtection = ApiBranchProtection( enabled = info.enabled, required_status_checks = Some(Status(EnforcementLevel(info.enabled, info.includeAdministrators), info.contexts))) val statusNone = Status(Off, Seq.empty) diff --git a/src/main/scala/gitbucket/core/controller/PullRequestsController.scala b/src/main/scala/gitbucket/core/controller/PullRequestsController.scala index eaafacc00..7a95c4238 100644 --- a/src/main/scala/gitbucket/core/controller/PullRequestsController.scala +++ b/src/main/scala/gitbucket/core/controller/PullRequestsController.scala @@ -27,13 +27,13 @@ import scala.collection.JavaConverters._ class PullRequestsController extends PullRequestsControllerBase with RepositoryService with AccountService with IssuesService with PullRequestService with MilestonesService with LabelsService with CommitsService with ActivityService with WebHookPullRequestService with ReferrerAuthenticator with CollaboratorsAuthenticator - with CommitStatusService with MergeService with ProtectedBrancheService + with CommitStatusService with MergeService with ProtectedBranchService trait PullRequestsControllerBase extends ControllerBase { self: RepositoryService with AccountService with IssuesService with MilestonesService with LabelsService with CommitsService with ActivityService with PullRequestService with WebHookPullRequestService with ReferrerAuthenticator with CollaboratorsAuthenticator - with CommitStatusService with MergeService with ProtectedBrancheService => + with CommitStatusService with MergeService with ProtectedBranchService => private val logger = LoggerFactory.getLogger(classOf[PullRequestsControllerBase]) diff --git a/src/main/scala/gitbucket/core/controller/RepositorySettingsController.scala b/src/main/scala/gitbucket/core/controller/RepositorySettingsController.scala index ac6bd8265..2c65df6d1 100644 --- a/src/main/scala/gitbucket/core/controller/RepositorySettingsController.scala +++ b/src/main/scala/gitbucket/core/controller/RepositorySettingsController.scala @@ -2,7 +2,7 @@ package gitbucket.core.controller import gitbucket.core.settings.html import gitbucket.core.model.WebHook -import gitbucket.core.service.{RepositoryService, AccountService, WebHookService, ProtectedBrancheService, CommitStatusService} +import gitbucket.core.service.{RepositoryService, AccountService, WebHookService, ProtectedBranchService, CommitStatusService} import gitbucket.core.service.WebHookService._ import gitbucket.core.util._ import gitbucket.core.util.JGitUtil._ @@ -18,11 +18,11 @@ import org.eclipse.jgit.lib.ObjectId class RepositorySettingsController extends RepositorySettingsControllerBase - with RepositoryService with AccountService with WebHookService with ProtectedBrancheService with CommitStatusService + with RepositoryService with AccountService with WebHookService with ProtectedBranchService with CommitStatusService with OwnerAuthenticator with UsersAuthenticator trait RepositorySettingsControllerBase extends ControllerBase { - self: RepositoryService with AccountService with WebHookService with ProtectedBrancheService with CommitStatusService + self: RepositoryService with AccountService with WebHookService with ProtectedBranchService with CommitStatusService with OwnerAuthenticator with UsersAuthenticator => // for repository options diff --git a/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala b/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala index 998103315..da9b2d9e1 100644 --- a/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala +++ b/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala @@ -33,7 +33,7 @@ import org.scalatra._ class RepositoryViewerController extends RepositoryViewerControllerBase with RepositoryService with AccountService with ActivityService with IssuesService with WebHookService with CommitsService with ReadableUsersAuthenticator with ReferrerAuthenticator with CollaboratorsAuthenticator with PullRequestService with CommitStatusService - with WebHookPullRequestService with WebHookPullRequestReviewCommentService with ProtectedBrancheService + with WebHookPullRequestService with WebHookPullRequestReviewCommentService with ProtectedBranchService /** * The repository viewer. @@ -41,7 +41,7 @@ class RepositoryViewerController extends RepositoryViewerControllerBase trait RepositoryViewerControllerBase extends ControllerBase { self: RepositoryService with AccountService with ActivityService with IssuesService with WebHookService with CommitsService with ReadableUsersAuthenticator with ReferrerAuthenticator with CollaboratorsAuthenticator with PullRequestService with CommitStatusService - with WebHookPullRequestService with WebHookPullRequestReviewCommentService with ProtectedBrancheService => + with WebHookPullRequestService with WebHookPullRequestReviewCommentService with ProtectedBranchService => ArchiveCommand.registerFormat("zip", new ZipFormat) ArchiveCommand.registerFormat("tar.gz", new TgzFormat) diff --git a/src/main/scala/gitbucket/core/plugin/CommitHook.scala b/src/main/scala/gitbucket/core/plugin/CommitHook.scala new file mode 100644 index 000000000..bf01e35d0 --- /dev/null +++ b/src/main/scala/gitbucket/core/plugin/CommitHook.scala @@ -0,0 +1,12 @@ +package gitbucket.core.plugin + +import gitbucket.core.model.Profile._ +import org.eclipse.jgit.transport.ReceiveCommand +import profile.simple._ + +trait CommitHook { + + def hook(owner: String, repository: String, isAllowNonFastForwards: Boolean, command: ReceiveCommand, pusher: String) + (implicit session: Session): Option[String] + +} diff --git a/src/main/scala/gitbucket/core/plugin/PluginRegistory.scala b/src/main/scala/gitbucket/core/plugin/PluginRegistory.scala index b0323699f..0b87c6878 100644 --- a/src/main/scala/gitbucket/core/plugin/PluginRegistory.scala +++ b/src/main/scala/gitbucket/core/plugin/PluginRegistory.scala @@ -6,6 +6,7 @@ import javax.servlet.ServletContext import javax.servlet.http.{HttpServletRequest, HttpServletResponse} import gitbucket.core.controller.{Context, ControllerBase} +import gitbucket.core.service.ProtectedBranchService.ProtectedBranchCommitHook import gitbucket.core.service.RepositoryService.RepositoryInfo import gitbucket.core.service.SystemSettingsService.SystemSettings import gitbucket.core.util.ControlUtil._ @@ -29,6 +30,8 @@ class PluginRegistry { "md" -> MarkdownRenderer, "markdown" -> MarkdownRenderer ) private val repositoryRoutings = new ListBuffer[GitRepositoryRouting] + private val commitHooks = new ListBuffer[CommitHook] + commitHooks += new ProtectedBranchCommitHook() def addPlugin(pluginInfo: PluginInfo): Unit = { plugins += pluginInfo @@ -98,6 +101,12 @@ class PluginRegistry { } } + def addCommitHook(commitHook: CommitHook): Unit = { + commitHooks += commitHook + } + + def getCommitHooks: Seq[CommitHook] = commitHooks.toSeq + private case class GlobalAction( method: String, path: String, diff --git a/src/main/scala/gitbucket/core/service/ProtectedBrancheService.scala b/src/main/scala/gitbucket/core/service/ProtectedBranchService.scala similarity index 85% rename from src/main/scala/gitbucket/core/service/ProtectedBrancheService.scala rename to src/main/scala/gitbucket/core/service/ProtectedBranchService.scala index 97652aeae..618106f50 100644 --- a/src/main/scala/gitbucket/core/service/ProtectedBrancheService.scala +++ b/src/main/scala/gitbucket/core/service/ProtectedBranchService.scala @@ -1,17 +1,15 @@ package gitbucket.core.service -import gitbucket.core.model.{Collaborator, Repository, Account, CommitState, CommitStatus, ProtectedBranch, ProtectedBranchContext} +import gitbucket.core.model._ import gitbucket.core.model.Profile._ -import gitbucket.core.util.JGitUtil +import gitbucket.core.plugin.CommitHook import profile.simple._ import org.eclipse.jgit.transport.ReceiveCommand -import org.eclipse.jgit.transport.ReceivePack -import org.eclipse.jgit.lib.ObjectId -trait ProtectedBrancheService { - import ProtectedBrancheService._ +trait ProtectedBranchService { + import ProtectedBranchService._ private def getProtectedBranchInfoOpt(owner: String, repository: String, branch: String)(implicit session: Session): Option[ProtectedBranchInfo] = ProtectedBranches .leftJoin(ProtectedBranchContexts) @@ -43,17 +41,23 @@ trait ProtectedBrancheService { def disableBranchProtection(owner: String, repository: String, branch:String)(implicit session: Session): Unit = ProtectedBranches.filter(_.byPrimaryKey(owner, repository, branch)).delete - def getBranchProtectedReason(owner: String, repository: String, isAllowNonFastForwards: Boolean, command: ReceiveCommand, pusher: String) - (implicit session: Session): Option[String] = { - val branch = command.getRefName.stripPrefix("refs/heads/") - if(branch != command.getRefName){ - getProtectedBranchInfo(owner, repository, branch).getStopReason(isAllowNonFastForwards, command, pusher) - } else { - None +} + +object ProtectedBranchService { + + class ProtectedBranchCommitHook extends CommitHook with ProtectedBranchService { + override def hook(owner: String, repository: String, isAllowNonFastForwards: Boolean, command: ReceiveCommand, pusher: String) + (implicit session: Session): Option[String] = { + val branch = command.getRefName.stripPrefix("refs/heads/") + if(branch != command.getRefName){ + getProtectedBranchInfo(owner, repository, branch).getStopReason(isAllowNonFastForwards, command, pusher) + } else { + None + } } } -} -object ProtectedBrancheService { + + case class ProtectedBranchInfo( owner: String, repository: String, diff --git a/src/main/scala/gitbucket/core/service/PullRequestService.scala b/src/main/scala/gitbucket/core/service/PullRequestService.scala index 789a09d59..e90ba3fcb 100644 --- a/src/main/scala/gitbucket/core/service/PullRequestService.scala +++ b/src/main/scala/gitbucket/core/service/PullRequestService.scala @@ -148,7 +148,7 @@ object PullRequestService { case class MergeStatus( hasConflict: Boolean, commitStatues:List[CommitStatus], - branchProtection: ProtectedBrancheService.ProtectedBranchInfo, + branchProtection: ProtectedBranchService.ProtectedBranchInfo, branchIsOutOfDate: Boolean, hasUpdatePermission: Boolean, needStatusCheck: Boolean, diff --git a/src/main/scala/gitbucket/core/servlet/GitRepositoryServlet.scala b/src/main/scala/gitbucket/core/servlet/GitRepositoryServlet.scala index eb9a26349..045aef129 100644 --- a/src/main/scala/gitbucket/core/servlet/GitRepositoryServlet.scala +++ b/src/main/scala/gitbucket/core/servlet/GitRepositoryServlet.scala @@ -111,7 +111,7 @@ import scala.collection.JavaConverters._ class CommitLogHook(owner: String, repository: String, pusher: String, baseUrl: String)(implicit session: Session) extends PostReceiveHook with PreReceiveHook with RepositoryService with AccountService with IssuesService with ActivityService with PullRequestService with WebHookService - with WebHookPullRequestService with ProtectedBrancheService { + with WebHookPullRequestService with ProtectedBranchService { private val logger = LoggerFactory.getLogger(classOf[CommitLogHook]) private var existIds: Seq[String] = Nil @@ -119,9 +119,10 @@ class CommitLogHook(owner: String, repository: String, pusher: String, baseUrl: def onPreReceive(receivePack: ReceivePack, commands: java.util.Collection[ReceiveCommand]): Unit = { try { commands.asScala.foreach { command => - - getBranchProtectedReason(owner, repository, receivePack.isAllowNonFastForwards, command, pusher).map { reason => - command.setResult(ReceiveCommand.Result.REJECTED_OTHER_REASON, reason) + PluginRegistry().getCommitHooks + .flatMap(_.hook(owner, repository, receivePack.isAllowNonFastForwards, command, pusher)) + .headOption.foreach { error => + command.setResult(ReceiveCommand.Result.REJECTED_OTHER_REASON, error) } } using(Git.open(Directory.getRepositoryDir(owner, repository))) { git =>