mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
apply patch: show diff with conflicts
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.openapi.diff;
|
||||
|
||||
import com.intellij.openapi.actionSystem.DataKey;
|
||||
import com.intellij.openapi.actionSystem.IdeActions;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Factory;
|
||||
@@ -23,8 +24,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A request for a diff or merge operation.
|
||||
@@ -35,9 +35,12 @@ public abstract class DiffRequest {
|
||||
private ToolbarAddons myToolbarAddons = ToolbarAddons.NOTHING;
|
||||
@NonNls private static final String COMMON_DIFF_GROUP_KEY = "DiffWindow";
|
||||
private Factory<JComponent> myBottomComponentFactory = null;
|
||||
private final HashSet myHints = new HashSet();
|
||||
private final Map<String, Object> myGenericData;
|
||||
|
||||
protected DiffRequest(Project project) {
|
||||
myProject = project;
|
||||
myGenericData = new HashMap<String, Object>(2);
|
||||
}
|
||||
|
||||
public void setToolbarAddons(@NotNull ToolbarAddons toolbarAddons) {
|
||||
@@ -75,7 +78,31 @@ public abstract class DiffRequest {
|
||||
* @return not null (possibly empty) collection of hints for diff tool.
|
||||
*/
|
||||
public Collection getHints() {
|
||||
return Collections.emptySet();
|
||||
return Collections.unmodifiableCollection(myHints);
|
||||
}
|
||||
|
||||
public void passForDataContext(final DataKey key, final Object value) {
|
||||
myGenericData.put(key.getName(), value);
|
||||
}
|
||||
|
||||
public Map<String, Object> getGenericData() {
|
||||
return myGenericData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param hint
|
||||
* @see DiffRequest#getHints()
|
||||
*/
|
||||
public void addHint(Object hint) {
|
||||
myHints.add(hint);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param hint
|
||||
* @see DiffRequest#getHints()
|
||||
*/
|
||||
public void removeHint(Object hint) {
|
||||
myHints.remove(hint);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -26,4 +26,6 @@ public interface DiffViewer {
|
||||
JComponent getComponent();
|
||||
|
||||
JComponent getPreferredFocusedComponent();
|
||||
|
||||
int getContentsNumber();
|
||||
}
|
||||
|
||||
@@ -31,47 +31,16 @@ public class SimpleDiffRequest extends DiffRequest {
|
||||
private final DiffContent[] myContents = new DiffContent[2];
|
||||
private final String[] myContentTitles = new String[2];
|
||||
private String myWindowTitle;
|
||||
private final HashSet myHints = new HashSet();
|
||||
private final Map<String, Object> myGenericData;
|
||||
|
||||
public SimpleDiffRequest(Project project, String windowtitle) {
|
||||
super(project);
|
||||
myWindowTitle = windowtitle;
|
||||
myGenericData = new HashMap<String, Object>(2);
|
||||
}
|
||||
|
||||
public DiffContent[] getContents() { return myContents; }
|
||||
public String[] getContentTitles() { return myContentTitles; }
|
||||
public String getWindowTitle() { return myWindowTitle; }
|
||||
|
||||
public Collection getHints() {
|
||||
return Collections.unmodifiableCollection(myHints);
|
||||
}
|
||||
|
||||
public void passForDataContext(final DataKey key, final Object value) {
|
||||
myGenericData.put(key.getName(), value);
|
||||
}
|
||||
|
||||
public Map<String, Object> getGenericData() {
|
||||
return myGenericData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param hint
|
||||
* @see DiffRequest#getHints()
|
||||
*/
|
||||
public void addHint(Object hint) {
|
||||
myHints.add(hint);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param hint
|
||||
* @see DiffRequest#getHints()
|
||||
*/
|
||||
public void removeHint(Object hint) {
|
||||
myHints.remove(hint);
|
||||
}
|
||||
|
||||
public void setContents(@NotNull DiffContent content1, @NotNull DiffContent content2) {
|
||||
myContents[0] = content1;
|
||||
myContents[1] = content2;
|
||||
|
||||
@@ -19,7 +19,6 @@ import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.ActionManager;
|
||||
import com.intellij.openapi.actionSystem.DataConstants;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.actionSystem.DataProvider;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.diff.*;
|
||||
import com.intellij.openapi.diff.actions.MergeActionGroup;
|
||||
@@ -49,8 +48,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.security.InvalidParameterException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSidesContainer {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.DiffPanelImpl");
|
||||
@@ -79,7 +76,7 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid
|
||||
}
|
||||
};
|
||||
private boolean myDisposed = false;
|
||||
private final DiffPanelImpl.MyDataProvider myDataProvider;
|
||||
private final GenericDataProvider myDataProvider;
|
||||
|
||||
public DiffPanelImpl(final Window owner, Project project, boolean enableToolbar) {
|
||||
myOptions = new DiffPanelOptions(this);
|
||||
@@ -96,7 +93,7 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid
|
||||
mySplitter = new DiffSplitter(myLeftSide.getComponent(), myRightSide.getComponent(),
|
||||
new DiffDividerPaint(this, FragmentSide.SIDE1));
|
||||
myPanel.insertDiffComponent(mySplitter, new MyScrollingPanel());
|
||||
myDataProvider = new MyDataProvider();
|
||||
myDataProvider = new MyGenericDataProvider(this);
|
||||
myPanel.setDataProvider(myDataProvider);
|
||||
|
||||
final ComparisonPolicy comparisonPolicy = getComparisonPolicy();
|
||||
@@ -202,6 +199,10 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid
|
||||
return myCurrentSide.getFocusableComponent();
|
||||
}
|
||||
|
||||
public int getContentsNumber() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
public ComparisonPolicy getComparisonPolicy() {
|
||||
return myData.getComparisonPolicy();
|
||||
}
|
||||
@@ -306,9 +307,7 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid
|
||||
if (data.getHints().contains(DiffTool.HINT_DO_NOT_IGNORE_WHITESPACES)) {
|
||||
setComparisonPolicy(ComparisonPolicy.DEFAULT, false);
|
||||
}
|
||||
if (myDiffRequest instanceof SimpleDiffRequest) {
|
||||
myDataProvider.putData(((SimpleDiffRequest) myDiffRequest).getGenericData());
|
||||
}
|
||||
myDataProvider.putData(myDiffRequest.getGenericData());
|
||||
|
||||
setContents(data.getContents()[0], data.getContents()[1]);
|
||||
setTitle1(data.getContentTitles()[0]);
|
||||
@@ -360,32 +359,28 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid
|
||||
}
|
||||
}
|
||||
|
||||
private class MyDataProvider implements DataProvider {
|
||||
private final Map<String, Object> myGenericData;
|
||||
private class MyGenericDataProvider extends GenericDataProvider {
|
||||
private DiffPanelImpl myDiffPanel;
|
||||
|
||||
private MyDataProvider() {
|
||||
myGenericData = new HashMap<String, Object>();
|
||||
private MyGenericDataProvider(DiffPanelImpl diffPanel) {
|
||||
myDiffPanel = diffPanel;
|
||||
}
|
||||
|
||||
private final FocusDiffSide myFocusDiffSide = new FocusDiffSide() {
|
||||
public Editor getEditor() {
|
||||
return getCurrentSide().getEditor();
|
||||
return myDiffPanel.getCurrentSide().getEditor();
|
||||
}
|
||||
|
||||
public int[] getFragmentStartingLines() {
|
||||
return getFragmentBeginnings();
|
||||
return myDiffPanel.getFragmentBeginnings();
|
||||
}
|
||||
};
|
||||
|
||||
void putData(final Map<String, Object> map) {
|
||||
myGenericData.putAll(map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getData(String dataId) {
|
||||
if (DataConstants.DIFF_VIEWER.equals(dataId)) return DiffPanelImpl.this;
|
||||
if (FocusDiffSide.FOCUSED_DIFF_SIDE.equals(dataId)) return myCurrentSide == null ? null : myFocusDiffSide;
|
||||
return myGenericData.get(dataId);
|
||||
if (DataConstants.DIFF_VIEWER.equals(dataId)) return myDiffPanel;
|
||||
if (FocusDiffSide.FOCUSED_DIFF_SIDE.equals(dataId)) return myDiffPanel.myCurrentSide == null ? null : myFocusDiffSide;
|
||||
return super.getData(dataId);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.diff.impl;
|
||||
|
||||
import com.intellij.openapi.actionSystem.DataConstants;
|
||||
import com.intellij.openapi.actionSystem.DataProvider;
|
||||
import com.intellij.openapi.diff.impl.util.FocusDiffSide;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class GenericDataProvider implements DataProvider {
|
||||
private final Map<String, Object> myGenericData;
|
||||
|
||||
public GenericDataProvider() {
|
||||
myGenericData = new HashMap<String, Object>();
|
||||
}
|
||||
|
||||
public void putData(final Map<String, Object> map) {
|
||||
myGenericData.putAll(map);
|
||||
}
|
||||
|
||||
public Object getData(String dataId) {
|
||||
return myGenericData.get(dataId);
|
||||
}
|
||||
}
|
||||
+11
-3
@@ -23,6 +23,7 @@ import com.intellij.openapi.diff.actions.NextDiffAction;
|
||||
import com.intellij.openapi.diff.actions.PreviousDiffAction;
|
||||
import com.intellij.openapi.diff.impl.DiffUtil;
|
||||
import com.intellij.openapi.diff.impl.EditingSides;
|
||||
import com.intellij.openapi.diff.impl.GenericDataProvider;
|
||||
import com.intellij.openapi.diff.impl.highlighting.FragmentSide;
|
||||
import com.intellij.openapi.diff.impl.incrementalMerge.ChangeCounter;
|
||||
import com.intellij.openapi.diff.impl.incrementalMerge.ChangeList;
|
||||
@@ -72,6 +73,7 @@ public class MergePanel2 implements DiffViewer {
|
||||
private final DividersRepainter myDividersRepainter = new DividersRepainter();
|
||||
private StatusUpdater myStatusUpdater;
|
||||
private final DialogBuilder myBuilder;
|
||||
private MergePanel2.MyDataProvider myProvider;
|
||||
|
||||
public MergePanel2(DialogBuilder builder, Disposable parent) {
|
||||
ArrayList<EditorPlace> editorPlaces = new ArrayList<EditorPlace>();
|
||||
@@ -105,7 +107,8 @@ public class MergePanel2 implements DiffViewer {
|
||||
FontSizeSynchronizer.attachTo(editorPlaces);
|
||||
myPanel = new DiffPanelOutterComponent(TextDiffType.MERGE_TYPES, TOOLBAR);
|
||||
myPanel.insertDiffComponent(new ThreePanels(myEditorsPanels, myDividers), new MyScrollingPanel());
|
||||
myPanel.setDataProvider(new MyDataProvider());
|
||||
myProvider = new MyDataProvider();
|
||||
myPanel.setDataProvider(myProvider);
|
||||
myBuilder = builder;
|
||||
}
|
||||
|
||||
@@ -233,6 +236,7 @@ public class MergePanel2 implements DiffViewer {
|
||||
}
|
||||
LOG.assertTrue(!myDuringCreation);
|
||||
myDuringCreation = true;
|
||||
myProvider.putData(data.getGenericData());
|
||||
try {
|
||||
myData = data;
|
||||
String[] titles = myData.getContentTitles();
|
||||
@@ -275,6 +279,10 @@ public class MergePanel2 implements DiffViewer {
|
||||
return getEditorPlace(1).getContentComponent();
|
||||
}
|
||||
|
||||
public int getContentsNumber() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
private boolean hasAllEditors() {
|
||||
for (int i = 0; i < EDITORS_COUNT; i++) {
|
||||
if (getEditor(i) == null) return false;
|
||||
@@ -390,7 +398,7 @@ public class MergePanel2 implements DiffViewer {
|
||||
return contentType;
|
||||
}
|
||||
|
||||
private class MyDataProvider implements DataProvider {
|
||||
private class MyDataProvider extends GenericDataProvider {
|
||||
public Object getData(String dataId) {
|
||||
if (FocusDiffSide.FOCUSED_DIFF_SIDE.equals(dataId)) {
|
||||
int index = getFocusedEditorIndex();
|
||||
@@ -405,7 +413,7 @@ public class MergePanel2 implements DiffViewer {
|
||||
}
|
||||
}
|
||||
else if (DataConstants.DIFF_VIEWER.equals(dataId)) return MergePanel2.this;
|
||||
return null;
|
||||
return super.getData(dataId);
|
||||
}
|
||||
|
||||
private int getFocusedEditorIndex() {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.openapi.vcs.changes;
|
||||
|
||||
import com.intellij.openapi.diff.DiffRequest;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import com.intellij.openapi.diff.SimpleDiffRequest;
|
||||
|
||||
@@ -24,8 +25,8 @@ public interface ChangeRequestChain {
|
||||
boolean canMoveBack();
|
||||
|
||||
@Nullable
|
||||
SimpleDiffRequest moveForward();
|
||||
DiffRequest moveForward();
|
||||
|
||||
@Nullable
|
||||
SimpleDiffRequest moveBack();
|
||||
DiffRequest moveBack();
|
||||
}
|
||||
|
||||
+43
-163
@@ -28,6 +28,7 @@ import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.NullableFactory;
|
||||
import com.intellij.openapi.vcs.FilePath;
|
||||
import com.intellij.openapi.vcs.VcsBundle;
|
||||
import com.intellij.openapi.vcs.VcsDataKeys;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.changes.Change;
|
||||
import com.intellij.openapi.vcs.changes.ChangeRequestChain;
|
||||
@@ -44,7 +45,8 @@ import java.util.List;
|
||||
* @author yole
|
||||
*/
|
||||
public class ChangeDiffRequest implements ChangeRequestChain {
|
||||
private final List<Change> myChanges;
|
||||
private final List<DiffRequestPresentable> mySteps;
|
||||
private final boolean myShowFrame;
|
||||
private int myIndex;
|
||||
|
||||
private final ShowDiffAction.DiffExtendUIFactory myActionsFactory;
|
||||
@@ -53,9 +55,11 @@ public class ChangeDiffRequest implements ChangeRequestChain {
|
||||
private final AnAction myNextChangeAction;
|
||||
private final Project myProject;
|
||||
|
||||
public ChangeDiffRequest(final Project project, final List<Change> changes, final ShowDiffAction.DiffExtendUIFactory actionsFactory) {
|
||||
public ChangeDiffRequest(final Project project, final List<DiffRequestPresentable> steps, final ShowDiffAction.DiffExtendUIFactory actionsFactory,
|
||||
final boolean showFrame) {
|
||||
myProject = project;
|
||||
myChanges = changes;
|
||||
mySteps = steps;
|
||||
myShowFrame = showFrame;
|
||||
|
||||
myIndex = 0;
|
||||
myActionsFactory = actionsFactory;
|
||||
@@ -64,24 +68,36 @@ public class ChangeDiffRequest implements ChangeRequestChain {
|
||||
myNextChangeAction = ActionManager.getInstance().getAction("Diff.NextChange");
|
||||
}
|
||||
|
||||
private void onEveryMove(final DiffRequest simpleRequest, final boolean showFrame) {
|
||||
simpleRequest.passForDataContext(VcsDataKeys.DIFF_REQUEST_CHAIN, this);
|
||||
if (showFrame) {
|
||||
simpleRequest.addHint(DiffTool.HINT_SHOW_FRAME);
|
||||
}
|
||||
else {
|
||||
simpleRequest.addHint(DiffTool.HINT_SHOW_MODAL_DIALOG);
|
||||
}
|
||||
if (mySteps.size() > 1) {
|
||||
simpleRequest.addHint(DiffTool.HINT_ALLOW_NO_DIFFERENCES);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean quickCheckHaveStuff() {
|
||||
if (myChanges.isEmpty()) return false;
|
||||
if (myChanges.size() == 1) {
|
||||
final Change change = myChanges.get(0);
|
||||
return checkContentsAvailable(change.getBeforeRevision(), change.getAfterRevision());
|
||||
if (mySteps.isEmpty()) return false;
|
||||
if (mySteps.size() == 1) {
|
||||
return mySteps.get(0).haveStuff();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public SimpleDiffRequest init(final int idx) {
|
||||
if (idx < 0 || idx > (myChanges.size() - 1)) return null;
|
||||
public DiffRequest init(final int idx) {
|
||||
if (idx < 0 || idx > (mySteps.size() - 1)) return null;
|
||||
myIndex = idx - 1;
|
||||
return moveForward();
|
||||
}
|
||||
|
||||
public boolean canMoveForward() {
|
||||
return myIndex < (myChanges.size() - 1);
|
||||
return myIndex < (mySteps.size() - 1);
|
||||
}
|
||||
|
||||
public boolean canMoveBack() {
|
||||
@@ -89,7 +105,7 @@ public class ChangeDiffRequest implements ChangeRequestChain {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public SimpleDiffRequest moveForward() {
|
||||
public DiffRequest moveForward() {
|
||||
return moveImpl(new MoveDirection() {
|
||||
public boolean canMove() {
|
||||
return canMoveForward();
|
||||
@@ -101,20 +117,24 @@ public class ChangeDiffRequest implements ChangeRequestChain {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private SimpleDiffRequest moveImpl(final MoveDirection moveDirection) {
|
||||
private DiffRequest moveImpl(final MoveDirection moveDirection) {
|
||||
while (moveDirection.canMove()) {
|
||||
final int nextIdx = myIndex + moveDirection.direction();
|
||||
final Change change = myChanges.get(nextIdx);
|
||||
final SimpleDiffRequest request = new SimpleDiffRequest(myProject, null);
|
||||
final MyReturnValue returnValue = getRequestForChange(request, change);
|
||||
if (MyReturnValue.quit.equals(returnValue)) {
|
||||
|
||||
final DiffRequestPresentable diffRequestPresentable = mySteps.get(nextIdx);
|
||||
final DiffRequestPresentable.MyResult result = diffRequestPresentable.step();
|
||||
final DiffPresentationReturnValue returnValue = result.getReturnValue();
|
||||
if (DiffPresentationReturnValue.quit.equals(returnValue)) {
|
||||
return null;
|
||||
}
|
||||
if (MyReturnValue.removeFromList.equals(returnValue)) {
|
||||
myChanges.remove(nextIdx);
|
||||
if (DiffPresentationReturnValue.removeFromList.equals(returnValue)) {
|
||||
mySteps.remove(nextIdx);
|
||||
continue;
|
||||
}
|
||||
final DiffRequest request = result.getRequest();
|
||||
takeStuffFromFactory(request, diffRequestPresentable.createActions(myActionsFactory));
|
||||
myIndex = nextIdx;
|
||||
onEveryMove(request, myShowFrame);
|
||||
return request;
|
||||
}
|
||||
return null;
|
||||
@@ -126,7 +146,7 @@ public class ChangeDiffRequest implements ChangeRequestChain {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public SimpleDiffRequest moveBack() {
|
||||
public DiffRequest moveBack() {
|
||||
return moveImpl(new MoveDirection() {
|
||||
public boolean canMove() {
|
||||
return canMoveBack();
|
||||
@@ -137,32 +157,18 @@ public class ChangeDiffRequest implements ChangeRequestChain {
|
||||
});
|
||||
}
|
||||
|
||||
private static enum MyReturnValue {
|
||||
removeFromList,
|
||||
useRequest,
|
||||
quit;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private MyReturnValue getRequestForChange(final SimpleDiffRequest request, final Change change) {
|
||||
if (! canShowChange(change)) return MyReturnValue.removeFromList;
|
||||
if (! loadCurrentContents(request, change)) return MyReturnValue.quit;
|
||||
takeStuffFromFactory(request, change);
|
||||
return MyReturnValue.useRequest;
|
||||
}
|
||||
|
||||
private void takeStuffFromFactory(final SimpleDiffRequest request, final Change change) {
|
||||
if (myChanges.size() > 1 || (myActionsFactory != null)) {
|
||||
private void takeStuffFromFactory(final DiffRequest request, final List<? extends AnAction> actions) {
|
||||
if (mySteps.size() > 1 || (myActionsFactory != null)) {
|
||||
request.setToolbarAddons(new DiffRequest.ToolbarAddons() {
|
||||
public void customize(DiffToolbar toolbar) {
|
||||
if (myChanges.size() > 1)
|
||||
if (mySteps.size() > 1)
|
||||
toolbar.addSeparator();
|
||||
toolbar.addAction(myPrevChangeAction);
|
||||
toolbar.addAction(myNextChangeAction);
|
||||
|
||||
if (myActionsFactory != null) {
|
||||
toolbar.addSeparator();
|
||||
for (AnAction action : myActionsFactory.createActions(change)) {
|
||||
for (AnAction action : actions) {
|
||||
toolbar.addAction(action);
|
||||
}
|
||||
}
|
||||
@@ -178,130 +184,4 @@ public class ChangeDiffRequest implements ChangeRequestChain {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private boolean loadCurrentContents(final SimpleDiffRequest request, final Change change) {
|
||||
final ContentRevision bRev = change.getBeforeRevision();
|
||||
final ContentRevision aRev = change.getAfterRevision();
|
||||
|
||||
String beforePath = bRev != null ? bRev.getFile().getPath() : null;
|
||||
String afterPath = aRev != null ? aRev.getFile().getPath() : null;
|
||||
String title;
|
||||
if (beforePath != null && afterPath != null && !beforePath.equals(afterPath)) {
|
||||
title = beforePath + " -> " + afterPath;
|
||||
}
|
||||
else if (beforePath != null) {
|
||||
title = beforePath;
|
||||
}
|
||||
else if (afterPath != null) {
|
||||
title = afterPath;
|
||||
}
|
||||
else {
|
||||
title = VcsBundle.message("diff.unknown.path.title");
|
||||
}
|
||||
request.setWindowTitle(title);
|
||||
|
||||
boolean result = ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
|
||||
public void run() {
|
||||
request.setContents(createContent(bRev), createContent(aRev));
|
||||
}
|
||||
}, VcsBundle.message("progress.loading.diff.revisions"), true, myProject);
|
||||
if (! result) return false;
|
||||
|
||||
String beforeRevisionTitle = (bRev != null) ? bRev.getRevisionNumber().asString() : "";
|
||||
String afterRevisionTitle = (aRev != null) ? aRev.getRevisionNumber().asString() : "";
|
||||
if (beforeRevisionTitle.length() == 0) {
|
||||
beforeRevisionTitle = "Base version";
|
||||
}
|
||||
if (afterRevisionTitle.length() == 0) {
|
||||
afterRevisionTitle = "Your version";
|
||||
}
|
||||
request.setContentTitles(beforeRevisionTitle, afterRevisionTitle);
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private DiffContent createContent(final ContentRevision revision) {
|
||||
ProgressManager.checkCanceled();
|
||||
if (revision == null) return new SimpleContent("");
|
||||
if (revision instanceof CurrentContentRevision) {
|
||||
final CurrentContentRevision current = (CurrentContentRevision)revision;
|
||||
final VirtualFile vFile = current.getVirtualFile();
|
||||
return vFile != null ? new FileContent(myProject, vFile) : new SimpleContent("");
|
||||
}
|
||||
|
||||
String revisionContent;
|
||||
try {
|
||||
revisionContent = revision.getContent();
|
||||
}
|
||||
catch(VcsException ex) {
|
||||
// TODO: correct exception handling
|
||||
revisionContent = null;
|
||||
}
|
||||
SimpleContent content = revisionContent == null
|
||||
? new SimpleContent("")
|
||||
: new SimpleContent(revisionContent, revision.getFile().getFileType());
|
||||
VirtualFile vFile = revision.getFile().getVirtualFile();
|
||||
if (vFile != null) {
|
||||
content.setCharset(vFile.getCharset());
|
||||
content.setBOM(vFile.getBOM());
|
||||
}
|
||||
content.setReadOnly(true);
|
||||
return content;
|
||||
}
|
||||
|
||||
private boolean canShowChange(final Change change) {
|
||||
final ContentRevision bRev = change.getBeforeRevision();
|
||||
final ContentRevision aRev = change.getAfterRevision();
|
||||
|
||||
if ((bRev != null && (bRev.getFile().getFileType().isBinary() || bRev.getFile().isDirectory())) ||
|
||||
(aRev != null && (aRev.getFile().getFileType().isBinary() || aRev.getFile().isDirectory()))) {
|
||||
if (bRev != null && bRev.getFile().getFileType() == FileTypes.UNKNOWN && !bRev.getFile().isDirectory()) {
|
||||
if (! checkContentsAvailable(bRev, aRev)) return false;
|
||||
if (!checkAssociate(myProject, bRev.getFile())) return false;
|
||||
}
|
||||
else if (aRev != null && aRev.getFile().getFileType() == FileTypes.UNKNOWN && !aRev.getFile().isDirectory()) {
|
||||
if (! checkContentsAvailable(bRev, aRev)) return false;
|
||||
if (!checkAssociate(myProject, aRev.getFile())) return false;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean checkContentsAvailable(@Nullable final ContentRevision bRev, @Nullable final ContentRevision aRev) {
|
||||
String bContents = null;
|
||||
if (bRev != null) {
|
||||
try {
|
||||
bContents = bRev.getContent();
|
||||
} catch (VcsException e) {
|
||||
//
|
||||
}
|
||||
}
|
||||
String aContents = null;
|
||||
if (aRev != null) {
|
||||
try {
|
||||
aContents = aRev.getContent();
|
||||
} catch (VcsException e) {
|
||||
//
|
||||
}
|
||||
}
|
||||
return (bContents != null) || (aContents != null);
|
||||
}
|
||||
|
||||
private static boolean checkAssociate(final Project project, final FilePath file) {
|
||||
int rc = Messages.showDialog(project,
|
||||
VcsBundle.message("diff.unknown.file.type.prompt", file.getName()),
|
||||
VcsBundle.message("diff.unknown.file.type.title"),
|
||||
new String[] {
|
||||
VcsBundle.message("diff.unknown.file.type.associate"),
|
||||
CommonBundle.getCancelButtonText()
|
||||
}, 0, Messages.getQuestionIcon());
|
||||
if (rc == 0) {
|
||||
FileType fileType = FileTypeChooser.associateFileType(file.getName());
|
||||
return fileType != null && !fileType.isBinary();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+196
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.vcs.changes.actions;
|
||||
|
||||
import com.intellij.CommonBundle;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.diff.DiffContent;
|
||||
import com.intellij.openapi.diff.FileContent;
|
||||
import com.intellij.openapi.diff.SimpleContent;
|
||||
import com.intellij.openapi.diff.SimpleDiffRequest;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.FileTypes;
|
||||
import com.intellij.openapi.fileTypes.ex.FileTypeChooser;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.vcs.FilePath;
|
||||
import com.intellij.openapi.vcs.VcsBundle;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.changes.Change;
|
||||
import com.intellij.openapi.vcs.changes.ContentRevision;
|
||||
import com.intellij.openapi.vcs.changes.CurrentContentRevision;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ChangeDiffRequestPresentable implements DiffRequestPresentable {
|
||||
private final Project myProject;
|
||||
private final Change myChange;
|
||||
|
||||
public ChangeDiffRequestPresentable(final Project project, final Change change) {
|
||||
myChange = change;
|
||||
myProject = project;
|
||||
}
|
||||
|
||||
public MyResult step() {
|
||||
final SimpleDiffRequest request = new SimpleDiffRequest(myProject, null);
|
||||
return new MyResult(request, getRequestForChange(request));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private DiffPresentationReturnValue getRequestForChange(final SimpleDiffRequest request) {
|
||||
if (! canShowChange()) return DiffPresentationReturnValue.removeFromList;
|
||||
if (! loadCurrentContents(request, myChange)) return DiffPresentationReturnValue.quit;
|
||||
return DiffPresentationReturnValue.useRequest;
|
||||
}
|
||||
|
||||
public boolean haveStuff() {
|
||||
return checkContentsAvailable(myChange.getBeforeRevision(), myChange.getAfterRevision());
|
||||
}
|
||||
|
||||
public List<? extends AnAction> createActions(ShowDiffAction.DiffExtendUIFactory uiFactory) {
|
||||
return uiFactory.createActions(myChange);
|
||||
}
|
||||
|
||||
private boolean loadCurrentContents(final SimpleDiffRequest request, final Change change) {
|
||||
final ContentRevision bRev = change.getBeforeRevision();
|
||||
final ContentRevision aRev = change.getAfterRevision();
|
||||
|
||||
String beforePath = bRev != null ? bRev.getFile().getPath() : null;
|
||||
String afterPath = aRev != null ? aRev.getFile().getPath() : null;
|
||||
String title;
|
||||
if (beforePath != null && afterPath != null && !beforePath.equals(afterPath)) {
|
||||
title = beforePath + " -> " + afterPath;
|
||||
}
|
||||
else if (beforePath != null) {
|
||||
title = beforePath;
|
||||
}
|
||||
else if (afterPath != null) {
|
||||
title = afterPath;
|
||||
}
|
||||
else {
|
||||
title = VcsBundle.message("diff.unknown.path.title");
|
||||
}
|
||||
request.setWindowTitle(title);
|
||||
|
||||
boolean result = ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
|
||||
public void run() {
|
||||
request.setContents(createContent(bRev), createContent(aRev));
|
||||
}
|
||||
}, VcsBundle.message("progress.loading.diff.revisions"), true, myProject);
|
||||
if (! result) return false;
|
||||
|
||||
String beforeRevisionTitle = (bRev != null) ? bRev.getRevisionNumber().asString() : "";
|
||||
String afterRevisionTitle = (aRev != null) ? aRev.getRevisionNumber().asString() : "";
|
||||
if (beforeRevisionTitle.length() == 0) {
|
||||
beforeRevisionTitle = "Base version";
|
||||
}
|
||||
if (afterRevisionTitle.length() == 0) {
|
||||
afterRevisionTitle = "Your version";
|
||||
}
|
||||
request.setContentTitles(beforeRevisionTitle, afterRevisionTitle);
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private DiffContent createContent(final ContentRevision revision) {
|
||||
ProgressManager.checkCanceled();
|
||||
if (revision == null) return new SimpleContent("");
|
||||
if (revision instanceof CurrentContentRevision) {
|
||||
final CurrentContentRevision current = (CurrentContentRevision)revision;
|
||||
final VirtualFile vFile = current.getVirtualFile();
|
||||
return vFile != null ? new FileContent(myProject, vFile) : new SimpleContent("");
|
||||
}
|
||||
|
||||
String revisionContent;
|
||||
try {
|
||||
revisionContent = revision.getContent();
|
||||
}
|
||||
catch(VcsException ex) {
|
||||
// TODO: correct exception handling
|
||||
revisionContent = null;
|
||||
}
|
||||
SimpleContent content = revisionContent == null
|
||||
? new SimpleContent("")
|
||||
: new SimpleContent(revisionContent, revision.getFile().getFileType());
|
||||
VirtualFile vFile = revision.getFile().getVirtualFile();
|
||||
if (vFile != null) {
|
||||
content.setCharset(vFile.getCharset());
|
||||
content.setBOM(vFile.getBOM());
|
||||
}
|
||||
content.setReadOnly(true);
|
||||
return content;
|
||||
}
|
||||
|
||||
private boolean canShowChange() {
|
||||
final ContentRevision bRev = myChange.getBeforeRevision();
|
||||
final ContentRevision aRev = myChange.getAfterRevision();
|
||||
|
||||
if ((bRev != null && (bRev.getFile().getFileType().isBinary() || bRev.getFile().isDirectory())) ||
|
||||
(aRev != null && (aRev.getFile().getFileType().isBinary() || aRev.getFile().isDirectory()))) {
|
||||
if (bRev != null && bRev.getFile().getFileType() == FileTypes.UNKNOWN && !bRev.getFile().isDirectory()) {
|
||||
if (! checkContentsAvailable(bRev, aRev)) return false;
|
||||
if (!checkAssociate(myProject, bRev.getFile())) return false;
|
||||
}
|
||||
else if (aRev != null && aRev.getFile().getFileType() == FileTypes.UNKNOWN && !aRev.getFile().isDirectory()) {
|
||||
if (! checkContentsAvailable(bRev, aRev)) return false;
|
||||
if (!checkAssociate(myProject, aRev.getFile())) return false;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean checkContentsAvailable(@Nullable final ContentRevision bRev, @Nullable final ContentRevision aRev) {
|
||||
String bContents = null;
|
||||
if (bRev != null) {
|
||||
try {
|
||||
bContents = bRev.getContent();
|
||||
} catch (VcsException e) {
|
||||
//
|
||||
}
|
||||
}
|
||||
String aContents = null;
|
||||
if (aRev != null) {
|
||||
try {
|
||||
aContents = aRev.getContent();
|
||||
} catch (VcsException e) {
|
||||
//
|
||||
}
|
||||
}
|
||||
return (bContents != null) || (aContents != null);
|
||||
}
|
||||
|
||||
private static boolean checkAssociate(final Project project, final FilePath file) {
|
||||
int rc = Messages.showDialog(project,
|
||||
VcsBundle.message("diff.unknown.file.type.prompt", file.getName()),
|
||||
VcsBundle.message("diff.unknown.file.type.title"),
|
||||
new String[] {
|
||||
VcsBundle.message("diff.unknown.file.type.associate"),
|
||||
CommonBundle.getCancelButtonText()
|
||||
}, 0, Messages.getQuestionIcon());
|
||||
if (rc == 0) {
|
||||
FileType fileType = FileTypeChooser.associateFileType(file.getName());
|
||||
return fileType != null && !fileType.isBinary();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.vcs.changes.actions;
|
||||
|
||||
public enum DiffPresentationReturnValue {
|
||||
removeFromList,
|
||||
useRequest,
|
||||
quit
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.vcs.changes.actions;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.diff.DiffRequest;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface DiffRequestPresentable {
|
||||
MyResult step();
|
||||
boolean haveStuff();
|
||||
List<? extends AnAction> createActions(final ShowDiffAction.DiffExtendUIFactory uiFactory);
|
||||
|
||||
class MyResult {
|
||||
private final DiffRequest myRequest;
|
||||
private final DiffPresentationReturnValue myReturnValue;
|
||||
|
||||
public MyResult(DiffRequest request, DiffPresentationReturnValue returnValue) {
|
||||
myRequest = request;
|
||||
myReturnValue = returnValue;
|
||||
}
|
||||
|
||||
public DiffRequest getRequest() {
|
||||
return myRequest;
|
||||
}
|
||||
|
||||
public DiffPresentationReturnValue getReturnValue() {
|
||||
return myReturnValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
+19
-21
@@ -21,6 +21,7 @@ import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.diff.DiffManager;
|
||||
import com.intellij.openapi.diff.DiffRequest;
|
||||
import com.intellij.openapi.diff.DiffTool;
|
||||
import com.intellij.openapi.diff.SimpleDiffRequest;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
@@ -29,12 +30,10 @@ import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.openapi.vcs.FilePath;
|
||||
import com.intellij.openapi.vcs.VcsBundle;
|
||||
import com.intellij.openapi.vcs.VcsDataKeys;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.*;
|
||||
import com.intellij.openapi.vcs.changes.*;
|
||||
import com.intellij.util.NotNullFunction;
|
||||
import com.intellij.util.containers.Convertor;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -193,7 +192,12 @@ public class ShowDiffAction extends AnAction implements DumbAware {
|
||||
newIndex = 0;
|
||||
}
|
||||
|
||||
showDiffImpl(project, changeList, newIndex, actionsFactory, showFrame);
|
||||
showDiffImpl(project, ObjectsConvertor.convert(changeList,
|
||||
new Convertor<Change, DiffRequestPresentable>() {
|
||||
public ChangeDiffRequestPresentable convert(Change o) {
|
||||
return new ChangeDiffRequestPresentable(project, o);
|
||||
}
|
||||
}), newIndex, actionsFactory, showFrame);
|
||||
}
|
||||
|
||||
public static void showDiffForChange(Change[] changes, int index, final Project project, @Nullable DiffExtendUIFactory actionsFactory,
|
||||
@@ -210,27 +214,21 @@ public class ShowDiffAction extends AnAction implements DumbAware {
|
||||
break;
|
||||
}
|
||||
}
|
||||
showDiffImpl(project, changeList, index, actionsFactory, showFrame);
|
||||
showDiffImpl(project, ObjectsConvertor.convert(changeList,
|
||||
new Convertor<Change, DiffRequestPresentable>() {
|
||||
public ChangeDiffRequestPresentable convert(Change o) {
|
||||
return new ChangeDiffRequestPresentable(project, o);
|
||||
}
|
||||
}), index, actionsFactory, showFrame);
|
||||
}
|
||||
|
||||
private static void showDiffImpl(Project project, List<Change> changeList, int index, DiffExtendUIFactory actionsFactory, boolean showFrame) {
|
||||
public static void showDiffImpl(final Project project, List<DiffRequestPresentable> changeList, int index, DiffExtendUIFactory actionsFactory, boolean showFrame) {
|
||||
final ChangeDiffRequest request = new ChangeDiffRequest(project, changeList, actionsFactory, showFrame);
|
||||
|
||||
final DiffTool tool = DiffManager.getInstance().getDiffTool();
|
||||
|
||||
final ChangeDiffRequest request = new ChangeDiffRequest(project, changeList, actionsFactory);
|
||||
if (! request.quickCheckHaveStuff()) return;
|
||||
final SimpleDiffRequest simpleRequest = request.init(index);
|
||||
final DiffRequest simpleRequest = request.init(index);
|
||||
if (simpleRequest != null) {
|
||||
simpleRequest.passForDataContext(VcsDataKeys.DIFF_REQUEST_CHAIN, request);
|
||||
|
||||
if (showFrame) {
|
||||
simpleRequest.addHint(DiffTool.HINT_SHOW_FRAME);
|
||||
}
|
||||
else {
|
||||
simpleRequest.addHint(DiffTool.HINT_SHOW_MODAL_DIALOG);
|
||||
}
|
||||
if (changeList.size() > 1) {
|
||||
simpleRequest.addHint(DiffTool.HINT_ALLOW_NO_DIFFERENCES);
|
||||
}
|
||||
tool.show(simpleRequest);
|
||||
}
|
||||
}
|
||||
|
||||
+13
-2
@@ -18,12 +18,17 @@ package com.intellij.openapi.vcs.changes.actions;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.diff.DiffManager;
|
||||
import com.intellij.openapi.diff.DiffRequest;
|
||||
import com.intellij.openapi.diff.SimpleDiffRequest;
|
||||
import com.intellij.openapi.diff.DiffViewer;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.vcs.VcsDataKeys;
|
||||
import com.intellij.openapi.vcs.changes.ChangeRequestChain;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
@@ -47,9 +52,15 @@ public class ShowNextChangeAction extends AnAction implements DumbAware {
|
||||
|
||||
final DiffViewer diffViewer = e.getData(PlatformDataKeys.DIFF_VIEWER);
|
||||
if (diffViewer == null) return;
|
||||
final SimpleDiffRequest request = chain.moveForward();
|
||||
final DiffRequest request = chain.moveForward();
|
||||
if (request != null) {
|
||||
diffViewer.setDiffRequest(request);
|
||||
if (diffViewer.getContentsNumber() == request.getContents().length) {
|
||||
diffViewer.setDiffRequest(request);
|
||||
} else {
|
||||
final Window window = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow();
|
||||
window.setVisible(false);
|
||||
DiffManager.getInstance().getDiffTool().show(request);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
-2
@@ -18,6 +18,8 @@ package com.intellij.openapi.vcs.changes.actions;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.diff.DiffManager;
|
||||
import com.intellij.openapi.diff.DiffRequest;
|
||||
import com.intellij.openapi.diff.SimpleDiffRequest;
|
||||
import com.intellij.openapi.diff.DiffViewer;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -25,6 +27,8 @@ import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.vcs.VcsDataKeys;
|
||||
import com.intellij.openapi.vcs.changes.ChangeRequestChain;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
@@ -47,9 +51,16 @@ public class ShowPrevChangeAction extends AnAction implements DumbAware {
|
||||
|
||||
final DiffViewer diffViewer = e.getData(PlatformDataKeys.DIFF_VIEWER);
|
||||
if (diffViewer == null) return;
|
||||
final SimpleDiffRequest request = chain.moveBack();
|
||||
|
||||
final DiffRequest request = chain.moveBack();
|
||||
if (request != null) {
|
||||
diffViewer.setDiffRequest(request);
|
||||
if (diffViewer.getContentsNumber() == request.getContents().length) {
|
||||
diffViewer.setDiffRequest(request);
|
||||
} else {
|
||||
final Window window = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow();
|
||||
window.setVisible(false);
|
||||
DiffManager.getInstance().getDiffTool().show(request);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
-39
@@ -33,16 +33,15 @@ import com.intellij.openapi.diff.DiffRequestFactory;
|
||||
import com.intellij.openapi.diff.MergeRequest;
|
||||
import com.intellij.openapi.diff.impl.patch.*;
|
||||
import com.intellij.openapi.diff.impl.patch.formove.PatchApplier;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.vcs.*;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.containers.Convertor;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -83,6 +82,7 @@ public class ApplyPatchAction extends AnAction {
|
||||
PatchApplier.executePatchGroup(appliers);
|
||||
}
|
||||
};
|
||||
FileDocumentManager.getInstance().saveAllDocuments();
|
||||
final ApplyPatchDifferentiatedDialog dialog = new ApplyPatchDifferentiatedDialog(project, callback);
|
||||
dialog.show();
|
||||
}
|
||||
@@ -140,46 +140,23 @@ public class ApplyPatchAction extends AnAction {
|
||||
@Nullable
|
||||
public static ApplyPatchStatus mergeAgainstBaseVersion(final Project project, final VirtualFile file, final FilePath pathBeforeRename,
|
||||
final TextFilePatch patch, final PatchMergeRequestFactory mergeRequestFactory) {
|
||||
final String beforeVersionId = patch.getBeforeVersionId();
|
||||
if (beforeVersionId == null) {
|
||||
final ApplyPatchForBaseRevisionTexts threeTexts = ApplyPatchForBaseRevisionTexts.create(project, file, pathBeforeRename, patch);
|
||||
if (threeTexts == null) {
|
||||
return null;
|
||||
}
|
||||
final DefaultPatchBaseVersionProvider provider = new DefaultPatchBaseVersionProvider(project, file, beforeVersionId);
|
||||
if (provider.canProvideContent()) {
|
||||
final StringBuilder newText = new StringBuilder();
|
||||
final Ref<CharSequence> contentRef = new Ref<CharSequence>();
|
||||
final Ref<ApplyPatchStatus> statusRef = new Ref<ApplyPatchStatus>();
|
||||
try {
|
||||
provider.getBaseVersionContent(pathBeforeRename, new Processor<CharSequence>() {
|
||||
public boolean process(final CharSequence text) {
|
||||
newText.setLength(0);
|
||||
try {
|
||||
statusRef.set(patch.applyModifications(text, newText));
|
||||
}
|
||||
catch(ApplyPatchException ex) {
|
||||
return true; // continue to older versions
|
||||
}
|
||||
contentRef.set(text);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (VcsException vcsEx) {
|
||||
Messages.showErrorDialog(project, VcsBundle.message("patch.load.base.revision.error", patch.getBeforeName(), vcsEx.getMessage()),
|
||||
VcsBundle.message("patch.apply.dialog.title"));
|
||||
return ApplyPatchStatus.FAILURE;
|
||||
}
|
||||
ApplyPatchStatus status = statusRef.get();
|
||||
if (status != null) {
|
||||
if (status != ApplyPatchStatus.ALREADY_APPLIED) {
|
||||
return showMergeDialog(project, file, contentRef.get(), newText.toString(), mergeRequestFactory);
|
||||
}
|
||||
else {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
ApplyPatchStatus status = threeTexts.getStatus();
|
||||
if (ApplyPatchStatus.FAILURE.equals(status)) {
|
||||
final VcsException vcsExc = threeTexts.getException();
|
||||
Messages.showErrorDialog(project, VcsBundle.message("patch.load.base.revision.error", patch.getBeforeName(),
|
||||
vcsExc == null ? null : vcsExc.getMessage()), VcsBundle.message("patch.apply.dialog.title"));
|
||||
return status;
|
||||
}
|
||||
if (status != ApplyPatchStatus.ALREADY_APPLIED) {
|
||||
return showMergeDialog(project, file, threeTexts.getBase(), threeTexts.getPatched(), mergeRequestFactory);
|
||||
}
|
||||
else {
|
||||
return status;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static ApplyPatchStatus showMergeDialog(Project project, VirtualFile file, CharSequence content, final String patchedContent,
|
||||
|
||||
+32
-8
@@ -17,6 +17,8 @@ package com.intellij.openapi.vcs.changes.patch;
|
||||
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diff.DiffRequestFactory;
|
||||
import com.intellij.openapi.diff.MergeRequest;
|
||||
import com.intellij.openapi.diff.impl.patch.FilePatch;
|
||||
import com.intellij.openapi.diff.impl.patch.PatchReader;
|
||||
import com.intellij.openapi.diff.impl.patch.PatchSyntaxException;
|
||||
@@ -36,12 +38,16 @@ import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.FilePathImpl;
|
||||
import com.intellij.openapi.vcs.ObjectsConvertor;
|
||||
import com.intellij.openapi.vcs.VcsBundle;
|
||||
import com.intellij.openapi.vcs.ZipperUpdater;
|
||||
import com.intellij.openapi.vcs.changes.Change;
|
||||
import com.intellij.openapi.vcs.changes.ChangeListManager;
|
||||
import com.intellij.openapi.vcs.changes.LocalChangeList;
|
||||
import com.intellij.openapi.vcs.changes.actions.ChangeDiffRequestPresentable;
|
||||
import com.intellij.openapi.vcs.changes.actions.DiffPresentationReturnValue;
|
||||
import com.intellij.openapi.vcs.changes.actions.DiffRequestPresentable;
|
||||
import com.intellij.openapi.vcs.changes.actions.ShowDiffAction;
|
||||
import com.intellij.openapi.vcs.changes.ui.*;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
@@ -753,24 +759,42 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper {
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
if (myPatches.isEmpty() || (! myContainBasedChanges)) return;
|
||||
final List<FilePatchInProgress.PatchChange> changes = getAllChanges();
|
||||
Collections.sort(changes, MyChangeComparator.getInstance());
|
||||
final List<FilePatchInProgress.PatchChange> selectedChanges = myChangesTreeList.getSelectedChanges();
|
||||
|
||||
int selectedIdx = 0;
|
||||
int idx = 0;
|
||||
boolean goodChange = false;
|
||||
final ArrayList<DiffRequestPresentable> diffRequestPresentables = new ArrayList<DiffRequestPresentable>(changes.size());
|
||||
if (! selectedChanges.isEmpty()) {
|
||||
final FilePatchInProgress.PatchChange c = selectedChanges.get(0);
|
||||
for (FilePatchInProgress.PatchChange change : changes) {
|
||||
if (! change.getPatchInProgress().baseExistsOrAdded()) continue;
|
||||
goodChange = true;
|
||||
final FilePatchInProgress patchInProgress = change.getPatchInProgress();
|
||||
if (! patchInProgress.baseExistsOrAdded()) continue;
|
||||
final DiffRequestPresentable diffRequestPresentable = change.createDiffRequestPresentable(myProject);
|
||||
if (diffRequestPresentable != null) {
|
||||
diffRequestPresentables.add(diffRequestPresentable);
|
||||
}
|
||||
if (change.equals(c)) {
|
||||
break;
|
||||
selectedIdx = idx;
|
||||
}
|
||||
++ idx;
|
||||
}
|
||||
}
|
||||
if (! goodChange) return;
|
||||
idx = (idx == changes.size()) ? 0 : idx;
|
||||
ShowDiffAction.showDiffForChange(changes.toArray(new Change[changes.size()]), idx, myProject,
|
||||
ShowDiffAction.DiffExtendUIFactory.NONE, false);
|
||||
if (diffRequestPresentables.isEmpty()) return;
|
||||
selectedIdx = (selectedIdx >= diffRequestPresentables.size()) ? 0 : selectedIdx;
|
||||
ShowDiffAction.showDiffImpl(myProject, diffRequestPresentables, selectedIdx, ShowDiffAction.DiffExtendUIFactory.NONE, false);
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyChangeComparator implements Comparator<FilePatchInProgress.PatchChange> {
|
||||
private static final MyChangeComparator ourInstance = new MyChangeComparator();
|
||||
|
||||
public static MyChangeComparator getInstance() {
|
||||
return ourInstance;
|
||||
}
|
||||
|
||||
public int compare(FilePatchInProgress.PatchChange o1, FilePatchInProgress.PatchChange o2) {
|
||||
return o1.getPatchInProgress().getIoCurrentBase().compareTo(o2.getPatchInProgress().getIoCurrentBase());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.vcs.changes.patch;
|
||||
|
||||
import com.intellij.openapi.diff.impl.patch.ApplyPatchException;
|
||||
import com.intellij.openapi.diff.impl.patch.ApplyPatchStatus;
|
||||
import com.intellij.openapi.diff.impl.patch.TextFilePatch;
|
||||
import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vcs.FilePath;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.Processor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class ApplyPatchForBaseRevisionTexts {
|
||||
private CharSequence myLocal;
|
||||
private CharSequence myBase;
|
||||
private String myPatched;
|
||||
@NotNull
|
||||
private ApplyPatchStatus myStatus;
|
||||
private VcsException myException;
|
||||
|
||||
@Nullable
|
||||
public static ApplyPatchForBaseRevisionTexts create(final Project project, final VirtualFile file, final FilePath pathBeforeRename,
|
||||
final TextFilePatch patch) {
|
||||
|
||||
final String beforeVersionId = patch.getBeforeVersionId();
|
||||
if (beforeVersionId == null) {
|
||||
return null;
|
||||
}
|
||||
final DefaultPatchBaseVersionProvider provider = new DefaultPatchBaseVersionProvider(project, file, beforeVersionId);
|
||||
if (provider.canProvideContent()) {
|
||||
return new ApplyPatchForBaseRevisionTexts(provider, pathBeforeRename, patch, file);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
ApplyPatchForBaseRevisionTexts(final DefaultPatchBaseVersionProvider provider, final FilePath pathBeforeRename, final TextFilePatch patch,
|
||||
final VirtualFile file) {
|
||||
myLocal = LoadTextUtil.loadText(file);
|
||||
final StringBuilder newText = new StringBuilder();
|
||||
try {
|
||||
provider.getBaseVersionContent(pathBeforeRename, new Processor<CharSequence>() {
|
||||
public boolean process(final CharSequence text) {
|
||||
newText.setLength(0);
|
||||
try {
|
||||
myStatus = patch.applyModifications(text, newText);
|
||||
}
|
||||
catch(ApplyPatchException ex) {
|
||||
return true; // continue to older versions
|
||||
}
|
||||
myBase = text;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (VcsException vcsEx) {
|
||||
myException = vcsEx;
|
||||
myStatus = ApplyPatchStatus.FAILURE;
|
||||
}
|
||||
myPatched = newText.toString();
|
||||
}
|
||||
|
||||
public CharSequence getLocal() {
|
||||
return myLocal;
|
||||
}
|
||||
|
||||
public CharSequence getBase() {
|
||||
return myBase;
|
||||
}
|
||||
|
||||
public String getPatched() {
|
||||
return myPatched;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ApplyPatchStatus getStatus() {
|
||||
return myStatus;
|
||||
}
|
||||
|
||||
public VcsException getException() {
|
||||
return myException;
|
||||
}
|
||||
}
|
||||
+80
-3
@@ -15,18 +15,26 @@
|
||||
*/
|
||||
package com.intellij.openapi.vcs.changes.patch;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diff.DiffRequestFactory;
|
||||
import com.intellij.openapi.diff.MergeRequest;
|
||||
import com.intellij.openapi.diff.impl.patch.TextFilePatch;
|
||||
import com.intellij.openapi.diff.impl.patch.formove.PathMerger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.vcs.FilePath;
|
||||
import com.intellij.openapi.vcs.FilePathImpl;
|
||||
import com.intellij.openapi.vcs.FileStatus;
|
||||
import com.intellij.openapi.vcs.*;
|
||||
import com.intellij.openapi.vcs.changes.Change;
|
||||
import com.intellij.openapi.vcs.changes.ContentRevision;
|
||||
import com.intellij.openapi.vcs.changes.CurrentContentRevision;
|
||||
import com.intellij.openapi.vcs.changes.SimpleContentRevision;
|
||||
import com.intellij.openapi.vcs.changes.actions.ChangeDiffRequestPresentable;
|
||||
import com.intellij.openapi.vcs.changes.actions.DiffPresentationReturnValue;
|
||||
import com.intellij.openapi.vcs.changes.actions.DiffRequestPresentable;
|
||||
import com.intellij.openapi.vcs.changes.actions.ShowDiffAction;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.vcsUtil.VcsUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
@@ -45,6 +53,7 @@ public class FilePatchInProgress {
|
||||
private ContentRevision myNewContentRevision;
|
||||
private ContentRevision myCurrentRevision;
|
||||
private final List<VirtualFile> myAutoBases;
|
||||
private volatile Boolean myConflicts;
|
||||
|
||||
private File myAfterFile;
|
||||
|
||||
@@ -93,6 +102,7 @@ public class FilePatchInProgress {
|
||||
myNewContentRevision = null;
|
||||
myCurrentRevision = null;
|
||||
myAfterFile = null;
|
||||
myConflicts = null;
|
||||
|
||||
final String beforeName = myPatch.getBeforeName();
|
||||
if (beforeName != null) {
|
||||
@@ -144,6 +154,7 @@ public class FilePatchInProgress {
|
||||
if (FilePatchStatus.DELETED.equals(myStatus)) return null;
|
||||
|
||||
if (myNewContentRevision == null) {
|
||||
myConflicts = null;
|
||||
if (FilePatchStatus.ADDED.equals(myStatus)) {
|
||||
final FilePath newFilePath = FilePathImpl.createNonLocal(myIoCurrentBase.getAbsolutePath(), false);
|
||||
final String content = myPatch.getNewFileText();
|
||||
@@ -156,11 +167,30 @@ public class FilePatchInProgress {
|
||||
newFilePath = (myCurrentBase != null) ? new FilePathImpl(myCurrentBase) : new FilePathImpl(myIoCurrentBase, false);
|
||||
}
|
||||
myNewContentRevision = new LazyPatchContentRevision(myCurrentBase, newFilePath, myPatch.getAfterVersionId(), myPatch);
|
||||
if (myCurrentBase != null) {
|
||||
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
|
||||
public void run() {
|
||||
((LazyPatchContentRevision) myNewContentRevision).getContent();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return myNewContentRevision;
|
||||
}
|
||||
|
||||
public boolean isConflictingChange() {
|
||||
if (myConflicts == null) {
|
||||
if ((myCurrentBase != null) && (myNewContentRevision instanceof LazyPatchContentRevision)) {
|
||||
((LazyPatchContentRevision) myNewContentRevision).getContent();
|
||||
myConflicts = ((LazyPatchContentRevision) myNewContentRevision).isPatchApplyFailed();
|
||||
} else {
|
||||
myConflicts = false;
|
||||
}
|
||||
}
|
||||
return myConflicts;
|
||||
}
|
||||
|
||||
public ContentRevision getCurrentRevision() {
|
||||
if (FilePatchStatus.ADDED.equals(myStatus)) return null;
|
||||
if (myCurrentRevision == null) {
|
||||
@@ -182,8 +212,55 @@ public class FilePatchInProgress {
|
||||
public FilePatchInProgress getPatchInProgress() {
|
||||
return myPatchInProgress;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public DiffRequestPresentable createDiffRequestPresentable(final Project project) {
|
||||
if (myPatchInProgress.isConflictingChange()) {
|
||||
final ApplyPatchForBaseRevisionTexts texts = ApplyPatchForBaseRevisionTexts
|
||||
.create(project, myPatchInProgress.getCurrentBase(), new FilePathImpl(myPatchInProgress.getCurrentBase()),
|
||||
myPatchInProgress.getPatch());
|
||||
if (texts != null) {
|
||||
return new MergedDiffRequestPresentable(project, texts,
|
||||
myPatchInProgress.getCurrentBase(), myPatchInProgress.getPatch().getAfterVersionId());
|
||||
}
|
||||
return null;
|
||||
} else {
|
||||
return new ChangeDiffRequestPresentable(project, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class MergedDiffRequestPresentable implements DiffRequestPresentable {
|
||||
private final Project myProject;
|
||||
private final VirtualFile myFile;
|
||||
private final String myAfterTitle;
|
||||
private final ApplyPatchForBaseRevisionTexts myTexts;
|
||||
|
||||
private MergedDiffRequestPresentable(final Project project, final ApplyPatchForBaseRevisionTexts texts, final VirtualFile file, final String afterTitle) {
|
||||
myTexts = texts;
|
||||
myProject = project;
|
||||
myFile = file;
|
||||
myAfterTitle = afterTitle;
|
||||
}
|
||||
|
||||
public MyResult step() {
|
||||
final MergeRequest request = DiffRequestFactory.getInstance()
|
||||
.create3WayDiffRequest(myTexts.getLocal().toString(), myTexts.getPatched(), myTexts.getBase().toString(), myProject, null);
|
||||
request.setWindowTitle(VcsBundle.message("patch.apply.conflict.title", myFile.getPresentableUrl()));
|
||||
request.setVersionTitles(new String[] {"Current Version", "Base Version", myAfterTitle});
|
||||
return new MyResult(request, DiffPresentationReturnValue.useRequest);
|
||||
}
|
||||
|
||||
public boolean haveStuff() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public List<? extends AnAction> createActions(ShowDiffAction.DiffExtendUIFactory uiFactory) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public List<VirtualFile> getAutoBasesCopy() {
|
||||
final ArrayList<VirtualFile> result = new ArrayList<VirtualFile>(myAutoBases.size() + 1);
|
||||
result.addAll(myAutoBases);
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ public class LazyPatchContentRevision implements ContentRevision {
|
||||
myPatch = patch;
|
||||
}
|
||||
|
||||
public String getContent() throws VcsException {
|
||||
public String getContent() {
|
||||
if (myContent == null) {
|
||||
try {
|
||||
final Document doc = FileDocumentManager.getInstance().getDocument(myVf);
|
||||
|
||||
Reference in New Issue
Block a user