Display the sha1 of each branch for all relevant projects in ssh

Having the ability to know the sha1 of a branch for all projects in
gerrit can make an automatic build server more efficient so as to not
resync the projects that it already has.

This change adds an optional '--show-branch' argument to gerrit
ls-projects that can be used to specify a branch name. The revision of
that branch will be displayed next to the name of the project in the
list returned by the command.

Change-Id: Iaf662fb1d46e640a88a7e1dbb68f0f4052defe4c
diff --git a/Documentation/cmd-ls-projects.txt b/Documentation/cmd-ls-projects.txt
index 02c03ae..1200e18 100644
--- a/Documentation/cmd-ls-projects.txt
+++ b/Documentation/cmd-ls-projects.txt
@@ -8,7 +8,7 @@
 SYNOPSIS
 --------
 [verse]
-'ssh' -p <port> <host> 'gerrit ls-projects'
+'ssh' -p <port> <host> 'gerrit ls-projects' [\--show-branch <BRANCH>]
 
 DESCRIPTION
 -----------
@@ -26,6 +26,12 @@
 ---------
 This command is intended to be used in scripts.
 
+OPTIONS
+-------
+\--show-branch::
+\-b::
+	Name of the branch for which the command will display the sha of each project.
+
 EXAMPLES
 --------
 
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ListProjects.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ListProjects.java
index 299dbe7..fb714fe 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ListProjects.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ListProjects.java
@@ -14,19 +14,35 @@
 
 package com.google.gerrit.sshd.commands;
 
+import com.google.gerrit.reviewdb.Branch;
 import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.RevId;
 import com.google.gerrit.reviewdb.ReviewDb;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.config.WildProjectName;
+import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.project.ProjectCache;
+import com.google.gerrit.server.project.ProjectControl;
 import com.google.gerrit.server.project.ProjectState;
 import com.google.gerrit.sshd.BaseCommand;
 import com.google.gwtorm.client.OrmException;
 import com.google.inject.Inject;
 
 import org.apache.sshd.server.Environment;
+import org.eclipse.jgit.errors.RepositoryNotFoundException;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.Repository;
+import org.kohsuke.args4j.Option;
 
+import java.io.IOException;
 import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
 
 final class ListProjects extends BaseCommand {
   @Inject
@@ -39,9 +55,16 @@
   private ProjectCache projectCache;
 
   @Inject
+  private GitRepositoryManager repoManager;
+
+  @Inject
   @WildProjectName
   private Project.NameKey wildProject;
 
+  @Option(name = "--show-branch", aliases = {"-b"},
+      usage = "displays the sha of each project in the specified branch")
+  private String showBranch;
+
   @Override
   public void start(final Environment env) {
     startThread(new CommandRunnable() {
@@ -53,6 +76,21 @@
     });
   }
 
+  private final ObjectId getObjectIdForBranch(Project.NameKey projectName,
+      String branch) {
+    try {
+      final Repository r = repoManager.openRepository(projectName.get());
+      try {
+        Ref ref = r.getRef(branch);
+        return ref == null ? null : ref.getObjectId();
+      } finally {
+        r.close();
+      }
+    } catch (IOException ioe) {
+      return null;
+    }
+  }
+
   private void display() throws Failure {
     final PrintWriter stdout = toPrintWriter(out);
     try {
@@ -65,8 +103,17 @@
 
         final ProjectState e = projectCache.get(p.getNameKey());
         if (e != null && e.controlFor(currentUser).isVisible()) {
-          stdout.print(p.getName());
-          stdout.println();
+          if (showBranch != null) {
+            ObjectId id = getObjectIdForBranch(p.getNameKey(), showBranch);
+            if (id != null) {
+              stdout.print(id.name() + " ");
+              stdout.print(p.getName());
+              stdout.println();
+            }
+          } else {
+            stdout.print(p.getName());
+            stdout.println();
+          }
         }
       }
     } catch (OrmException e) {