blob: bf9de35abd6006f92e29973d3fd502f3511f540b [file] [log] [blame]
Dave Borowitz9de65952012-08-13 16:09:45 -07001// Copyright 2012 Google Inc. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package com.google.gitiles;
16
17import static com.google.common.base.Preconditions.checkNotNull;
18import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
19import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
20import static org.eclipse.jgit.lib.Constants.OBJ_COMMIT;
21import static org.eclipse.jgit.lib.Constants.OBJ_TAG;
22import static org.eclipse.jgit.lib.Constants.OBJ_TREE;
23
24import com.google.common.collect.ImmutableMap;
25import com.google.common.collect.Lists;
26import com.google.gitiles.CommitSoyData.KeySet;
27
28import org.eclipse.jgit.errors.IncorrectObjectTypeException;
29import org.eclipse.jgit.errors.MissingObjectException;
30import org.eclipse.jgit.http.server.ServletUtils;
31import org.eclipse.jgit.lib.Constants;
32import org.eclipse.jgit.lib.ObjectId;
33import org.eclipse.jgit.lib.Repository;
34import org.eclipse.jgit.revwalk.RevCommit;
35import org.eclipse.jgit.revwalk.RevObject;
36import org.eclipse.jgit.revwalk.RevTag;
37import org.eclipse.jgit.revwalk.RevWalk;
38import org.slf4j.Logger;
39import org.slf4j.LoggerFactory;
40
41import java.io.IOException;
42import java.util.List;
43import java.util.Map;
44
45import javax.servlet.http.HttpServletRequest;
46import javax.servlet.http.HttpServletResponse;
47
48/** Serves an HTML page with detailed information about a ref. */
49public class RevisionServlet extends BaseServlet {
Chad Horohoead23f142012-11-12 09:45:39 -080050 private static final long serialVersionUID = 1L;
Dave Borowitz9de65952012-08-13 16:09:45 -070051 private static final Logger log = LoggerFactory.getLogger(RevisionServlet.class);
52
53 private final Linkifier linkifier;
54
55 public RevisionServlet(Renderer renderer, Linkifier linkifier) {
56 super(renderer);
57 this.linkifier = checkNotNull(linkifier, "linkifier");
58 }
59
60 @Override
61 protected void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
62 GitilesView view = ViewFilter.getView(req);
63 Repository repo = ServletUtils.getRepository(req);
64
65 RevWalk walk = new RevWalk(repo);
66 try {
Dave Borowitz558005d2012-12-20 15:48:08 -080067 List<RevObject> objects = listObjects(walk, view.getRevision());
Dave Borowitz9de65952012-08-13 16:09:45 -070068 List<Map<String, ?>> soyObjects = Lists.newArrayListWithCapacity(objects.size());
69 boolean hasBlob = false;
70
71 // TODO(sop): Allow caching commits by SHA-1 when no S cookie is sent.
72 for (RevObject obj : objects) {
73 try {
74 switch (obj.getType()) {
75 case OBJ_COMMIT:
76 soyObjects.add(ImmutableMap.of(
77 "type", Constants.TYPE_COMMIT,
Dave Borowitz3b086a72013-07-02 15:03:03 -070078 "data", new CommitSoyData()
79 .setLinkifier(linkifier)
80 .setRevWalk(walk)
81 .toSoyData(req, (RevCommit) obj, KeySet.DETAIL_DIFF_TREE)));
Dave Borowitz9de65952012-08-13 16:09:45 -070082 break;
83 case OBJ_TREE:
84 soyObjects.add(ImmutableMap.of(
85 "type", Constants.TYPE_TREE,
86 "data", new TreeSoyData(walk, view).toSoyData(obj)));
87 break;
88 case OBJ_BLOB:
89 soyObjects.add(ImmutableMap.of(
90 "type", Constants.TYPE_BLOB,
91 "data", new BlobSoyData(walk, view).toSoyData(obj)));
92 hasBlob = true;
93 break;
94 case OBJ_TAG:
95 soyObjects.add(ImmutableMap.of(
96 "type", Constants.TYPE_TAG,
97 "data", new TagSoyData(linkifier, req).toSoyData((RevTag) obj)));
98 break;
99 default:
Dave Borowitzfd25c3a2013-01-11 14:37:11 -0800100 log.warn("Bad object type for {}: {}", ObjectId.toString(obj.getId()), obj.getType());
Dave Borowitz9de65952012-08-13 16:09:45 -0700101 res.setStatus(SC_NOT_FOUND);
102 return;
103 }
104 } catch (MissingObjectException e) {
105 log.warn("Missing object " + ObjectId.toString(obj.getId()), e);
106 res.setStatus(SC_NOT_FOUND);
107 return;
108 } catch (IncorrectObjectTypeException e) {
109 log.warn("Incorrect object type for " + ObjectId.toString(obj.getId()), e);
110 res.setStatus(SC_NOT_FOUND);
111 return;
112 }
113 }
114
Dave Borowitzb1c628f2013-01-11 11:28:20 -0800115 renderHtml(req, res, "gitiles.revisionDetail", ImmutableMap.of(
Dave Borowitz9de65952012-08-13 16:09:45 -0700116 "title", view.getRevision().getName(),
117 "objects", soyObjects,
118 "hasBlob", hasBlob));
119 } finally {
120 walk.release();
121 }
122 }
123
124 // TODO(dborowitz): Extract this.
Dave Borowitz558005d2012-12-20 15:48:08 -0800125 static List<RevObject> listObjects(RevWalk walk, Revision rev)
Dave Borowitz9de65952012-08-13 16:09:45 -0700126 throws MissingObjectException, IOException {
127 List<RevObject> objects = Lists.newArrayListWithExpectedSize(1);
Dave Borowitz558005d2012-12-20 15:48:08 -0800128 ObjectId id = rev.getId();
129 RevObject cur;
Dave Borowitz9de65952012-08-13 16:09:45 -0700130 while (true) {
Dave Borowitz558005d2012-12-20 15:48:08 -0800131 cur = walk.parseAny(id);
Dave Borowitz9de65952012-08-13 16:09:45 -0700132 objects.add(cur);
Dave Borowitz558005d2012-12-20 15:48:08 -0800133 if (cur.getType() != Constants.OBJ_TAG) {
Dave Borowitz9de65952012-08-13 16:09:45 -0700134 break;
135 }
Dave Borowitz558005d2012-12-20 15:48:08 -0800136 id = ((RevTag) cur).getObject();
137 }
138 if (cur.getType() == Constants.OBJ_COMMIT) {
139 objects.add(walk.parseTree(((RevCommit) cur).getTree()));
Dave Borowitz9de65952012-08-13 16:09:45 -0700140 }
141 return objects;
142 }
143}