Support JSON view of commits in RevisionServlet Example output: $ curl 'http://localhost:8080/gitiles/+/1040ab8d5861e2804f725a936ca9b6f3be6f6239?format=JSON' )]}' { "commit": "1040ab8d5861e2804f725a936ca9b6f3be6f6239", "parents": [ "0ad024fb5aa3e4994ede801428b4e30ba06a837d" ], "author": { "name": "Dave Borowitz", "email": "[email protected]", "time": "Sun Mar 16 13:49:37 2014 -0700" }, "committer": { "name": "Dave Borowitz", "email": "[email protected]", "time": "Sun Mar 16 13:49:37 2014 -0700" }, "message": "Use CommitData to produce CommitJsonData\n\nChange-Id: I7261b0c40e97119c32627c4ea89038bbe174925f\n", "tree_diff": [ { "type": "modify", "old_id": "87f3456c40f24662d28411fda9b2cf05b82bf007", "old_mode": 33188, "old_path": "gitiles-servlet/src/main/java/com/google/gitiles/CommitJsonData.java", "new_id": "07fbd1e0eb753aa41dee53c758ced595f18f67bf", "new_mode": 33188, "new_path": "gitiles-servlet/src/main/java/com/google/gitiles/CommitJsonData.java" }, { "type": "modify", "old_id": "aa6bd34861cf2f49abd357edff0b2f3ff354aa91", "old_mode": 33188, "old_path": "gitiles-servlet/src/main/java/com/google/gitiles/LogServlet.java", "new_id": "e6ae4c2062bfe3dfb6f059f282e90af64bbd10d3", "new_mode": 33188, "new_path": "gitiles-servlet/src/main/java/com/google/gitiles/LogServlet.java" } ] } Change-Id: I29b76ce331bd6876476e3ddd56f2f484450b7e87
diff --git a/gitiles-servlet/src/main/java/com/google/gitiles/CommitData.java b/gitiles-servlet/src/main/java/com/google/gitiles/CommitData.java index 1c118dd..0f614e6 100644 --- a/gitiles-servlet/src/main/java/com/google/gitiles/CommitData.java +++ b/gitiles-servlet/src/main/java/com/google/gitiles/CommitData.java
@@ -22,7 +22,9 @@ import com.google.common.base.Predicate; import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; import com.google.common.collect.Ordering; +import com.google.common.collect.Sets; import org.eclipse.jgit.diff.DiffEntry; import org.eclipse.jgit.diff.DiffFormatter; @@ -70,6 +72,10 @@ TREE, TREE_URL, URL; + + static ImmutableSet<Field> setOf(Iterable<Field> base, Field... fields) { + return Sets.immutableEnumSet(Iterables.concat(base, Arrays.asList(fields))); + } } static class DiffList {
diff --git a/gitiles-servlet/src/main/java/com/google/gitiles/CommitJsonData.java b/gitiles-servlet/src/main/java/com/google/gitiles/CommitJsonData.java index 10a8c24..e887441 100644 --- a/gitiles-servlet/src/main/java/com/google/gitiles/CommitJsonData.java +++ b/gitiles-servlet/src/main/java/com/google/gitiles/CommitJsonData.java
@@ -17,8 +17,10 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; import com.google.common.collect.Sets; +import com.google.gitiles.CommitData.DiffList; import com.google.gitiles.CommitData.Field; +import org.eclipse.jgit.diff.DiffEntry; import org.eclipse.jgit.lib.PersonIdent; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevWalk; @@ -26,12 +28,13 @@ import java.io.IOException; import java.util.List; +import java.util.Set; import javax.annotation.Nullable; import javax.servlet.http.HttpServletRequest; class CommitJsonData { - private static final ImmutableSet<Field> DEFAULT_FIELDS = Sets.immutableEnumSet( + static final ImmutableSet<Field> DEFAULT_FIELDS = Sets.immutableEnumSet( Field.SHA, Field.PARENTS, Field.AUTHOR, Field.COMMITTER, Field.MESSAGE); static class Commit { @@ -40,6 +43,8 @@ Ident author; Ident committer; String message; + + List<Diff> treeDiff; } static class Ident { @@ -48,6 +53,18 @@ String time; } + /** @see DiffEntry */ + static class Diff { + String type; + String oldId; + int oldMode; + String oldPath; + String newId; + int newMode; + String newPath; + Integer score; + } + private RevWalk walk; CommitJsonData setRevWalk(@Nullable RevWalk walk) { @@ -55,11 +72,15 @@ return this; } - Commit toJsonData(HttpServletRequest req, RevCommit c, GitDateFormatter df) + Commit toJsonData(HttpServletRequest req, RevCommit c, GitDateFormatter df) throws IOException { + return toJsonData(req, c, DEFAULT_FIELDS, df); + } + + Commit toJsonData(HttpServletRequest req, RevCommit c, Set<Field> fs, GitDateFormatter df) throws IOException { CommitData cd = new CommitData.Builder() .setRevWalk(walk) - .build(req, c, DEFAULT_FIELDS); + .build(req, c, fs); Commit result = new Commit(); if (cd.sha != null) { @@ -80,6 +101,9 @@ if (cd.message != null) { result.message = cd.message; } + if (cd.diffEntries != null) { + result.treeDiff = toJsonData(cd.diffEntries); + } return result; } @@ -90,4 +114,30 @@ result.time = df.formatDate(ident); return result; } + + private static List<Diff> toJsonData(DiffList dl) { + List<Diff> result = Lists.newArrayListWithCapacity(dl.entries.size()); + for (DiffEntry de : dl.entries) { + Diff d = new Diff(); + d.type = de.getChangeType().name().toLowerCase(); + d.oldId = de.getOldId().name(); + d.oldMode = de.getOldMode().getBits(); + d.oldPath = de.getOldPath(); + d.newId = de.getNewId().name(); + d.newMode = de.getNewMode().getBits(); + d.newPath = de.getNewPath(); + + switch (de.getChangeType()) { + case COPY: + case RENAME: + d.score = de.getScore(); + break; + default: + break; + } + + result.add(d); + } + return result; + } }
diff --git a/gitiles-servlet/src/main/java/com/google/gitiles/RevisionServlet.java b/gitiles-servlet/src/main/java/com/google/gitiles/RevisionServlet.java index ccdaa53..5ac2ad0 100644 --- a/gitiles-servlet/src/main/java/com/google/gitiles/RevisionServlet.java +++ b/gitiles-servlet/src/main/java/com/google/gitiles/RevisionServlet.java
@@ -21,13 +21,11 @@ import static org.eclipse.jgit.lib.Constants.OBJ_TAG; import static org.eclipse.jgit.lib.Constants.OBJ_TREE; -import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Iterables; import com.google.common.collect.Lists; -import com.google.common.collect.Sets; import com.google.gitiles.CommitData.Field; +import com.google.gitiles.CommitJsonData.Commit; import org.eclipse.jgit.errors.IncorrectObjectTypeException; import org.eclipse.jgit.errors.MissingObjectException; @@ -53,8 +51,10 @@ /** Serves an HTML page with detailed information about a ref. */ public class RevisionServlet extends BaseServlet { - private static final ImmutableSet<Field> COMMIT_FIELDS = Sets.immutableEnumSet( - Iterables.concat(CommitSoyData.DEFAULT_FIELDS, ImmutableList.of(Field.DIFF_TREE))); + private static final ImmutableSet<Field> COMMIT_SOY_FIELDS = + Field.setOf(CommitSoyData.DEFAULT_FIELDS, Field.DIFF_TREE); + private static final ImmutableSet<Field> COMMIT_JSON_FIELDS = + Field.setOf(CommitJsonData.DEFAULT_FIELDS, Field.DIFF_TREE); private static final long serialVersionUID = 1L; private static final Logger log = LoggerFactory.getLogger(RevisionServlet.class); @@ -70,7 +70,7 @@ } @Override - protected void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException { + protected void doGetHtml(HttpServletRequest req, HttpServletResponse res) throws IOException { GitilesView view = ViewFilter.getView(req); Repository repo = ServletUtils.getRepository(req); @@ -92,7 +92,7 @@ .setLinkifier(linkifier) .setRevWalk(walk) .setArchiveFormat(getArchiveFormat(accessFactory.forRequest(req))) - .toSoyData(req, (RevCommit) obj, COMMIT_FIELDS, df))); + .toSoyData(req, (RevCommit) obj, COMMIT_SOY_FIELDS, df))); break; case OBJ_TREE: soyObjects.add(ImmutableMap.of( @@ -135,6 +135,32 @@ } } + @Override + protected void doGetJson(HttpServletRequest req, HttpServletResponse res) throws IOException { + GitilesView view = ViewFilter.getView(req); + Repository repo = ServletUtils.getRepository(req); + + RevWalk walk = new RevWalk(repo); + try { + GitDateFormatter df = new GitDateFormatter(Format.DEFAULT); + RevObject obj = walk.parseAny(view.getRevision().getId()); + switch (obj.getType()) { + case OBJ_COMMIT: + renderJson(req, res, new CommitJsonData() + .setRevWalk(walk) + .toJsonData(req, (RevCommit) obj, COMMIT_JSON_FIELDS, df), + Commit.class); + break; + default: + // TODO(dborowitz): Support showing other types. + res.setStatus(SC_NOT_FOUND); + break; + } + } finally { + walk.release(); + } + } + // TODO(dborowitz): Extract this. static List<RevObject> listObjects(RevWalk walk, Revision rev) throws MissingObjectException, IOException {