Paul Martin
2016-04-06 5bb79fbb553a11e6582392f658233cf58a4ceb11
commit | author | age
32dc8c 1 /*
A 2  * Copyright 2011 gitblit.com.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.gitblit.wicket.pages;
17
77c38a 18 import java.io.OutputStream;
32dc8c 19 import java.util.ArrayList;
67b82a 20 import java.util.Arrays;
32dc8c 21 import java.util.List;
A 22
23 import org.apache.wicket.PageParameters;
24 import org.apache.wicket.markup.html.basic.Label;
25 import org.apache.wicket.markup.html.link.BookmarkablePageLink;
9cc56a 26 import org.apache.wicket.markup.html.link.ExternalLink;
77c38a 27 import org.apache.wicket.markup.html.link.Link;
32dc8c 28 import org.apache.wicket.markup.repeater.Item;
A 29 import org.apache.wicket.markup.repeater.data.DataView;
30 import org.apache.wicket.markup.repeater.data.ListDataProvider;
77c38a 31 import org.apache.wicket.request.target.resource.ResourceStreamRequestTarget;
PM 32 import org.apache.wicket.util.resource.AbstractResourceStreamWriter;
33 import org.apache.wicket.util.resource.IResourceStream;
32dc8c 34 import org.eclipse.jgit.diff.DiffEntry.ChangeType;
A 35 import org.eclipse.jgit.lib.Repository;
36 import org.eclipse.jgit.revwalk.RevCommit;
37
67b82a 38 import com.gitblit.Constants;
7dd99f 39 import com.gitblit.Keys;
67b82a 40 import com.gitblit.models.GitNote;
319342 41 import com.gitblit.models.PathModel.PathChangeModel;
32dc8c 42 import com.gitblit.models.SubmoduleModel;
77c38a 43 import com.gitblit.models.UserModel;
ff17f7 44 import com.gitblit.servlet.RawServlet;
32dc8c 45 import com.gitblit.utils.DiffUtils;
cff352 46 import com.gitblit.utils.DiffUtils.DiffComparator;
319342 47 import com.gitblit.utils.DiffUtils.DiffOutput;
32dc8c 48 import com.gitblit.utils.DiffUtils.DiffOutputType;
A 49 import com.gitblit.utils.JGitUtils;
a7db57 50 import com.gitblit.wicket.CacheControl;
77c38a 51 import com.gitblit.wicket.GitBlitWebSession;
a7db57 52 import com.gitblit.wicket.CacheControl.LastModified;
32dc8c 53 import com.gitblit.wicket.WicketUtils;
A 54 import com.gitblit.wicket.panels.CommitHeaderPanel;
55 import com.gitblit.wicket.panels.CommitLegendPanel;
319342 56 import com.gitblit.wicket.panels.DiffStatPanel;
b57b9e 57 import com.gitblit.wicket.panels.AvatarImage;
32dc8c 58 import com.gitblit.wicket.panels.LinkPanel;
67b82a 59 import com.gitblit.wicket.panels.RefsPanel;
32dc8c 60
a7db57 61 @CacheControl(LastModified.BOOT)
32dc8c 62 public class CommitDiffPage extends RepositoryPage {
A 63
64     public CommitDiffPage(PageParameters params) {
65         super(params);
66
5d59b9 67         final Repository r = getRepository();
JM 68         final RevCommit commit = getCommit();
69         final DiffComparator diffComparator = WicketUtils.getDiffComparator(params);
32dc8c 70
A 71         List<String> parents = new ArrayList<String>();
72         if (commit.getParentCount() > 0) {
73             for (RevCommit parent : commit.getParents()) {
74                 parents.add(parent.name());
75             }
76         }
77
78         // commit page links
79         if (parents.size() == 0) {
80             add(new Label("parentLink", getString("gb.none")));
81         } else {
82             add(new LinkPanel("parentLink", null, parents.get(0).substring(0, 8),
83                     CommitDiffPage.class, newCommitParameter(parents.get(0))));
84         }
85         add(new BookmarkablePageLink<Void>("patchLink", PatchPage.class,
86                 WicketUtils.newObjectParameter(repositoryName, objectId)));
87         add(new BookmarkablePageLink<Void>("commitLink", CommitPage.class,
88                 WicketUtils.newObjectParameter(repositoryName, objectId)));
5d59b9 89         add(new LinkPanel("whitespaceLink", null, getString(diffComparator.getOpposite().getTranslationKey()),
JM 90                 CommitDiffPage.class, WicketUtils.newDiffParameter(repositoryName, objectId, diffComparator.getOpposite())));
32dc8c 91
A 92         add(new CommitHeaderPanel("commitHeader", repositoryName, commit));
319342 93
7dd99f 94         final List<String> imageExtensions = app().settings().getStrings(Keys.web.imageExtensions);
b6f475 95         final ImageDiffHandler handler = new ImageDiffHandler(this, repositoryName,
7dd99f 96                 parents.isEmpty() ? null : parents.get(0), commit.getName(), imageExtensions);
310a80 97         final int tabLength = app().settings().getInteger(Keys.web.tabLength, 4);
JM 98         final DiffOutput diff = DiffUtils.getCommitDiff(r, commit, diffComparator, DiffOutputType.HTML, handler, tabLength);
3e1336 99         if (handler.getImgDiffCount() > 0) {
T 100             addBottomScript("scripts/imgdiff.js"); // Tiny support script for image diffs
101         }
7dd99f 102
319342 103         // add commit diffstat
JM 104         int insertions = 0;
105         int deletions = 0;
106         for (PathChangeModel pcm : diff.stat.paths) {
107             insertions += pcm.insertions;
108             deletions += pcm.deletions;
109         }
110         add(new DiffStatPanel("diffStat", insertions, deletions));
32dc8c 111
cd9461 112         addFullText("fullMessage", commit.getFullMessage());
684cfd 113
67b82a 114         // git notes
JM 115         List<GitNote> notes = JGitUtils.getNotesOnCommit(r, commit);
116         ListDataProvider<GitNote> notesDp = new ListDataProvider<GitNote>(notes);
117         DataView<GitNote> notesView = new DataView<GitNote>("notes", notesDp) {
118             private static final long serialVersionUID = 1L;
119
699e71 120             @Override
67b82a 121             public void populateItem(final Item<GitNote> item) {
JM 122                 GitNote entry = item.getModelObject();
123                 item.add(new RefsPanel("refName", repositoryName, Arrays.asList(entry.notesRef)));
124                 item.add(createPersonPanel("authorName", entry.notesRef.getAuthorIdent(),
125                         Constants.SearchType.AUTHOR));
b57b9e 126                 item.add(new AvatarImage("noteAuthorAvatar", entry.notesRef.getAuthorIdent()));
67b82a 127                 item.add(WicketUtils.createTimestampLabel("authorDate", entry.notesRef
JM 128                         .getAuthorIdent().getWhen(), getTimeZone(), getTimeUtils()));
fef234 129                 item.add(new Label("noteContent", bugtraqProcessor().processPlainCommitMessage(getRepository(), repositoryName,
67b82a 130                         entry.content)).setEscapeModelStrings(false));
JM 131             }
132         };
133         add(notesView.setVisible(notes.size() > 0));
699e71 134
32dc8c 135         // changed paths list
319342 136         add(new CommitLegendPanel("commitLegend", diff.stat.paths));
JM 137         ListDataProvider<PathChangeModel> pathsDp = new ListDataProvider<PathChangeModel>(diff.stat.paths);
32dc8c 138         DataView<PathChangeModel> pathsView = new DataView<PathChangeModel>("changedPath", pathsDp) {
A 139             private static final long serialVersionUID = 1L;
140             int counter;
141
699e71 142             @Override
32dc8c 143             public void populateItem(final Item<PathChangeModel> item) {
A 144                 final PathChangeModel entry = item.getModelObject();
46f33f 145                 
32dc8c 146                 Label changeType = new Label("changeType", "");
A 147                 WicketUtils.setChangeTypeCssClass(changeType, entry.changeType);
148                 setChangeTypeTooltip(changeType, entry.changeType);
149                 item.add(changeType);
319342 150                 item.add(new DiffStatPanel("diffStat", entry.insertions, entry.deletions, true));
5bb79f 151                 item.add(WicketUtils.setHtmlTooltip(new Label("filestore", ""), getString("gb.filestore"))
PM 152                                     .setVisible(entry.isFilestoreItem()));
32dc8c 153
A 154                 boolean hasSubmodule = false;
155                 String submodulePath = null;
46f33f 156                 
32dc8c 157                 if (entry.isTree()) {
A 158                     // tree
159                     item.add(new LinkPanel("pathName", null, entry.path, TreePage.class,
160                             WicketUtils
161                                     .newPathParameter(repositoryName, entry.commitId, entry.path)));
162                 } else if (entry.isSubmodule()) {
163                     // submodule
164                     String submoduleId = entry.objectId;
165                     SubmoduleModel submodule = getSubmodule(entry.path);
166                     submodulePath = submodule.gitblitPath;
167                     hasSubmodule = submodule.hasSubmodule;
168
5c0605 169                     // add relative link
f0ebfe 170                     item.add(new LinkPanel("pathName", "list", entry.path + " @ " + getShortObjectId(submoduleId), "#n" + entry.objectId));
32dc8c 171                 } else {
5c0605 172                     // add relative link
77c38a 173                     if (entry.isFilestoreItem()) {
PM 174                     
175                         item.add(new LinkPanel("pathName", "list", entry.path, new Link<Object>("link", null) {
176                              
177                             private static final long serialVersionUID = 1L;
178
179                             @Override
180                             public void onClick() {
181                                 IResourceStream resourceStream = new AbstractResourceStreamWriter() {
182                                                                              
183                                     private static final long serialVersionUID = 1L;
184     
185                                     @Override 
186                                     public void write(OutputStream output) {
187                                         UserModel user =  GitBlitWebSession.get().getUser();
188                                         user = user == null ? UserModel.ANONYMOUS : user;
189                                             
190                                         app().filestore().downloadBlob(entry.getFilestoreOid(), user, getRepositoryModel(), output);
191                                     }
192                                 };
193                                 
194                                 getRequestCycle().setRequestTarget(new ResourceStreamRequestTarget(resourceStream, entry.path));
195                             }}));
196                     }
197                     else
198                     {
199                         item.add(new LinkPanel("pathName", "list", entry.path, "#n" + entry.objectId));
200                     }
32dc8c 201                 }
A 202
203                 // quick links
204                 if (entry.isSubmodule()) {
4cec4b 205                     item.add(new ExternalLink("raw", "").setEnabled(false));
32dc8c 206                     // submodule
9cc56a 207                     item.add(new ExternalLink("patch", "").setEnabled(false));
32dc8c 208                     item.add(new BookmarkablePageLink<Void>("view", CommitPage.class, WicketUtils
A 209                             .newObjectParameter(submodulePath, entry.objectId)).setEnabled(hasSubmodule));
9cc56a 210                     item.add(new ExternalLink("blame", "").setEnabled(false));
32dc8c 211                     item.add(new BookmarkablePageLink<Void>("history", HistoryPage.class, WicketUtils
6b8976 212                             .newPathParameter(repositoryName, entry.commitId, entry.path))
JM 213                             .setEnabled(!entry.changeType.equals(ChangeType.ADD)));
32dc8c 214                 } else {
A 215                     // tree or blob
216                     item.add(new BookmarkablePageLink<Void>("patch", PatchPage.class, WicketUtils
6b8976 217                             .newPathParameter(repositoryName, entry.commitId, entry.path))
JM 218                             .setEnabled(!entry.changeType.equals(ChangeType.ADD)
219                                     && !entry.changeType.equals(ChangeType.DELETE)));
46f33f 220                     
PM 221                     if (entry.isFilestoreItem()) {
77c38a 222                         item.add(new Link<Object>("view", null) {
PM 223                              
224                             private static final long serialVersionUID = 1L;
225
226                             @Override
227                             public void onClick() {
228                          
229                                  IResourceStream resourceStream = new AbstractResourceStreamWriter() {
230                                                                              
231                                     private static final long serialVersionUID = 1L;
232
233                                     @Override 
234                                       public void write(OutputStream output) {
235                                             UserModel user =  GitBlitWebSession.get().getUser();
236                                          user = user == null ? UserModel.ANONYMOUS : user;
237                                             
238                                         app().filestore().downloadBlob(entry.getFilestoreOid(), user, getRepositoryModel(), output);
239                                       }
240                                   };
241                                       
242                                 
243                                 getRequestCycle().setRequestTarget(new ResourceStreamRequestTarget(resourceStream, entry.path));
244                             }});
245                         
246                         item.add(new Link<Object>("raw", null) {
247                              
248                             private static final long serialVersionUID = 1L;
249
250                             @Override
251                             public void onClick() {
252                          
253                                  IResourceStream resourceStream = new AbstractResourceStreamWriter() {
254                                                                              
255                                     private static final long serialVersionUID = 1L;
256
257                                     @Override 
258                                       public void write(OutputStream output) {
259                                             UserModel user =  GitBlitWebSession.get().getUser();
260                                          user = user == null ? UserModel.ANONYMOUS : user;
261                                             
262                                         app().filestore().downloadBlob(entry.getFilestoreOid(), user, getRepositoryModel(), output);
263                                       }
264                                   };
265                                       
266                                 
267                                 getRequestCycle().setRequestTarget(new ResourceStreamRequestTarget(resourceStream, entry.path));
268                             }});
46f33f 269                     } else {
PM 270                         item.add(new BookmarkablePageLink<Void>("view", BlobPage.class, WicketUtils
271                                 .newPathParameter(repositoryName, entry.commitId, entry.path))
272                                 .setEnabled(!entry.changeType.equals(ChangeType.DELETE)));
273                         
274                         item.add(new ExternalLink("raw", RawServlet.asLink(getContextUrl(), repositoryName, entry.commitId, entry.path))
275                                 .setEnabled(!entry.changeType.equals(ChangeType.DELETE)));
276                     }
277                     
32dc8c 278                     item.add(new BookmarkablePageLink<Void>("blame", BlamePage.class, WicketUtils
6b8976 279                             .newPathParameter(repositoryName, entry.commitId, entry.path))
JM 280                             .setEnabled(!entry.changeType.equals(ChangeType.ADD)
281                                     && !entry.changeType.equals(ChangeType.DELETE)));
32dc8c 282                     item.add(new BookmarkablePageLink<Void>("history", HistoryPage.class, WicketUtils
A 283                             .newPathParameter(repositoryName, entry.commitId, entry.path))
284                             .setEnabled(!entry.changeType.equals(ChangeType.ADD)));
285                 }
699e71 286
32dc8c 287                 WicketUtils.setAlternatingBackground(item, counter);
A 288                 counter++;
289             }
290         };
291         add(pathsView);
319342 292         add(new Label("diffText", diff.content).setEscapeModelStrings(false));
32dc8c 293     }
A 294
295     @Override
296     protected String getPageName() {
297         return getString("gb.commitdiff");
298     }
699e71 299
6ef8d7 300     @Override
5d5e55 301     protected boolean isCommitPage() {
JM 302         return true;
303     }
304
305     @Override
6ef8d7 306     protected Class<? extends BasePage> getRepoNavPageClass() {
JM 307         return LogPage.class;
32dc8c 308     }
A 309 }