blob: adc280adfb8c972eeb6c4a50f4c1c40b8097a8a9 [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);
Han-Wen Nienhuysc0200f62016-05-02 17:34:51 +020052 return !values.isEmpty() && (values.get(0).isEmpty() || values.get(0).equals("1"));
Dave Borowitzba9c1182013-03-13 14:16:43 -070053 }
54
Dave Borowitz8d6d6872014-03-16 15:18:14 -070055 protected DescribeServlet(GitilesAccess.Factory accessFactory) {
56 super(null, accessFactory);
Dave Borowitzba9c1182013-03-13 14:16:43 -070057 }
58
59 @Override
Han-Wen Nienhuysc0200f62016-05-02 17:34:51 +020060 protected void doGetText(HttpServletRequest req, HttpServletResponse res) throws IOException {
Dave Borowitzba9c1182013-03-13 14:16:43 -070061 String name = describe(ServletUtils.getRepository(req), ViewFilter.getView(req), req, res);
62 if (name == null) {
63 return;
64 }
Dave Borowitz673d1982014-05-02 12:30:49 -070065 Writer out = startRenderText(req, res);
Dave Borowitzba9c1182013-03-13 14:16:43 -070066 out.write(RefServlet.sanitizeRefForText(name));
67 out.close();
68 }
69
70 @Override
Han-Wen Nienhuysc0200f62016-05-02 17:34:51 +020071 protected void doGetJson(HttpServletRequest req, HttpServletResponse res) throws IOException {
Dave Borowitzba9c1182013-03-13 14:16:43 -070072 String name = describe(ServletUtils.getRepository(req), ViewFilter.getView(req), req, res);
73 if (name == null) {
74 return;
75 }
Han-Wen Nienhuysc0200f62016-05-02 17:34:51 +020076 renderJson(
77 req,
78 res,
Dave Borowitzba9c1182013-03-13 14:16:43 -070079 ImmutableMap.of(ViewFilter.getView(req).getPathPart(), name),
80 new TypeToken<Map<String, String>>() {}.getType());
81 }
82
Han-Wen Nienhuysc0200f62016-05-02 17:34:51 +020083 private ObjectId resolve(
84 Repository repo, GitilesView view, HttpServletRequest req, HttpServletResponse res)
85 throws IOException {
Dave Borowitzba9c1182013-03-13 14:16:43 -070086 String rev = view.getPathPart();
87 try {
88 return repo.resolve(rev);
89 } catch (RevisionSyntaxException e) {
Han-Wen Nienhuysc0200f62016-05-02 17:34:51 +020090 renderTextError(
91 req,
92 res,
93 SC_BAD_REQUEST,
Dave Borowitzba9c1182013-03-13 14:16:43 -070094 "Invalid revision syntax: " + RefServlet.sanitizeRefForText(rev));
95 return null;
96 } catch (AmbiguousObjectException e) {
Han-Wen Nienhuysc0200f62016-05-02 17:34:51 +020097 renderTextError(
98 req,
99 res,
100 SC_BAD_REQUEST,
101 String.format(
102 "Ambiguous short SHA-1 %s (%s)",
103 e.getAbbreviatedObjectId(),
104 Joiner.on(", ").join(e.getCandidates())));
Dave Borowitzba9c1182013-03-13 14:16:43 -0700105 return null;
106 }
107 }
108
Han-Wen Nienhuysc0200f62016-05-02 17:34:51 +0200109 private String describe(
110 Repository repo, GitilesView view, HttpServletRequest req, HttpServletResponse res)
111 throws IOException {
Dave Borowitzba9c1182013-03-13 14:16:43 -0700112 if (!getBooleanParam(view, CONTAINS_PARAM)) {
113 res.setStatus(SC_BAD_REQUEST);
114 return null;
115 }
116 ObjectId id = resolve(repo, view, req, res);
117 if (id == null) {
118 return null;
119 }
Dave Borowitzba9c1182013-03-13 14:16:43 -0700120 String name;
Dave Borowitzc35311d2015-08-10 11:21:51 -0400121 try (Git git = new Git(repo)) {
122 NameRevCommand cmd = nameRevCommand(git, id, req, res);
123 if (cmd == null) {
124 return null;
125 }
Dave Borowitzba9c1182013-03-13 14:16:43 -0700126 name = cmd.call().get(id);
127 } catch (GitAPIException e) {
128 throw new IOException(e);
129 }
130 if (name == null) {
131 res.setStatus(SC_NOT_FOUND);
132 return null;
133 }
134 return name;
135 }
136
Han-Wen Nienhuysc0200f62016-05-02 17:34:51 +0200137 private NameRevCommand nameRevCommand(
138 Git git, ObjectId id, HttpServletRequest req, HttpServletResponse res) throws IOException {
Dave Borowitzba9c1182013-03-13 14:16:43 -0700139 GitilesView view = ViewFilter.getView(req);
Dave Borowitzc35311d2015-08-10 11:21:51 -0400140 NameRevCommand cmd = git.nameRev();
Dave Borowitzba9c1182013-03-13 14:16:43 -0700141 boolean all = getBooleanParam(view, ALL_PARAM);
142 boolean tags = getBooleanParam(view, TAGS_PARAM);
143 if (all && tags) {
144 renderTextError(req, res, SC_BAD_REQUEST, "Cannot specify both \"all\" and \"tags\"");
145 return null;
146 }
147 if (all) {
148 cmd.addPrefix(Constants.R_REFS);
149 } else if (tags) {
150 cmd.addPrefix(Constants.R_TAGS);
151 } else {
152 cmd.addAnnotatedTags();
153 }
154 cmd.add(id);
155 return cmd;
156 }
157}