Paul Martin
2016-03-21 77c38a1865564a4ea4544bfb1f52bedf4326d481
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));
32dc8c 151
A 152                 boolean hasSubmodule = false;
153                 String submodulePath = null;
46f33f 154                 
32dc8c 155                 if (entry.isTree()) {
A 156                     // tree
157                     item.add(new LinkPanel("pathName", null, entry.path, TreePage.class,
158                             WicketUtils
159                                     .newPathParameter(repositoryName, entry.commitId, entry.path)));
160                 } else if (entry.isSubmodule()) {
161                     // submodule
162                     String submoduleId = entry.objectId;
163                     SubmoduleModel submodule = getSubmodule(entry.path);
164                     submodulePath = submodule.gitblitPath;
165                     hasSubmodule = submodule.hasSubmodule;
166
5c0605 167                     // add relative link
f0ebfe 168                     item.add(new LinkPanel("pathName", "list", entry.path + " @ " + getShortObjectId(submoduleId), "#n" + entry.objectId));
32dc8c 169                 } else {
5c0605 170                     // add relative link
77c38a 171                     if (entry.isFilestoreItem()) {
PM 172                     
173                         item.add(new LinkPanel("pathName", "list", entry.path, new Link<Object>("link", null) {
174                              
175                             private static final long serialVersionUID = 1L;
176
177                             @Override
178                             public void onClick() {
179                                 IResourceStream resourceStream = new AbstractResourceStreamWriter() {
180                                                                              
181                                     private static final long serialVersionUID = 1L;
182     
183                                     @Override 
184                                     public void write(OutputStream output) {
185                                         UserModel user =  GitBlitWebSession.get().getUser();
186                                         user = user == null ? UserModel.ANONYMOUS : user;
187                                             
188                                         app().filestore().downloadBlob(entry.getFilestoreOid(), user, getRepositoryModel(), output);
189                                     }
190                                 };
191                                 
192                                 getRequestCycle().setRequestTarget(new ResourceStreamRequestTarget(resourceStream, entry.path));
193                             }}));
194                     }
195                     else
196                     {
197                         item.add(new LinkPanel("pathName", "list", entry.path, "#n" + entry.objectId));
198                     }
32dc8c 199                 }
A 200
201                 // quick links
202                 if (entry.isSubmodule()) {
46f33f 203                     item.add(new Label("filestore", getString("gb.filestore")).setVisible(false));
PM 204                     
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()) {
222                         item.add(new Label("filestore", getString("gb.filestore")).setVisible(true));
223                         
77c38a 224                         item.add(new Link<Object>("view", null) {
PM 225                              
226                             private static final long serialVersionUID = 1L;
227
228                             @Override
229                             public void onClick() {
230                          
231                                  IResourceStream resourceStream = new AbstractResourceStreamWriter() {
232                                                                              
233                                     private static final long serialVersionUID = 1L;
234
235                                     @Override 
236                                       public void write(OutputStream output) {
237                                             UserModel user =  GitBlitWebSession.get().getUser();
238                                          user = user == null ? UserModel.ANONYMOUS : user;
239                                             
240                                         app().filestore().downloadBlob(entry.getFilestoreOid(), user, getRepositoryModel(), output);
241                                       }
242                                   };
243                                       
244                                 
245                                 getRequestCycle().setRequestTarget(new ResourceStreamRequestTarget(resourceStream, entry.path));
246                             }});
247                         
248                         item.add(new Link<Object>("raw", null) {
249                              
250                             private static final long serialVersionUID = 1L;
251
252                             @Override
253                             public void onClick() {
254                          
255                                  IResourceStream resourceStream = new AbstractResourceStreamWriter() {
256                                                                              
257                                     private static final long serialVersionUID = 1L;
258
259                                     @Override 
260                                       public void write(OutputStream output) {
261                                             UserModel user =  GitBlitWebSession.get().getUser();
262                                          user = user == null ? UserModel.ANONYMOUS : user;
263                                             
264                                         app().filestore().downloadBlob(entry.getFilestoreOid(), user, getRepositoryModel(), output);
265                                       }
266                                   };
267                                       
268                                 
269                                 getRequestCycle().setRequestTarget(new ResourceStreamRequestTarget(resourceStream, entry.path));
270                             }});
46f33f 271                     } else {
PM 272                         
273                         item.add(new Label("filestore", getString("gb.filestore")).setVisible(false));
274                         
275                         item.add(new BookmarkablePageLink<Void>("view", BlobPage.class, WicketUtils
276                                 .newPathParameter(repositoryName, entry.commitId, entry.path))
277                                 .setEnabled(!entry.changeType.equals(ChangeType.DELETE)));
278                         
279                         item.add(new ExternalLink("raw", RawServlet.asLink(getContextUrl(), repositoryName, entry.commitId, entry.path))
280                                 .setEnabled(!entry.changeType.equals(ChangeType.DELETE)));
281                     }
282                     
32dc8c 283                     item.add(new BookmarkablePageLink<Void>("blame", BlamePage.class, WicketUtils
6b8976 284                             .newPathParameter(repositoryName, entry.commitId, entry.path))
JM 285                             .setEnabled(!entry.changeType.equals(ChangeType.ADD)
286                                     && !entry.changeType.equals(ChangeType.DELETE)));
32dc8c 287                     item.add(new BookmarkablePageLink<Void>("history", HistoryPage.class, WicketUtils
A 288                             .newPathParameter(repositoryName, entry.commitId, entry.path))
289                             .setEnabled(!entry.changeType.equals(ChangeType.ADD)));
290                 }
699e71 291
32dc8c 292                 WicketUtils.setAlternatingBackground(item, counter);
A 293                 counter++;
294             }
295         };
296         add(pathsView);
319342 297         add(new Label("diffText", diff.content).setEscapeModelStrings(false));
32dc8c 298     }
A 299
300     @Override
301     protected String getPageName() {
302         return getString("gb.commitdiff");
303     }
699e71 304
6ef8d7 305     @Override
5d5e55 306     protected boolean isCommitPage() {
JM 307         return true;
308     }
309
310     @Override
6ef8d7 311     protected Class<? extends BasePage> getRepoNavPageClass() {
JM 312         return LogPage.class;
32dc8c 313     }
A 314 }