Add a checkout+branch command

Bug: Issue 11609
Change-Id: Ic8307132782e42b58a1652b8975176730b2f86c0
diff --git a/src/main/java/com/googlesource/gerrit/plugins/download/command/BranchCommand.java b/src/main/java/com/googlesource/gerrit/plugins/download/command/BranchCommand.java
new file mode 100644
index 0000000..e38ccd4
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/download/command/BranchCommand.java
@@ -0,0 +1,49 @@
+// Copyright 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.googlesource.gerrit.plugins.download.command;
+
+import static com.google.gerrit.extensions.client.GeneralPreferencesInfo.DownloadCommand.CHECKOUT;
+
+import com.google.gerrit.server.config.DownloadConfig;
+import com.google.gerrit.server.config.GerritServerConfig;
+import com.google.gerrit.server.git.GitRepositoryManager;
+import com.google.inject.Inject;
+import org.eclipse.jgit.lib.Config;
+
+class BranchCommand extends GitDownloadCommand {
+  @Inject
+  BranchCommand(
+      @GerritServerConfig Config cfg,
+      DownloadConfig downloadConfig,
+      GitRepositoryManager repoManager) {
+    super(cfg, downloadConfig, CHECKOUT, repoManager);
+  }
+
+  @Override
+  String getCommand(String url, String ref, String id) {
+    return "git fetch "
+        + QuoteUtil.quote(url)
+        + " "
+        + ref
+        + " && git checkout -b CL-"
+        + id.replaceAll("/", "-")
+        + " FETCH_HEAD";
+  }
+
+  @Override
+  String getRepoCommand(String url, String id) {
+    return "repo download -b CL-" + id.replaceAll("/", "-") + " " + QuoteUtil.quote(url) + " " + id;
+  }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/download/command/CheckoutCommand.java b/src/main/java/com/googlesource/gerrit/plugins/download/command/CheckoutCommand.java
index 34ca19c..bc3ede6 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/download/command/CheckoutCommand.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/download/command/CheckoutCommand.java
@@ -32,7 +32,7 @@
   }
 
   @Override
-  String getCommand(String url, String ref) {
+  String getCommand(String url, String ref, String id) {
     return "git fetch " + QuoteUtil.quote(url) + " " + ref + " && git checkout FETCH_HEAD";
   }
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/download/command/CherryPickCommand.java b/src/main/java/com/googlesource/gerrit/plugins/download/command/CherryPickCommand.java
index 0e964be..4856e83 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/download/command/CherryPickCommand.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/download/command/CherryPickCommand.java
@@ -32,7 +32,7 @@
   }
 
   @Override
-  String getCommand(String url, String ref) {
+  String getCommand(String url, String ref, String id) {
     return "git fetch " + QuoteUtil.quote(url) + " " + ref + " && git cherry-pick FETCH_HEAD";
   }
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/download/command/DownloadCommandsModule.java b/src/main/java/com/googlesource/gerrit/plugins/download/command/DownloadCommandsModule.java
index 7ab47f2..2f64b71 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/download/command/DownloadCommandsModule.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/download/command/DownloadCommandsModule.java
@@ -23,6 +23,8 @@
   protected void configure() {
     bind(DownloadCommand.class).annotatedWith(Exports.named("Checkout")).to(CheckoutCommand.class);
 
+    bind(DownloadCommand.class).annotatedWith(Exports.named("Branch")).to(BranchCommand.class);
+
     bind(DownloadCommand.class)
         .annotatedWith(Exports.named("Cherry Pick"))
         .to(CherryPickCommand.class);
diff --git a/src/main/java/com/googlesource/gerrit/plugins/download/command/FormatPatchCommand.java b/src/main/java/com/googlesource/gerrit/plugins/download/command/FormatPatchCommand.java
index a65b5e1..eb3ec3a 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/download/command/FormatPatchCommand.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/download/command/FormatPatchCommand.java
@@ -32,7 +32,7 @@
   }
 
   @Override
-  String getCommand(String url, String ref) {
+  String getCommand(String url, String ref, String id) {
     return "git fetch "
         + QuoteUtil.quote(url)
         + " "
diff --git a/src/main/java/com/googlesource/gerrit/plugins/download/command/GitDownloadCommand.java b/src/main/java/com/googlesource/gerrit/plugins/download/command/GitDownloadCommand.java
index e47a31a..f85ffb4 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/download/command/GitDownloadCommand.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/download/command/GitDownloadCommand.java
@@ -61,20 +61,25 @@
   @Override
   public final String getCommand(DownloadScheme scheme, String project, String ref) {
     if (commandAllowed) {
+      String id = refToId(ref);
+      if (id == null) {
+        return null;
+      }
+
       String url = scheme.getUrl(project);
+      if (url == null) {
+        return null;
+      }
+
       if (scheme instanceof RepoScheme) {
-        String id = refToId(ref);
-        if (id != null) {
-          return getRepoCommand(url, id);
+        return getRepoCommand(url, id);
+      }
+      if (isValidUrl(url)) {
+        if (checkForHiddenChangeRefs) {
+          ref = resolveRef(project, ref);
         }
-      } else {
-        if (url != null && isValidUrl(url)) {
-          if (checkForHiddenChangeRefs) {
-            ref = resolveRef(project, ref);
-          }
-          if (ref != null) {
-            return getCommand(url, ref);
-          }
+        if (ref != null) {
+          return getCommand(url, ref, id);
         }
       }
     }
@@ -134,7 +139,12 @@
     }
   }
 
-  abstract String getCommand(String url, String ref);
+  /**
+   * @param url The project URL this change is for.
+   * @param ref Git named ref to this CL/patchset.
+   * @param id The CL/PS numbers.
+   */
+  abstract String getCommand(String url, String ref, String id);
 
   /**
    * @param url The project URL this change is for.
diff --git a/src/main/java/com/googlesource/gerrit/plugins/download/command/PullCommand.java b/src/main/java/com/googlesource/gerrit/plugins/download/command/PullCommand.java
index d93f6b6..97b4c6e 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/download/command/PullCommand.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/download/command/PullCommand.java
@@ -32,7 +32,7 @@
   }
 
   @Override
-  String getCommand(String url, String ref) {
+  String getCommand(String url, String ref, String id) {
     return "git pull " + QuoteUtil.quote(url) + " " + ref;
   }
 }