2 * Copyright 2000-2014 JetBrains s.r.o.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package com.intellij.openapi.vcs.update;
18 import com.intellij.diff.*;
19 import com.intellij.diff.actions.impl.GoToChangePopupBuilder;
20 import com.intellij.diff.chains.DiffRequestChain;
21 import com.intellij.diff.chains.DiffRequestProducer;
22 import com.intellij.diff.chains.DiffRequestProducerException;
23 import com.intellij.diff.contents.DiffContent;
24 import com.intellij.diff.requests.DiffRequest;
25 import com.intellij.diff.requests.SimpleDiffRequest;
26 import com.intellij.history.ByteContent;
27 import com.intellij.history.Label;
28 import com.intellij.openapi.actionSystem.*;
29 import com.intellij.openapi.progress.ProcessCanceledException;
30 import com.intellij.openapi.progress.ProgressIndicator;
31 import com.intellij.openapi.project.DumbAware;
32 import com.intellij.openapi.project.Project;
33 import com.intellij.openapi.util.Pair;
34 import com.intellij.openapi.util.UserDataHolder;
35 import com.intellij.openapi.util.UserDataHolderBase;
36 import com.intellij.openapi.util.io.FileUtil;
37 import com.intellij.openapi.vcs.FilePath;
38 import com.intellij.openapi.vcs.FileStatus;
39 import com.intellij.openapi.vcs.VcsDataKeys;
40 import com.intellij.openapi.vcs.changes.actions.diff.ChangeGoToChangePopupAction;
41 import com.intellij.openapi.vfs.pointers.VirtualFilePointer;
42 import com.intellij.util.Consumer;
43 import com.intellij.vcsUtil.VcsUtil;
44 import org.jetbrains.annotations.NotNull;
45 import org.jetbrains.annotations.Nullable;
47 import java.io.IOException;
48 import java.util.ArrayList;
49 import java.util.List;
51 public class ShowUpdatedDiffAction extends AnAction implements DumbAware {
53 public void update(AnActionEvent e) {
54 final DataContext dc = e.getDataContext();
56 final Presentation presentation = e.getPresentation();
58 //presentation.setVisible(isVisible(dc));
59 presentation.setEnabled(isVisible(dc) && isEnabled(dc));
62 private boolean isVisible(final DataContext dc) {
63 final Project project = CommonDataKeys.PROJECT.getData(dc);
64 return (project != null) && (VcsDataKeys.LABEL_BEFORE.getData(dc) != null) && (VcsDataKeys.LABEL_AFTER.getData(dc) != null);
67 private boolean isEnabled(final DataContext dc) {
68 final Iterable<Pair<VirtualFilePointer, FileStatus>> iterable = VcsDataKeys.UPDATE_VIEW_FILES_ITERABLE.getData(dc);
69 return iterable != null;
72 public void actionPerformed(AnActionEvent e) {
73 final DataContext dc = e.getDataContext();
74 if ((!isVisible(dc)) || (!isEnabled(dc))) return;
76 final Project project = CommonDataKeys.PROJECT.getData(dc);
77 final Iterable<Pair<VirtualFilePointer, FileStatus>> iterable = e.getRequiredData(VcsDataKeys.UPDATE_VIEW_FILES_ITERABLE);
78 final Label before = (Label)e.getRequiredData(VcsDataKeys.LABEL_BEFORE);
79 final Label after = (Label)e.getRequiredData(VcsDataKeys.LABEL_AFTER);
80 final String selectedUrl = VcsDataKeys.UPDATE_VIEW_SELECTED_PATH.getData(dc);
82 MyDiffRequestChain requestChain = new MyDiffRequestChain(project, iterable, before, after, selectedUrl);
83 DiffManager.getInstance().showDiff(project, requestChain, DiffDialogHints.FRAME);
86 private static class MyDiffRequestChain extends UserDataHolderBase implements DiffRequestChain, GoToChangePopupBuilder.Chain {
87 @Nullable private final Project myProject;
88 @NotNull private final Label myBefore;
89 @NotNull private final Label myAfter;
90 @NotNull private final List<MyDiffRequestProducer> myRequests = new ArrayList<MyDiffRequestProducer>();
94 public MyDiffRequestChain(@Nullable Project project,
95 @NotNull Iterable<Pair<VirtualFilePointer, FileStatus>> iterable,
96 @NotNull Label before,
98 @Nullable String selectedUrl) {
104 for (Pair<VirtualFilePointer, FileStatus> pair : iterable) {
105 if (selected == -1 && pair.first.getUrl().equals(selectedUrl)) selected = myRequests.size();
106 myRequests.add(new MyDiffRequestProducer(pair.first, pair.second));
108 if (selected != -1) myIndex = selected;
113 public List<MyDiffRequestProducer> getRequests() {
118 public int getIndex() {
123 public void setIndex(int index) {
129 public AnAction createGoToChangeAction(@NotNull Consumer<Integer> onSelected) {
130 return new ChangeGoToChangePopupAction.Fake<MyDiffRequestChain>(this, myIndex, onSelected) {
133 protected FilePath getFilePath(int index) {
134 return myRequests.get(index).getFilePath();
139 protected FileStatus getFileStatus(int index) {
140 return myRequests.get(index).getFileStatus();
145 private class MyDiffRequestProducer implements DiffRequestProducer {
146 @NotNull private final VirtualFilePointer myFilePointer;
147 @NotNull private final FileStatus myFileStatus;
148 @NotNull private final FilePath myFilePath;
150 public MyDiffRequestProducer(@NotNull VirtualFilePointer filePointer, @NotNull FileStatus fileStatus) {
151 myFilePointer = filePointer;
152 myFileStatus = fileStatus;
154 myFilePath = VcsUtil.getFilePath(myFilePointer.getPresentableUrl(), false);
159 public String getName() {
160 return myFilePointer.getUrl();
164 public FilePath getFilePath() {
169 public FileStatus getFileStatus() {
175 public DiffRequest process(@NotNull UserDataHolder context, @NotNull ProgressIndicator indicator)
176 throws DiffRequestProducerException, ProcessCanceledException {
178 DiffContent content1;
179 DiffContent content2;
181 if (FileStatus.ADDED.equals(myFileStatus)) {
182 content1 = DiffContentFactory.getInstance().createEmpty();
185 byte[] bytes1 = loadContent(myFilePointer, myBefore);
186 content1 = DiffContentFactoryImpl.getInstanceImpl().createFromBytes(myProject, myFilePath, bytes1);
189 if (FileStatus.DELETED.equals(myFileStatus)) {
190 content2 = DiffContentFactory.getInstance().createEmpty();
193 byte[] bytes2 = loadContent(myFilePointer, myAfter);
194 content2 = DiffContentFactoryImpl.getInstanceImpl().createFromBytes(myProject, myFilePath, bytes2);
197 String title = DiffRequestFactoryImpl.getContentTitle(myFilePath);
198 return new SimpleDiffRequest(title, content1, content2, "Before update", "After update");
200 catch (IOException e) {
201 throw new DiffRequestProducerException("Can't load content", e);
207 private static byte[] loadContent(@NotNull VirtualFilePointer filePointer, @NotNull Label label) throws DiffRequestProducerException {
208 String path = filePointer.getPresentableUrl();
209 ByteContent byteContent = label.getByteContent(FileUtil.toSystemIndependentName(path));
211 if (byteContent == null || byteContent.isDirectory() || byteContent.getBytes() == null) {
212 throw new DiffRequestProducerException("Can't load content");
215 return byteContent.getBytes();