Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

CommitDiffPage.java 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. /*
  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. import java.io.OutputStream;
  18. import java.util.ArrayList;
  19. import java.util.Arrays;
  20. import java.util.List;
  21. import org.apache.wicket.PageParameters;
  22. import org.apache.wicket.markup.html.basic.Label;
  23. import org.apache.wicket.markup.html.link.BookmarkablePageLink;
  24. import org.apache.wicket.markup.html.link.ExternalLink;
  25. import org.apache.wicket.markup.html.link.Link;
  26. import org.apache.wicket.markup.repeater.Item;
  27. import org.apache.wicket.markup.repeater.data.DataView;
  28. import org.apache.wicket.markup.repeater.data.ListDataProvider;
  29. import org.apache.wicket.request.target.resource.ResourceStreamRequestTarget;
  30. import org.apache.wicket.util.resource.AbstractResourceStreamWriter;
  31. import org.apache.wicket.util.resource.IResourceStream;
  32. import org.eclipse.jgit.diff.DiffEntry.ChangeType;
  33. import org.eclipse.jgit.lib.Repository;
  34. import org.eclipse.jgit.revwalk.RevCommit;
  35. import com.gitblit.Constants;
  36. import com.gitblit.Keys;
  37. import com.gitblit.models.GitNote;
  38. import com.gitblit.models.PathModel.PathChangeModel;
  39. import com.gitblit.models.SubmoduleModel;
  40. import com.gitblit.models.UserModel;
  41. import com.gitblit.servlet.RawServlet;
  42. import com.gitblit.utils.DiffUtils;
  43. import com.gitblit.utils.DiffUtils.DiffComparator;
  44. import com.gitblit.utils.DiffUtils.DiffOutput;
  45. import com.gitblit.utils.DiffUtils.DiffOutputType;
  46. import com.gitblit.utils.JGitUtils;
  47. import com.gitblit.wicket.CacheControl;
  48. import com.gitblit.wicket.GitBlitWebSession;
  49. import com.gitblit.wicket.CacheControl.LastModified;
  50. import com.gitblit.wicket.WicketUtils;
  51. import com.gitblit.wicket.panels.CommitHeaderPanel;
  52. import com.gitblit.wicket.panels.CommitLegendPanel;
  53. import com.gitblit.wicket.panels.DiffStatPanel;
  54. import com.gitblit.wicket.panels.AvatarImage;
  55. import com.gitblit.wicket.panels.LinkPanel;
  56. import com.gitblit.wicket.panels.RefsPanel;
  57. @CacheControl(LastModified.BOOT)
  58. public class CommitDiffPage extends RepositoryPage {
  59. public CommitDiffPage(PageParameters params) {
  60. super(params);
  61. final Repository r = getRepository();
  62. final RevCommit commit = getCommit();
  63. final DiffComparator diffComparator = WicketUtils.getDiffComparator(params);
  64. List<String> parents = new ArrayList<String>();
  65. if (commit.getParentCount() > 0) {
  66. for (RevCommit parent : commit.getParents()) {
  67. parents.add(parent.name());
  68. }
  69. }
  70. // commit page links
  71. if (parents.size() == 0) {
  72. add(new Label("parentLink", getString("gb.none")));
  73. } else {
  74. add(new LinkPanel("parentLink", null, parents.get(0).substring(0, 8),
  75. CommitDiffPage.class, newCommitParameter(parents.get(0))));
  76. }
  77. add(new BookmarkablePageLink<Void>("patchLink", PatchPage.class,
  78. WicketUtils.newObjectParameter(repositoryName, objectId)));
  79. add(new BookmarkablePageLink<Void>("commitLink", CommitPage.class,
  80. WicketUtils.newObjectParameter(repositoryName, objectId)));
  81. add(new LinkPanel("whitespaceLink", null, getString(diffComparator.getOpposite().getTranslationKey()),
  82. CommitDiffPage.class, WicketUtils.newDiffParameter(repositoryName, objectId, diffComparator.getOpposite())));
  83. add(new CommitHeaderPanel("commitHeader", repositoryName, commit));
  84. final List<String> imageExtensions = app().settings().getStrings(Keys.web.imageExtensions);
  85. final ImageDiffHandler handler = new ImageDiffHandler(this, repositoryName,
  86. parents.isEmpty() ? null : parents.get(0), commit.getName(), imageExtensions);
  87. final int tabLength = app().settings().getInteger(Keys.web.tabLength, 4);
  88. final DiffOutput diff = DiffUtils.getCommitDiff(r, commit, diffComparator, DiffOutputType.HTML, handler, tabLength);
  89. if (handler.getImgDiffCount() > 0) {
  90. addBottomScript("scripts/imgdiff.js"); // Tiny support script for image diffs
  91. }
  92. // add commit diffstat
  93. int insertions = 0;
  94. int deletions = 0;
  95. for (PathChangeModel pcm : diff.stat.paths) {
  96. insertions += pcm.insertions;
  97. deletions += pcm.deletions;
  98. }
  99. add(new DiffStatPanel("diffStat", insertions, deletions));
  100. addFullText("fullMessage", commit.getFullMessage());
  101. // git notes
  102. List<GitNote> notes = JGitUtils.getNotesOnCommit(r, commit);
  103. ListDataProvider<GitNote> notesDp = new ListDataProvider<GitNote>(notes);
  104. DataView<GitNote> notesView = new DataView<GitNote>("notes", notesDp) {
  105. private static final long serialVersionUID = 1L;
  106. @Override
  107. public void populateItem(final Item<GitNote> item) {
  108. GitNote entry = item.getModelObject();
  109. item.add(new RefsPanel("refName", repositoryName, Arrays.asList(entry.notesRef)));
  110. item.add(createPersonPanel("authorName", entry.notesRef.getAuthorIdent(),
  111. Constants.SearchType.AUTHOR));
  112. item.add(new AvatarImage("noteAuthorAvatar", entry.notesRef.getAuthorIdent()));
  113. item.add(WicketUtils.createTimestampLabel("authorDate", entry.notesRef
  114. .getAuthorIdent().getWhen(), getTimeZone(), getTimeUtils()));
  115. item.add(new Label("noteContent", bugtraqProcessor().processPlainCommitMessage(getRepository(), repositoryName,
  116. entry.content)).setEscapeModelStrings(false));
  117. }
  118. };
  119. add(notesView.setVisible(notes.size() > 0));
  120. // changed paths list
  121. add(new CommitLegendPanel("commitLegend", diff.stat.paths));
  122. ListDataProvider<PathChangeModel> pathsDp = new ListDataProvider<PathChangeModel>(diff.stat.paths);
  123. DataView<PathChangeModel> pathsView = new DataView<PathChangeModel>("changedPath", pathsDp) {
  124. private static final long serialVersionUID = 1L;
  125. int counter;
  126. @Override
  127. public void populateItem(final Item<PathChangeModel> item) {
  128. final PathChangeModel entry = item.getModelObject();
  129. Label changeType = new Label("changeType", "");
  130. WicketUtils.setChangeTypeCssClass(changeType, entry.changeType);
  131. setChangeTypeTooltip(changeType, entry.changeType);
  132. item.add(changeType);
  133. item.add(new DiffStatPanel("diffStat", entry.insertions, entry.deletions, true));
  134. item.add(WicketUtils.setHtmlTooltip(new Label("filestore", ""), getString("gb.filestore"))
  135. .setVisible(entry.isFilestoreItem()));
  136. boolean hasSubmodule = false;
  137. String submodulePath = null;
  138. if (entry.isTree()) {
  139. // tree
  140. item.add(new LinkPanel("pathName", null, entry.path, TreePage.class,
  141. WicketUtils
  142. .newPathParameter(repositoryName, entry.commitId, entry.path)));
  143. } else if (entry.isSubmodule()) {
  144. // submodule
  145. String submoduleId = entry.objectId;
  146. SubmoduleModel submodule = getSubmodule(entry.path);
  147. submodulePath = submodule.gitblitPath;
  148. hasSubmodule = submodule.hasSubmodule;
  149. // add relative link
  150. item.add(new LinkPanel("pathName", "list", entry.path + " @ " + getShortObjectId(submoduleId), "#n" + entry.objectId));
  151. } else {
  152. // add relative link
  153. if (entry.isFilestoreItem()) {
  154. item.add(new LinkPanel("pathName", "list", entry.path, new Link<Object>("link", null) {
  155. private static final long serialVersionUID = 1L;
  156. @Override
  157. public void onClick() {
  158. IResourceStream resourceStream = new AbstractResourceStreamWriter() {
  159. private static final long serialVersionUID = 1L;
  160. @Override
  161. public void write(OutputStream output) {
  162. UserModel user = GitBlitWebSession.get().getUser();
  163. user = user == null ? UserModel.ANONYMOUS : user;
  164. app().filestore().downloadBlob(entry.getFilestoreOid(), user, getRepositoryModel(), output);
  165. }
  166. };
  167. getRequestCycle().setRequestTarget(new ResourceStreamRequestTarget(resourceStream, entry.path));
  168. }}));
  169. }
  170. else
  171. {
  172. item.add(new LinkPanel("pathName", "list", entry.path, "#n" + entry.objectId));
  173. }
  174. }
  175. // quick links
  176. if (entry.isSubmodule()) {
  177. item.add(new ExternalLink("raw", "").setEnabled(false));
  178. // submodule
  179. item.add(new ExternalLink("patch", "").setEnabled(false));
  180. item.add(new BookmarkablePageLink<Void>("view", CommitPage.class, WicketUtils
  181. .newObjectParameter(submodulePath, entry.objectId)).setEnabled(hasSubmodule));
  182. item.add(new ExternalLink("blame", "").setEnabled(false));
  183. item.add(new BookmarkablePageLink<Void>("history", HistoryPage.class, WicketUtils
  184. .newPathParameter(repositoryName, entry.commitId, entry.path))
  185. .setEnabled(!entry.changeType.equals(ChangeType.ADD)));
  186. } else {
  187. // tree or blob
  188. item.add(new BookmarkablePageLink<Void>("patch", PatchPage.class, WicketUtils
  189. .newPathParameter(repositoryName, entry.commitId, entry.path))
  190. .setEnabled(!entry.changeType.equals(ChangeType.ADD)
  191. && !entry.changeType.equals(ChangeType.DELETE)));
  192. if (entry.isFilestoreItem()) {
  193. item.add(new Link<Object>("view", null) {
  194. private static final long serialVersionUID = 1L;
  195. @Override
  196. public void onClick() {
  197. IResourceStream resourceStream = new AbstractResourceStreamWriter() {
  198. private static final long serialVersionUID = 1L;
  199. @Override
  200. public void write(OutputStream output) {
  201. UserModel user = GitBlitWebSession.get().getUser();
  202. user = user == null ? UserModel.ANONYMOUS : user;
  203. app().filestore().downloadBlob(entry.getFilestoreOid(), user, getRepositoryModel(), output);
  204. }
  205. };
  206. getRequestCycle().setRequestTarget(new ResourceStreamRequestTarget(resourceStream, entry.path));
  207. }});
  208. item.add(new Link<Object>("raw", null) {
  209. private static final long serialVersionUID = 1L;
  210. @Override
  211. public void onClick() {
  212. IResourceStream resourceStream = new AbstractResourceStreamWriter() {
  213. private static final long serialVersionUID = 1L;
  214. @Override
  215. public void write(OutputStream output) {
  216. UserModel user = GitBlitWebSession.get().getUser();
  217. user = user == null ? UserModel.ANONYMOUS : user;
  218. app().filestore().downloadBlob(entry.getFilestoreOid(), user, getRepositoryModel(), output);
  219. }
  220. };
  221. getRequestCycle().setRequestTarget(new ResourceStreamRequestTarget(resourceStream, entry.path));
  222. }});
  223. } else {
  224. item.add(new BookmarkablePageLink<Void>("view", BlobPage.class, WicketUtils
  225. .newPathParameter(repositoryName, entry.commitId, entry.path))
  226. .setEnabled(!entry.changeType.equals(ChangeType.DELETE)));
  227. item.add(new ExternalLink("raw", RawServlet.asLink(getContextUrl(), repositoryName, entry.commitId, entry.path))
  228. .setEnabled(!entry.changeType.equals(ChangeType.DELETE)));
  229. }
  230. item.add(new BookmarkablePageLink<Void>("blame", BlamePage.class, WicketUtils
  231. .newPathParameter(repositoryName, entry.commitId, entry.path))
  232. .setEnabled(!entry.changeType.equals(ChangeType.ADD)
  233. && !entry.changeType.equals(ChangeType.DELETE)));
  234. item.add(new BookmarkablePageLink<Void>("history", HistoryPage.class, WicketUtils
  235. .newPathParameter(repositoryName, entry.commitId, entry.path))
  236. .setEnabled(!entry.changeType.equals(ChangeType.ADD)));
  237. }
  238. WicketUtils.setAlternatingBackground(item, counter);
  239. counter++;
  240. }
  241. };
  242. add(pathsView);
  243. add(new Label("diffText", diff.content).setEscapeModelStrings(false));
  244. }
  245. @Override
  246. protected String getPageName() {
  247. return getString("gb.commitdiff");
  248. }
  249. @Override
  250. protected boolean isCommitPage() {
  251. return true;
  252. }
  253. @Override
  254. protected Class<? extends BasePage> getRepoNavPageClass() {
  255. return LogPage.class;
  256. }
  257. }