support ignoreRemoteFailures in the SuperManifest plugin.

Change-Id: I8d555af2df98feef346ac8823b8c39809124e718
diff --git a/BUILD b/BUILD
index b9d6b89..cea89cb 100644
--- a/BUILD
+++ b/BUILD
@@ -27,5 +27,6 @@
         "//gerrit-acceptance-framework:lib",
         "//gerrit-plugin-api:lib",
         "//lib/bouncycastle:bcprov",
+        "//lib/jetty:http",
     ],
 )
diff --git a/src/main/java/com/googlesource/gerrit/plugins/supermanifest/ConfigEntry.java b/src/main/java/com/googlesource/gerrit/plugins/supermanifest/ConfigEntry.java
index 2d4e5ec..ad5e90d 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/supermanifest/ConfigEntry.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/supermanifest/ConfigEntry.java
@@ -35,6 +35,7 @@
   String xmlPath;
   Project.NameKey destRepoKey;
   boolean recordSubmoduleLabels;
+  boolean ignoreRemoteFailures;
 
   // destBranch can be "*" in which case srcRef is ignored.
   String destBranch;
@@ -110,6 +111,7 @@
     destBranch = destRef.substring(REFS_HEADS.length());
 
     recordSubmoduleLabels = cfg.getBoolean(SECTION_NAME, name, "recordSubmoduleLabels", false);
+    ignoreRemoteFailures = cfg.getBoolean(SECTION_NAME, name, "ignoreRemoteFailures", false);
 
     try {
       // http://foo/platform/manifest => http://foo/platform/
diff --git a/src/main/java/com/googlesource/gerrit/plugins/supermanifest/RepoUpdater.java b/src/main/java/com/googlesource/gerrit/plugins/supermanifest/RepoUpdater.java
index 35fb856..094afe5 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/supermanifest/RepoUpdater.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/supermanifest/RepoUpdater.java
@@ -54,6 +54,7 @@
     cmd.setAuthor(serverIdent)
         .setRecordRemoteBranch(true)
         .setRecordSubmoduleLabels(c.isRecordSubmoduleLabels())
+        .setIgnoreRemoteFailures(c.ignoreRemoteFailures)
         .setInputStream(manifestStream)
         .setRecommendShallow(true)
         .setRemoteReader(reader)
diff --git a/src/main/resources/Documentation/about.md b/src/main/resources/Documentation/about.md
index 9321096..f2623d3 100644
--- a/src/main/resources/Documentation/about.md
+++ b/src/main/resources/Documentation/about.md
@@ -16,9 +16,18 @@
 `nyc`, for which the contents corresponds to the manifest file
 `manifest.xml` on branch `refs/heads/nyc` in project `platforms/manifest`.
 
-valid value(s) for `toolType` right now is `repo`. It can be left blank to 
+valid value(s) for `toolType` right now is `repo`. It can be left blank to
 default to `repo`.
 
+The plugin supports the following options:
+
+*  `recordSubmoduleLabels` (defaults to false). Sets recordSubmoduleLabels
+   setting for JGit's RepoCommand
+
+*  `ignoreRemoteFailures = true` (defaults to false). Sets ignoreRemoteFailures.
+   Setting it true will cause repos that are not accessible to be ignored.
+
+
 For the destination branch, you may also specify `*` to copy all
 branches in the manifest repository.
 
diff --git a/src/test/java/com/googlesource/gerrit/plugins/supermanifest/RepoSuperManifestIT.java b/src/test/java/com/googlesource/gerrit/plugins/supermanifest/RepoSuperManifestIT.java
index 71cb82a..a00a8aa 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/supermanifest/RepoSuperManifestIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/supermanifest/RepoSuperManifestIT.java
@@ -29,6 +29,7 @@
 import com.google.gerrit.reviewdb.client.RefNames;
 import java.net.URI;
 import java.util.Arrays;
+import org.eclipse.jetty.http.HttpStatus;
 import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
 import org.eclipse.jgit.junit.TestRepository;
 import org.eclipse.jgit.lib.BlobBasedConfig;
@@ -216,6 +217,69 @@
     assertThat(branch.file("project1").getContentType()).isEqualTo("x-git/gitlink; charset=UTF-8");
   }
 
+  @Test
+  public void testIgnoreRemoteFailure() throws Exception {
+    setupTestRepos("project");
+
+    // Make sure the manifest exists so the configuration loads successfully.
+    Project.NameKey manifestKey = createProject("manifest");
+    TestRepository<InMemoryRepository> manifestRepo = cloneProject(manifestKey, admin);
+
+    Project.NameKey superKey = createProject("superproject");
+    cloneProject(superKey, admin);
+
+    String remoteXml = "  <remote name=\"origin\" fetch=\"" + canonicalWebUrl.get() + "\" />\n";
+    String defaultXml = "  <default remote=\"origin\" revision=\"refs/heads/master\" />\n";
+    String xml =
+        "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+            + "<manifest>\n"
+            + remoteXml
+            + " <remote fetch=\"https://example.invalid/\" name=\"invalid\" /> "
+            + defaultXml
+            + "  <project name=\""
+            + testRepoKeys[0].get()
+            + "\" path=\"project1\" />\n"
+            + "  <project name=\"unavailable\" remote=\"invalid\" path=\"invalid\" />"
+            + "</manifest>\n";
+
+    pushFactory
+        .create(db, admin.getIdent(), manifestRepo, "Subject", "default.xml", xml)
+        .to("refs/heads/srcbranch")
+        .assertOkStatus();
+
+    // Push config after XML. Needs a manual trigger to create the destination.
+    pushConfig(
+        "[superproject \""
+            + superKey.get()
+            + ":refs/heads/destbranch\"]\n"
+            + "  srcRepo = "
+            + manifestKey.get()
+            + "\n"
+            + "  srcRef = refs/heads/srcbranch\n"
+            + "  srcPath = default.xml\n");
+
+    RestResponse r =
+        adminRestSession.post("/projects/" + manifestKey + "/branches/srcbranch/update_manifest");
+    r.assertStatus(HttpStatus.INTERNAL_SERVER_ERROR_500);
+
+    pushConfig(
+        "[superproject \""
+            + superKey.get()
+            + ":refs/heads/destbranch\"]\n"
+            + "  srcRepo = "
+            + manifestKey.get()
+            + "\n"
+            + "  srcRef = refs/heads/srcbranch\n"
+            + "  srcPath = default.xml\n"
+            + "  ignoreRemoteFailures = true\n");
+
+    r = adminRestSession.post("/projects/" + manifestKey + "/branches/srcbranch/update_manifest");
+    r.assertNoContent();
+
+    BranchApi branch = gApi.projects().name(superKey.get()).branch("refs/heads/destbranch");
+    assertThat(branch.file("project1").getContentType()).isEqualTo("x-git/gitlink; charset=UTF-8");
+  }
+
   private void outer() {
     inner();
   }