Merge branch 'stable-2.8'

* stable-2.8:
  Never replicate automerge-cache commits
  Fix: failure to create to missing remote repository via git://
  Improve info logging related to repository creation and deletion
  Clarify replication of refs/meta/config when refspec is 'all refs'
  Differentiate error logs for local and remote repository errors

Conflicts:
	src/main/java/com/googlesource/gerrit/plugins/replication/PushOne.java

Change-Id: I41eac82e06f35ba45e984e65e970cd967cfeff46
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 46a6d00..5b6daea 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/PushOne.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/PushOne.java
@@ -266,25 +266,25 @@
       git = gitManager.openRepository(projectName);
       runImpl();
     } catch (RepositoryNotFoundException e) {
-      wrappedLog.error("Cannot replicate " + projectName + "; " + e.getMessage(), getStatesAsArray());
+      wrappedLog.error("Cannot replicate " + projectName
+          + "; Local repository error: "
+          + e.getMessage(), getStatesAsArray());
 
     } catch (RemoteRepositoryException e) {
-      log.error("Cannot replicate " + projectName + "; " + e.getMessage());
-
-    } catch (NoRemoteRepositoryException e) {
-      if (pool.isCreateMissingRepos()) {
-        try {
-          createRepository();
-          log.warn("Missing repository created; retry replication to " + uri);
-          pool.reschedule(this, Destination.RetryReason.REPOSITORY_MISSING);
-        } catch (IOException ioe) {
-          wrappedLog.error("Cannot replicate to " + uri + "; failed to create missing repository",
-              ioe, getStatesAsArray());
-        }
+      // Tried to replicate to a remote via anonymous git:// but the repository
+      // does not exist.  In this case NoRemoteRepositoryException is not
+      // raised.
+      final String msg = e.getMessage();
+      if (msg.contains("access denied")) {
+        createRepository();
       } else {
-        wrappedLog.error("Cannot replicate to " + uri + "; repository not found", getStatesAsArray());
+        log.error("Cannot replicate " + projectName
+            + "; Remote repository error: "
+            + msg);
       }
 
+    } catch (NoRemoteRepositoryException e) {
+      createRepository();
     } catch (NotSupportedException e) {
       wrappedLog.error("Cannot replicate to " + uri, e, getStatesAsArray());
 
@@ -316,21 +316,32 @@
     }
   }
 
-  private void createRepository() throws IOException {
-    final Ref head = git.getRef(Constants.HEAD);
-    NewProjectCreatedListener.Event event =
-        new NewProjectCreatedListener.Event() {
-          @Override
-          public String getProjectName() {
-            return projectName.get();
-          }
+  private void createRepository() {
+    if (pool.isCreateMissingRepos()) {
+      try {
+        final Ref head = git.getRef(Constants.HEAD);
+        NewProjectCreatedListener.Event event =
+            new NewProjectCreatedListener.Event() {
+              @Override
+              public String getProjectName() {
+                return projectName.get();
+              }
 
-          @Override
-          public String getHeadName() {
-            return head != null ? head.getName() : null;
-          }
-        };
-    replicationQueue.onNewProjectCreated(event);
+              @Override
+              public String getHeadName() {
+                return head != null ? head.getName() : null;
+              }
+            };
+        replicationQueue.onNewProjectCreated(event);
+        log.warn("Missing repository created; retry replication to " + uri);
+        pool.reschedule(this, Destination.RetryReason.REPOSITORY_MISSING);
+      } catch (IOException ioe) {
+        wrappedLog.error("Cannot replicate to " + uri + "; failed to create missing repository",
+            ioe, getStatesAsArray());
+      }
+    } else {
+      wrappedLog.error("Cannot replicate to " + uri + "; repository not found", getStatesAsArray());
+    }
   }
 
   private void runImpl() throws IOException {
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 eea1448..e28060b 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationQueue.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationQueue.java
@@ -228,8 +228,10 @@
   private void createProject(URIish replicateURI, String head) {
     if (!replicateURI.isRemote()) {
       createLocally(replicateURI, head);
+      log.info("Created local repository: " + replicateURI);
     } else if (isSSH(replicateURI)) {
       createRemoteSsh(replicateURI, head);
+      log.info("Created remote repository: " + replicateURI);
     } else {
       log.warn(String.format("Cannot create new project on remote site %s."
           + " Only local paths and SSH URLs are supported"
@@ -252,7 +254,9 @@
         repo.close();
       }
     } catch (IOException e) {
-      log.error(String.format("Failed to create repository %s", uri.getPath()), e);
+      log.error(String.format(
+          "Error creating local repository %s:\n",
+          uri.getPath()), e);
     }
   }
 
@@ -280,8 +284,10 @@
   private void deleteProject(URIish replicateURI) {
     if (!replicateURI.isRemote()) {
       deleteLocally(replicateURI);
+      log.info("Deleted local repository: " + replicateURI);
     } else if (isSSH(replicateURI)) {
       deleteRemoteSsh(replicateURI);
+      log.info("Deleted remote repository: " + replicateURI);
     } else {
       log.warn(String.format("Cannot delete project on remote site %s."
           + " Only local paths and SSH URLs are supported"
@@ -293,7 +299,9 @@
     try {
       recursivelyDelete(new File(uri.getPath()));
     } catch (IOException e) {
-      log.error(String.format("Failed to delete repository %s", uri.getPath()), e);
+      log.error(String.format(
+          "Error deleting local repository %s:\n",
+          uri.getPath()), e);
     }
   }
 
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md
index de0b907..e8f9473 100644
--- a/src/main/resources/Documentation/config.md
+++ b/src/main/resources/Documentation/config.md
@@ -149,6 +149,10 @@
 	or `+refs/*:refs/*` (force push all refs) if not specified and
 	`gerrit.defaultForceUpdate` is true.
 
+	Note that the `refs/meta/config` branch is only replicated
+	when `replicatePermissions` is true, even if the push refspec
+	is 'all refs'.
+
 [2]: #example_file
 
 remote.NAME.timeout