Make uploadvalidator ref-aware
Add support to limit validation on specific refs.
feature: issue 5230
Change-Id: Iba99d6dd73c403857faaa9aeb7aff4d1de1bb591
diff --git a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/BlockedKeywordValidator.java b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/BlockedKeywordValidator.java
index b6c581c..cf6f31a 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/BlockedKeywordValidator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/BlockedKeywordValidator.java
@@ -83,18 +83,21 @@
private final GitRepositoryManager repoManager;
private final LoadingCache<String, Pattern> patternCache;
private final ContentTypeUtil contentTypeUtil;
+ private final ValidatorConfig validatorConfig;
@Inject
BlockedKeywordValidator(@PluginName String pluginName,
ContentTypeUtil contentTypeUtil,
@Named(CACHE_NAME) LoadingCache<String, Pattern> patternCache,
PluginConfigFactory cfgFactory,
- GitRepositoryManager repoManager) {
+ GitRepositoryManager repoManager,
+ ValidatorConfig validatorConfig) {
this.pluginName = pluginName;
this.patternCache = patternCache;
this.cfgFactory = cfgFactory;
this.repoManager = repoManager;
this.contentTypeUtil = contentTypeUtil;
+ this.validatorConfig = validatorConfig;
}
static boolean isActive(PluginConfig cfg) {
@@ -108,20 +111,20 @@
PluginConfig cfg = cfgFactory
.getFromProjectConfigWithInheritance(
receiveEvent.project.getNameKey(), pluginName);
- if (!isActive(cfg)) {
- return Collections.emptyList();
- }
- ImmutableMap<String, Pattern> blockedKeywordPatterns =
- patternCache.getAll(Arrays
- .asList(cfg.getStringList(KEY_CHECK_BLOCKED_KEYWORD_PATTERN)));
- try (Repository repo =
- repoManager.openRepository(receiveEvent.project.getNameKey())) {
- List<CommitValidationMessage> messages =
- performValidation(repo, receiveEvent.commit,
- blockedKeywordPatterns.values(), cfg);
- if (!messages.isEmpty()) {
- throw new CommitValidationException(
- "includes files containing blocked keywords", messages);
+ if (isActive(cfg) && validatorConfig.isEnabledForRef(
+ receiveEvent.getProjectNameKey(), receiveEvent.getRefName())) {
+ ImmutableMap<String, Pattern> blockedKeywordPatterns =
+ patternCache.getAll(Arrays
+ .asList(cfg.getStringList(KEY_CHECK_BLOCKED_KEYWORD_PATTERN)));
+ try (Repository repo =
+ repoManager.openRepository(receiveEvent.project.getNameKey())) {
+ List<CommitValidationMessage> messages =
+ performValidation(repo, receiveEvent.commit,
+ blockedKeywordPatterns.values(), cfg);
+ if (!messages.isEmpty()) {
+ throw new CommitValidationException(
+ "includes files containing blocked keywords", messages);
+ }
}
}
} catch (NoSuchProjectException | IOException | ExecutionException e) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/ConfigFactory.java b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/ConfigFactory.java
new file mode 100644
index 0000000..7f80460
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/ConfigFactory.java
@@ -0,0 +1,23 @@
+// 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 com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.server.config.PluginConfig;
+
+public interface ConfigFactory {
+
+ public PluginConfig get(Project.NameKey projectName);
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/ContentTypeValidator.java b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/ContentTypeValidator.java
index ee598c3..d137252 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/ContentTypeValidator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/ContentTypeValidator.java
@@ -92,16 +92,19 @@
private final PluginConfigFactory cfgFactory;
private final GitRepositoryManager repoManager;
private final ContentTypeUtil contentTypeUtil;
+ private final ValidatorConfig validatorConfig;
@Inject
ContentTypeValidator(@PluginName String pluginName,
ContentTypeUtil contentTypeUtil,
PluginConfigFactory cfgFactory,
- GitRepositoryManager repoManager) {
+ GitRepositoryManager repoManager,
+ ValidatorConfig validatorConfig) {
this.pluginName = pluginName;
this.contentTypeUtil = contentTypeUtil;
this.cfgFactory = cfgFactory;
this.repoManager = repoManager;
+ this.validatorConfig = validatorConfig;
}
@Override
@@ -111,17 +114,17 @@
PluginConfig cfg = cfgFactory
.getFromProjectConfigWithInheritance(
receiveEvent.project.getNameKey(), pluginName);
- if (!isActive(cfg)) {
- return Collections.emptyList();
- }
- try (Repository repo =
- repoManager.openRepository(receiveEvent.project.getNameKey())) {
- List<CommitValidationMessage> messages =
- performValidation(repo, receiveEvent.commit, getBlockedTypes(cfg),
- isWhitelist(cfg));
- if (!messages.isEmpty()) {
- throw new CommitValidationException("contains blocked content type",
- messages);
+ if (isActive(cfg) && validatorConfig.isEnabledForRef(
+ receiveEvent.getProjectNameKey(), receiveEvent.getRefName())) {
+ try (Repository repo =
+ repoManager.openRepository(receiveEvent.project.getNameKey())) {
+ List<CommitValidationMessage> messages =
+ performValidation(repo, receiveEvent.commit, getBlockedTypes(cfg),
+ isWhitelist(cfg));
+ if (!messages.isEmpty()) {
+ throw new CommitValidationException("contains blocked content type",
+ messages);
+ }
}
}
} catch (NoSuchProjectException | IOException | ExecutionException e) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/DuplicatePathnameValidator.java b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/DuplicatePathnameValidator.java
index 75c18d2..3a44758 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/DuplicatePathnameValidator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/DuplicatePathnameValidator.java
@@ -145,6 +145,7 @@
private final String pluginName;
private final PluginConfigFactory cfgFactory;
private final GitRepositoryManager repoManager;
+ private final ValidatorConfig validatorConfig;
private Locale locale;
@@ -155,10 +156,12 @@
@Inject
DuplicatePathnameValidator(@PluginName String pluginName,
- PluginConfigFactory cfgFactory, GitRepositoryManager repoManager) {
+ PluginConfigFactory cfgFactory, GitRepositoryManager repoManager,
+ ValidatorConfig validatorConfig) {
this.pluginName = pluginName;
this.cfgFactory = cfgFactory;
this.repoManager = repoManager;
+ this.validatorConfig = validatorConfig;
}
@Override
@@ -168,17 +171,17 @@
PluginConfig cfg = cfgFactory
.getFromProjectConfigWithInheritance(
receiveEvent.project.getNameKey(), pluginName);
- if (!isActive(cfg)) {
- return Collections.emptyList();
- }
- locale = getLocale(cfg);
- try (Repository repo =
- repoManager.openRepository(receiveEvent.project.getNameKey())) {
- List<CommitValidationMessage> messages =
- performValidation(repo, receiveEvent.commit);
- if (!messages.isEmpty()) {
- throw new CommitValidationException("contains duplicate pathnames",
- messages);
+ if (isActive(cfg) && validatorConfig.isEnabledForRef(
+ receiveEvent.getProjectNameKey(), receiveEvent.getRefName())) {
+ locale = getLocale(cfg);
+ try (Repository repo =
+ repoManager.openRepository(receiveEvent.project.getNameKey())) {
+ List<CommitValidationMessage> messages =
+ performValidation(repo, receiveEvent.commit);
+ if (!messages.isEmpty()) {
+ throw new CommitValidationException("contains duplicate pathnames",
+ messages);
+ }
}
}
} catch (NoSuchProjectException | IOException e) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/FileExtensionValidator.java b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/FileExtensionValidator.java
index 3f455bd..3e61ee6 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/FileExtensionValidator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/FileExtensionValidator.java
@@ -64,13 +64,16 @@
private final String pluginName;
private final PluginConfigFactory cfgFactory;
private final GitRepositoryManager repoManager;
+ private final ValidatorConfig validatorConfig;
@Inject
FileExtensionValidator(@PluginName String pluginName,
- PluginConfigFactory cfgFactory, GitRepositoryManager repoManager) {
+ PluginConfigFactory cfgFactory, GitRepositoryManager repoManager,
+ ValidatorConfig validatorConfig) {
this.pluginName = pluginName;
this.cfgFactory = cfgFactory;
this.repoManager = repoManager;
+ this.validatorConfig = validatorConfig;
}
private static List<String> getBlockedExtensions(PluginConfig cfg) {
@@ -92,16 +95,16 @@
PluginConfig cfg = cfgFactory
.getFromProjectConfigWithInheritance(
receiveEvent.project.getNameKey(), pluginName);
- if (!isActive(cfg)) {
- return Collections.emptyList();
- }
- try (Repository repo =
- repoManager.openRepository(receiveEvent.project.getNameKey())) {
- List<CommitValidationMessage> messages = performValidation(repo,
- receiveEvent.commit, getBlockedExtensions(cfg));
- if (!messages.isEmpty()) {
- throw new CommitValidationException(
- "contains files with blocked file extensions", messages);
+ if (isActive(cfg) && validatorConfig.isEnabledForRef(
+ receiveEvent.getProjectNameKey(), receiveEvent.getRefName())) {
+ try (Repository repo =
+ repoManager.openRepository(receiveEvent.project.getNameKey())) {
+ List<CommitValidationMessage> messages = performValidation(repo,
+ receiveEvent.commit, getBlockedExtensions(cfg));
+ if (!messages.isEmpty()) {
+ throw new CommitValidationException(
+ "contains files with blocked file extensions", messages);
+ }
}
}
} catch (NoSuchProjectException | IOException e) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/FooterValidator.java b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/FooterValidator.java
index 420e47a..3c466d8 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/FooterValidator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/FooterValidator.java
@@ -62,11 +62,14 @@
private final String pluginName;
private final PluginConfigFactory cfgFactory;
+ private final ValidatorConfig validatorConfig;
@Inject
- FooterValidator(@PluginName String pluginName, PluginConfigFactory cfgFactory) {
+ FooterValidator(@PluginName String pluginName, PluginConfigFactory cfgFactory,
+ ValidatorConfig validatorConfig) {
this.pluginName = pluginName;
this.cfgFactory = cfgFactory;
+ this.validatorConfig = validatorConfig;
}
@Override
@@ -78,7 +81,8 @@
receiveEvent.project.getNameKey(), pluginName);
String[] requiredFooters =
cfg.getStringList(KEY_REQUIRED_FOOTER);
- if (requiredFooters.length > 0) {
+ if (requiredFooters.length > 0 && validatorConfig.isEnabledForRef(
+ receiveEvent.getProjectNameKey(), receiveEvent.getRefName())) {
List<CommitValidationMessage> messages = new LinkedList<>();
Set<String> footers = FluentIterable.from(receiveEvent.commit.getFooterLines())
.transform(new Function<FooterLine, String>() {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/InvalidFilenameValidator.java b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/InvalidFilenameValidator.java
index 973be15..d912f5c 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/InvalidFilenameValidator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/InvalidFilenameValidator.java
@@ -64,13 +64,16 @@
private final String pluginName;
private final PluginConfigFactory cfgFactory;
private final GitRepositoryManager repoManager;
+ private final ValidatorConfig validatorConfig;
@Inject
InvalidFilenameValidator(@PluginName String pluginName,
- PluginConfigFactory cfgFactory, GitRepositoryManager repoManager) {
+ PluginConfigFactory cfgFactory, GitRepositoryManager repoManager,
+ ValidatorConfig validatorConfig) {
this.pluginName = pluginName;
this.cfgFactory = cfgFactory;
this.repoManager = repoManager;
+ this.validatorConfig = validatorConfig;
}
static boolean isActive(PluginConfig cfg) {
@@ -84,17 +87,17 @@
PluginConfig cfg =
cfgFactory.getFromProjectConfigWithInheritance(
receiveEvent.project.getNameKey(), pluginName);
- if (!isActive(cfg)) {
- return Collections.emptyList();
- }
- try (Repository repo = repoManager.openRepository(
- receiveEvent.project.getNameKey())) {
- List<CommitValidationMessage> messages =
- performValidation(repo, receiveEvent.commit,
- cfg.getStringList(KEY_INVALID_FILENAME_PATTERN));
- if (!messages.isEmpty()) {
- throw new CommitValidationException(
- "contains files with an invalid filename", messages);
+ if (isActive(cfg) && validatorConfig.isEnabledForRef(
+ receiveEvent.getProjectNameKey(), receiveEvent.getRefName())) {
+ try (Repository repo = repoManager.openRepository(
+ receiveEvent.project.getNameKey())) {
+ List<CommitValidationMessage> messages =
+ performValidation(repo, receiveEvent.commit,
+ cfg.getStringList(KEY_INVALID_FILENAME_PATTERN));
+ if (!messages.isEmpty()) {
+ throw new CommitValidationException(
+ "contains files with an invalid filename", messages);
+ }
}
}
} catch (NoSuchProjectException | IOException e) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/InvalidLineEndingValidator.java b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/InvalidLineEndingValidator.java
index 7183b69..8e50232 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/InvalidLineEndingValidator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/InvalidLineEndingValidator.java
@@ -73,16 +73,19 @@
private final PluginConfigFactory cfgFactory;
private final GitRepositoryManager repoManager;
private final ContentTypeUtil contentTypeUtil;
+ private final ValidatorConfig validatorConfig;
@Inject
InvalidLineEndingValidator(@PluginName String pluginName,
ContentTypeUtil contentTypeUtil,
PluginConfigFactory cfgFactory,
- GitRepositoryManager repoManager) {
+ GitRepositoryManager repoManager,
+ ValidatorConfig validatorConfig) {
this.pluginName = pluginName;
this.cfgFactory = cfgFactory;
this.repoManager = repoManager;
this.contentTypeUtil = contentTypeUtil;
+ this.validatorConfig = validatorConfig;
}
static boolean isActive(PluginConfig cfg) {
@@ -96,16 +99,16 @@
PluginConfig cfg =
cfgFactory.getFromProjectConfigWithInheritance(
receiveEvent.project.getNameKey(), pluginName);
- if (!isActive(cfg)) {
- return Collections.emptyList();
- }
- try (Repository repo =
- repoManager.openRepository(receiveEvent.project.getNameKey())) {
- List<CommitValidationMessage> messages =
- performValidation(repo, receiveEvent.commit, cfg);
- if (!messages.isEmpty()) {
- throw new CommitValidationException(
- "contains files with a Windows line ending", messages);
+ if (isActive(cfg) && validatorConfig.isEnabledForRef(
+ receiveEvent.getProjectNameKey(), receiveEvent.getRefName())) {
+ try (Repository repo =
+ repoManager.openRepository(receiveEvent.project.getNameKey())) {
+ List<CommitValidationMessage> messages =
+ performValidation(repo, receiveEvent.commit, cfg);
+ if (!messages.isEmpty()) {
+ throw new CommitValidationException(
+ "contains files with a Windows line ending", messages);
+ }
}
}
} catch (NoSuchProjectException | IOException | ExecutionException e) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/MaxPathLengthValidator.java b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/MaxPathLengthValidator.java
index aa898dd..f13d16b 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/MaxPathLengthValidator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/MaxPathLengthValidator.java
@@ -61,13 +61,16 @@
private final String pluginName;
private final PluginConfigFactory cfgFactory;
private final GitRepositoryManager repoManager;
+ private final ValidatorConfig validatorConfig;
@Inject
MaxPathLengthValidator(@PluginName String pluginName,
- PluginConfigFactory cfgFactory, GitRepositoryManager repoManager) {
+ PluginConfigFactory cfgFactory, GitRepositoryManager repoManager,
+ ValidatorConfig validatorConfig) {
this.pluginName = pluginName;
this.cfgFactory = cfgFactory;
this.repoManager = repoManager;
+ this.validatorConfig = validatorConfig;
}
static boolean isActive(PluginConfig cfg) {
@@ -81,18 +84,18 @@
PluginConfig cfg =
cfgFactory.getFromProjectConfigWithInheritance(
receiveEvent.project.getNameKey(), pluginName);
- if (!isActive(cfg)) {
- return Collections.emptyList();
- }
- int maxPathLength = cfg.getInt(KEY_MAX_PATH_LENGTH, 0);
- try (Repository repo =
- repoManager.openRepository(receiveEvent.project.getNameKey())) {
- List<CommitValidationMessage> messages =
- performValidation(repo, receiveEvent.commit, maxPathLength);
- if (!messages.isEmpty()) {
- throw new CommitValidationException(
- "contains files with too long paths (max path length: "
- + maxPathLength + ")", messages);
+ if (isActive(cfg) && validatorConfig.isEnabledForRef(
+ receiveEvent.getProjectNameKey(), receiveEvent.getRefName())) {
+ int maxPathLength = cfg.getInt(KEY_MAX_PATH_LENGTH, 0);
+ try (Repository repo =
+ repoManager.openRepository(receiveEvent.project.getNameKey())) {
+ List<CommitValidationMessage> messages =
+ performValidation(repo, receiveEvent.commit, maxPathLength);
+ if (!messages.isEmpty()) {
+ throw new CommitValidationException(
+ "contains files with too long paths (max path length: "
+ + maxPathLength + ")", messages);
+ }
}
}
} catch (NoSuchProjectException | IOException e) {
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 a3cbfc4..b1cba3c 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/Module.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/Module.java
@@ -15,6 +15,7 @@
package com.googlesource.gerrit.plugins.uploadvalidator;
import com.google.inject.AbstractModule;
+import com.google.inject.Scopes;
class Module extends AbstractModule {
@@ -33,5 +34,8 @@
install(InvalidLineEndingValidator.module());
install(ContentTypeValidator.module());
install(DuplicatePathnameValidator.module());
+
+ bind(ConfigFactory.class).to(PluginConfigWithInheritanceFactory.class).in(
+ Scopes.SINGLETON);
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/PluginConfigWithInheritanceFactory.java b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/PluginConfigWithInheritanceFactory.java
new file mode 100644
index 0000000..1e90f2c
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/PluginConfigWithInheritanceFactory.java
@@ -0,0 +1,49 @@
+// 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 com.google.gerrit.extensions.annotations.PluginName;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.server.config.PluginConfig;
+import com.google.gerrit.server.config.PluginConfigFactory;
+import com.google.gerrit.server.project.NoSuchProjectException;
+import com.google.inject.Inject;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PluginConfigWithInheritanceFactory implements ConfigFactory {
+ private static final Logger log = LoggerFactory.getLogger(PluginConfigWithInheritanceFactory.class);
+ private final PluginConfigFactory pluginConfigFactory;
+ private final String pluginName;
+
+ @Inject
+ public PluginConfigWithInheritanceFactory(PluginConfigFactory pcf,
+ @PluginName String pn) {
+ this.pluginConfigFactory = pcf;
+ this.pluginName = pn;
+ }
+
+ @Override
+ public PluginConfig get(Project.NameKey projectName) {
+ try {
+ return pluginConfigFactory.getFromProjectConfigWithInheritance(projectName,
+ pluginName);
+ } catch (NoSuchProjectException e) {
+ log.warn(projectName.get() + " not found");
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/SubmoduleValidator.java b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/SubmoduleValidator.java
index b58418d..e1a492f 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/SubmoduleValidator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/SubmoduleValidator.java
@@ -63,13 +63,16 @@
private final String pluginName;
private final PluginConfigFactory cfgFactory;
private final GitRepositoryManager repoManager;
+ private final ValidatorConfig validatorConfig;
@Inject
SubmoduleValidator(@PluginName String pluginName,
- PluginConfigFactory cfgFactory, GitRepositoryManager repoManager) {
+ PluginConfigFactory cfgFactory, GitRepositoryManager repoManager,
+ ValidatorConfig validatorConfig) {
this.pluginName = pluginName;
this.cfgFactory = cfgFactory;
this.repoManager = repoManager;
+ this.validatorConfig = validatorConfig;
}
static boolean isActive(PluginConfig cfg) {
@@ -83,15 +86,15 @@
PluginConfig cfg = cfgFactory
.getFromProjectConfigWithInheritance(
receiveEvent.project.getNameKey(), pluginName);
- if (!isActive(cfg)) {
- return Collections.emptyList();
- }
- try (Repository repo =
- repoManager.openRepository(receiveEvent.project.getNameKey())) {
- List<CommitValidationMessage> messages =
- performValidation(repo, receiveEvent.commit);
- if (!messages.isEmpty()) {
- throw new CommitValidationException("contains submodules", messages);
+ if (isActive(cfg) && validatorConfig.isEnabledForRef(
+ receiveEvent.getProjectNameKey(), receiveEvent.getRefName())) {
+ try (Repository repo =
+ repoManager.openRepository(receiveEvent.project.getNameKey())) {
+ List<CommitValidationMessage> messages =
+ performValidation(repo, receiveEvent.commit);
+ if (!messages.isEmpty()) {
+ throw new CommitValidationException("contains submodules", messages);
+ }
}
}
} catch (NoSuchProjectException | IOException e) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/SymlinkValidator.java b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/SymlinkValidator.java
index b5a090d..f3c4123 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/SymlinkValidator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/SymlinkValidator.java
@@ -64,13 +64,16 @@
private final String pluginName;
private final PluginConfigFactory cfgFactory;
private final GitRepositoryManager repoManager;
+ private final ValidatorConfig validatorConfig;
@Inject
SymlinkValidator(@PluginName String pluginName,
- PluginConfigFactory cfgFactory, GitRepositoryManager repoManager) {
+ PluginConfigFactory cfgFactory, GitRepositoryManager repoManager,
+ ValidatorConfig validatorConfig) {
this.pluginName = pluginName;
this.cfgFactory = cfgFactory;
this.repoManager = repoManager;
+ this.validatorConfig = validatorConfig;
}
static boolean isActive(PluginConfig cfg) {
@@ -84,16 +87,16 @@
PluginConfig cfg =
cfgFactory.getFromProjectConfigWithInheritance(
receiveEvent.project.getNameKey(), pluginName);
- if (!isActive(cfg)) {
- return Collections.emptyList();
- }
- try (Repository repo =
- repoManager.openRepository(receiveEvent.project.getNameKey())) {
- List<CommitValidationMessage> messages =
- performValidation(repo, receiveEvent.commit);
- if (!messages.isEmpty()) {
- throw new CommitValidationException("contains symbolic links",
- messages);
+ if (isActive(cfg) && validatorConfig.isEnabledForRef(
+ receiveEvent.getProjectNameKey(), receiveEvent.getRefName())) {
+ try (Repository repo =
+ repoManager.openRepository(receiveEvent.project.getNameKey())) {
+ List<CommitValidationMessage> messages =
+ performValidation(repo, receiveEvent.commit);
+ if (!messages.isEmpty()) {
+ throw new CommitValidationException("contains symbolic links",
+ messages);
+ }
}
}
} catch (NoSuchProjectException | IOException e) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/ValidatorConfig.java b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/ValidatorConfig.java
new file mode 100644
index 0000000..3a48288
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/uploadvalidator/ValidatorConfig.java
@@ -0,0 +1,78 @@
+// 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 com.google.gerrit.common.data.RefConfigSection;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.server.config.PluginConfig;
+import com.google.gerrit.server.project.RefPatternMatcher;
+import com.google.inject.Inject;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ValidatorConfig {
+ private static final Logger log = LoggerFactory
+ .getLogger(ValidatorConfig.class);
+
+ private final ConfigFactory configFactory;
+
+ @Inject
+ public ValidatorConfig(ConfigFactory configFactory) {
+ this.configFactory = configFactory;
+ }
+
+ public boolean isEnabledForRef(Project.NameKey projectName, String refName) {
+ PluginConfig pluginConfig = configFactory.get(projectName);
+ if (pluginConfig == null) {
+ log.error("Failed to check if validation is enabled for project "
+ + projectName.get() + ": Plugin config not found");
+ return false;
+ }
+ if(!isValidConfig(pluginConfig, projectName)) {
+ return false;
+ }
+
+ String[] refPatterns = pluginConfig.getStringList("ref");
+ if (refPatterns.length == 0) {
+ return true; // Default behavior: no branch-specific config
+ }
+
+ for (String refPattern : refPatterns) {
+ if (match(refName, refPattern)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isValidConfig(PluginConfig config, Project.NameKey projectName) {
+ boolean valid = true;
+ for (String refPattern : config.getStringList("ref")) {
+ if (!RefConfigSection.isValid(refPattern)) {
+ log.error(
+ "Invalid ref name/pattern/regex '{}' in {} project's plugin config",
+ refPattern, projectName.get());
+ valid = false;
+ }
+ }
+
+ return valid;
+ }
+
+ private static boolean match(String refName, String refPattern) {
+ return RefPatternMatcher.getMatcher(refPattern).match(refName, null);
+ }
+}
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md
index 2fafca7..f958126 100644
--- a/src/main/resources/Documentation/config.md
+++ b/src/main/resources/Documentation/config.md
@@ -206,3 +206,24 @@
[Project's inheritance rules][7].
[7]: config-project-config.html#file-project_config
+
+Ref-specific validations
+---------------------------
+
+By default, the validation will be enabled for all refs. However, it can
+be limited to particular refs by setting `plugin.@PLUGIN@.ref`. The
+refs may be configured using specific ref names, ref patterns, or regular
+expressions. Multiple refs may be specified.
+
+NOTE: ref needs to start with "ref/" for name and pattern or "^ref/" for regex
+matching. When an invalid ref is specified in the Project config, the plugin
+functionality is disabled, and an error is reported in the Gerrit log.
+
+E.g. to limit the validation to the `master` branch and all stable
+branches the following could be configured:
+
+```
+ [plugin "@PLUGIN@"]
+ ref = refs/heads/master
+ ref = ^refs/heads/stable-.*
+```
diff --git a/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/BlockedKeywordValidatorTest.java b/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/BlockedKeywordValidatorTest.java
index 5f066ed..0a2722f 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/BlockedKeywordValidatorTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/BlockedKeywordValidatorTest.java
@@ -76,7 +76,7 @@
public void testKeywords() throws Exception {
RevCommit c = makeCommit();
BlockedKeywordValidator validator = new BlockedKeywordValidator(null,
- new ContentTypeUtil(PATTERN_CACHE), PATTERN_CACHE, null, null);
+ new ContentTypeUtil(PATTERN_CACHE), PATTERN_CACHE, null, null, null);
List<CommitValidationMessage> m = validator.performValidation(
repo, c, getPatterns().values(), EMPTY_PLUGIN_CONFIG);
Set<String> expected = ImmutableSet.of(
diff --git a/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/ContentTypeValidatorTest.java b/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/ContentTypeValidatorTest.java
index 6d2c373..7a509ce 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/ContentTypeValidatorTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/ContentTypeValidatorTest.java
@@ -58,7 +58,7 @@
@Before
public void setUp() {
validator = new ContentTypeValidator(
- null, new ContentTypeUtil(PATTERN_CACHE), null, null);
+ null, new ContentTypeUtil(PATTERN_CACHE), null, null, null);
}
@Test
diff --git a/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/DuplicatePathnameValidatorTest.java b/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/DuplicatePathnameValidatorTest.java
index f3be61b..5ebb53f 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/DuplicatePathnameValidatorTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/DuplicatePathnameValidatorTest.java
@@ -72,7 +72,7 @@
public void init() throws IOException {
super.init();
testRepo = new TestRepository<>(repo);
- validator = new DuplicatePathnameValidator(null, null, null);
+ validator = new DuplicatePathnameValidator(null, null, null, null);
validator.setLocale(Locale.ENGLISH);
}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/FakeConfigFactory.java b/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/FakeConfigFactory.java
new file mode 100644
index 0000000..181810e
--- /dev/null
+++ b/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/FakeConfigFactory.java
@@ -0,0 +1,43 @@
+// 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 com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.Project.NameKey;
+import com.google.gerrit.server.config.PluginConfig;
+
+import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.lib.Config;
+
+public class FakeConfigFactory implements ConfigFactory {
+ private final Config config;
+ private final Project.NameKey projectName;
+
+ public FakeConfigFactory(Project.NameKey projectName, String configText)
+ throws ConfigInvalidException {
+ this.config = new Config();
+ this.config.fromText(configText);
+ this.projectName = projectName;
+ }
+
+ @Override
+ public PluginConfig get(NameKey projectName) {
+ if (this.projectName.equals(projectName)) {
+ return new PluginConfig("uploadvalidator", config);
+ }
+
+ return new PluginConfig("uploadvalidator", new Config());
+ }
+}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/InvalidLineEndingValidatorTest.java b/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/InvalidLineEndingValidatorTest.java
index 3ea1b1b..50981be 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/InvalidLineEndingValidatorTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/InvalidLineEndingValidatorTest.java
@@ -59,7 +59,7 @@
public void testCarriageReturn() throws Exception {
RevCommit c = makeCommit();
InvalidLineEndingValidator validator = new InvalidLineEndingValidator(null,
- new ContentTypeUtil(PATTERN_CACHE), null, null);
+ new ContentTypeUtil(PATTERN_CACHE), null, null, null);
List<CommitValidationMessage> m = validator.performValidation(repo, c,
EMPTY_PLUGIN_CONFIG);
assertThat(TestUtils.transformMessages(m))
diff --git a/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/RefAwareValidatorConfigTest.java b/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/RefAwareValidatorConfigTest.java
new file mode 100644
index 0000000..962963b
--- /dev/null
+++ b/src/test/java/com/googlesource/gerrit/plugins/uploadvalidator/RefAwareValidatorConfigTest.java
@@ -0,0 +1,93 @@
+// 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 com.google.gerrit.reviewdb.client.Project;
+
+import static com.google.common.truth.Truth.*;
+
+import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.junit.Test;
+
+public class RefAwareValidatorConfigTest {
+ private Project.NameKey projectName = new Project.NameKey("testProject");
+
+ @Test
+ public void isEnabledForAllRefsByDefault() throws Exception {
+ ValidatorConfig config =
+ getConfig("[plugin \"uploadvalidator\"]\n"
+ + "blockedFileExtension = jar");
+
+ assertThat(config.isEnabledForRef(projectName, "anyRef")).isTrue();
+ }
+
+ @Test
+ public void isEnabledForSingleRef() throws Exception {
+ ValidatorConfig config =
+ getConfig("[plugin \"uploadvalidator\"]\n"
+ + " ref = refs/heads/anyref\n"
+ + " blockedFileExtension = jar");
+
+ assertThat(config.isEnabledForRef(projectName, "refs/heads/anyref"))
+ .isTrue();
+ }
+
+ @Test
+ public void isDisabledForInvalidRef() throws Exception {
+ ValidatorConfig config =
+ getConfig("[plugin \"uploadvalidator\"]\n"
+ + " ref = anInvalidRef\n"
+ + " blockedFileExtension = jar");
+
+ assertThat(config.isEnabledForRef(projectName, "refs/heads/anyref"))
+ .isFalse();
+ }
+
+ @Test
+ public void isEnabledForRegexRef() throws Exception {
+ ValidatorConfig config =
+ getConfig("[plugin \"uploadvalidator\"]\n"
+ + " ref = ^refs/heads/mybranch.*\n"
+ + " blockedFileExtension = jar");
+
+ assertThat(config.isEnabledForRef(projectName, "refs/heads/anotherref"))
+ .isFalse();
+ assertThat(config.isEnabledForRef(projectName, "refs/heads/mybranch123"))
+ .isTrue();
+ }
+
+ @Test
+ public void isEnabledForMultipleRefs() throws Exception {
+ ValidatorConfig config =
+ getConfig("[plugin \"uploadvalidator\"]\n"
+ + " ref = refs/heads/branch1\n"
+ + " ref = refs/heads/branch2\n"
+ + " blockedFileExtension = jar");
+
+ assertThat(config.isEnabledForRef(projectName, "refs/heads/branch1"))
+ .isTrue();
+ assertThat(config.isEnabledForRef(projectName, "refs/heads/branch2"))
+ .isTrue();
+ assertThat(config.isEnabledForRef(projectName, "refs/heads/branch3"))
+ .isFalse();
+ }
+
+ private ValidatorConfig getConfig(String defaultConfig)
+ throws ConfigInvalidException {
+ ValidatorConfig config =
+ new ValidatorConfig(new FakeConfigFactory(projectName, defaultConfig));
+ return config;
+ }
+}