Get commentLink w/ association from project.config
Align its-base behaviour with Gerrit hierarchical configuration of
commentLink:
- project.config with inheritance
- gerrit.config as fallback
With regards to the association policy, on project.config is taken
from the plugin-specific section.
Example of gerrit.config association policy:
[plugin "its-jira"]
association = MANDATORY
Change-Id: I7dadb6f0bd6b1952fdc18d8c24ead36cca33ae9d
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/base/its/ItsConfig.java b/src/main/java/com/googlesource/gerrit/plugins/its/base/its/ItsConfig.java
index 1241b8a..17d31a1 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/its/base/its/ItsConfig.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/base/its/ItsConfig.java
@@ -14,9 +14,14 @@
package com.googlesource.gerrit.plugins.its.base.its;
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.FluentIterable;
import com.google.gerrit.common.data.RefConfigSection;
import com.google.gerrit.extensions.annotations.PluginName;
+import com.google.gerrit.extensions.api.projects.CommentLinkInfo;
import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.Project.NameKey;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.PluginConfig;
import com.google.gerrit.server.config.PluginConfigFactory;
@@ -28,6 +33,7 @@
import com.google.gerrit.server.events.Event;
import com.google.gerrit.server.events.PatchSetCreatedEvent;
import com.google.gerrit.server.events.RefUpdatedEvent;
+import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.project.RefPatternMatcher;
@@ -39,10 +45,14 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.Collections;
+import java.util.List;
import java.util.regex.Pattern;
public class ItsConfig {
+ private static final String PLUGIN = "plugin";
+
private static final Logger log = LoggerFactory.getLogger(ItsConfig.class);
private final String pluginName;
@@ -50,6 +60,18 @@
private final PluginConfigFactory pluginCfgFactory;
private final Config gerritConfig;
+ private static final ThreadLocal<Project.NameKey> currentProjectName =
+ new ThreadLocal<Project.NameKey>() {
+ @Override
+ protected Project.NameKey initialValue() {
+ return null;
+ }
+ };
+
+ public static void setCurrentProjectName(Project.NameKey projectName) {
+ currentProjectName.set(projectName);
+ }
+
@Inject
public ItsConfig(@PluginName String pluginName, ProjectCache projectCache,
PluginConfigFactory pluginCfgFactory, @GerritServerConfig Config gerritConfig) {
@@ -148,7 +170,7 @@
public String getCommentLinkName() {
String ret;
- ret = gerritConfig.getString(pluginName, null, "commentlink");
+ ret = getPluginConfigString("commentlink");
if (ret == null) {
ret = pluginName;
}
@@ -166,9 +188,26 @@
* to match issue ids.
*/
public Pattern getIssuePattern() {
+ String match =
+ FluentIterable
+ .from(getCommitLinkInfo(getCommentLinkName()))
+ .filter(new Predicate<CommentLinkInfo>() {
+ @Override
+ public boolean apply(CommentLinkInfo input) {
+ return input.match != null && !input.match.trim().isEmpty();
+ }
+ })
+ .transform(new Function<CommentLinkInfo, String>() {
+ @Override
+ public String apply(CommentLinkInfo input) {
+ return input.match;
+ }
+ })
+ .last()
+ .or(gerritConfig.getString("commentlink", getCommentLinkName(),
+ "match"));
Pattern ret = null;
- String match = gerritConfig.getString("commentlink",
- getCommentLinkName(), "match");
+
if (match != null) {
ret = Pattern.compile(match);
}
@@ -186,7 +225,7 @@
public int getIssuePatternGroupIndex() {
Pattern pattern = getIssuePattern();
int groupCount = pattern.matcher("").groupCount();
- int index = gerritConfig.getInt(pluginName, "commentlinkGroupIndex", 1);
+ int index = getPluginConfigInt("commentlinkGroupIndex", 1);
if (index < 0 || index > groupCount) {
index = (groupCount == 0 ? 0 : 1);
}
@@ -195,14 +234,59 @@
/**
* Gets how necessary it is to associate commits with issues
+ *
* @return policy on how necessary association with issues is
*/
public ItsAssociationPolicy getItsAssociationPolicy() {
- ItsAssociationPolicy legacyAssociatonPolicy =
- gerritConfig.getEnum("commentlink", getCommentLinkName(),
+ ItsAssociationPolicy legacyItsAssociationPolicy =
+ gerritConfig.getEnum("commentLink", getCommentLinkName(),
"association", ItsAssociationPolicy.OPTIONAL);
- return gerritConfig.getEnum("plugin", pluginName, "association",
- legacyAssociatonPolicy);
+ return getPluginConfigEnum("association", legacyItsAssociationPolicy);
+ }
+
+ private String getPluginConfigString(String key) {
+ return getCurrentPluginConfig().getString(key,
+ gerritConfig.getString(PLUGIN, pluginName, key));
+ }
+
+ private int getPluginConfigInt(String key, int defaultValue) {
+ return getCurrentPluginConfig().getInt(key,
+ gerritConfig.getInt(PLUGIN, pluginName, key, defaultValue));
+ }
+
+ private <T extends Enum<?>> T getPluginConfigEnum(String key, T defaultValue) {
+ return getCurrentPluginConfig().getEnum(key,
+ gerritConfig.getEnum(PLUGIN, pluginName, key, defaultValue));
+ }
+
+ private PluginConfig getCurrentPluginConfig() {
+ NameKey projectName = currentProjectName.get();
+ if (projectName != null) {
+ try {
+ return pluginCfgFactory.getFromProjectConfigWithInheritance(
+ projectName, pluginName);
+ } catch (NoSuchProjectException e) {
+ log.error("Cannot access " + projectName + " configuration for plugin "
+ + pluginName, e);
+ }
+ }
+ return new PluginConfig(pluginName, new Config());
+ }
+
+ private List<CommentLinkInfo> getCommitLinkInfo(final String commentLinkName) {
+ NameKey projectName = currentProjectName.get();
+ if (projectName != null) {
+ List<CommentLinkInfo> commentLinks =
+ projectCache.get(projectName).getCommentLinks();
+ return FluentIterable.from(commentLinks)
+ .filter(new Predicate<CommentLinkInfo>() {
+ @Override
+ public boolean apply(CommentLinkInfo input) {
+ return input.name.equals(commentLinkName);
+ }
+ }).toList();
+ }
+ return Collections.emptyList();
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/base/validation/ItsValidateComment.java b/src/main/java/com/googlesource/gerrit/plugins/its/base/validation/ItsValidateComment.java
index 4ce687d..ff2b38a 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/its/base/validation/ItsValidateComment.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/base/validation/ItsValidateComment.java
@@ -143,6 +143,8 @@
@Override
public List<CommitValidationMessage> onCommitReceived(
CommitReceivedEvent receiveEvent) throws CommitValidationException {
+ ItsConfig.setCurrentProjectName(receiveEvent.getProjectNameKey());
+
if (itsConfig.isEnabled(receiveEvent.getProjectNameKey(), receiveEvent.getRefName())) {
return validCommit(receiveEvent.commit);
} else {
diff --git a/src/main/resources/Documentation/config-common.md b/src/main/resources/Documentation/config-common.md
index bf36852..d53b0c6 100644
--- a/src/main/resources/Documentation/config-common.md
+++ b/src/main/resources/Documentation/config-common.md
@@ -68,6 +68,10 @@
You are encouraged to move the association policy to the plugin section, the
commentLink.association will be discontinued in the next major release.
+The association can be overridden at project level in the project.config
+using the same syntax used in the gerrit.config. Project's hierarchy will be respected
+when evaluating the links configuration and association policy.
+
[enabling-its-integration]: #enabling-its-integration
<a name="enabling-its-integration">Enabling ITS integration</a>
---------------------------------------------------------------