blob: e4258c08dbc1ba6ad3a164c824c0eece692ac713 [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,
78 "data", new CommitSoyData(linkifier, req, repo, walk, view)
79 .toSoyData((RevCommit) obj, KeySet.DETAIL_DIFF_TREE)));
80 break;
81 case OBJ_TREE:
82 soyObjects.add(ImmutableMap.of(
83 "type", Constants.TYPE_TREE,
84 "data", new TreeSoyData(walk, view).toSoyData(obj)));
85 break;
86 case OBJ_BLOB:
87 soyObjects.add(ImmutableMap.of(
88 "type", Constants.TYPE_BLOB,
89 "data", new BlobSoyData(walk, view).toSoyData(obj)));
90 hasBlob = true;
91 break;
92 case OBJ_TAG:
93 soyObjects.add(ImmutableMap.of(
94 "type", Constants.TYPE_TAG,
95 "data", new TagSoyData(linkifier, req).toSoyData((RevTag) obj)));
96 break;
97 default:
Dave Borowitzfd25c3a2013-01-11 14:37:11 -080098 log.warn("Bad object type for {}: {}", ObjectId.toString(obj.getId()), obj.getType());
Dave Borowitz9de65952012-08-13 16:09:45 -070099 res.setStatus(SC_NOT_FOUND);
100 return;
101 }
102 } catch (MissingObjectException e) {
103 log.warn("Missing object " + ObjectId.toString(obj.getId()), e);
104 res.setStatus(SC_NOT_FOUND);
105 return;
106 } catch (IncorrectObjectTypeException e) {
107 log.warn("Incorrect object type for " + ObjectId.toString(obj.getId()), e);
108 res.setStatus(SC_NOT_FOUND);
109 return;
110 }
111 }
112
Dave Borowitzb1c628f2013-01-11 11:28:20 -0800113 renderHtml(req, res, "gitiles.revisionDetail", ImmutableMap.of(
Dave Borowitz9de65952012-08-13 16:09:45 -0700114 "title", view.getRevision().getName(),
115 "objects", soyObjects,
116 "hasBlob", hasBlob));
117 } finally {
118 walk.release();
119 }
120 }
121
122 // TODO(dborowitz): Extract this.
Dave Borowitz558005d2012-12-20 15:48:08 -0800123 static List<RevObject> listObjects(RevWalk walk, Revision rev)
Dave Borowitz9de65952012-08-13 16:09:45 -0700124 throws MissingObjectException, IOException {
125 List<RevObject> objects = Lists.newArrayListWithExpectedSize(1);
Dave Borowitz558005d2012-12-20 15:48:08 -0800126 ObjectId id = rev.getId();
127 RevObject cur;
Dave Borowitz9de65952012-08-13 16:09:45 -0700128 while (true) {
Dave Borowitz558005d2012-12-20 15:48:08 -0800129 cur = walk.parseAny(id);
Dave Borowitz9de65952012-08-13 16:09:45 -0700130 objects.add(cur);
Dave Borowitz558005d2012-12-20 15:48:08 -0800131 if (cur.getType() != Constants.OBJ_TAG) {
Dave Borowitz9de65952012-08-13 16:09:45 -0700132 break;
133 }
Dave Borowitz558005d2012-12-20 15:48:08 -0800134 id = ((RevTag) cur).getObject();
135 }
136 if (cur.getType() == Constants.OBJ_COMMIT) {
137 objects.add(walk.parseTree(((RevCommit) cur).getTree()));
Dave Borowitz9de65952012-08-13 16:09:45 -0700138 }
139 return objects;
140 }
141}