blob: 9182a8836fa987a1fd2cd6fcaa85ba42a723b4f9 [file] [log] [blame]
Dave Borowitzba9c1182013-03-13 14:16:43 -07001// Copyright 2013 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 javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
18import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
19
Dave Borowitz54271462013-11-11 11:43:11 -080020import com.google.common.base.Joiner;
21import com.google.common.collect.ImmutableMap;
22import com.google.gson.reflect.TypeToken;
Dave Borowitzba9c1182013-03-13 14:16:43 -070023
24import org.eclipse.jgit.api.Git;
25import org.eclipse.jgit.api.NameRevCommand;
26import org.eclipse.jgit.api.errors.GitAPIException;
27import org.eclipse.jgit.errors.AmbiguousObjectException;
28import org.eclipse.jgit.errors.RevisionSyntaxException;
29import org.eclipse.jgit.http.server.ServletUtils;
30import org.eclipse.jgit.lib.Constants;
31import org.eclipse.jgit.lib.ObjectId;
32import org.eclipse.jgit.lib.Repository;
33
Dave Borowitz54271462013-11-11 11:43:11 -080034import java.io.IOException;
Dave Borowitz673d1982014-05-02 12:30:49 -070035import java.io.Writer;
Dave Borowitz54271462013-11-11 11:43:11 -080036import java.util.List;
37import java.util.Map;
38
39import javax.servlet.http.HttpServletRequest;
40import javax.servlet.http.HttpServletResponse;
Dave Borowitzba9c1182013-03-13 14:16:43 -070041
42/** Serves an API result describing an object. */
43public class DescribeServlet extends BaseServlet {
44 private static final long serialVersionUID = 1L;
45
46 private static final String ALL_PARAM = "all";
47 private static final String CONTAINS_PARAM = "contains";
48 private static final String TAGS_PARAM = "tags";
49
50 private static boolean getBooleanParam(GitilesView view, String name) {
51 List<String> values = view.getParameters().get(name);
52 return !values.isEmpty()
Dave Borowitz27058932014-12-03 15:44:46 -080053 && (values.get(0).isEmpty() || values.get(0).equals("1"));
Dave Borowitzba9c1182013-03-13 14:16:43 -070054 }
55
Dave Borowitz8d6d6872014-03-16 15:18:14 -070056 protected DescribeServlet(GitilesAccess.Factory accessFactory) {
57 super(null, accessFactory);
Dave Borowitzba9c1182013-03-13 14:16:43 -070058 }
59
60 @Override
61 protected void doGetText(HttpServletRequest req, HttpServletResponse res)
62 throws IOException {
63 String name = describe(ServletUtils.getRepository(req), ViewFilter.getView(req), req, res);
64 if (name == null) {
65 return;
66 }
Dave Borowitz673d1982014-05-02 12:30:49 -070067 Writer out = startRenderText(req, res);
Dave Borowitzba9c1182013-03-13 14:16:43 -070068 out.write(RefServlet.sanitizeRefForText(name));
69 out.close();
70 }
71
72 @Override
73 protected void doGetJson(HttpServletRequest req, HttpServletResponse res)
74 throws IOException {
75 String name = describe(ServletUtils.getRepository(req), ViewFilter.getView(req), req, res);
76 if (name == null) {
77 return;
78 }
79 renderJson(req, res,
80 ImmutableMap.of(ViewFilter.getView(req).getPathPart(), name),
81 new TypeToken<Map<String, String>>() {}.getType());
82 }
83
84 private ObjectId resolve(Repository repo, GitilesView view, HttpServletRequest req,
85 HttpServletResponse res) throws IOException {
86 String rev = view.getPathPart();
87 try {
88 return repo.resolve(rev);
89 } catch (RevisionSyntaxException e) {
90 renderTextError(req, res, SC_BAD_REQUEST,
91 "Invalid revision syntax: " + RefServlet.sanitizeRefForText(rev));
92 return null;
93 } catch (AmbiguousObjectException e) {
94 renderTextError(req, res, SC_BAD_REQUEST, String.format(
95 "Ambiguous short SHA-1 %s (%s)",
96 e.getAbbreviatedObjectId(), Joiner.on(", ").join(e.getCandidates())));
97 return null;
98 }
99 }
100
101 private String describe(Repository repo, GitilesView view, HttpServletRequest req,
102 HttpServletResponse res) throws IOException {
103 if (!getBooleanParam(view, CONTAINS_PARAM)) {
104 res.setStatus(SC_BAD_REQUEST);
105 return null;
106 }
107 ObjectId id = resolve(repo, view, req, res);
108 if (id == null) {
109 return null;
110 }
111 NameRevCommand cmd = nameRevCommand(id, req, res);
112 if (cmd == null) {
113 return null;
114 }
115 String name;
116 try {
117 name = cmd.call().get(id);
118 } catch (GitAPIException e) {
119 throw new IOException(e);
120 }
121 if (name == null) {
122 res.setStatus(SC_NOT_FOUND);
123 return null;
124 }
125 return name;
126 }
127
128 private NameRevCommand nameRevCommand(ObjectId id, HttpServletRequest req,
129 HttpServletResponse res) throws IOException {
130 Repository repo = ServletUtils.getRepository(req);
131 GitilesView view = ViewFilter.getView(req);
132 NameRevCommand cmd = new Git(repo).nameRev();
133 boolean all = getBooleanParam(view, ALL_PARAM);
134 boolean tags = getBooleanParam(view, TAGS_PARAM);
135 if (all && tags) {
136 renderTextError(req, res, SC_BAD_REQUEST, "Cannot specify both \"all\" and \"tags\"");
137 return null;
138 }
139 if (all) {
140 cmd.addPrefix(Constants.R_REFS);
141 } else if (tags) {
142 cmd.addPrefix(Constants.R_TAGS);
143 } else {
144 cmd.addAnnotatedTags();
145 }
146 cmd.add(id);
147 return cmd;
148 }
149}