Merge branch 'stable-3.2' into stable-3.3

* stable-3.2:
  Introduce an optional configuration to define a regex for naming rules

Change-Id: Ia493f7b3b219547e8cc2197d99758e73ab476067
diff --git a/src/main/java/com/googlesource/gerrit/plugins/renameproject/Configuration.java b/src/main/java/com/googlesource/gerrit/plugins/renameproject/Configuration.java
index 1a3570d..a74c4cb 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/renameproject/Configuration.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/renameproject/Configuration.java
@@ -33,6 +33,7 @@
   private final int indexThreads;
   private final int sshCommandTimeout;
   private final int sshConnectionTimeout;
+  private final String renameRegex;
 
   private final Set<String> urls;
 
@@ -42,6 +43,7 @@
     indexThreads = cfg.getInt("indexThreads", 4);
     sshCommandTimeout = cfg.getInt("sshCommandTimeout", 0);
     sshConnectionTimeout = cfg.getInt("sshConnectionTimeout", DEFAULT_SSH_CONNECTION_TIMEOUT_MS);
+    renameRegex = cfg.getString("renameRegex", ".+");
 
     urls =
         Arrays.stream(cfg.getStringList(URL_KEY))
@@ -66,4 +68,8 @@
   public int getSshConnectionTimeout() {
     return sshConnectionTimeout;
   }
+
+  public String getRenameRegex() {
+    return renameRegex;
+  }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/renameproject/RenameProject.java b/src/main/java/com/googlesource/gerrit/plugins/renameproject/RenameProject.java
index f4a5418..0cf1ca4 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/renameproject/RenameProject.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/renameproject/RenameProject.java
@@ -151,6 +151,14 @@
     }
   }
 
+  private void assertNewNameMatchesRegex(Input input) throws BadRequestException {
+    if (!input.name.matches(cfg.getRenameRegex())) {
+      throw new BadRequestException(
+          String.format(
+              "Name of the repo should match the expected regex: %s", cfg.getRenameRegex()));
+    }
+  }
+
   private void assertRenamePermission(ProjectResource rsrc) throws AuthException {
     if (!canRename(rsrc)) {
       throw new AuthException("Not allowed to rename project");
@@ -195,6 +203,7 @@
       pm.ifPresent(progressMonitor -> progressMonitor.beginTask("Checking preconditions"));
 
       assertNewNameNotNull(input);
+      assertNewNameMatchesRegex(input);
       assertRenamePermission(rsrc);
       renamePreconditions.assertCanRename(rsrc, Project.nameKey(input.name));
       log.debug("Rename preconditions check successful.");
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md
index 7a5faeb..80872a1 100644
--- a/src/main/resources/Documentation/config.md
+++ b/src/main/resources/Documentation/config.md
@@ -43,3 +43,14 @@
 the client waits indefinitely. By default, 0.
 * `sshConnectionTimeout` : Timeout for SSH connections in minutes. If 0, there is no timeout, and
 the client waits indefinitely. By default, 2 minutes.
+
+Also, this plugin offers a way to restrict the new names of the projects to match an optionally
+configured regex. For example:
+
+```
+  [plugin "@PLUGIN@"]
+    renameRegex = [a-z0-9]+
+```
+
+In this example the new names for projects will be restricted to only non-capital letters and
+numbers.
diff --git a/src/test/java/com/googlesource/gerrit/plugins/renameproject/RenameIT.java b/src/test/java/com/googlesource/gerrit/plugins/renameproject/RenameIT.java
index 7b41fb2..c436745 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/renameproject/RenameIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/renameproject/RenameIT.java
@@ -58,6 +58,7 @@
   private static final String CACHE_NAME = "changeid_project";
   private static final String REPLICATION_OPTION = "--replication";
   private static final String URL = "ssh://localhost:29418";
+  private static final String RENAME_REGEX = "[a-zA-Z]+";
 
   @Inject private RequestScopeOperations requestScopeOperations;
 
@@ -254,6 +255,32 @@
     assertThat(projectState.isPresent()).isFalse();
   }
 
+  @Test
+  @UseLocalDisk
+  @GerritConfig(name = "plugin.rename-project.renameRegex", value = RENAME_REGEX)
+  public void testRenameViaHttpWithNonMatchingNameFail() throws Exception {
+    createChange();
+    RestResponse r = renameProjectTo(NEW_PROJECT_NAME + "1");
+    r.assertBadRequest();
+
+    Optional<ProjectState> projectState = projectCache.get(Project.nameKey(NEW_PROJECT_NAME));
+    assertThat(projectState.isPresent()).isFalse();
+  }
+
+  @Test
+  @UseLocalDisk
+  @GerritConfig(name = "plugin.rename-project.renameRegex", value = RENAME_REGEX)
+  public void testRenameViaHttpWithMatchingNameSuccess() throws Exception {
+    createChange();
+    RestResponse r = renameProjectTo(NEW_PROJECT_NAME);
+    r.assertOK();
+
+    Optional<ProjectState> projectState = projectCache.get(Project.nameKey(NEW_PROJECT_NAME));
+    assertThat(projectState.isPresent()).isTrue();
+    assertThat(queryProvider.get().byProject(project)).isEmpty();
+    assertThat(queryProvider.get().byProject(Project.nameKey(NEW_PROJECT_NAME))).isNotEmpty();
+  }
+
   private RestResponse renameProjectTo(String newName) throws Exception {
     requestScopeOperations.setApiUser(user.id());
     sender.clear();