Inject the SuperManifestRepoManager

When a manifest contains a project in a second host, the manifest parser
generates a correct .gitmodules but when reading the SHA1, the
SuperManifestRepoManager returns <this-host>/project. In some cases this
produces an inconsistent superproject: the .gitmodules points to a repo
but the SHA1 in the gitlink doesn't exist there.

Inject the implementation of the SuperManifestRepoManager. Providers can
offer an implementation that reads correctly cross-host if their backend
supports it.

Change-Id: I88187f883b59b7b9e7428963865b790ec8e87ca3
diff --git a/java/com/googlesource/gerrit/plugins/supermanifest/ConfigEntry.java b/java/com/googlesource/gerrit/plugins/supermanifest/ConfigEntry.java
index 0adfe2f..6c2cf84 100644
--- a/java/com/googlesource/gerrit/plugins/supermanifest/ConfigEntry.java
+++ b/java/com/googlesource/gerrit/plugins/supermanifest/ConfigEntry.java
@@ -28,7 +28,7 @@
 import org.eclipse.jgit.lib.Config;
 import org.eclipse.jgit.lib.Repository;
 
-class ConfigEntry {
+public class ConfigEntry {
   public static final String SECTION_NAME = "superproject";
 
   Project.NameKey srcRepoKey;
diff --git a/java/com/googlesource/gerrit/plugins/supermanifest/SuperManifestModule.java b/java/com/googlesource/gerrit/plugins/supermanifest/SuperManifestModule.java
index 33aa1dd..99ea379 100644
--- a/java/com/googlesource/gerrit/plugins/supermanifest/SuperManifestModule.java
+++ b/java/com/googlesource/gerrit/plugins/supermanifest/SuperManifestModule.java
@@ -21,6 +21,7 @@
 import com.google.gerrit.extensions.events.LifecycleListener;
 import com.google.gerrit.extensions.registration.DynamicSet;
 import com.google.gerrit.extensions.restapi.RestApiModule;
+import com.google.inject.assistedinject.FactoryModuleBuilder;
 
 public class SuperManifestModule extends RestApiModule {
   SuperManifestModule() {}
@@ -33,6 +34,12 @@
     DynamicSet.bind(binder(), LifecycleListener.class)
         .to(SuperManifestRefUpdatedListener.class)
         .in(SINGLETON);
+    install(
+        new FactoryModuleBuilder()
+            .implement(
+                SuperManifestRefUpdatedListener.SuperManifestRepoManager.class,
+                SuperManifestRefUpdatedListener.GerritSuperManifestRepoManager.class)
+            .build(SuperManifestRefUpdatedListener.SuperManifestRepoManager.Factory.class));
     post(BRANCH_KIND, "update_manifest").to(SuperManifestRefUpdatedListener.class).in(SINGLETON);
   }
 }
diff --git a/java/com/googlesource/gerrit/plugins/supermanifest/SuperManifestRefUpdatedListener.java b/java/com/googlesource/gerrit/plugins/supermanifest/SuperManifestRefUpdatedListener.java
index c82c830..bca414c 100644
--- a/java/com/googlesource/gerrit/plugins/supermanifest/SuperManifestRefUpdatedListener.java
+++ b/java/com/googlesource/gerrit/plugins/supermanifest/SuperManifestRefUpdatedListener.java
@@ -43,6 +43,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.Singleton;
+import com.google.inject.assistedinject.Assisted;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.StringWriter;
@@ -79,7 +80,7 @@
         RestModifyView<BranchResource, BranchInput> {
   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
 
-  private final GitRepositoryManager repoManager;
+  private final SuperManifestRepoManager.Factory repoManagerFactory;
   private final URI canonicalWebUrl;
   private final PluginConfigFactory cfgFactory;
   private final String pluginName;
@@ -102,14 +103,14 @@
       PluginConfigFactory cfgFactory,
       ProjectCache projectCache,
       @GerritPersonIdent Provider<PersonIdent> serverIdent,
-      GitRepositoryManager repoManager,
+      SuperManifestRepoManager.Factory repoManagerFactory,
       Provider<IdentifiedUser> identifiedUser,
       PermissionBackend permissionBackend) {
 
     this.pluginName = pluginName;
     this.serverIdent = serverIdent;
     this.allProjectsName = allProjectsName;
-    this.repoManager = repoManager;
+    this.repoManagerFactory = repoManagerFactory;
     try {
       this.canonicalWebUrl = new URI(canonicalWebUrl);
     } catch (URISyntaxException e) {
@@ -329,9 +330,7 @@
             String.format("invalid toolType: %s", c.getToolType().name()));
     }
     try (GerritRemoteReader reader =
-        new GerritRemoteReader(
-            new GerritSuperManifestRepoManager(repoManager, canonicalWebUrl.toString()),
-            canonicalWebUrl.toString())) {
+        new GerritRemoteReader(repoManagerFactory.create(c), canonicalWebUrl.toString())) {
       subModuleUpdater.update(reader, c, refName);
     }
   }
@@ -443,6 +442,10 @@
     Repository openByUri(String uriStr) throws IOException;
 
     Repository openByName(Project.NameKey repoName) throws IOException;
+
+    interface Factory {
+      SuperManifestRepoManager create(ConfigEntry c);
+    }
   }
 
   static class GerritSuperManifestRepoManager implements SuperManifestRepoManager {
@@ -450,8 +453,11 @@
     private final GitRepositoryManager repoManager;
     private final String canonicalWebUrl;
 
+    @Inject
     GerritSuperManifestRepoManager(
-        GitRepositoryManager repoManager, @CanonicalWebUrl String canonicalWebUrl) {
+        GitRepositoryManager repoManager,
+        @CanonicalWebUrl String canonicalWebUrl,
+        @Assisted ConfigEntry e) {
       this.repos = new HashMap<>();
       this.repoManager = repoManager;
       this.canonicalWebUrl = canonicalWebUrl;
diff --git a/javatests/com/googlesource/gerrit/plugins/supermanifest/GerritRemoteReaderTest.java b/javatests/com/googlesource/gerrit/plugins/supermanifest/GerritRemoteReaderTest.java
index bf32da6..4b4c832 100644
--- a/javatests/com/googlesource/gerrit/plugins/supermanifest/GerritRemoteReaderTest.java
+++ b/javatests/com/googlesource/gerrit/plugins/supermanifest/GerritRemoteReaderTest.java
@@ -27,7 +27,7 @@
   private GitRepositoryManager repoManager = new InMemoryRepositoryManager();
   SuperManifestRefUpdatedListener.GerritSuperManifestRepoManager superManifestRepoManager =
       new SuperManifestRefUpdatedListener.GerritSuperManifestRepoManager(
-          repoManager, CANONICAL_WEB_URL);
+          repoManager, CANONICAL_WEB_URL, null);
   private SuperManifestRefUpdatedListener.GerritRemoteReader reader =
       new SuperManifestRefUpdatedListener.GerritRemoteReader(
           superManifestRepoManager, CANONICAL_WEB_URL);
diff --git a/javatests/com/googlesource/gerrit/plugins/supermanifest/GerritSuperManifestRepoManagerTest.java b/javatests/com/googlesource/gerrit/plugins/supermanifest/GerritSuperManifestRepoManagerTest.java
index 08980fe..9dad5ea 100644
--- a/javatests/com/googlesource/gerrit/plugins/supermanifest/GerritSuperManifestRepoManagerTest.java
+++ b/javatests/com/googlesource/gerrit/plugins/supermanifest/GerritSuperManifestRepoManagerTest.java
@@ -23,7 +23,7 @@
     repoManager.createRepository(Project.nameKey("project/x"));
     superManifestRepoManager =
         new SuperManifestRefUpdatedListener.GerritSuperManifestRepoManager(
-            repoManager, CANONICAL_WEB_URL);
+            repoManager, CANONICAL_WEB_URL, null);
   }
 
   @Test