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
This commit is contained in:
Dave Borowitz 2017-10-03 09:55:51 +01:00
parent b8a2bae6db
commit 223580f314
5 changed files with 69 additions and 1 deletions

View File

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

View File

@ -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<Context> {
private final Provider<CurrentUser> userProvider;
private final VisibleRefFilter.Factory refFilterFactory;
private final TransferConfig transferConfig;
private final DynamicSet<UploadPackInitializer> uploadPackInitializers;
private final DynamicSet<PreUploadHook> preUploadHooks;
private final UploadValidators.Factory uploadValidatorsFactory;
private final ThreadLocalRequestContext threadContext;
@ -222,6 +224,7 @@ class InProcessProtocol extends TestProtocol<Context> {
Provider<CurrentUser> userProvider,
VisibleRefFilter.Factory refFilterFactory,
TransferConfig transferConfig,
DynamicSet<UploadPackInitializer> uploadPackInitializers,
DynamicSet<PreUploadHook> preUploadHooks,
UploadValidators.Factory uploadValidatorsFactory,
ThreadLocalRequestContext threadContext,
@ -230,6 +233,7 @@ class InProcessProtocol extends TestProtocol<Context> {
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<Context> {
List<PreUploadHook> 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;
}
}

View File

@ -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<PreUploadHook> preUploadHooks;
private final DynamicSet<PostUploadHook> postUploadHooks;
private final DynamicSet<UploadPackInitializer> uploadPackInitializers;
@Inject
UploadFactory(
TransferConfig tc,
DynamicSet<PreUploadHook> preUploadHooks,
DynamicSet<PostUploadHook> postUploadHooks) {
DynamicSet<PostUploadHook> postUploadHooks,
DynamicSet<UploadPackInitializer> 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;
}
}

View File

@ -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.
*
* <p>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);
}

View File

@ -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<PreUploadHook> preUploadHooks;
@Inject private DynamicSet<PostUploadHook> postUploadHooks;
@Inject private DynamicSet<UploadPackInitializer> 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());