Add JSON view for trees Sample output: $ curl -s 'http://localhost:8080/gitiles/+/master/lib?format=JSON' )]}' { "entries": [ { "mode": 33188, "type": "blob", "id": "abed91637554aa423806eb199958d007a6b72510", "name": "BUCK" }, { "mode": 16384, "type": "tree", "id": "1c0b739a3b621f4d004daf16eed83121c69c1ff0", "name": "guice" }, { "mode": 16384, "type": "tree", "id": "0337998ca4c09f2956c2f21497d7324027874139", "name": "jetty" }, { "mode": 16384, "type": "tree", "id": "84a4af5fd7a250365d82855a8d34364f7afb9797", "name": "jgit" }, { "mode": 16384, "type": "tree", "id": "e238f03c6d6d08426e335c9a30d06e0db28e9db3", "name": "slf4j" } ] } Change-Id: I38e37fed4f0d529bc319f637c90b2d0ce4519eda
diff --git a/gitiles-servlet/src/main/java/com/google/gitiles/PathServlet.java b/gitiles-servlet/src/main/java/com/google/gitiles/PathServlet.java index 1ba2477..118e4e0 100644 --- a/gitiles-servlet/src/main/java/com/google/gitiles/PathServlet.java +++ b/gitiles-servlet/src/main/java/com/google/gitiles/PathServlet.java
@@ -235,6 +235,37 @@ } } + @Override + protected void doGetJson(HttpServletRequest req, HttpServletResponse res) throws IOException { + GitilesView view = ViewFilter.getView(req); + Repository repo = ServletUtils.getRepository(req); + + RevWalk rw = new RevWalk(repo); + WalkResult wr = null; + try { + wr = WalkResult.forPath(rw, view); + if (wr == null) { + res.setStatus(SC_NOT_FOUND); + return; + } + switch (wr.type) { + case TREE: + renderJson(req, res, TreeJsonData.toJsonData(wr.tw), TreeJsonData.Tree.class); + break; + default: + res.setStatus(SC_NOT_FOUND); + break; + } + } catch (LargeObjectException e) { + res.setStatus(SC_INTERNAL_SERVER_ERROR); + } finally { + if (wr != null) { + wr.release(); + } + rw.release(); + } + } + private static RevTree getRoot(GitilesView view, RevWalk rw) throws IOException { RevObject obj = rw.peel(rw.parseAny(view.getRevision().getId())); switch (obj.getType()) {
diff --git a/gitiles-servlet/src/main/java/com/google/gitiles/TreeJsonData.java b/gitiles-servlet/src/main/java/com/google/gitiles/TreeJsonData.java new file mode 100644 index 0000000..be4ba4f --- /dev/null +++ b/gitiles-servlet/src/main/java/com/google/gitiles/TreeJsonData.java
@@ -0,0 +1,55 @@ +// Copyright (C) 2014 Google Inc. All Rights Reserved. +// +// 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.gitiles; + +import com.google.common.collect.Lists; + +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.treewalk.TreeWalk; + +import java.io.IOException; +import java.util.List; + +class TreeJsonData { + static class Tree { + List<Entry> entries; + } + + static class Entry { + int mode; + String type; + String id; + String name; + } + + static Tree toJsonData(TreeWalk tw) throws IOException { + Tree tree = new Tree(); + tree.entries = Lists.newArrayList(); + while (tw.next()) { + Entry e = new Entry(); + FileMode mode = tw.getFileMode(0); + e.mode = mode.getBits(); + e.type = Constants.typeString(mode.getObjectType()); + e.id = tw.getObjectId(0).name(); + e.name = tw.getNameString(); + tree.entries.add(e); + } + return tree; + } + + private TreeJsonData() { + } +}
diff --git a/gitiles-servlet/src/test/java/com/google/gitiles/PathServletTest.java b/gitiles-servlet/src/test/java/com/google/gitiles/PathServletTest.java index 02d7463..fbd0792 100644 --- a/gitiles-servlet/src/test/java/com/google/gitiles/PathServletTest.java +++ b/gitiles-servlet/src/test/java/com/google/gitiles/PathServletTest.java
@@ -20,7 +20,9 @@ import com.google.common.collect.ImmutableList; import com.google.common.io.BaseEncoding; +import com.google.gitiles.TreeJsonData.Tree; import com.google.common.net.HttpHeaders; +import com.google.gson.Gson; import com.google.template.soy.data.SoyListData; import com.google.template.soy.data.restricted.StringData; @@ -33,6 +35,7 @@ import org.eclipse.jgit.lib.FileMode; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.revwalk.RevBlob; +import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevTree; import org.junit.Before; import org.junit.Test; @@ -224,6 +227,39 @@ assertNotFound("/repo/+/master/gitiles?format=TEXT"); } + @Test + public void treeJson() throws Exception { + RevCommit c = repo.parseBody(repo.branch("master").commit() + .add("foo/bar", "bar contents") + .add("baz", "baz contents") + .create()); + + Tree tree = buildJson("/repo/+/master/?format=JSON", Tree.class); + assertEquals(2, tree.entries.size()); + assertEquals(0100644, tree.entries.get(0).mode); + assertEquals("blob", tree.entries.get(0).type); + assertEquals(repo.get(c.getTree(), "baz").name(), tree.entries.get(0).id); + assertEquals("baz", tree.entries.get(0).name); + assertEquals(040000, tree.entries.get(1).mode); + assertEquals("tree", tree.entries.get(1).type); + assertEquals(repo.get(c.getTree(), "foo").name(), tree.entries.get(1).id); + assertEquals("foo", tree.entries.get(1).name); + + tree = buildJson("/repo/+/master/foo?format=JSON", Tree.class); + assertEquals(1, tree.entries.size()); + assertEquals(0100644, tree.entries.get(0).mode); + assertEquals("blob", tree.entries.get(0).type); + assertEquals(repo.get(c.getTree(), "foo/bar").name(), tree.entries.get(0).id); + assertEquals("bar", tree.entries.get(0).name); + + tree = buildJson("/repo/+/master/foo/?format=JSON", Tree.class); + assertEquals(1, tree.entries.size()); + assertEquals(0100644, tree.entries.get(0).mode); + assertEquals("blob", tree.entries.get(0).type); + assertEquals(repo.get(c.getTree(), "foo/bar").name(), tree.entries.get(0).id); + assertEquals("bar", tree.entries.get(0).name); + } + private Map<String, ?> getBlobData(Map<String, ?> data) { return ((Map<String, Map<String, ?>>) data).get("data"); } @@ -251,6 +287,15 @@ return res.getResponse().getActualBodyString(); } + private <T> T buildJson(String pathAndQuery, Class<T> clazz) throws Exception { + TestViewFilter.Result res = service(pathAndQuery); + assertEquals("application/json", res.getResponse().getHeader(HttpHeaders.CONTENT_TYPE)); + String body = res.getResponse().getActualBodyString(); + String magic = ")]}'\n"; + assertEquals(magic, body.substring(0, magic.length())); + return new Gson().fromJson(body.substring(magic.length()), clazz); + } + private Map<String, ?> buildData(String pathAndQuery) throws Exception { // Render the page through Soy to ensure templates are valid, then return // the Soy data for introspection.