Add tarball download link to commit detail

Change-Id: Icadb5abf99dabc6f45d5b074562f7967fd8df18e
diff --git a/gitiles-servlet/src/main/java/com/google/gitiles/CommitSoyData.java b/gitiles-servlet/src/main/java/com/google/gitiles/CommitSoyData.java
index 73be524..425a1a2 100644
--- a/gitiles-servlet/src/main/java/com/google/gitiles/CommitSoyData.java
+++ b/gitiles-servlet/src/main/java/com/google/gitiles/CommitSoyData.java
@@ -62,7 +62,8 @@
 public class CommitSoyData {
   /** Valid sets of keys to include in Soy data for commits. */
   public static enum KeySet {
-    DETAIL("author", "committer", "sha", "tree", "treeUrl", "parents", "message", "logUrl"),
+    DETAIL("author", "committer", "sha", "tree", "treeUrl", "parents", "message", "logUrl",
+        "tgzUrl"),
     DETAIL_DIFF_TREE(DETAIL, "diffTree"),
     SHORTLOG("abbrevSha", "url", "shortMessage", "author", "branches", "tags"),
     DEFAULT(DETAIL);
@@ -129,13 +130,10 @@
           .toUrl());
     }
     if (keys.keys.contains("logUrl")) {
-      Revision rev = view.getRevision();
-      GitilesView.Builder logView = GitilesView.log()
-          .copyFrom(view)
-          .setRevision(rev.getId().equals(commit) ? rev.getName() : commit.name(), commit)
-          .setOldRevision(Revision.NULL)
-          .setPathPart(null);
-      data.put("logUrl", logView.toUrl());
+      data.put("logUrl", urlFromView(view, commit, GitilesView.log()));
+    }
+    if (keys.keys.contains("tgzUrl")) {
+      data.put("tgzUrl", urlFromView(view, commit, GitilesView.archive().setExtension(".tar.gz")));
     }
     if (keys.keys.contains("tree")) {
       data.put("tree", ObjectId.toString(commit.getTree()));
@@ -300,4 +298,12 @@
     Collections.sort(result, NAME_COMPARATOR);
     return result;
   }
+
+  private String urlFromView(GitilesView view, RevCommit commit, GitilesView.Builder builder) {
+    Revision rev = view.getRevision();
+    return builder.copyFrom(view)
+        .setRevision(rev.getId().equals(commit) ? rev.getName() : commit.name(), commit)
+        .setPathPart(null)
+        .toUrl();
+  }
 }
diff --git a/gitiles-servlet/src/main/java/com/google/gitiles/GitilesView.java b/gitiles-servlet/src/main/java/com/google/gitiles/GitilesView.java
index 9121578..4567031 100644
--- a/gitiles-servlet/src/main/java/com/google/gitiles/GitilesView.java
+++ b/gitiles-servlet/src/main/java/com/google/gitiles/GitilesView.java
@@ -193,11 +193,13 @@
         case DIFF:
         case LOG:
           this.oldRevision = revision;
-          return this;
+          break;
         default:
-          throw new IllegalStateException(
-              String.format("cannot set old revision on %s view", type));
+          checkState(revision == null, "cannot set old revision on %s view", type);
+          this.oldRevision = revision;
+          break;
       }
+      return this;
     }
 
     public Builder setOldRevision(RevObject obj) {
@@ -217,15 +219,18 @@
         case PATH:
         case DIFF:
           this.path = maybeTrimLeadingAndTrailingSlash(checkNotNull(path));
-          return this;
+          break;
         case DESCRIBE:
         case REFS:
         case LOG:
           this.path = path != null ? maybeTrimLeadingAndTrailingSlash(path) : null;
-          return this;
+          break;
         default:
-          throw new IllegalStateException(String.format("cannot set path on %s view", type));
+          checkState(path == null, "cannot set path on %s view", type);
+          this.path = path;
+          break;
       }
+      return this;
     }
 
     public String getPathPart() {
diff --git a/gitiles-servlet/src/main/resources/com/google/gitiles/static/gitiles.css b/gitiles-servlet/src/main/resources/com/google/gitiles/static/gitiles.css
index a1f8df1..0f1f67b 100644
--- a/gitiles-servlet/src/main/resources/com/google/gitiles/static/gitiles.css
+++ b/gitiles-servlet/src/main/resources/com/google/gitiles/static/gitiles.css
@@ -60,7 +60,7 @@
   padding-top: 0.25em;
   padding-bottom: 0.25em;
 }
-.log-link {
+.log-link, .download-link {
   margin-left: 0.5em
 }
 
diff --git a/gitiles-servlet/src/main/resources/com/google/gitiles/templates/ObjectDetail.soy b/gitiles-servlet/src/main/resources/com/google/gitiles/templates/ObjectDetail.soy
index badf43c..2d3a259 100644
--- a/gitiles-servlet/src/main/resources/com/google/gitiles/templates/ObjectDetail.soy
+++ b/gitiles-servlet/src/main/resources/com/google/gitiles/templates/ObjectDetail.soy
@@ -36,6 +36,7 @@
  *     url: URL to a detail page for the tree entry.
  *     diffUrl: URL to a diff page for the tree entry's diff in this commit.
  * @param logUrl URL to a log page starting at this commit.
+ * @param tgzUrl URL to a download link of this commit as a tarball.
  */
 {template .commitDetail}
 <div class="git-commit">
@@ -47,6 +48,9 @@
         <span class="log-link">
           [<a href="{$logUrl}">{msg desc="text for the log link"}log{/msg}</a>]
         </span>
+        <span class="download-link">
+          [<a href="{$tgzUrl}">{msg desc="text for the tarball link"}tgz{/msg}</a>]
+        </span>
       </td>
       <td>{sp}</td>
     </tr>