blob: ebd2ea47379c5620bac25ac1c8f07362696e8b9e [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
Dave Borowitz54271462013-11-11 11:43:11 -080017import com.google.common.base.Joiner;
18import com.google.common.collect.ImmutableMap;
Masaya Suzuki5cecb862019-03-25 17:35:44 -070019import com.google.gitiles.GitilesRequestFailureException.FailureReason;
Dave Borowitz54271462013-11-11 11:43:11 -080020import com.google.gson.reflect.TypeToken;
Dave Borowitz3b744b12016-08-19 16:11:10 -040021import java.io.IOException;
22import java.io.Writer;
23import java.util.List;
24import java.util.Map;
25import javax.servlet.http.HttpServletRequest;
26import javax.servlet.http.HttpServletResponse;
Dave Borowitzba9c1182013-03-13 14:16:43 -070027import org.eclipse.jgit.api.Git;
28import org.eclipse.jgit.api.NameRevCommand;
29import org.eclipse.jgit.api.errors.GitAPIException;
30import org.eclipse.jgit.errors.AmbiguousObjectException;
31import org.eclipse.jgit.errors.RevisionSyntaxException;
32import org.eclipse.jgit.http.server.ServletUtils;
33import org.eclipse.jgit.lib.Constants;
34import org.eclipse.jgit.lib.ObjectId;
35import org.eclipse.jgit.lib.Repository;
36
Dave Borowitzba9c1182013-03-13 14:16:43 -070037/** Serves an API result describing an object. */
38public class DescribeServlet extends BaseServlet {
39 private static final long serialVersionUID = 1L;
40
41 private static final String ALL_PARAM = "all";
42 private static final String CONTAINS_PARAM = "contains";
43 private static final String TAGS_PARAM = "tags";
44
45 private static boolean getBooleanParam(GitilesView view, String name) {
46 List<String> values = view.getParameters().get(name);
Han-Wen Nienhuysc0200f62016-05-02 17:34:51 +020047 return !values.isEmpty() && (values.get(0).isEmpty() || values.get(0).equals("1"));
Dave Borowitzba9c1182013-03-13 14:16:43 -070048 }
49
Dave Borowitz8d6d6872014-03-16 15:18:14 -070050 protected DescribeServlet(GitilesAccess.Factory accessFactory) {
51 super(null, accessFactory);
Dave Borowitzba9c1182013-03-13 14:16:43 -070052 }
53
54 @Override
Han-Wen Nienhuysc0200f62016-05-02 17:34:51 +020055 protected void doGetText(HttpServletRequest req, HttpServletResponse res) throws IOException {
Dave Borowitzba9c1182013-03-13 14:16:43 -070056 String name = describe(ServletUtils.getRepository(req), ViewFilter.getView(req), req, res);
57 if (name == null) {
58 return;
59 }
David Pursehousec3e772a2016-06-15 21:49:35 +090060 try (Writer out = startRenderText(req, res)) {
61 out.write(RefServlet.sanitizeRefForText(name));
62 }
Dave Borowitzba9c1182013-03-13 14:16:43 -070063 }
64
65 @Override
Han-Wen Nienhuysc0200f62016-05-02 17:34:51 +020066 protected void doGetJson(HttpServletRequest req, HttpServletResponse res) throws IOException {
Dave Borowitzba9c1182013-03-13 14:16:43 -070067 String name = describe(ServletUtils.getRepository(req), ViewFilter.getView(req), req, res);
68 if (name == null) {
69 return;
70 }
Han-Wen Nienhuysc0200f62016-05-02 17:34:51 +020071 renderJson(
72 req,
73 res,
Dave Borowitzba9c1182013-03-13 14:16:43 -070074 ImmutableMap.of(ViewFilter.getView(req).getPathPart(), name),
75 new TypeToken<Map<String, String>>() {}.getType());
76 }
77
Han-Wen Nienhuysc0200f62016-05-02 17:34:51 +020078 private ObjectId resolve(
79 Repository repo, GitilesView view, HttpServletRequest req, HttpServletResponse res)
80 throws IOException {
Dave Borowitzba9c1182013-03-13 14:16:43 -070081 String rev = view.getPathPart();
82 try {
83 return repo.resolve(rev);
84 } catch (RevisionSyntaxException e) {
Masaya Suzuki5cecb862019-03-25 17:35:44 -070085 throw new GitilesRequestFailureException(FailureReason.INCORECT_PARAMETER)
86 .withPublicErrorMessage(
87 "Invalid revision syntax: %s", RefServlet.sanitizeRefForText(rev));
Dave Borowitzba9c1182013-03-13 14:16:43 -070088 } catch (AmbiguousObjectException e) {
Masaya Suzuki5cecb862019-03-25 17:35:44 -070089 throw new GitilesRequestFailureException(FailureReason.AMBIGUOUS_OBJECT)
90 .withPublicErrorMessage(
Han-Wen Nienhuysc0200f62016-05-02 17:34:51 +020091 "Ambiguous short SHA-1 %s (%s)",
Masaya Suzuki5cecb862019-03-25 17:35:44 -070092 e.getAbbreviatedObjectId(), Joiner.on(", ").join(e.getCandidates()));
Dave Borowitzba9c1182013-03-13 14:16:43 -070093 }
94 }
95
Han-Wen Nienhuysc0200f62016-05-02 17:34:51 +020096 private String describe(
97 Repository repo, GitilesView view, HttpServletRequest req, HttpServletResponse res)
98 throws IOException {
Dave Borowitzba9c1182013-03-13 14:16:43 -070099 if (!getBooleanParam(view, CONTAINS_PARAM)) {
Masaya Suzuki5cecb862019-03-25 17:35:44 -0700100 throw new GitilesRequestFailureException(FailureReason.INCORECT_PARAMETER);
Dave Borowitzba9c1182013-03-13 14:16:43 -0700101 }
102 ObjectId id = resolve(repo, view, req, res);
103 if (id == null) {
104 return null;
105 }
Dave Borowitzba9c1182013-03-13 14:16:43 -0700106 String name;
Dave Borowitzc35311d2015-08-10 11:21:51 -0400107 try (Git git = new Git(repo)) {
108 NameRevCommand cmd = nameRevCommand(git, id, req, res);
109 if (cmd == null) {
110 return null;
111 }
Dave Borowitzba9c1182013-03-13 14:16:43 -0700112 name = cmd.call().get(id);
113 } catch (GitAPIException e) {
114 throw new IOException(e);
115 }
116 if (name == null) {
Masaya Suzuki5cecb862019-03-25 17:35:44 -0700117 throw new GitilesRequestFailureException(FailureReason.OBJECT_NOT_FOUND);
Dave Borowitzba9c1182013-03-13 14:16:43 -0700118 }
119 return name;
120 }
121
Han-Wen Nienhuysc0200f62016-05-02 17:34:51 +0200122 private NameRevCommand nameRevCommand(
123 Git git, ObjectId id, HttpServletRequest req, HttpServletResponse res) throws IOException {
Dave Borowitzba9c1182013-03-13 14:16:43 -0700124 GitilesView view = ViewFilter.getView(req);
Dave Borowitzc35311d2015-08-10 11:21:51 -0400125 NameRevCommand cmd = git.nameRev();
Dave Borowitzba9c1182013-03-13 14:16:43 -0700126 boolean all = getBooleanParam(view, ALL_PARAM);
127 boolean tags = getBooleanParam(view, TAGS_PARAM);
128 if (all && tags) {
Masaya Suzuki5cecb862019-03-25 17:35:44 -0700129 throw new GitilesRequestFailureException(FailureReason.UNSUPPORTED_REVISION_NAMES)
130 .withPublicErrorMessage("Cannot specify both \"all\" and \"tags\"");
Dave Borowitzba9c1182013-03-13 14:16:43 -0700131 }
132 if (all) {
133 cmd.addPrefix(Constants.R_REFS);
134 } else if (tags) {
135 cmd.addPrefix(Constants.R_TAGS);
136 } else {
137 cmd.addAnnotatedTags();
138 }
139 cmd.add(id);
140 return cmd;
141 }
142}