blob: 785d4528550b6ffa6ff72200ce5493d18865dbd0 [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 Borowitz3b744b12016-08-19 16:11:10 -040023import java.io.IOException;
24import java.io.Writer;
25import java.util.List;
26import java.util.Map;
27import javax.servlet.http.HttpServletRequest;
28import javax.servlet.http.HttpServletResponse;
Dave Borowitzba9c1182013-03-13 14:16:43 -070029import org.eclipse.jgit.api.Git;
30import org.eclipse.jgit.api.NameRevCommand;
31import org.eclipse.jgit.api.errors.GitAPIException;
32import org.eclipse.jgit.errors.AmbiguousObjectException;
33import org.eclipse.jgit.errors.RevisionSyntaxException;
34import org.eclipse.jgit.http.server.ServletUtils;
35import org.eclipse.jgit.lib.Constants;
36import org.eclipse.jgit.lib.ObjectId;
37import org.eclipse.jgit.lib.Repository;
38
Dave Borowitzba9c1182013-03-13 14:16:43 -070039/** Serves an API result describing an object. */
40public class DescribeServlet extends BaseServlet {
41 private static final long serialVersionUID = 1L;
42
43 private static final String ALL_PARAM = "all";
44 private static final String CONTAINS_PARAM = "contains";
45 private static final String TAGS_PARAM = "tags";
46
47 private static boolean getBooleanParam(GitilesView view, String name) {
48 List<String> values = view.getParameters().get(name);
Han-Wen Nienhuysc0200f62016-05-02 17:34:51 +020049 return !values.isEmpty() && (values.get(0).isEmpty() || values.get(0).equals("1"));
Dave Borowitzba9c1182013-03-13 14:16:43 -070050 }
51
Dave Borowitz8d6d6872014-03-16 15:18:14 -070052 protected DescribeServlet(GitilesAccess.Factory accessFactory) {
53 super(null, accessFactory);
Dave Borowitzba9c1182013-03-13 14:16:43 -070054 }
55
56 @Override
Han-Wen Nienhuysc0200f62016-05-02 17:34:51 +020057 protected void doGetText(HttpServletRequest req, HttpServletResponse res) throws IOException {
Dave Borowitzba9c1182013-03-13 14:16:43 -070058 String name = describe(ServletUtils.getRepository(req), ViewFilter.getView(req), req, res);
59 if (name == null) {
60 return;
61 }
David Pursehousec3e772a2016-06-15 21:49:35 +090062 try (Writer out = startRenderText(req, res)) {
63 out.write(RefServlet.sanitizeRefForText(name));
64 }
Dave Borowitzba9c1182013-03-13 14:16:43 -070065 }
66
67 @Override
Han-Wen Nienhuysc0200f62016-05-02 17:34:51 +020068 protected void doGetJson(HttpServletRequest req, HttpServletResponse res) throws IOException {
Dave Borowitzba9c1182013-03-13 14:16:43 -070069 String name = describe(ServletUtils.getRepository(req), ViewFilter.getView(req), req, res);
70 if (name == null) {
71 return;
72 }
Han-Wen Nienhuysc0200f62016-05-02 17:34:51 +020073 renderJson(
74 req,
75 res,
Dave Borowitzba9c1182013-03-13 14:16:43 -070076 ImmutableMap.of(ViewFilter.getView(req).getPathPart(), name),
77 new TypeToken<Map<String, String>>() {}.getType());
78 }
79
Han-Wen Nienhuysc0200f62016-05-02 17:34:51 +020080 private ObjectId resolve(
81 Repository repo, GitilesView view, HttpServletRequest req, HttpServletResponse res)
82 throws IOException {
Dave Borowitzba9c1182013-03-13 14:16:43 -070083 String rev = view.getPathPart();
84 try {
85 return repo.resolve(rev);
86 } catch (RevisionSyntaxException e) {
Han-Wen Nienhuysc0200f62016-05-02 17:34:51 +020087 renderTextError(
88 req,
89 res,
90 SC_BAD_REQUEST,
Dave Borowitzba9c1182013-03-13 14:16:43 -070091 "Invalid revision syntax: " + RefServlet.sanitizeRefForText(rev));
92 return null;
93 } catch (AmbiguousObjectException e) {
Han-Wen Nienhuysc0200f62016-05-02 17:34:51 +020094 renderTextError(
95 req,
96 res,
97 SC_BAD_REQUEST,
98 String.format(
99 "Ambiguous short SHA-1 %s (%s)",
Dave Borowitz40255d52016-08-19 16:16:22 -0400100 e.getAbbreviatedObjectId(), Joiner.on(", ").join(e.getCandidates())));
Dave Borowitzba9c1182013-03-13 14:16:43 -0700101 return null;
102 }
103 }
104
Han-Wen Nienhuysc0200f62016-05-02 17:34:51 +0200105 private String describe(
106 Repository repo, GitilesView view, HttpServletRequest req, HttpServletResponse res)
107 throws IOException {
Dave Borowitzba9c1182013-03-13 14:16:43 -0700108 if (!getBooleanParam(view, CONTAINS_PARAM)) {
109 res.setStatus(SC_BAD_REQUEST);
110 return null;
111 }
112 ObjectId id = resolve(repo, view, req, res);
113 if (id == null) {
114 return null;
115 }
Dave Borowitzba9c1182013-03-13 14:16:43 -0700116 String name;
Dave Borowitzc35311d2015-08-10 11:21:51 -0400117 try (Git git = new Git(repo)) {
118 NameRevCommand cmd = nameRevCommand(git, id, req, res);
119 if (cmd == null) {
120 return null;
121 }
Dave Borowitzba9c1182013-03-13 14:16:43 -0700122 name = cmd.call().get(id);
123 } catch (GitAPIException e) {
124 throw new IOException(e);
125 }
126 if (name == null) {
127 res.setStatus(SC_NOT_FOUND);
128 return null;
129 }
130 return name;
131 }
132
Han-Wen Nienhuysc0200f62016-05-02 17:34:51 +0200133 private NameRevCommand nameRevCommand(
134 Git git, ObjectId id, HttpServletRequest req, HttpServletResponse res) throws IOException {
Dave Borowitzba9c1182013-03-13 14:16:43 -0700135 GitilesView view = ViewFilter.getView(req);
Dave Borowitzc35311d2015-08-10 11:21:51 -0400136 NameRevCommand cmd = git.nameRev();
Dave Borowitzba9c1182013-03-13 14:16:43 -0700137 boolean all = getBooleanParam(view, ALL_PARAM);
138 boolean tags = getBooleanParam(view, TAGS_PARAM);
139 if (all && tags) {
140 renderTextError(req, res, SC_BAD_REQUEST, "Cannot specify both \"all\" and \"tags\"");
141 return null;
142 }
143 if (all) {
144 cmd.addPrefix(Constants.R_REFS);
145 } else if (tags) {
146 cmd.addPrefix(Constants.R_TAGS);
147 } else {
148 cmd.addAnnotatedTags();
149 }
150 cmd.add(id);
151 return cmd;
152 }
153}