Add ssh command create-branch for creating branches

This command will allow users to create branches via ssh.

Feature: Issue 1156
Change-Id: I270df6bc3ed95581aa2fc6845c654f2d9a5c72b1
diff --git a/Documentation/access-control.txt b/Documentation/access-control.txt
index b6f7d7c..facc8f2 100644
--- a/Documentation/access-control.txt
+++ b/Documentation/access-control.txt
@@ -542,13 +542,12 @@
 configuration.  Users who are members of an owner group can:
 
 * Change the project description
-* Create/delete a branch through the web UI (not SSH)
+* Create a branch through SSH
+* Create/delete a branch through the web UI
 * Grant/revoke any access rights, including `Owner`
 
-Note that project owners implicitly have branch creation or deletion
-through the web UI, but not through SSH.  To get SSH branch access
-project owners must grant an access right to a group they are a
-member of, just like for any other user.
+To get SSH branch access project owners must grant an access right to a group
+they are a member of, just like for any other user.
 
 Ownership over a particular branch subspace may be delegated by
 entering a branch pattern.  To delegate control over all branches
diff --git a/Documentation/cmd-create-branch.txt b/Documentation/cmd-create-branch.txt
new file mode 100644
index 0000000..6e6d561
--- /dev/null
+++ b/Documentation/cmd-create-branch.txt
@@ -0,0 +1,58 @@
+gerrit create-branch
+====================
+
+NAME
+----
+gerrit create-branch - Create a new branch
+
+SYNOPSIS
+--------
+--
+'ssh' -p <port> <host> 'gerrit create-branch'
+  <PROJECT>
+  <NAME>
+  <REVISION>
+--
+
+DESCRIPTION
+-----------
+Creates a new branch for a project.
+
+ACCESS
+------
+Caller should have link:access-control.html#category_create[Create Reference]
+permission on the project.
+
+Administrators do not automatically have permission to create branches. It must
+be granted via the Create Reference permission.
+
+SCRIPTING
+---------
+This command is intended to be used in scripts.
+
+OPTIONS
+-------
+<PROJECT>::
+    Required; name of the project.
+
+<NAME>::
+    Required; name of the branch to be created.
+
+<REVISION>::
+    Required; base revision of the new branch.
+
+EXAMPLES
+--------
+Create a new branch called 'newbranch' from the 'master' branch of
+the project 'myproject'.
+
+====
+    $ ssh -p 29418 review.example.com gerrit create-branch myproject newbranch master
+====
+
+GERRIT
+------
+Part of link:index.html[Gerrit Code Review]
+
+SEARCHBOX
+---------
diff --git a/Documentation/cmd-index.txt b/Documentation/cmd-index.txt
index 4e62451..6ddfa36 100644
--- a/Documentation/cmd-index.txt
+++ b/Documentation/cmd-index.txt
@@ -96,6 +96,9 @@
 Also implements the magic associated with uploading commits for
 review.  See link:user-upload.html#push_create[Creating Changes].
 
+link:cmd-create-branch.html[gerrit create-branch]::
+	Create a new project branch.
+
 [[admin_commands]]Administrator Commands
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateBranchCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateBranchCommand.java
new file mode 100644
index 0000000..16ffe28
--- /dev/null
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateBranchCommand.java
@@ -0,0 +1,59 @@
+// Copyright (C) 2013 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.google.gerrit.sshd.commands;
+
+import com.google.gerrit.extensions.api.GerritApi;
+import com.google.gerrit.extensions.api.projects.BranchApi;
+import com.google.gerrit.extensions.api.projects.BranchInput;
+import com.google.gerrit.extensions.restapi.RestApiException;
+import com.google.gerrit.server.project.CreateBranch;
+import com.google.gerrit.server.project.ProjectControl;
+import com.google.gerrit.sshd.CommandMetaData;
+import com.google.gerrit.sshd.SshCommand;
+import com.google.inject.Inject;
+
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.Option;
+
+import java.io.IOException;
+
+/** Create a new branch. **/
+@CommandMetaData(name = "create-branch", description = "Create a new branch")
+final public class CreateBranchCommand extends SshCommand {
+
+  @Argument(index = 0, required = true, metaVar = "PROJECT", usage = "name of the project")
+  private ProjectControl project;
+
+  @Argument(index = 1, required = true, metaVar = "NAME", usage = "name of branch to be created")
+  private String name;
+
+  @Argument(index = 2, required = true, metaVar = "REVISION", usage = "base revision of the new branch")
+  private String revision;
+
+  @Inject
+  GerritApi gApi;
+
+  @Override
+  protected void run() throws UnloggedFailure {
+    try {
+      BranchInput in = new BranchInput();
+      in.revision = revision;
+      gApi.projects().name(project.getProject().getNameKey().get())
+          .branch(name).create(in);
+    } catch (RestApiException e) {
+      throw new UnloggedFailure(1, "fatal: " + e.getMessage(), e);
+    }
+  }
+}
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/MasterCommandModule.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/MasterCommandModule.java
index a8d5c4d..a79e862 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/MasterCommandModule.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/MasterCommandModule.java
@@ -31,6 +31,7 @@
     command(gerrit, CreateGroupCommand.class);
     command(gerrit, RenameGroupCommand.class);
     command(gerrit, CreateProjectCommand.class);
+    command(gerrit, CreateBranchCommand.class);
     command(gerrit, AdminQueryShell.class);
     command(gerrit, SetReviewersCommand.class);
     command(gerrit, Receive.class);