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