Add user/password authentication for CGit client

CGit client must provide user and password authentication for
pull-replication fetch calls when specified in secure.config.
Amend replication uri with credentials from secure.config.

Bug: Issue 15629
Change-Id: Ib8a67650671997cd9044ce54e56f3f2e1b75c271
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/fetch/CGitFetch.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/fetch/CGitFetch.java
index 9f055c8..c404e30 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/fetch/CGitFetch.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/fetch/CGitFetch.java
@@ -19,6 +19,7 @@
 import com.google.common.collect.Lists;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
+import com.googlesource.gerrit.plugins.replication.CredentialsFactory;
 import com.googlesource.gerrit.plugins.replication.pull.SourceConfiguration;
 import java.io.BufferedReader;
 import java.io.File;
@@ -30,6 +31,8 @@
 import org.eclipse.jgit.errors.TransportException;
 import org.eclipse.jgit.lib.RefUpdate;
 import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.transport.CredentialItem;
+import org.eclipse.jgit.transport.CredentialsProvider;
 import org.eclipse.jgit.transport.RefSpec;
 import org.eclipse.jgit.transport.URIish;
 
@@ -40,17 +43,20 @@
   private int timeout;
 
   @Inject
-  public CGitFetch(SourceConfiguration config, @Assisted URIish uri, @Assisted Repository git) {
-
+  public CGitFetch(
+      SourceConfiguration config,
+      CredentialsFactory cpFactory,
+      @Assisted URIish uri,
+      @Assisted Repository git) {
     this.localProjectDirectory = git.getDirectory();
-    this.uri = uri;
+    this.uri = appendCredentials(uri, cpFactory.create(config.getRemoteConfig().getName()));
     this.timeout = config.getRemoteConfig().getTimeout();
   }
 
   @Override
   public List<RefUpdateState> fetch(List<RefSpec> refsSpec) throws IOException {
     List<String> refs = refsSpec.stream().map(s -> s.toString()).collect(Collectors.toList());
-    List<String> command = Lists.newArrayList("git", "fetch", uri.toASCIIString());
+    List<String> command = Lists.newArrayList("git", "fetch", uri.toPrivateASCIIString());
     command.addAll(refs);
     ProcessBuilder pb = new ProcessBuilder().command(command).directory(localProjectDirectory);
     repLog.info("Fetch references {} from {}", refs, uri);
@@ -83,6 +89,19 @@
     }
   }
 
+  protected URIish appendCredentials(URIish uri, CredentialsProvider credentialsProvider) {
+    CredentialItem.Username user = new CredentialItem.Username();
+    CredentialItem.Password pass = new CredentialItem.Password();
+    if (credentialsProvider.supports(user, pass)
+        && credentialsProvider.get(uri, user, pass)
+        && uri.getScheme() != null
+        && !"ssh".equalsIgnoreCase(uri.getScheme())) {
+      return uri.setUser(user.getValue()).setPass(String.valueOf(pass.getValue()));
+    }
+
+    return uri;
+  }
+
   public boolean waitForTaskToFinish(Process process) throws InterruptedException {
     if (timeout == 0) {
       process.waitFor();
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/CGitFetchIT.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/CGitFetchIT.java
index a02f43f..406cd8c 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/CGitFetchIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/CGitFetchIT.java
@@ -34,7 +34,12 @@
 import com.google.gerrit.extensions.config.FactoryModule;
 import com.google.gerrit.server.config.SitePaths;
 import com.google.inject.Inject;
+import com.google.inject.Scopes;
 import com.google.inject.assistedinject.FactoryModuleBuilder;
+import com.googlesource.gerrit.plugins.replication.AutoReloadSecureCredentialsFactoryDecorator;
+import com.googlesource.gerrit.plugins.replication.CredentialsFactory;
+import com.googlesource.gerrit.plugins.replication.ReplicationConfig;
+import com.googlesource.gerrit.plugins.replication.ReplicationFileBasedConfig;
 import com.googlesource.gerrit.plugins.replication.pull.fetch.BatchFetchClient;
 import com.googlesource.gerrit.plugins.replication.pull.fetch.CGitFetch;
 import com.googlesource.gerrit.plugins.replication.pull.fetch.Fetch;
@@ -270,6 +275,10 @@
       try {
         RemoteConfig remoteConfig = new RemoteConfig(cf, "test_config");
         SourceConfiguration sourceConfig = new SourceConfiguration(remoteConfig, cf);
+        bind(ReplicationConfig.class).to(ReplicationFileBasedConfig.class);
+        bind(CredentialsFactory.class)
+            .to(AutoReloadSecureCredentialsFactoryDecorator.class)
+            .in(Scopes.SINGLETON);
 
         bind(SourceConfiguration.class).toInstance(sourceConfig);
         install(