Merge branch 'stable-2.11'

* stable-2.11:
  Replicate HEAD reference when replicating a project
  Revert "Remove obsolete remote.NAME.timeout from config documentation"
  Add logging of cancelled replication events

Change-Id: I0324d64aaafe5baa92136cfc1d9cf2100e5ae1e5
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/Destination.java b/src/main/java/com/googlesource/gerrit/plugins/replication/Destination.java
index ee8d08d..8744284 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/Destination.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/Destination.java
@@ -195,6 +195,9 @@
   int shutdown() {
     int cnt = 0;
     if (pool != null) {
+      for (Runnable r : pool.getQueue()) {
+        repLog.warn(String.format("Cancelling replication event %s", r));
+      }
       cnt = pool.shutdownNow().size();
       pool.unregisterWorkQueue();
       pool = null;
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 4a2d01b..331f8fd 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/PushOne.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/PushOne.java
@@ -373,6 +373,7 @@
     PushResult res;
     try {
       res = pushVia(tn);
+      updateHead();
     } finally {
       try {
         tn.close();
@@ -540,6 +541,11 @@
     cmds.add(new RemoteRefUpdate(git, (Ref) null, dst, force, null, null));
   }
 
+  private void updateHead() throws IOException {
+    replicationQueue.updateHead(projectName, git.getRef(Constants.HEAD)
+        .getTarget().getName());
+  }
+
   private void updateStates(Collection<RemoteRefUpdate> refUpdates)
       throws LockFailureException {
     Set<String> doneRefs = new HashSet<>();
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 67d172f..58721bf 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationQueue.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationQueue.java
@@ -167,9 +167,13 @@
 
   @Override
   public void onHeadUpdated(HeadUpdatedListener.Event event) {
-    for (URIish uri : getURIs(new Project.NameKey(event.getProjectName()),
-        FilterType.ALL)) {
-      updateHead(uri, event.getNewHeadName());
+    updateHead(new Project.NameKey(event.getProjectName()),
+        event.getNewHeadName());
+  }
+
+  void updateHead(Project.NameKey project, String newHeadName) {
+    for (URIish uri : getURIs(project, FilterType.ALL)) {
+      updateHead(uri, newHeadName);
     }
   }
 
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md
index 54251ce..a528565 100644
--- a/src/main/resources/Documentation/config.md
+++ b/src/main/resources/Documentation/config.md
@@ -182,6 +182,19 @@
 
 [2]: #example_file
 
+remote.NAME.timeout
+:	Number of seconds to wait for a network read or write to
+	complete before giving up and declaring the remote side is not
+	responding.  If 0, there is no timeout, and the push client
+	waits indefinitely.
+
+	A timeout should be large enough to mostly transfer the
+	objects to the other side.  1 second may be too small for
+	larger projects, especially over a WAN link, while 10-30
+	seconds is a much more reasonable timeout value.
+
+	Defaults to 0 seconds, wait indefinitely.
+
 remote.NAME.replicationDelay
 :	Time to wait before scheduling a remote push operation. Setting
 	the delay to 0 effectively disables the delay, causing the push