Add method to push changes directly to given replica

This makes it possible to push changes directly to given replica
instance without sending unnecessary requests to others.

The method is intended to be used by other plugins that extend the
replication plugin.

Change-Id: Ib3e5a6c3afde834855d055b31beb43a560f8d785
Signed-off-by: Dariusz Luksza <dariusz@luksza.org>
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 d73ab7b..0f03e57 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationQueue.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationQueue.java
@@ -28,6 +28,7 @@
 import com.google.gerrit.extensions.events.ProjectDeletedListener;
 import com.google.gerrit.extensions.registration.DynamicItem;
 import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.server.UsedAt;
 import com.google.gerrit.server.events.EventDispatcher;
 import com.google.gerrit.server.git.WorkQueue;
 import com.google.inject.Inject;
@@ -161,17 +162,36 @@
 
     Project.NameKey project = new Project.NameKey(projectName);
     for (Destination cfg : config.getDestinations(FilterType.ALL)) {
-      if (cfg.wouldPushProject(project) && cfg.wouldPushRef(refName)) {
-        for (URIish uri : cfg.getURIs(project, null)) {
-          replicationTasksStorage.persist(
-              new ReplicateRefUpdate(projectName, refName, uri, cfg.getRemoteConfigName()));
-          cfg.schedule(project, refName, uri, state);
-        }
-      }
+      pushReference(cfg, project, refName, state);
     }
     state.markAllPushTasksScheduled();
   }
 
+  @UsedAt(UsedAt.Project.COLLABNET)
+  public void pushReference(Destination cfg, Project.NameKey project, String refName) {
+    pushReference(cfg, project, refName, null);
+  }
+
+  private void pushReference(
+      Destination cfg, Project.NameKey project, String refName, ReplicationState state) {
+    boolean withoutState = state == null;
+    if (withoutState) {
+      state = new ReplicationState(new GitUpdateProcessing(dispatcher.get()));
+    }
+
+    if (cfg.wouldPushProject(project) && cfg.wouldPushRef(refName)) {
+      for (URIish uri : cfg.getURIs(project, null)) {
+        replicationTasksStorage.persist(
+            new ReplicateRefUpdate(project.get(), refName, uri, cfg.getRemoteConfigName()));
+        cfg.schedule(project, refName, uri, state);
+      }
+    }
+
+    if (withoutState) {
+      state.markAllPushTasksScheduled();
+    }
+  }
+
   private void firePendingEvents() {
     try {
       Set<String> eventsReplayed = new HashSet<>();