Limit the number of paths that are included in change messages
We must ensure that the change message, that is posted on review and in
which we include the approved files, doesn't grow too big for large
changes that touch many files. This is why we limit the number of paths
that are included in the change message. By default we include at most
100 paths, but we allow to configure this limit.
Example change message if the limit is exceeded:
"By voting Code-Review+1 the following files are now code-owner
approved by John Doe:
* bar/baz.foo
* bar/foo.baz
(2 more files)"
By setting the limit to 0, including affected paths into change messages
can also be disabled.
Change-Id: I5cbaec24ef54973f3dfea7e05091b80d5f9df369
Signed-off-by: Edwin Kempin <ekempin@google.com>
diff --git a/java/com/google/gerrit/plugins/codeowners/backend/CodeOwnersOnPostReview.java b/java/com/google/gerrit/plugins/codeowners/backend/CodeOwnersOnPostReview.java
index 376c483..61574f4 100644
--- a/java/com/google/gerrit/plugins/codeowners/backend/CodeOwnersOnPostReview.java
+++ b/java/com/google/gerrit/plugins/codeowners/backend/CodeOwnersOnPostReview.java
@@ -98,6 +98,12 @@
Map<String, Short> oldApprovals,
Map<String, Short> approvals,
RequiredApproval requiredApproval) {
+ int maxPathsInChangeMessage =
+ codeOwnersPluginConfiguration.getMaxPathsInChangeMessages(changeNotes.getProjectName());
+ if (maxPathsInChangeMessage <= 0) {
+ return Optional.empty();
+ }
+
LabelVote newVote = getNewVote(requiredApproval, approvals);
ImmutableList<Path> ownedPaths = getOwnedPaths(changeNotes, user.getAccountId());
@@ -172,7 +178,14 @@
return Optional.empty();
}
- ownedPaths.forEach(path -> message.append(String.format("* %s\n", JgitPath.of(path).get())));
+ if (ownedPaths.size() <= maxPathsInChangeMessage) {
+ appendPaths(message, ownedPaths.stream());
+ } else {
+ // -1 so that we never show "(1 more files)"
+ int limit = maxPathsInChangeMessage - 1;
+ appendPaths(message, ownedPaths.stream().limit(limit));
+ message.append(String.format("(%s more files)\n", ownedPaths.size() - limit));
+ }
if (hasImplicitApprovalByUser && noLongerExplicitlyApproved) {
message.append(
@@ -183,6 +196,10 @@
return Optional.of(message.toString());
}
+ private void appendPaths(StringBuilder message, Stream<Path> pathsToAppend) {
+ pathsToAppend.forEach(path -> message.append(String.format("* %s\n", JgitPath.of(path).get())));
+ }
+
private boolean isCodeOwnerApprovalNewlyApplied(
RequiredApproval requiredApproval, Map<String, Short> oldApprovals, LabelVote newVote) {
String labelName = requiredApproval.labelType().getName();
diff --git a/java/com/google/gerrit/plugins/codeowners/config/CodeOwnersPluginConfiguration.java b/java/com/google/gerrit/plugins/codeowners/config/CodeOwnersPluginConfiguration.java
index 1a7985d..f55642b 100644
--- a/java/com/google/gerrit/plugins/codeowners/config/CodeOwnersPluginConfiguration.java
+++ b/java/com/google/gerrit/plugins/codeowners/config/CodeOwnersPluginConfiguration.java
@@ -166,6 +166,17 @@
}
/**
+ * Gets the max paths in change messages for the given project.
+ *
+ * @param project the project for which the fallback code owners should be retrieved
+ * @return the fallback code owners for the given project
+ */
+ public int getMaxPathsInChangeMessages(Project.NameKey project) {
+ requireNonNull(project, "project");
+ return generalConfig.getMaxPathsInChangeMessages(project, getPluginConfig(project));
+ }
+
+ /**
* Checks whether an implicit code owner approval from the last uploader is assumed.
*
* @param project the project for it should be checked whether implict approvals are enabled
diff --git a/java/com/google/gerrit/plugins/codeowners/config/GeneralConfig.java b/java/com/google/gerrit/plugins/codeowners/config/GeneralConfig.java
index 85fd19a..cafe8e7 100644
--- a/java/com/google/gerrit/plugins/codeowners/config/GeneralConfig.java
+++ b/java/com/google/gerrit/plugins/codeowners/config/GeneralConfig.java
@@ -69,6 +69,9 @@
@VisibleForTesting
public static final String KEY_ENABLE_VALIDATION_ON_SUBMIT = "enableValidationOnSubmit";
+ @VisibleForTesting
+ public static final String KEY_MAX_PATHS_IN_CHANGE_MESSAGES = "maxPathsInChangeMessages";
+
@VisibleForTesting public static final String KEY_MERGE_COMMIT_STRATEGY = "mergeCommitStrategy";
@VisibleForTesting public static final String KEY_GLOBAL_CODE_OWNER = "globalCodeOwner";
@@ -77,6 +80,8 @@
@VisibleForTesting public static final String KEY_OVERRIDE_INFO_URL = "overrideInfoUrl";
+ @VisibleForTesting static final int DEFAULT_MAX_PATHS_IN_CHANGE_MESSAGES = 100;
+
private final String pluginName;
private final PluginConfig pluginConfigFromGerritConfig;
@@ -141,6 +146,29 @@
ValidationMessage.Type.ERROR));
}
+ try {
+ projectLevelConfig
+ .getConfig()
+ .getInt(
+ SECTION_CODE_OWNERS,
+ null,
+ KEY_MAX_PATHS_IN_CHANGE_MESSAGES,
+ DEFAULT_MAX_PATHS_IN_CHANGE_MESSAGES);
+ } catch (IllegalArgumentException e) {
+ validationMessages.add(
+ new CommitValidationMessage(
+ String.format(
+ "The value for max paths in change messages '%s' that is configured in %s"
+ + " (parameter %s.%s) is invalid.",
+ projectLevelConfig
+ .getConfig()
+ .getString(SECTION_CODE_OWNERS, null, KEY_MAX_PATHS_IN_CHANGE_MESSAGES),
+ fileName,
+ SECTION_CODE_OWNERS,
+ KEY_MAX_PATHS_IN_CHANGE_MESSAGES),
+ ValidationMessage.Type.ERROR));
+ }
+
return ImmutableList.copyOf(validationMessages);
}
@@ -237,6 +265,51 @@
}
/**
+ * Gets the maximum number of paths that should be incuded in change messages.
+ *
+ * @param project the project for which the maximum number of paths in change messages should be
+ * read
+ * @param pluginConfig the plugin config from which the maximum number of paths in change messages
+ * should be read
+ * @return the maximum number of paths in change messages
+ */
+ int getMaxPathsInChangeMessages(Project.NameKey project, Config pluginConfig) {
+ requireNonNull(project, "project");
+ requireNonNull(pluginConfig, "pluginConfig");
+
+ String maxPathInChangeMessagesString =
+ pluginConfig.getString(SECTION_CODE_OWNERS, null, KEY_MAX_PATHS_IN_CHANGE_MESSAGES);
+ if (maxPathInChangeMessagesString != null) {
+ try {
+ return pluginConfig.getInt(
+ SECTION_CODE_OWNERS,
+ null,
+ KEY_MAX_PATHS_IN_CHANGE_MESSAGES,
+ DEFAULT_MAX_PATHS_IN_CHANGE_MESSAGES);
+ } catch (IllegalArgumentException e) {
+ logger.atWarning().log(
+ "Ignoring invalid value %s for max paths in change messages in '%s.config' of"
+ + " project %s. Falling back to global config.",
+ maxPathInChangeMessagesString, pluginName, project.get());
+ }
+ }
+
+ try {
+ return pluginConfigFromGerritConfig.getInt(
+ KEY_MAX_PATHS_IN_CHANGE_MESSAGES, DEFAULT_MAX_PATHS_IN_CHANGE_MESSAGES);
+ } catch (IllegalArgumentException e) {
+ logger.atWarning().log(
+ "Ignoring invalid value %s for max paths in change messages in gerrit.config (parameter"
+ + " plugin.%s.%s). Falling back to default value %s.",
+ pluginConfigFromGerritConfig.getString(KEY_MAX_PATHS_IN_CHANGE_MESSAGES),
+ pluginName,
+ KEY_MAX_PATHS_IN_CHANGE_MESSAGES,
+ DEFAULT_MAX_PATHS_IN_CHANGE_MESSAGES);
+ return DEFAULT_MAX_PATHS_IN_CHANGE_MESSAGES;
+ }
+ }
+
+ /**
* Gets the enable validation on commit received configuration from the given plugin config with
* fallback to {@code gerrit.config} and default to {@code true}.
*
diff --git a/javatests/com/google/gerrit/plugins/codeowners/acceptance/api/CodeOwnersOnPostReviewIT.java b/javatests/com/google/gerrit/plugins/codeowners/acceptance/api/CodeOwnersOnPostReviewIT.java
index f3507a9..e17570a 100644
--- a/javatests/com/google/gerrit/plugins/codeowners/acceptance/api/CodeOwnersOnPostReviewIT.java
+++ b/javatests/com/google/gerrit/plugins/codeowners/acceptance/api/CodeOwnersOnPostReviewIT.java
@@ -446,4 +446,124 @@
+ "* %s\n",
admin.fullName(), path));
}
+
+ @Test
+ @GerritConfig(name = "plugin.code-owners.maxPathsInChangeMessages", value = "4")
+ public void pathsInChangeMessageAreLimited_limitNotReached() throws Exception {
+ codeOwnerConfigOperations
+ .newCodeOwnerConfig()
+ .project(project)
+ .branch("master")
+ .folderPath("/")
+ .addCodeOwnerEmail(admin.email())
+ .create();
+
+ String path1 = "foo/bar.baz";
+ String path2 = "foo/baz.bar";
+ String path3 = "bar/foo.baz";
+ String path4 = "bar/baz.foo";
+ String changeId =
+ createChange(
+ "Test Change",
+ ImmutableMap.of(
+ path1,
+ "file content",
+ path2,
+ "file content",
+ path3,
+ "file content",
+ path4,
+ "file content"))
+ .getChangeId();
+
+ recommend(changeId);
+
+ Collection<ChangeMessageInfo> messages = gApi.changes().id(changeId).get().messages;
+ assertThat(Iterables.getLast(messages).message)
+ .isEqualTo(
+ String.format(
+ "Patch Set 1: Code-Review+1\n\n"
+ + "By voting Code-Review+1 the following files are now code-owner approved by"
+ + " %s:\n"
+ + "* %s\n"
+ + "* %s\n"
+ + "* %s\n"
+ + "* %s\n",
+ admin.fullName(), path4, path3, path1, path2));
+ }
+
+ @Test
+ @GerritConfig(name = "plugin.code-owners.maxPathsInChangeMessages", value = "3")
+ public void pathsInChangeMessageAreLimited_limitReached() throws Exception {
+ codeOwnerConfigOperations
+ .newCodeOwnerConfig()
+ .project(project)
+ .branch("master")
+ .folderPath("/")
+ .addCodeOwnerEmail(admin.email())
+ .create();
+
+ String path1 = "foo/bar.baz";
+ String path2 = "foo/baz.bar";
+ String path3 = "bar/foo.baz";
+ String path4 = "bar/baz.foo";
+ String changeId =
+ createChange(
+ "Test Change",
+ ImmutableMap.of(
+ path1,
+ "file content",
+ path2,
+ "file content",
+ path3,
+ "file content",
+ path4,
+ "file content"))
+ .getChangeId();
+
+ recommend(changeId);
+
+ Collection<ChangeMessageInfo> messages = gApi.changes().id(changeId).get().messages;
+ assertThat(Iterables.getLast(messages).message)
+ .isEqualTo(
+ String.format(
+ "Patch Set 1: Code-Review+1\n\n"
+ + "By voting Code-Review+1 the following files are now code-owner approved by"
+ + " %s:\n"
+ + "* %s\n"
+ + "* %s\n"
+ + "(2 more files)\n",
+ admin.fullName(), path4, path3));
+ }
+
+ @Test
+ @GerritConfig(name = "plugin.code-owners.maxPathsInChangeMessages", value = "0")
+ public void pathsInChangeMessagesDisabled() throws Exception {
+ codeOwnerConfigOperations
+ .newCodeOwnerConfig()
+ .project(project)
+ .branch("master")
+ .folderPath("/")
+ .addCodeOwnerEmail(admin.email())
+ .create();
+
+ String changeId =
+ createChange(
+ "Test Change",
+ ImmutableMap.of(
+ "foo/bar.baz",
+ "file content",
+ "foo/baz.bar",
+ "file content",
+ "bar/foo.baz",
+ "file content",
+ "bar/baz.foo",
+ "file content"))
+ .getChangeId();
+
+ recommend(changeId);
+
+ Collection<ChangeMessageInfo> messages = gApi.changes().id(changeId).get().messages;
+ assertThat(Iterables.getLast(messages).message).isEqualTo("Patch Set 1: Code-Review+1");
+ }
}
diff --git a/javatests/com/google/gerrit/plugins/codeowners/acceptance/api/CodeOwnersPluginConfigValidatorIT.java b/javatests/com/google/gerrit/plugins/codeowners/acceptance/api/CodeOwnersPluginConfigValidatorIT.java
index 1ea4183..e22062e 100644
--- a/javatests/com/google/gerrit/plugins/codeowners/acceptance/api/CodeOwnersPluginConfigValidatorIT.java
+++ b/javatests/com/google/gerrit/plugins/codeowners/acceptance/api/CodeOwnersPluginConfigValidatorIT.java
@@ -494,6 +494,44 @@
+ " (parameter codeOwners.fallbackCodeOwners) is invalid.");
}
+ @Test
+ public void configureMaxPathsInChangeMessages() throws Exception {
+ fetchRefsMetaConfig();
+
+ Config cfg = new Config();
+ cfg.setInt(
+ CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
+ /* subsection= */ null,
+ GeneralConfig.KEY_MAX_PATHS_IN_CHANGE_MESSAGES,
+ 50);
+ setCodeOwnersConfig(cfg);
+
+ PushResult r = pushRefsMetaConfig();
+ assertThat(r.getRemoteUpdate(RefNames.REFS_CONFIG).getStatus()).isEqualTo(Status.OK);
+ assertThat(codeOwnersPluginConfiguration.getMaxPathsInChangeMessages(project)).isEqualTo(50);
+ }
+
+ @Test
+ public void cannotSetInvalidMaxPathsInChangeMessages() throws Exception {
+ fetchRefsMetaConfig();
+
+ Config cfg = new Config();
+ cfg.setString(
+ CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS,
+ /* subsection= */ null,
+ GeneralConfig.KEY_MAX_PATHS_IN_CHANGE_MESSAGES,
+ "INVALID");
+ setCodeOwnersConfig(cfg);
+
+ PushResult r = pushRefsMetaConfig();
+ assertThat(r.getRemoteUpdate(RefNames.REFS_CONFIG).getStatus())
+ .isEqualTo(Status.REJECTED_OTHER_REASON);
+ assertThat(r.getMessages())
+ .contains(
+ "The value for max paths in change messages 'INVALID' that is configured in"
+ + " code-owners.config (parameter codeOwners.maxPathsInChangeMessages) is invalid.");
+ }
+
private void fetchRefsMetaConfig() throws Exception {
fetch(testRepo, RefNames.REFS_CONFIG + ":" + RefNames.REFS_CONFIG);
testRepo.reset(RefNames.REFS_CONFIG);
diff --git a/javatests/com/google/gerrit/plugins/codeowners/config/CodeOwnersPluginConfigurationTest.java b/javatests/com/google/gerrit/plugins/codeowners/config/CodeOwnersPluginConfigurationTest.java
index 641bf10..f03427d 100644
--- a/javatests/com/google/gerrit/plugins/codeowners/config/CodeOwnersPluginConfigurationTest.java
+++ b/javatests/com/google/gerrit/plugins/codeowners/config/CodeOwnersPluginConfigurationTest.java
@@ -922,6 +922,50 @@
assertThat(codeOwnersPluginConfiguration.areImplicitApprovalsEnabled(project)).isFalse();
}
+ @Test
+ public void cannotGetMaxPathsInChangeMessagesForNullProject() throws Exception {
+ NullPointerException npe =
+ assertThrows(
+ NullPointerException.class,
+ () -> codeOwnersPluginConfiguration.getMaxPathsInChangeMessages(/* project= */ null));
+ assertThat(npe).hasMessageThat().isEqualTo("project");
+ }
+
+ @Test
+ public void getMaxPathsInChangeMessagesIfNoneIsConfigured() throws Exception {
+ assertThat(codeOwnersPluginConfiguration.getMaxPathsInChangeMessages(project))
+ .isEqualTo(GeneralConfig.DEFAULT_MAX_PATHS_IN_CHANGE_MESSAGES);
+ }
+
+ @Test
+ @GerritConfig(name = "plugin.code-owners.maxPathsInChangeMessages", value = "50")
+ public void getMaxPathsInChangeMessagesIfNoneIsConfiguredOnProjectLevel() throws Exception {
+ assertThat(codeOwnersPluginConfiguration.getMaxPathsInChangeMessages(project)).isEqualTo(50);
+ }
+
+ @Test
+ @GerritConfig(name = "plugin.code-owners.maxPathsInChangeMessages", value = "50")
+ public void maxPathInChangeMessagesOnProjectLevelOverridesGlobalMaxPathInChangeMessages()
+ throws Exception {
+ configureFallbackCodeOwners(project, FallbackCodeOwners.NONE);
+ assertThat(codeOwnersPluginConfiguration.getFallbackCodeOwners(project))
+ .isEqualTo(FallbackCodeOwners.NONE);
+ }
+
+ @Test
+ @GerritConfig(name = "plugin.code-owners.maxPathsInChangeMessages", value = "50")
+ public void maxPathInChangeMessagesIsInheritedFromParentProject() throws Exception {
+ configureMaxPathsInChangeMessages(allProjects, 20);
+ assertThat(codeOwnersPluginConfiguration.getMaxPathsInChangeMessages(project)).isEqualTo(20);
+ }
+
+ @Test
+ public void inheritedMaxPathInChangeMessagesCanBeOverridden() throws Exception {
+ configureMaxPathsInChangeMessages(allProjects, 50);
+ configureMaxPathsInChangeMessages(project, 20);
+ assertThat(codeOwnersPluginConfiguration.getMaxPathsInChangeMessages(project)).isEqualTo(20);
+ }
+
private void configureDisabled(Project.NameKey project, String disabled) throws Exception {
setCodeOwnersConfig(project, /* subsection= */ null, StatusConfig.KEY_DISABLED, disabled);
}
@@ -987,6 +1031,15 @@
fallbackCodeOwners.name());
}
+ private void configureMaxPathsInChangeMessages(
+ Project.NameKey project, int maxPathsInChangeMessages) throws Exception {
+ setCodeOwnersConfig(
+ project,
+ /* subsection= */ null,
+ GeneralConfig.KEY_MAX_PATHS_IN_CHANGE_MESSAGES,
+ Integer.toString(maxPathsInChangeMessages));
+ }
+
private AutoCloseable registerTestBackend() {
RegistrationHandle registrationHandle =
((PrivateInternals_DynamicMapImpl<CodeOwnerBackend>) codeOwnerBackends)
diff --git a/javatests/com/google/gerrit/plugins/codeowners/config/GeneralConfigTest.java b/javatests/com/google/gerrit/plugins/codeowners/config/GeneralConfigTest.java
index 6bc8ac5..78adae8 100644
--- a/javatests/com/google/gerrit/plugins/codeowners/config/GeneralConfigTest.java
+++ b/javatests/com/google/gerrit/plugins/codeowners/config/GeneralConfigTest.java
@@ -16,12 +16,14 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.plugins.codeowners.config.CodeOwnersPluginConfiguration.SECTION_CODE_OWNERS;
+import static com.google.gerrit.plugins.codeowners.config.GeneralConfig.DEFAULT_MAX_PATHS_IN_CHANGE_MESSAGES;
import static com.google.gerrit.plugins.codeowners.config.GeneralConfig.KEY_ENABLE_IMPLICIT_APPROVALS;
import static com.google.gerrit.plugins.codeowners.config.GeneralConfig.KEY_ENABLE_VALIDATION_ON_COMMIT_RECEIVED;
import static com.google.gerrit.plugins.codeowners.config.GeneralConfig.KEY_ENABLE_VALIDATION_ON_SUBMIT;
import static com.google.gerrit.plugins.codeowners.config.GeneralConfig.KEY_FALLBACK_CODE_OWNERS;
import static com.google.gerrit.plugins.codeowners.config.GeneralConfig.KEY_FILE_EXTENSION;
import static com.google.gerrit.plugins.codeowners.config.GeneralConfig.KEY_GLOBAL_CODE_OWNER;
+import static com.google.gerrit.plugins.codeowners.config.GeneralConfig.KEY_MAX_PATHS_IN_CHANGE_MESSAGES;
import static com.google.gerrit.plugins.codeowners.config.GeneralConfig.KEY_MERGE_COMMIT_STRATEGY;
import static com.google.gerrit.plugins.codeowners.config.GeneralConfig.KEY_OVERRIDE_INFO_URL;
import static com.google.gerrit.plugins.codeowners.config.GeneralConfig.KEY_READ_ONLY;
@@ -500,4 +502,61 @@
assertThat(generalConfig.getFallbackCodeOwners(project, new Config()))
.isEqualTo(FallbackCodeOwners.NONE);
}
+
+ @Test
+ public void cannotGetMaxPathsInChangeMessagesForNullProject() throws Exception {
+ NullPointerException npe =
+ assertThrows(
+ NullPointerException.class,
+ () -> generalConfig.getMaxPathsInChangeMessages(/* project= */ null, new Config()));
+ assertThat(npe).hasMessageThat().isEqualTo("project");
+ }
+
+ @Test
+ public void cannotGetMaxPathsInChangeMessagesForNullPluginConfig() throws Exception {
+ NullPointerException npe =
+ assertThrows(
+ NullPointerException.class,
+ () -> generalConfig.getMaxPathsInChangeMessages(project, /* pluginConfig= */ null));
+ assertThat(npe).hasMessageThat().isEqualTo("pluginConfig");
+ }
+
+ @Test
+ public void noMaxPathsInChangeMessagesConfigured() throws Exception {
+ assertThat(generalConfig.getMaxPathsInChangeMessages(project, new Config()))
+ .isEqualTo(DEFAULT_MAX_PATHS_IN_CHANGE_MESSAGES);
+ }
+
+ @Test
+ @GerritConfig(name = "plugin.code-owners.maxPathsInChangeMessages", value = "50")
+ public void maxPathsInChangeMessagesIsRetrievedFromGerritConfigIfNotSpecifiedOnProjectLevel()
+ throws Exception {
+ assertThat(generalConfig.getMaxPathsInChangeMessages(project, new Config())).isEqualTo(50);
+ }
+
+ @Test
+ @GerritConfig(name = "plugin.code-owners.maxPathsInChangeMessages", value = "50")
+ public void
+ maxPathsInChangeMessagesInPluginConfigOverridesMaxPathsInChangeMessagesInGerritConfig()
+ throws Exception {
+ Config cfg = new Config();
+ cfg.setString(SECTION_CODE_OWNERS, null, KEY_MAX_PATHS_IN_CHANGE_MESSAGES, "10");
+ assertThat(generalConfig.getMaxPathsInChangeMessages(project, cfg)).isEqualTo(10);
+ }
+
+ @Test
+ @GerritConfig(name = "plugin.code-owners.maxPathsInChangeMessages", value = "50")
+ public void globalMaxPathsInChangeMessagesUsedIfInvalidMaxPathsInChangeMessagesConfigured()
+ throws Exception {
+ Config cfg = new Config();
+ cfg.setString(SECTION_CODE_OWNERS, null, KEY_MAX_PATHS_IN_CHANGE_MESSAGES, "INVALID");
+ assertThat(generalConfig.getMaxPathsInChangeMessages(project, cfg)).isEqualTo(50);
+ }
+
+ @Test
+ @GerritConfig(name = "plugin.code-owners.maxPathsInChangeMessages", value = "INVALID")
+ public void defaultValueUsedIfInvalidMaxPathsInChangeMessagesConfigured() throws Exception {
+ assertThat(generalConfig.getMaxPathsInChangeMessages(project, new Config()))
+ .isEqualTo(DEFAULT_MAX_PATHS_IN_CHANGE_MESSAGES);
+ }
}
diff --git a/resources/Documentation/config.md b/resources/Documentation/config.md
index 28c65b9..d546374 100644
--- a/resources/Documentation/config.md
+++ b/resources/Documentation/config.md
@@ -283,6 +283,21 @@
`@PLUGIN@.config`.\
By default `NONE`.
+<a id="pluginCodeOwnersMaxPathsInChangeMessages">plugin.@PLUGIN@.maxPathsInChangeMessages</a>
+: When a user votes on the [code owners
+ label](#pluginCodeOwnersRequiredApproval) the paths that are affected by
+ the vote are listed in the change message that is posted when the vote
+ is applied.\
+ This configuration parameter controls the maximum number of paths that
+ are included in change messages. This is to prevent that the change
+ messages become too big for large changes that touch many files.\
+ Setting the value to `0` disables including affected paths into change
+ messages.\
+ Can be overridden per project by setting
+ [codeOwners.maxPathsInChangeMessages](#codeOwnersMaxPathsInChangeMessages)
+ in `@PLUGIN@.config`.\
+ By default `100`.
+
# <a id="projectConfiguration">Project configuration in @PLUGIN@.config</a>
<a id="codeOwnersDisabled">codeOwners.disabled</a>
@@ -530,6 +545,24 @@
[plugin.@PLUGIN@.fallbackCodeOwners](#pluginCodeOwnersFallbackCodeOwners)
in `gerrit.config` is used.
+<a id="codeOwnersMaxPathsInChangeMessages">codeOwners.maxPathsInChangeMessages</a>
+: When a user votes on the [code owners
+ label](#codeOwnersRequiredApproval) the paths that are affected by the
+ vote are listed in the change message that is posted when the vote is
+ applied.\
+ This configuration parameter controls the maximum number of paths that
+ are included in change messages. This is to prevent that the change
+ messages become too big for large changes that touch many files.\
+ Setting the value to `0` disables including affected paths into change
+ messages.\
+ Overrides the global setting
+ [plugin.@PLUGIN@.maxPathsInChangeMessages](#pluginCodeOwnersMaxPathsInChangeMessages)
+ in `gerrit.config`.\
+ If not set, the global setting
+ [plugin.@PLUGIN@.maxPathsInChangeMessages](#pluginCodeOwnersMaxPathsInChangeMessages)
+ in `gerrit.config` is used.\
+ By default `100`.
+
---
Back to [@PLUGIN@ documentation index](index.html)
diff --git a/resources/Documentation/validation.md b/resources/Documentation/validation.md
index ef1b4ce..746221e 100644
--- a/resources/Documentation/validation.md
+++ b/resources/Documentation/validation.md
@@ -154,6 +154,8 @@
configuration is valid
* the [codeOwners.fallbackCodeOwners](config.html#codeOwnersFallbackCodeOwners)
configuration is valid
+* the [codeOwners.maxPathsInChangeMessages](config.html#codeOwnersMaxPathsInChangeMessages)
+ configuration is valid
---