Sort subdirectories alphabetically

Change-Id: I5f8716d115380fe68a718c03ae02dd79ebecb28e
diff --git a/java/com/google/gitiles/TreeSoyData.java b/java/com/google/gitiles/TreeSoyData.java
index e1aeb21..985edfa 100644
--- a/java/com/google/gitiles/TreeSoyData.java
+++ b/java/com/google/gitiles/TreeSoyData.java
@@ -73,8 +73,22 @@
     return lastSlash >= 0 ? "..." + target.substring(lastSlash) : target;
   }
 
-  static int sortByType(Map<String, String> m1, Map<String, String> m2) {
-    return TYPE_WEIGHT.get(m1.get("type")).compareTo(TYPE_WEIGHT.get(m2.get("type")));
+  static String stripEndingSolidus(String p) {
+    return p.endsWith("/") ? p.substring(0, p.length() - 1) : p;
+  }
+
+  static int sortByTypeAlpha(Map<String, String> m1, Map<String, String> m2) {
+    int weightDiff = TYPE_WEIGHT.get(m1.get("type")).compareTo(TYPE_WEIGHT.get(m2.get("type")));
+    if (weightDiff == 0) {
+      String s1 = m1.get("name");
+      String s2 = m2.get("name");
+      if (m1.get("type").equals("TREE")) {
+        s1 = stripEndingSolidus(s1);
+        s2 = stripEndingSolidus(s2);
+      }
+      return s1.compareToIgnoreCase(s2);
+    }
+    return weightDiff;
   }
 
   private final ObjectReader reader;
@@ -141,7 +155,7 @@
       entries.add(entry);
     }
 
-    entries.sort(TreeSoyData::sortByType);
+    entries.sort(TreeSoyData::sortByTypeAlpha);
 
     Map<String, Object> data = Maps.newHashMapWithExpectedSize(3);
     data.put("sha", treeId.name());
diff --git a/javatests/com/google/gitiles/TreeSoyDataTest.java b/javatests/com/google/gitiles/TreeSoyDataTest.java
index cafe4e2..75ae771 100644
--- a/javatests/com/google/gitiles/TreeSoyDataTest.java
+++ b/javatests/com/google/gitiles/TreeSoyDataTest.java
@@ -17,11 +17,11 @@
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.gitiles.TreeSoyData.getTargetDisplayName;
 import static com.google.gitiles.TreeSoyData.resolveTargetUrl;
-import static com.google.gitiles.TreeSoyData.sortByType;
+import static com.google.gitiles.TreeSoyData.sortByTypeAlpha;
 
 import com.google.common.base.Strings;
-import java.util.Map;
 import java.util.HashMap;
+import java.util.Map;
 import org.eclipse.jgit.lib.ObjectId;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -70,22 +70,44 @@
 
   @Test
   public void sortByTypeSortsCorrect() throws Exception {
-    Map<String, String> m1 = new HashMap<String, String>();
-    Map<String, String> m2 = new HashMap<String, String>();
-    Map<String, String> m3 = new HashMap<String, String>();
-    Map<String, String> m4 = new HashMap<String, String>();
-    Map<String, String> m5 = new HashMap<String, String>();
+    Map<String, String> m1 = new HashMap<>();
+    Map<String, String> m2 = new HashMap<>();
+    Map<String, String> m3 = new HashMap<>();
+    Map<String, String> m4 = new HashMap<>();
+    Map<String, String> m5 = new HashMap<>();
+    Map<String, String> m6 = new HashMap<>();
     m1.put("type", "TREE");
+    m1.put("name", "aa");
     m2.put("type", "TREE");
+    m2.put("name", "BB");
     m3.put("type", "SYMLINK");
     m4.put("type", "REGULAR_FILE");
     m5.put("type", "GITLINK");
-    assertThat(sortByType(m1, m2)).isEqualTo(0);
-    assertThat(sortByType(m2, m3)).isEqualTo(-1);
-    assertThat(sortByType(m3, m4)).isEqualTo(-1);
-    assertThat(sortByType(m4, m1)).isEqualTo(1);
-    assertThat(sortByType(m1, m4)).isEqualTo(-1);
-    assertThat(sortByType(m5, m2)).isEqualTo(1);
-    assertThat(sortByType(m2, m5)).isEqualTo(-1);
+    m6.put("type", "TREE");
+    m6.put("name", "AA");
+    assertThat(sortByTypeAlpha(m1, m2)).isEqualTo(-1);
+    assertThat(sortByTypeAlpha(m2, m3)).isEqualTo(-1);
+    assertThat(sortByTypeAlpha(m3, m4)).isEqualTo(-1);
+    assertThat(sortByTypeAlpha(m4, m1)).isEqualTo(1);
+    assertThat(sortByTypeAlpha(m1, m4)).isEqualTo(-1);
+    assertThat(sortByTypeAlpha(m5, m2)).isEqualTo(1);
+    assertThat(sortByTypeAlpha(m2, m5)).isEqualTo(-1);
+    assertThat(sortByTypeAlpha(m1, m6)).isEqualTo(0);
+    assertThat(sortByTypeAlpha(m2, m1)).isEqualTo(1);
+  }
+
+  @Test
+  public void sortByShortestPathFirst() throws Exception {
+    Map<String, String> p1 = new HashMap<>();
+    Map<String, String> p2 = new HashMap<>();
+    Map<String, String> p3 = new HashMap<>();
+    p1.put("type", "TREE");
+    p1.put("name", "short/");
+    p2.put("type", "TREE");
+    p2.put("name", "shortpath/");
+    p3.put("type", "TREE");
+    p3.put("name", "short.path/");
+    assertThat(sortByTypeAlpha(p1, p2)).isLessThan(0);
+    assertThat(sortByTypeAlpha(p1, p3)).isLessThan(0);
   }
 }