Add project-specific scoping
Also add project and ref scoping to the UI.
Change-Id: If89e95fea8d36b287fe0d1e174885f7f6f7f6311
Signed-off-by: Edwin Kempin <ekempin@google.com>
diff --git a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/Module.java b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/Module.java
index b1cba3c..9717779 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/Module.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/Module.java
@@ -34,6 +34,7 @@
install(InvalidLineEndingValidator.module());
install(ContentTypeValidator.module());
install(DuplicatePathnameValidator.module());
+ install(ValidatorConfig.module());
bind(ConfigFactory.class).to(PluginConfigWithInheritanceFactory.class).in(
Scopes.SINGLETON);
diff --git a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/ValidatorConfig.java b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/ValidatorConfig.java
index cf80a6c..30227fc 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/ValidatorConfig.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/ValidatorConfig.java
@@ -15,12 +15,16 @@
package com.googlesource.gerrit.plugins.uploadvalidator;
import com.google.gerrit.common.data.RefConfigSection;
+import com.google.gerrit.extensions.annotations.Exports;
+import com.google.gerrit.extensions.api.projects.ProjectConfigEntryType;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.config.PluginConfig;
+import com.google.gerrit.server.config.ProjectConfigEntry;
import com.google.gerrit.server.project.RefPatternMatcher;
+import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import org.slf4j.Logger;
@@ -33,9 +37,29 @@
public class ValidatorConfig {
private static final Logger log = LoggerFactory
.getLogger(ValidatorConfig.class);
+ private static final String KEY_PROJECT = "project";
+ private static final String KEY_REF = "ref";
private final ConfigFactory configFactory;
private final GroupCache groupCache;
+ public static AbstractModule module() {
+ return new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(ProjectConfigEntry.class)
+ .annotatedWith(Exports.named(KEY_PROJECT))
+ .toInstance(new ProjectConfigEntry("Projects", null,
+ ProjectConfigEntryType.ARRAY, null, false,
+ "Only projects that match this regex will be validated."));
+ bind(ProjectConfigEntry.class)
+ .annotatedWith(Exports.named(KEY_REF))
+ .toInstance(new ProjectConfigEntry("Refs", null,
+ ProjectConfigEntryType.ARRAY, null, false,
+ "Only refs that match this regex will be validated."));
+ }
+ };
+ }
+
@Inject
public ValidatorConfig(ConfigFactory configFactory,
GroupCache groupCache) {
@@ -51,6 +75,7 @@
&& isValidConfig(conf, projectName)
&& (activeForRef(conf, refName))
&& (activeForEmail(conf, user.getAccount().getPreferredEmail()))
+ && (activeForProject(conf, projectName.get()))
&& (!hasCriteria(conf, "skipGroup")
|| !canSkipValidation(conf, validatorOp)
|| !canSkipRef(conf, refName)
@@ -80,6 +105,10 @@
return config.getStringList(criteria).length > 0;
}
+ private boolean activeForProject(PluginConfig config, String project) {
+ return matchCriteria(config, "project", project, true, false);
+ }
+
private boolean activeForRef(PluginConfig config, String ref) {
return matchCriteria(config, "ref", ref, true, true);
}
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md
index a4151a0..04c04a1 100644
--- a/src/main/resources/Documentation/config.md
+++ b/src/main/resources/Documentation/config.md
@@ -241,6 +241,22 @@
email = .*@example.com$
```
+Project-specific validations
+---------------------------
+
+By default, the validation will be enabled for all projects. However, it can
+be limited to particular projects by setting `plugin.@PLUGIN@.project`. The
+projects may be configured using specific project names, project patterns, or
+regular expressions. Multiple projects may be specified.
+
+E.g. to limit the validation to all projects that match `^platform/.*` the
+following could be configured:
+
+```
+ [plugin "@PLUGIN@"]
+ project = ^platform/.*
+```
+
Permission to skip the rules
----------------------------
@@ -324,4 +340,4 @@
skipGroup = ldap/ReleaseManagers
skipGroup = ldap/GerritAdmins
skipRef = refs/heads/master
-```
\ No newline at end of file
+```
diff --git a/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/ProjectAwareValidatorConfigTest.java b/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/ProjectAwareValidatorConfigTest.java
new file mode 100644
index 0000000..1ddcdc3
--- /dev/null
+++ b/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/ProjectAwareValidatorConfigTest.java
@@ -0,0 +1,112 @@
+// 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.googlesource.gerrit.plugins.uploadvalidator;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.server.IdentifiedUser;
+
+import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.junit.Test;
+
+public class ProjectAwareValidatorConfigTest {
+ private Project.NameKey projectName = new Project.NameKey("testProject");
+ private IdentifiedUser anyUser = new FakeUserProvider().get();
+
+ @Test
+ public void isEnabledForAllProjectsByDefault() throws Exception {
+ ValidatorConfig config =
+ getConfig("[plugin \"uploadvalidator\"]\n"
+ + "blockedFileExtension = jar", projectName);
+
+ assertThat(
+ config.isEnabledForRef(anyUser, projectName, "anyRef",
+ "blockedFileExtension")).isTrue();
+ }
+
+ @Test
+ public void isEnabledForSingleProject() throws Exception {
+ ValidatorConfig config =
+ getConfig("[plugin \"uploadvalidator\"]\n"
+ + " project = testProject\n"
+ + " blockedFileExtension = jar", projectName);
+
+ assertThat(
+ config.isEnabledForRef(anyUser, projectName, "anyRef",
+ "blockedFileExtension")).isTrue();
+ }
+
+ @Test
+ public void isDisabledForInvalidProject() throws Exception {
+ ValidatorConfig config =
+ getConfig("[plugin \"uploadvalidator\"]\n"
+ + " project = someOtherProject\n"
+ + " blockedFileExtension = jar", projectName);
+
+ assertThat(
+ config.isEnabledForRef(anyUser, projectName, "anyRef",
+ "blockedFileExtension")).isFalse();
+ }
+
+ @Test
+ public void isEnabledForRegexProject() throws Exception {
+ String configString = "[plugin \"uploadvalidator\"]\n"
+ + " project = test.*\n"
+ + " blockedFileExtension = jar";
+ Project.NameKey otherNameKey = new Project.NameKey("someOtherProject");
+ ValidatorConfig config = getConfig(configString, projectName);
+ ValidatorConfig config2 = getConfig(configString, otherNameKey);
+
+ assertThat(
+ config.isEnabledForRef(anyUser, projectName, "anyRef",
+ "blockedFileExtension")).isTrue();
+ assertThat(
+ config2.isEnabledForRef(anyUser, otherNameKey,
+ "anyRef", "blockedFileExtension")).isFalse();
+ }
+
+ @Test
+ public void isEnabledForMultipleProjects() throws Exception {
+ String configString = "[plugin \"uploadvalidator\"]\n"
+ + " project = testProject\n"
+ + " project = another.*\n"
+ + " blockedFileExtension = jar";
+ Project.NameKey anotherNameKey = new Project.NameKey("anotherProject");
+ Project.NameKey someOtherNameKey = new Project.NameKey("someOtherProject");
+ ValidatorConfig config = getConfig(configString, projectName);
+ ValidatorConfig config2 = getConfig(configString, anotherNameKey);
+ ValidatorConfig config3 = getConfig(configString, someOtherNameKey);
+
+ assertThat(
+ config.isEnabledForRef(anyUser, projectName, "anyRef",
+ "blockedFileExtension")).isTrue();
+ assertThat(
+ config2.isEnabledForRef(anyUser, anotherNameKey, "anyRef",
+ "blockedFileExtension")).isTrue();
+ assertThat(
+ config3.isEnabledForRef(anyUser, someOtherNameKey, "anyRef",
+ "blockedFileExtension")).isFalse();
+ }
+
+ private ValidatorConfig getConfig(
+ String defaultConfig, Project.NameKey projName)
+ throws ConfigInvalidException {
+ ValidatorConfig config =
+ new ValidatorConfig(new FakeConfigFactory(projName, defaultConfig),
+ new FakeGroupCacheUUIDByName());
+ return config;
+ }
+}