DeletePreconditions: Limit child listing to 1 project

Limit "parent:<project>" predicate in ListChildProjects to 1 project
to avoid consuming too much resources on big gerrit sites.

Bug: Issue 10401
Change-Id: Ibb54d2f4a6b3caff9939a6f7953ad8bc083ec688
diff --git a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/DeletePreconditions.java b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/DeletePreconditions.java
index 9a105f3..9c92ec6 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/deleteproject/DeletePreconditions.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/deleteproject/DeletePreconditions.java
@@ -18,14 +18,15 @@
 import static com.google.gerrit.reviewdb.client.RefNames.REFS_TAGS;
 import static com.googlesource.gerrit.plugins.deleteproject.DeleteOwnProjectCapability.DELETE_OWN_PROJECT;
 import static com.googlesource.gerrit.plugins.deleteproject.DeleteProjectCapability.DELETE_PROJECT;
-import static java.util.stream.Collectors.joining;
 import static java.util.stream.Collectors.toSet;
 
+import com.google.common.collect.Iterables;
 import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.api.access.PluginPermission;
 import com.google.gerrit.extensions.common.ProjectInfo;
 import com.google.gerrit.extensions.restapi.AuthException;
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
+import com.google.gerrit.extensions.restapi.RestApiException;
 import com.google.gerrit.reviewdb.client.Branch;
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.CurrentUser;
@@ -136,13 +137,13 @@
 
   private void assertHasNoChildProjects(ProjectResource rsrc) throws CannotDeleteProjectException {
     try {
-      List<ProjectInfo> children = listChildProjectsProvider.get().apply(rsrc);
+      List<ProjectInfo> children = listChildProjectsProvider.get().withLimit(1).apply(rsrc);
       if (!children.isEmpty()) {
         throw new CannotDeleteProjectException(
-            "Cannot delete project because it has children: "
-                + children.stream().map(info -> info.name).collect(joining(",")));
+            "Cannot delete project because it has at least one child: "
+                + Iterables.getOnlyElement(children).name);
       }
-    } catch (PermissionBackendException | ResourceConflictException e) {
+    } catch (OrmException | PermissionBackendException | RestApiException e) {
       throw new CannotDeleteProjectException(
           String.format("Unable to verify if '%s' has children projects.", rsrc.getName()));
     }
diff --git a/src/test/java/com/googlesource/gerrit/plugins/deleteproject/DeletePreconditionsTest.java b/src/test/java/com/googlesource/gerrit/plugins/deleteproject/DeletePreconditionsTest.java
index 168a17c..6658478 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/deleteproject/DeletePreconditionsTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/deleteproject/DeletePreconditionsTest.java
@@ -138,9 +138,10 @@
     doNothing().when(protectedProjects).assertIsNotProtected(rsrc);
     ListChildProjects childProjects = mock(ListChildProjects.class);
     when(listChildProjectsProvider.get()).thenReturn(childProjects);
+    when(childProjects.withLimit(1)).thenReturn(childProjects);
     when(childProjects.apply(rsrc)).thenReturn(ImmutableList.of(new ProjectInfo()));
     expectedException.expect(ResourceConflictException.class);
-    expectedException.expectMessage("Cannot delete project because it has children:");
+    expectedException.expectMessage("Cannot delete project because it has at least one child:");
     preConditions.assertCanBeDeleted(rsrc, new DeleteProject.Input());
   }
 
diff --git a/src/test/java/com/googlesource/gerrit/plugins/deleteproject/DeleteProjectIT.java b/src/test/java/com/googlesource/gerrit/plugins/deleteproject/DeleteProjectIT.java
index 8a56fb7..206f231 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/deleteproject/DeleteProjectIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/deleteproject/DeleteProjectIT.java
@@ -191,7 +191,9 @@
     adminSshSession.exec(cmd);
     assertThat(adminSshSession.getError())
         .isEqualTo(
-            "fatal: Cannot delete project because it has children: " + childrenString + "\n");
+            "fatal: Cannot delete project because it has at least one child: "
+                + childrenString
+                + "\n");
     assertThat(projectDir.exists()).isTrue();
   }