/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ChangeDiffRequestPresentable.java

https://bitbucket.org/nbargnesi/idea · Java · 224 lines · 186 code · 21 blank · 17 comment · 75 complexity · abe4a7dcbaf30da08a0dfa92d12d2de5 MD5 · raw file

  1. /*
  2. * Copyright 2000-2009 JetBrains s.r.o.
  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.intellij.openapi.vcs.changes.actions;
  17. import com.intellij.CommonBundle;
  18. import com.intellij.openapi.actionSystem.AnAction;
  19. import com.intellij.openapi.diff.DiffContent;
  20. import com.intellij.openapi.diff.FileContent;
  21. import com.intellij.openapi.diff.SimpleContent;
  22. import com.intellij.openapi.diff.SimpleDiffRequest;
  23. import com.intellij.openapi.fileTypes.FileType;
  24. import com.intellij.openapi.fileTypes.FileTypes;
  25. import com.intellij.openapi.fileTypes.ex.FileTypeChooser;
  26. import com.intellij.openapi.progress.ProgressIndicator;
  27. import com.intellij.openapi.progress.ProgressManager;
  28. import com.intellij.openapi.project.Project;
  29. import com.intellij.openapi.ui.Messages;
  30. import com.intellij.openapi.util.io.FileUtil;
  31. import com.intellij.openapi.vcs.FilePath;
  32. import com.intellij.openapi.vcs.VcsBundle;
  33. import com.intellij.openapi.vcs.VcsException;
  34. import com.intellij.openapi.vcs.changes.*;
  35. import com.intellij.openapi.vfs.VirtualFile;
  36. import org.jetbrains.annotations.NotNull;
  37. import org.jetbrains.annotations.Nullable;
  38. import java.util.List;
  39. public class ChangeDiffRequestPresentable implements DiffRequestPresentable {
  40. private final Project myProject;
  41. private final Change myChange;
  42. // I don't like that much
  43. private boolean myIgnoreDirectoryFlag;
  44. public ChangeDiffRequestPresentable(final Project project, final Change change) {
  45. myChange = change;
  46. myProject = project;
  47. }
  48. public void setIgnoreDirectoryFlag(boolean ignoreDirectoryFlag) {
  49. myIgnoreDirectoryFlag = ignoreDirectoryFlag;
  50. }
  51. public MyResult step(DiffChainContext context) {
  52. final SimpleDiffRequest request = new SimpleDiffRequest(myProject, null);
  53. if (! canShowChange(context)) {
  54. return new MyResult(request, DiffPresentationReturnValue.removeFromList,
  55. "Can not show diff for binary '" + ChangesUtil.getFilePath(myChange).getPath() + "'");
  56. }
  57. if (! loadCurrentContents(request, myChange)) return new MyResult(request, DiffPresentationReturnValue.quit);
  58. return new MyResult(request, DiffPresentationReturnValue.useRequest);
  59. }
  60. @Override
  61. public String getPathPresentation() {
  62. return ChangesUtil.getFilePath(myChange).getPath();
  63. }
  64. @Nullable
  65. public void haveStuff() throws VcsException {
  66. final boolean canShow = checkContentsAvailable(myChange.getBeforeRevision(), myChange.getAfterRevision());
  67. if (! canShow) {
  68. throw new VcsException("Can not load contents of " + ChangesUtil.getFilePath(myChange).getPath());
  69. }
  70. }
  71. public List<? extends AnAction> createActions(ShowDiffAction.DiffExtendUIFactory uiFactory) {
  72. return uiFactory.createActions(myChange);
  73. }
  74. private boolean loadCurrentContents(final SimpleDiffRequest request, final Change change) {
  75. final ContentRevision bRev = change.getBeforeRevision();
  76. final ContentRevision aRev = change.getAfterRevision();
  77. String beforePath = bRev != null ? bRev.getFile().getPath() : null;
  78. String afterPath = aRev != null ? aRev.getFile().getPath() : null;
  79. String title;
  80. if (beforePath != null && afterPath != null && !beforePath.equals(afterPath)) {
  81. beforePath = FileUtil.toSystemDependentName(beforePath);
  82. afterPath = FileUtil.toSystemDependentName(afterPath);
  83. title = beforePath + " -> " + afterPath;
  84. }
  85. else if (beforePath != null) {
  86. beforePath = FileUtil.toSystemDependentName(beforePath);
  87. title = beforePath;
  88. }
  89. else if (afterPath != null) {
  90. afterPath = FileUtil.toSystemDependentName(afterPath);
  91. title = afterPath;
  92. }
  93. else {
  94. title = VcsBundle.message("diff.unknown.path.title");
  95. }
  96. request.setWindowTitle(title);
  97. boolean result = ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
  98. public void run() {
  99. final ProgressIndicator pi = ProgressManager.getInstance().getProgressIndicator();
  100. if (pi != null) {
  101. pi.setIndeterminate(true);
  102. }
  103. request.setContents(createContent(bRev), createContent(aRev));
  104. }
  105. }, VcsBundle.message("progress.loading.diff.revisions"), true, myProject);
  106. if (! result) return false;
  107. String beforeRevisionTitle = (bRev != null) ? bRev.getRevisionNumber().asString() : "";
  108. String afterRevisionTitle = (aRev != null) ? aRev.getRevisionNumber().asString() : "";
  109. if ((beforeRevisionTitle == null) || (beforeRevisionTitle.length() == 0)) {
  110. beforeRevisionTitle = "Base version";
  111. }
  112. if ((afterRevisionTitle == null) || (afterRevisionTitle.length() == 0)) {
  113. afterRevisionTitle = "Your version";
  114. }
  115. request.setContentTitles(beforeRevisionTitle, afterRevisionTitle);
  116. return true;
  117. }
  118. @NotNull
  119. private DiffContent createContent(final ContentRevision revision) {
  120. ProgressManager.checkCanceled();
  121. if (revision == null) return SimpleContent.createEmpty();
  122. if (revision instanceof CurrentContentRevision) {
  123. final CurrentContentRevision current = (CurrentContentRevision)revision;
  124. final VirtualFile vFile = current.getVirtualFile();
  125. return vFile != null ? new FileContent(myProject, vFile) : new SimpleContent("");
  126. }
  127. String revisionContent;
  128. try {
  129. revisionContent = revision.getContent();
  130. }
  131. catch(VcsException ex) {
  132. // TODO: correct exception handling
  133. revisionContent = null;
  134. }
  135. SimpleContent content = revisionContent == null
  136. ? new SimpleContent("")
  137. : new SimpleContent(revisionContent, revision.getFile().getFileType());
  138. VirtualFile vFile = revision.getFile().getVirtualFile();
  139. if (vFile != null) {
  140. content.setCharset(vFile.getCharset());
  141. content.setBOM(vFile.getBOM());
  142. }
  143. content.setReadOnly(true);
  144. return content;
  145. }
  146. private boolean canShowChange(DiffChainContext context) {
  147. final ContentRevision bRev = myChange.getBeforeRevision();
  148. final ContentRevision aRev = myChange.getAfterRevision();
  149. if (myIgnoreDirectoryFlag) {
  150. if (! checkContentsAvailable(bRev, aRev)) return false;
  151. return true;
  152. }
  153. if ((bRev != null && (bRev.getFile().getFileType().isBinary() || bRev.getFile().isDirectory())) ||
  154. (aRev != null && (aRev.getFile().getFileType().isBinary() || aRev.getFile().isDirectory()))) {
  155. if (bRev != null && bRev.getFile().getFileType() == FileTypes.UNKNOWN && !bRev.getFile().isDirectory()) {
  156. if (! checkContentsAvailable(bRev, aRev)) return false;
  157. if (!checkAssociate(myProject, bRev.getFile(), context)) return false;
  158. }
  159. else if (aRev != null && aRev.getFile().getFileType() == FileTypes.UNKNOWN && !aRev.getFile().isDirectory()) {
  160. if (! checkContentsAvailable(bRev, aRev)) return false;
  161. if (!checkAssociate(myProject, aRev.getFile(), context)) return false;
  162. }
  163. else {
  164. return false;
  165. }
  166. }
  167. return true;
  168. }
  169. private static boolean hasContents(@Nullable final ContentRevision rev) {
  170. if (rev == null) return false;
  171. try {
  172. if (rev instanceof BinaryContentRevision) {
  173. return ((BinaryContentRevision) rev).getBinaryContent() != null;
  174. } else {
  175. return rev.getContent() != null;
  176. }
  177. }
  178. catch (VcsException e) {
  179. return false;
  180. }
  181. }
  182. private static boolean checkContentsAvailable(@Nullable final ContentRevision bRev, @Nullable final ContentRevision aRev) {
  183. if (hasContents(bRev)) return true;
  184. return hasContents(aRev);
  185. }
  186. public static boolean checkAssociate(final Project project, final FilePath file, DiffChainContext context) {
  187. final String pattern = FileUtil.getExtension(file.getName());
  188. if (context.contains(pattern)) return false;
  189. int rc = Messages.showOkCancelDialog(project,
  190. VcsBundle.message("diff.unknown.file.type.prompt", file.getName()),
  191. VcsBundle.message("diff.unknown.file.type.title"),
  192. VcsBundle.message("diff.unknown.file.type.associate"),
  193. CommonBundle.getCancelButtonText(),
  194. Messages.getQuestionIcon());
  195. if (rc == 0) {
  196. FileType fileType = FileTypeChooser.associateFileType(file.getName());
  197. return fileType != null && !fileType.isBinary();
  198. } else {
  199. context.add(pattern);
  200. }
  201. return false;
  202. }
  203. }