From 223580f3149c9d7068de26c04a26d678f37fb5db Mon Sep 17 00:00:00 2001 From: Dave Borowitz Date: Tue, 3 Oct 2017 09:55:51 +0100 Subject: [PATCH] Add UploadPackInitializer extension point I suggested to Luca at the hackathon that he could use this mechanism to limit refs advertised to Jenkins, instead of writing a custom PermissionBackend. Getting this in 2.15 means people using his plugin won't have to wait for the next release to stop using the PermissionBackend hack. Change-Id: I8c38eef94d6e505b926b3da6c470e34f6613ca2c --- Documentation/dev-plugins.txt | 13 +++++++ .../gerrit/acceptance/InProcessProtocol.java | 7 ++++ .../gerrit/httpd/GitOverHttpServlet.java | 10 +++++- .../server/git/UploadPackInitializer.java | 35 +++++++++++++++++++ .../google/gerrit/sshd/commands/Upload.java | 5 +++ 5 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 gerrit-server/src/main/java/com/google/gerrit/server/git/UploadPackInitializer.java diff --git a/Documentation/dev-plugins.txt b/Documentation/dev-plugins.txt index 9117d65f14..1a026d101f 100644 --- a/Documentation/dev-plugins.txt +++ b/Documentation/dev-plugins.txt @@ -500,6 +500,19 @@ notified when JGit successfully receives a pack. This may be useful for those plugins which would like to monitor changes in Git repositories. +[[upload-pack]] +== Upload Pack Initializers + +Plugins may provide UploadPackInitializer instances, which will be +invoked by Gerrit just before a UploadPack instance will be used. +Usually, plugins will make use of the setXXX methods on the UploadPack +to set additional properties on it. + +The interactions with the core Gerrit UploadPack initialization and +between UploadPackInitializers can be complex. Please read the +UploadPack Javadoc and Gerrit Upload/UploadFactory implementations +carefully. + [[pre-upload-hook]] == Pre Upload-Pack Hooks diff --git a/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/InProcessProtocol.java b/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/InProcessProtocol.java index a508948780..e2e29c9221 100644 --- a/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/InProcessProtocol.java +++ b/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/InProcessProtocol.java @@ -32,6 +32,7 @@ import com.google.gerrit.server.config.GerritRequestModule; import com.google.gerrit.server.config.RequestScopedReviewDbProvider; import com.google.gerrit.server.git.ReceivePackInitializer; import com.google.gerrit.server.git.TransferConfig; +import com.google.gerrit.server.git.UploadPackInitializer; import com.google.gerrit.server.git.VisibleRefFilter; import com.google.gerrit.server.git.receive.AsyncReceiveCommits; import com.google.gerrit.server.git.validators.UploadValidators; @@ -211,6 +212,7 @@ class InProcessProtocol extends TestProtocol { private final Provider userProvider; private final VisibleRefFilter.Factory refFilterFactory; private final TransferConfig transferConfig; + private final DynamicSet uploadPackInitializers; private final DynamicSet preUploadHooks; private final UploadValidators.Factory uploadValidatorsFactory; private final ThreadLocalRequestContext threadContext; @@ -222,6 +224,7 @@ class InProcessProtocol extends TestProtocol { Provider userProvider, VisibleRefFilter.Factory refFilterFactory, TransferConfig transferConfig, + DynamicSet uploadPackInitializers, DynamicSet preUploadHooks, UploadValidators.Factory uploadValidatorsFactory, ThreadLocalRequestContext threadContext, @@ -230,6 +233,7 @@ class InProcessProtocol extends TestProtocol { this.userProvider = userProvider; this.refFilterFactory = refFilterFactory; this.transferConfig = transferConfig; + this.uploadPackInitializers = uploadPackInitializers; this.preUploadHooks = preUploadHooks; this.uploadValidatorsFactory = uploadValidatorsFactory; this.threadContext = threadContext; @@ -273,6 +277,9 @@ class InProcessProtocol extends TestProtocol { List hooks = Lists.newArrayList(preUploadHooks); hooks.add(uploadValidatorsFactory.create(projectState.getProject(), repo, "localhost-test")); up.setPreUploadHook(PreUploadHookChain.newChain(hooks)); + for (UploadPackInitializer initializer : uploadPackInitializers) { + initializer.init(req.project, up); + } return up; } } diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GitOverHttpServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GitOverHttpServlet.java index 72dcfb97e3..329beabfb7 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GitOverHttpServlet.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GitOverHttpServlet.java @@ -27,6 +27,7 @@ import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.cache.CacheModule; import com.google.gerrit.server.git.GitRepositoryManager; import com.google.gerrit.server.git.TransferConfig; +import com.google.gerrit.server.git.UploadPackInitializer; import com.google.gerrit.server.git.VisibleRefFilter; import com.google.gerrit.server.git.receive.AsyncReceiveCommits; import com.google.gerrit.server.git.validators.UploadValidators; @@ -209,15 +210,18 @@ public class GitOverHttpServlet extends GitServlet { private final TransferConfig config; private final DynamicSet preUploadHooks; private final DynamicSet postUploadHooks; + private final DynamicSet uploadPackInitializers; @Inject UploadFactory( TransferConfig tc, DynamicSet preUploadHooks, - DynamicSet postUploadHooks) { + DynamicSet postUploadHooks, + DynamicSet uploadPackInitializers) { this.config = tc; this.preUploadHooks = preUploadHooks; this.postUploadHooks = postUploadHooks; + this.uploadPackInitializers = uploadPackInitializers; } @Override @@ -227,6 +231,10 @@ public class GitOverHttpServlet extends GitServlet { up.setTimeout(config.getTimeout()); up.setPreUploadHook(PreUploadHookChain.newChain(Lists.newArrayList(preUploadHooks))); up.setPostUploadHook(PostUploadHookChain.newChain(Lists.newArrayList(postUploadHooks))); + ProjectControl pc = (ProjectControl) req.getAttribute(ATT_CONTROL); + for (UploadPackInitializer initializer : uploadPackInitializers) { + initializer.init(pc.getProject().getNameKey(), up); + } return up; } } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/UploadPackInitializer.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/UploadPackInitializer.java new file mode 100644 index 0000000000..b63c5b34e4 --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/UploadPackInitializer.java @@ -0,0 +1,35 @@ +// Copyright (C) 2017 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.gerrit.server.git; + +import com.google.gerrit.extensions.annotations.ExtensionPoint; +import com.google.gerrit.reviewdb.client.Project; +import org.eclipse.jgit.transport.UploadPack; + +@ExtensionPoint +public interface UploadPackInitializer { + + /** + * UploadPack initialization. + * + *

Invoked by Gerrit when a new UploadPack instance is created and just before it is used. + * Implementors will usually call setXXX methods on the uploadPack parameter in order to set + * additional properties on it. + * + * @param project project for which the UploadPack is created + * @param uploadPack the UploadPack instance which is being initialized + */ + void init(Project.NameKey project, UploadPack uploadPack); +} diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/Upload.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/Upload.java index 2d44b595ce..7049c7f585 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/Upload.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/Upload.java @@ -18,6 +18,7 @@ import com.google.common.collect.Lists; import com.google.gerrit.extensions.registration.DynamicSet; import com.google.gerrit.extensions.restapi.AuthException; import com.google.gerrit.server.git.TransferConfig; +import com.google.gerrit.server.git.UploadPackInitializer; import com.google.gerrit.server.git.VisibleRefFilter; import com.google.gerrit.server.git.validators.UploadValidationException; import com.google.gerrit.server.git.validators.UploadValidators; @@ -41,6 +42,7 @@ final class Upload extends AbstractGitCommand { @Inject private VisibleRefFilter.Factory refFilterFactory; @Inject private DynamicSet preUploadHooks; @Inject private DynamicSet postUploadHooks; + @Inject private DynamicSet uploadPackInitializers; @Inject private UploadValidators.Factory uploadValidatorsFactory; @Inject private SshSession session; @Inject private PermissionBackend permissionBackend; @@ -68,6 +70,9 @@ final class Upload extends AbstractGitCommand { allPreUploadHooks.add( uploadValidatorsFactory.create(project, repo, session.getRemoteAddressAsString())); up.setPreUploadHook(PreUploadHookChain.newChain(allPreUploadHooks)); + for (UploadPackInitializer initializer : uploadPackInitializers) { + initializer.init(projectControl.getProject().getNameKey(), up); + } try { up.upload(in, out, err); session.setPeerAgent(up.getPeerUserAgent());