Create missing repository only at the remote we are pushing to

When replication of a ref failed due to missing remote repository at one
remote site, we then initiated creation of the missing repository on all
remotes where this repository is replicated. The creation of the missing
repository is considered to be success if it succeeded for all remotes
and only in this case the ref replication was rescheduled. This logic
could cause a ref replication to not be rescheduled when creation of a
missing repository fails in a remote which is unrelated to the current
push operation. For example, if we replicate to two remote sites:

  [remote "foo"]
    url = https://foo.org/...
    adminUrl = ssh://gerrit@foo.org/...

  [remote "bar"]
    url = https://bar.org/...
    adminUrl = ssh://gerrit@bar.org/...

and if during a push to "foo" we find that the repository is missing
then we will try to create it on both "foo" and "bar". It could happen
that the creation of the missing repository succeeds on "foo" and then
fails on "bar" because "bar" is unreachable or down at that moment.
In this case the replication to "foo" will not be rescheduled but it
should be as we successfully created the missing repository in "foo".

Create missing repository only under the (admin) URL in the same remote.

Note that there will be one ref replication task for each remote which
ensures that the missing repository will be created in all remotes.

Change-Id: Idbc3f614df53bb3aabcc4cf6cb0d6540e7000e29
(cherry picked from commit abafb83c47eb50c0ec5ce9a4b8d04dc355d5a5bf)
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/PushOne.java b/src/main/java/com/googlesource/gerrit/plugins/replication/PushOne.java
index 293701a..6db6674 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/PushOne.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/PushOne.java
@@ -409,7 +409,8 @@
     if (pool.isCreateMissingRepos()) {
       try {
         Ref head = git.exactRef(Constants.HEAD);
-        if (replicationQueue.createProject(projectName, head != null ? getName(head) : null)) {
+        if (replicationQueue.createProject(
+            config.getName(), projectName, head != null ? getName(head) : null)) {
           repLog.warn("Missing repository created; retry replication to {}", uri);
           pool.reschedule(this, Destination.RetryReason.REPOSITORY_MISSING);
         } else {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationQueue.java b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationQueue.java
index 2c62b4e..d57fa2e 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationQueue.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationQueue.java
@@ -18,6 +18,7 @@
 import static com.googlesource.gerrit.plugins.replication.AdminApiFactory.isSSH;
 
 import com.google.common.base.Strings;
+import com.google.gerrit.common.Nullable;
 import com.google.gerrit.extensions.events.GitReferenceUpdatedListener;
 import com.google.gerrit.extensions.events.HeadUpdatedListener;
 import com.google.gerrit.extensions.events.LifecycleListener;
@@ -161,7 +162,7 @@
   @Override
   public void onProjectDeleted(ProjectDeletedListener.Event event) {
     Project.NameKey projectName = new Project.NameKey(event.getProjectName());
-    for (URIish uri : getURIs(projectName, FilterType.PROJECT_DELETION)) {
+    for (URIish uri : getURIs(null, projectName, FilterType.PROJECT_DELETION)) {
       deleteProject(uri, projectName);
     }
   }
@@ -169,12 +170,13 @@
   @Override
   public void onHeadUpdated(HeadUpdatedListener.Event event) {
     Project.NameKey project = new Project.NameKey(event.getProjectName());
-    for (URIish uri : getURIs(project, FilterType.ALL)) {
+    for (URIish uri : getURIs(null, project, FilterType.ALL)) {
       updateHead(uri, project, event.getNewHeadName());
     }
   }
 
-  private Set<URIish> getURIs(Project.NameKey projectName, FilterType filterType) {
+  private Set<URIish> getURIs(
+      @Nullable String remoteName, Project.NameKey projectName, FilterType filterType) {
     if (config.getDestinations(filterType).isEmpty()) {
       return Collections.emptySet();
     }
@@ -189,6 +191,10 @@
         continue;
       }
 
+      if (remoteName != null && !config.getRemoteConfigName().equals(remoteName)) {
+        continue;
+      }
+
       boolean adminURLUsed = false;
 
       for (String url : config.getAdminUrls()) {
@@ -231,9 +237,9 @@
     return uris;
   }
 
-  public boolean createProject(Project.NameKey project, String head) {
+  public boolean createProject(String remoteName, Project.NameKey project, String head) {
     boolean success = true;
-    for (URIish uri : getURIs(project, FilterType.PROJECT_CREATION)) {
+    for (URIish uri : getURIs(remoteName, project, FilterType.PROJECT_CREATION)) {
       success &= createProject(uri, project, head);
     }
     return success;