blob: 97fe1ce0e54cdc21d7e533666fe38c9f98b8a677 [file] [log] [blame]
Dave Borowitzb772cce2012-12-28 13:57:22 -08001// 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
Dave Borowitzc410f962014-09-23 10:49:26 -070017import static com.google.common.base.MoreObjects.firstNonNull;
Dave Borowitzba1bd222014-07-30 09:50:29 -070018import static com.google.common.base.Preconditions.checkNotNull;
19
Dave Borowitzf6dcf7a2014-07-30 10:26:58 -070020import com.google.common.collect.ImmutableMap;
Dave Borowitz01551272014-03-16 13:43:16 -070021import com.google.common.collect.ImmutableSet;
Dave Borowitz209d0aa2012-12-28 14:28:53 -080022import com.google.common.collect.Maps;
Dave Borowitz01551272014-03-16 13:43:16 -070023import com.google.common.collect.Sets;
24import com.google.gitiles.CommitData.Field;
Dave Borowitzf6dcf7a2014-07-30 10:26:58 -070025import com.google.template.soy.tofu.SoyTofu;
Dave Borowitzb772cce2012-12-28 13:57:22 -080026
Dave Borowitzcb88d4d2015-10-26 13:58:17 -040027import org.eclipse.jgit.diff.DiffEntry;
28import org.eclipse.jgit.diff.DiffEntry.ChangeType;
Dave Borowitzba1bd222014-07-30 09:50:29 -070029import org.eclipse.jgit.lib.Config;
Dave Borowitzb772cce2012-12-28 13:57:22 -080030import org.eclipse.jgit.lib.ObjectId;
Dave Borowitzb772cce2012-12-28 13:57:22 -080031import org.eclipse.jgit.revwalk.RevCommit;
Dave Borowitzb772cce2012-12-28 13:57:22 -080032
Dave Borowitz209d0aa2012-12-28 14:28:53 -080033import java.io.IOException;
Dave Borowitzf6dcf7a2014-07-30 10:26:58 -070034import java.io.Writer;
Dave Borowitz209d0aa2012-12-28 14:28:53 -080035import java.util.Map;
Michael Moss558f8642014-04-15 09:29:21 -070036import java.util.Set;
Dave Borowitz209d0aa2012-12-28 14:28:53 -080037
38import javax.annotation.Nullable;
39import javax.servlet.http.HttpServletRequest;
Dave Borowitzb772cce2012-12-28 13:57:22 -080040
41public class LogSoyData {
Dave Borowitz01551272014-03-16 13:43:16 -070042 private static final ImmutableSet<Field> FIELDS = Sets.immutableEnumSet(Field.ABBREV_SHA,
Michael Moss558f8642014-04-15 09:29:21 -070043 Field.SHA, Field.URL, Field.SHORT_MESSAGE, Field.MESSAGE, Field.AUTHOR, Field.COMMITTER,
44 Field.BRANCHES, Field.TAGS);
45 private static final ImmutableSet<Field> VERBOSE_FIELDS = Field.setOf(FIELDS, Field.DIFF_TREE);
Dave Borowitz01551272014-03-16 13:43:16 -070046
Dave Borowitzb772cce2012-12-28 13:57:22 -080047 private final HttpServletRequest req;
Dave Borowitzf6dcf7a2014-07-30 10:26:58 -070048 private final GitilesView view;
Dave Borowitzba1bd222014-07-30 09:50:29 -070049 private final Set<Field> fields;
Dave Borowitzba1bd222014-07-30 09:50:29 -070050 private final String variant;
Gustaf Lundh06a98702015-08-17 17:29:11 +020051 private CommitSoyData csd;
Dave Borowitzb772cce2012-12-28 13:57:22 -080052
Dave Borowitzba1bd222014-07-30 09:50:29 -070053 public LogSoyData(HttpServletRequest req, GitilesAccess access, String pretty)
54 throws IOException {
55 this.req = checkNotNull(req);
Dave Borowitzf6dcf7a2014-07-30 10:26:58 -070056 this.view = checkNotNull(ViewFilter.getView(req));
Dave Borowitzb15a5862015-09-16 15:14:56 -040057 checkNotNull(pretty);
Dave Borowitzba1bd222014-07-30 09:50:29 -070058 Config config = access.getConfig();
59 fields = config.getBoolean("logFormat", pretty, "verbose", false) ? VERBOSE_FIELDS : FIELDS;
Dave Borowitzc410f962014-09-23 10:49:26 -070060 variant = firstNonNull(config.getString("logFormat", pretty, "variant"), pretty);
Dave Borowitzb772cce2012-12-28 13:57:22 -080061 }
62
Dave Borowitzf6dcf7a2014-07-30 10:26:58 -070063 public void renderStreaming(Paginator paginator, @Nullable String revision, Renderer renderer,
64 Writer out, DateFormatter df) throws IOException {
65 renderer.newRenderer("gitiles.logEntriesHeader")
66 .setData(toHeaderSoyData(paginator, revision))
67 .render(out);
68 out.flush();
69
70 SoyTofu.Renderer entryRenderer = renderer.newRenderer("gitiles.logEntryWrapper");
Andrew Bonventreb33426e2015-09-09 18:28:28 -040071 boolean renderedEntries = false;
Dave Borowitzf6dcf7a2014-07-30 10:26:58 -070072 for (RevCommit c : paginator) {
Andrew Bonventreb33426e2015-09-09 18:28:28 -040073 entryRenderer.setData(toEntrySoyData(paginator, c, df)).render(out);
Dave Borowitzf6dcf7a2014-07-30 10:26:58 -070074 out.flush();
Andrew Bonventreb33426e2015-09-09 18:28:28 -040075 renderedEntries = true;
Dave Borowitzf6dcf7a2014-07-30 10:26:58 -070076 }
Andrew Bonventreb33426e2015-09-09 18:28:28 -040077 if (!renderedEntries) {
Dave Borowitzf6dcf7a2014-07-30 10:26:58 -070078 renderer.newRenderer("gitiles.emptyLog").render(out);
79 }
80
81 renderer.newRenderer("gitiles.logEntriesFooter")
82 .setData(toFooterSoyData(paginator, revision))
83 .render(out);
Dave Borowitz27fada42013-11-01 11:09:49 -070084 }
85
Dave Borowitzf6dcf7a2014-07-30 10:26:58 -070086 private Map<String, Object> toHeaderSoyData(Paginator paginator, @Nullable String revision) {
Andrew Bonventreb33426e2015-09-09 18:28:28 -040087 Map<String, Object> data = Maps.newHashMapWithExpectedSize(1);
Dave Borowitzb772cce2012-12-28 13:57:22 -080088 ObjectId prev = paginator.getPreviousStart();
89 if (prev != null) {
Dave Borowitzf6dcf7a2014-07-30 10:26:58 -070090 GitilesView.Builder prevView = copyAndCanonicalizeView(revision);
Dave Borowitzb772cce2012-12-28 13:57:22 -080091 if (!prevView.getRevision().getId().equals(prev)) {
92 prevView.replaceParam(LogServlet.START_PARAM, prev.name());
93 }
94 data.put("previousUrl", prevView.toUrl());
95 }
96 return data;
97 }
98
Andrew Bonventreb33426e2015-09-09 18:28:28 -040099 private Map<String, Object> toEntrySoyData(Paginator paginator, RevCommit c, DateFormatter df)
100 throws IOException {
Gustaf Lundh06a98702015-08-17 17:29:11 +0200101 if (csd == null) {
102 csd = new CommitSoyData();
103 }
104
Andrew Bonventreb33426e2015-09-09 18:28:28 -0400105 Map<String, Object> entry = csd.setRevWalk(paginator.getWalk()).toSoyData(req, c, fields, df);
Dave Borowitzcb88d4d2015-10-26 13:58:17 -0400106 DiffEntry rename = paginator.getRename(c);
107 if (rename != null) {
108 entry.put("rename", toRenameSoyData(rename));
109 }
Dave Borowitzf6dcf7a2014-07-30 10:26:58 -0700110 return ImmutableMap.of(
Dave Borowitzf6dcf7a2014-07-30 10:26:58 -0700111 "variant", variant,
112 "entry", entry);
113 }
114
Dave Borowitzcb88d4d2015-10-26 13:58:17 -0400115 private Map<String, Object> toRenameSoyData(DiffEntry entry) {
116 if (entry == null) {
117 return null;
118 }
119 ChangeType type = entry.getChangeType();
120 if (type != ChangeType.RENAME && type != ChangeType.COPY) {
121 return null;
122 }
123 return ImmutableMap.<String, Object> of(
124 "changeType", type.toString(),
125 "oldPath", entry.getOldPath(),
126 "newPath", entry.getNewPath(),
127 "score", entry.getScore());
128 }
129
Dave Borowitzf6dcf7a2014-07-30 10:26:58 -0700130 private Map<String, Object> toFooterSoyData(Paginator paginator, @Nullable String revision) {
131 Map<String, Object> data = Maps.newHashMapWithExpectedSize(1);
132 ObjectId next = paginator.getNextStart();
133 if (next != null) {
134 data.put("nextUrl", copyAndCanonicalizeView(revision)
135 .replaceParam(LogServlet.START_PARAM, next.name())
136 .toUrl());
137 }
138 return data;
139 }
140
141 private GitilesView.Builder copyAndCanonicalizeView(String revision) {
Dave Borowitzb772cce2012-12-28 13:57:22 -0800142 // Canonicalize the view by using full SHAs.
143 GitilesView.Builder copy = GitilesView.log().copyFrom(view);
144 if (view.getRevision() != Revision.NULL) {
145 copy.setRevision(view.getRevision());
146 } else {
147 copy.setRevision(Revision.named(revision));
148 }
149 if (view.getOldRevision() != Revision.NULL) {
150 copy.setOldRevision(view.getOldRevision());
151 }
152 return copy;
153 }
154}