blob: 66a7086e500bd76a692f4211bf0b8790c1bc29ec [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 {
50 private static final Logger log = LoggerFactory.getLogger(RevisionServlet.class);
51
52 private final Linkifier linkifier;
53
54 public RevisionServlet(Renderer renderer, Linkifier linkifier) {
55 super(renderer);
56 this.linkifier = checkNotNull(linkifier, "linkifier");
57 }
58
59 @Override
60 protected void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
61 GitilesView view = ViewFilter.getView(req);
62 Repository repo = ServletUtils.getRepository(req);
63
64 RevWalk walk = new RevWalk(repo);
65 try {
66 List<RevObject> objects = listObjects(walk, view.getRevision().getId());
67 List<Map<String, ?>> soyObjects = Lists.newArrayListWithCapacity(objects.size());
68 boolean hasBlob = false;
69
70 // TODO(sop): Allow caching commits by SHA-1 when no S cookie is sent.
71 for (RevObject obj : objects) {
72 try {
73 switch (obj.getType()) {
74 case OBJ_COMMIT:
75 soyObjects.add(ImmutableMap.of(
76 "type", Constants.TYPE_COMMIT,
77 "data", new CommitSoyData(linkifier, req, repo, walk, view)
78 .toSoyData((RevCommit) obj, KeySet.DETAIL_DIFF_TREE)));
79 break;
80 case OBJ_TREE:
81 soyObjects.add(ImmutableMap.of(
82 "type", Constants.TYPE_TREE,
83 "data", new TreeSoyData(walk, view).toSoyData(obj)));
84 break;
85 case OBJ_BLOB:
86 soyObjects.add(ImmutableMap.of(
87 "type", Constants.TYPE_BLOB,
88 "data", new BlobSoyData(walk, view).toSoyData(obj)));
89 hasBlob = true;
90 break;
91 case OBJ_TAG:
92 soyObjects.add(ImmutableMap.of(
93 "type", Constants.TYPE_TAG,
94 "data", new TagSoyData(linkifier, req).toSoyData((RevTag) obj)));
95 break;
96 default:
97 log.warn("Bad object type for %s: %s", ObjectId.toString(obj.getId()), obj.getType());
98 res.setStatus(SC_NOT_FOUND);
99 return;
100 }
101 } catch (MissingObjectException e) {
102 log.warn("Missing object " + ObjectId.toString(obj.getId()), e);
103 res.setStatus(SC_NOT_FOUND);
104 return;
105 } catch (IncorrectObjectTypeException e) {
106 log.warn("Incorrect object type for " + ObjectId.toString(obj.getId()), e);
107 res.setStatus(SC_NOT_FOUND);
108 return;
109 }
110 }
111
112 render(req, res, "gitiles.revisionDetail", ImmutableMap.of(
113 "title", view.getRevision().getName(),
114 "objects", soyObjects,
115 "hasBlob", hasBlob));
116 } finally {
117 walk.release();
118 }
119 }
120
121 // TODO(dborowitz): Extract this.
122 static List<RevObject> listObjects(RevWalk walk, ObjectId id)
123 throws MissingObjectException, IOException {
124 List<RevObject> objects = Lists.newArrayListWithExpectedSize(1);
125 while (true) {
126 RevObject cur = walk.parseAny(id);
127 objects.add(cur);
128 if (cur.getType() == Constants.OBJ_TAG) {
129 id = ((RevTag) cur).getObject();
130 } else {
131 break;
132 }
133 }
134 return objects;
135 }
136}