ReceiveCommits: Bypass commit count when skip-validation is used

When a plugin implements CommitValidationListener and overrides the
shouldValidateAllCommits method to return 'true', direct push fails if
the number of commits exceeds receive.maxBatchCommits, even when the
skip-validation push option is used, thus preventing direct push of any
non-trivial repository.

Bypass the check for receive.maxBatchCommits when the skip-validation
push option is used.

Extend the tests to cover this use case.

Bug: Issue 11222
Change-Id: Ie838da01c76aeba797c714476c8977cbe7caaacf
Signed-off-by: Jacek Centkowski <jcentkowski@collab.net>
Signed-off-by: David Pursehouse <dpursehouse@collab.net>
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/AbstractPushForReview.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/AbstractPushForReview.java
index 9577519..f07673b 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/AbstractPushForReview.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/AbstractPushForReview.java
@@ -1950,6 +1950,34 @@
   @GerritConfig(name = "receive.maxBatchCommits", value = "2")
   @Test
   public void maxBatchCommits() throws Exception {
+    testMaxBatchCommits();
+  }
+
+  @GerritConfig(name = "receive.maxBatchCommits", value = "2")
+  @Test
+  public void maxBatchCommitsWithDefaultValidator() throws Exception {
+    TestValidator validator = new TestValidator();
+    RegistrationHandle handle = commitValidators.add(validator);
+    try {
+      testMaxBatchCommits();
+    } finally {
+      handle.remove();
+    }
+  }
+
+  @GerritConfig(name = "receive.maxBatchCommits", value = "2")
+  @Test
+  public void maxBatchCommitsWithValidateAllCommitsValidator() throws Exception {
+    TestValidator validator = new TestValidator(true);
+    RegistrationHandle handle = commitValidators.add(validator);
+    try {
+      testMaxBatchCommits();
+    } finally {
+      handle.remove();
+    }
+  }
+
+  private void testMaxBatchCommits() throws Exception {
     List<RevCommit> commits = new ArrayList<>();
     commits.addAll(initChanges(2));
     String master = "refs/heads/master";
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/receive/ReceiveCommits.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
index d39c338..fba4aec 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
@@ -2745,7 +2745,10 @@
       int limit = receiveConfig.maxBatchCommits;
       int n = 0;
       for (RevCommit c; (c = walk.next()) != null; ) {
-        if (++n > limit) {
+        // Even if skipValidation is set, we still get here when at least one plugin
+        // commit validator requires to validate all commits. In this case, however,
+        // we don't need to check the commit limit.
+        if (!skipValidation && ++n > limit) {
           logDebug("Number of new commits exceeds limit of {}", limit);
           addMessage(
               "Cannot push more than "