Add extension point for receive-pack initialization.

Plugins can register ReceivePackInitializer's in order to provide custom
initialization of the ReceivePack instance. For example, the quota plugin
may use this extension point to set the maximum allowed pack size based
on its quota configuration and the disk space occupied by that project.

Change-Id: I8d6e7d4bb75099b0fa5f6968ae5371883bf865ee
This commit is contained in:
Saša Živkov 2014-01-28 10:08:25 +01:00
parent 8905dd4b96
commit ec85a070b3
5 changed files with 70 additions and 1 deletions

View File

@ -416,6 +416,14 @@ its own custom event class derived from `ChangeEvent`.
Certain operations in Gerrit can be validated by plugins by
implementing the corresponding link:config-validation.html[listeners].
[[receive-pack]]
== Receive Pack Initializers
Plugins may provide ReceivePack initializers which will be invoked
by Gerrit just before a ReceivePack instance will be used. Usually,
plugins will make use of the setXXX methods on the ReceivePack to
set additional properties on it.
[[ssh]]
== SSH Commands

View File

@ -16,6 +16,7 @@ package com.google.gerrit.httpd;
import com.google.common.cache.Cache;
import com.google.gerrit.common.data.Capable;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.AccessPath;
@ -23,6 +24,7 @@ import com.google.gerrit.server.AnonymousUser;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.cache.CacheModule;
import com.google.gerrit.server.config.ReceivePackInitializer;
import com.google.gerrit.server.git.AsyncReceiveCommits;
import com.google.gerrit.server.git.ChangeCache;
import com.google.gerrit.server.git.GitRepositoryManager;
@ -244,11 +246,14 @@ public class GitOverHttpServlet extends GitServlet {
static class ReceiveFactory implements ReceivePackFactory<HttpServletRequest> {
private final AsyncReceiveCommits.Factory factory;
private final TransferConfig config;
private DynamicSet<ReceivePackInitializer> receivePackInitializers;
@Inject
ReceiveFactory(AsyncReceiveCommits.Factory factory, TransferConfig config) {
ReceiveFactory(AsyncReceiveCommits.Factory factory, TransferConfig config,
DynamicSet<ReceivePackInitializer> receivePackInitializers) {
this.factory = factory;
this.config = config;
this.receivePackInitializers = receivePackInitializers;
}
@Override
@ -267,9 +272,16 @@ public class GitOverHttpServlet extends GitServlet {
rp.setRefLogIdent(user.newRefLogIdent());
rp.setTimeout(config.getTimeout());
rp.setMaxObjectSizeLimit(config.getMaxObjectSizeLimit());
init(pc.getProject().getNameKey(), rp);
req.setAttribute(ATT_RC, rc);
return rp;
}
private void init(Project.NameKey project, ReceivePack rp) {
for (ReceivePackInitializer initializer : receivePackInitializers) {
initializer.init(project, rp);
}
}
}
static class ReceiveFilter implements Filter {

View File

@ -243,6 +243,7 @@ public class GerritGlobalModule extends FactoryModule {
DynamicSet.setOf(binder(), CacheRemovalListener.class);
DynamicMap.mapOf(binder(), CapabilityDefinition.class);
DynamicSet.setOf(binder(), GitReferenceUpdatedListener.class);
DynamicSet.setOf(binder(), ReceivePackInitializer.class);
DynamicSet.setOf(binder(), NewProjectCreatedListener.class);
DynamicSet.setOf(binder(), ProjectDeletedListener.class);
DynamicSet.setOf(binder(), HeadUpdatedListener.class);

View File

@ -0,0 +1,36 @@
// Copyright (C) 2014 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.config;
import com.google.gerrit.extensions.annotations.ExtensionPoint;
import com.google.gerrit.reviewdb.client.Project;
import org.eclipse.jgit.transport.ReceivePack;
@ExtensionPoint
public interface ReceivePackInitializer {
/**
* ReceivePack initialization.
*
* Invoked by Gerrit when a new ReceivePack instance is created and just
* before it is used. Implementors will usually call setXXX methods on the
* receivePack parameter in order to set additional properties on it.
*
* @param project project for which the ReceivePack is created
* @param receivePack the ReceivePack instance which is being initialized
*/
public void init(Project.NameKey project, ReceivePack receivePack);
}

View File

@ -15,8 +15,10 @@
package com.google.gerrit.sshd.commands;
import com.google.gerrit.common.data.Capable;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.config.ReceivePackInitializer;
import com.google.gerrit.server.git.AsyncReceiveCommits;
import com.google.gerrit.server.git.ReceiveCommits;
import com.google.gerrit.server.git.TransferConfig;
@ -59,6 +61,9 @@ final class Receive extends AbstractGitCommand {
@Inject
private TransferConfig config;
@Inject
private DynamicSet<ReceivePackInitializer> receivePackInitializers;
private final Set<Account.Id> reviewerId = new HashSet<Account.Id>();
private final Set<Account.Id> ccId = new HashSet<Account.Id>();
@ -97,6 +102,7 @@ final class Receive extends AbstractGitCommand {
rp.setTimeout(config.getTimeout());
rp.setMaxObjectSizeLimit(config.getEffectiveMaxObjectSizeLimit(
projectControl.getProjectState()));
init(rp);
try {
rp.receive(in, out, err);
} catch (UnpackException badStream) {
@ -163,6 +169,12 @@ final class Receive extends AbstractGitCommand {
}
}
private void init(ReceivePack rp) {
for (ReceivePackInitializer initializer : receivePackInitializers) {
initializer.init(projectControl.getProject().getNameKey(), rp);
}
}
private void verifyProjectVisible(final String type, final Set<Account.Id> who)
throws UnloggedFailure {
for (final Account.Id id : who) {