mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
vcs: use custom MergeTool for patch conflicts without base revision
This commit is contained in:
@@ -50,6 +50,9 @@ public abstract class DiffContentFactory {
|
||||
@NotNull
|
||||
public abstract DocumentContent create(@NotNull String text, @Nullable FileType type, boolean respectLineSeparators);
|
||||
|
||||
@NotNull
|
||||
public abstract DocumentContent create(@NotNull String text, @Nullable VirtualFile highlightFile);
|
||||
|
||||
@NotNull
|
||||
public abstract DocumentContent create(@Nullable Project project, @NotNull Document document);
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ public class DiffContentFactoryImpl extends DiffContentFactory {
|
||||
@Override
|
||||
@NotNull
|
||||
public DocumentContent create(@NotNull String text) {
|
||||
return create(text, null);
|
||||
return create(text, (FileType)null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -73,6 +73,11 @@ public class DiffContentFactoryImpl extends DiffContentFactory {
|
||||
return createImpl(text, type, null, null, respectLineSeparators, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public DocumentContent create(@NotNull String text, @Nullable VirtualFile highlightFile) {
|
||||
return createImpl(text, highlightFile != null ? highlightFile.getFileType() : null, highlightFile, null, true, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public DocumentContent create(@Nullable Project project, @NotNull Document document) {
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
<projectService serviceInterface="com.intellij.openapi.vcs.CodeSmellDetector"
|
||||
serviceImplementation="com.intellij.openapi.vcs.impl.CodeSmellDetectorImpl"/>
|
||||
|
||||
<diff.merge.MergeTool implementation="com.intellij.openapi.vcs.changes.patch.ApplyPatchMergeTool"/>
|
||||
|
||||
<selectInTarget implementation="com.intellij.openapi.vcs.changes.SelectInChangesViewTarget"/>
|
||||
|
||||
<search.topHitProvider implementation="com.intellij.openapi.vcs.configurable.VcsOptionsTopHitProvider"/>
|
||||
|
||||
+1
-1
@@ -86,7 +86,7 @@ public class TestDiffRequestProcessor extends DiffRequestProcessor {
|
||||
}
|
||||
else {
|
||||
title = ExecutionBundle.message(titleKey);
|
||||
content = DiffContentFactory.getInstance().create(contentString, null);
|
||||
content = DiffContentFactory.getInstance().create(contentString);
|
||||
}
|
||||
return Pair.create(title, content);
|
||||
}
|
||||
|
||||
+15
-49
@@ -22,7 +22,10 @@
|
||||
*/
|
||||
package com.intellij.openapi.vcs.changes.patch;
|
||||
|
||||
import com.intellij.diff.*;
|
||||
import com.intellij.diff.DiffContentFactory;
|
||||
import com.intellij.diff.DiffManager;
|
||||
import com.intellij.diff.DiffRequestFactory;
|
||||
import com.intellij.diff.InvalidDiffRequestException;
|
||||
import com.intellij.diff.chains.DiffRequestProducerException;
|
||||
import com.intellij.diff.contents.DiffContent;
|
||||
import com.intellij.diff.contents.DocumentContent;
|
||||
@@ -47,8 +50,6 @@ import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.WindowWrapper;
|
||||
import com.intellij.openapi.util.BooleanGetter;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Getter;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
@@ -59,7 +60,6 @@ import com.intellij.openapi.vcs.changes.ChangeListManager;
|
||||
import com.intellij.openapi.vcs.changes.CommitContext;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.EditorNotificationPanel;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
@@ -254,52 +254,24 @@ public class ApplyPatchAction extends DumbAwareAction {
|
||||
final Document document = FileDocumentManager.getInstance().getDocument(file);
|
||||
if (texts.getLocal() == null || document == null) return ApplyPatchStatus.FAILURE;
|
||||
|
||||
final CharSequence oldContent = document.getImmutableCharSequence();
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
document.setText(texts.getPatched());
|
||||
}
|
||||
});
|
||||
|
||||
final String fullPath = file.getParent() == null ? file.getPath() : file.getParent().getPath();
|
||||
final String windowTitle = "Result Of Patch Apply To " + file.getName() + " (" + fullPath + ")";
|
||||
final List<String> titles = ContainerUtil.list(VcsBundle.message("diff.title.local"), "Patched (with problems)");
|
||||
|
||||
final DiffContentFactory contentFactory = DiffContentFactory.getInstance();
|
||||
final DocumentContent originalContent = contentFactory.create(texts.getLocal().toString(), file.getFileType());
|
||||
final DiffContent mergedContent = contentFactory.create(project, document);
|
||||
|
||||
final List<DiffContent> contents = ContainerUtil.list(originalContent, mergedContent);
|
||||
|
||||
final DiffRequest request = new SimpleDiffRequest(windowTitle, contents, titles);
|
||||
DiffUtil.addNotification(new DiffIsApproximateNotification(), request);
|
||||
|
||||
final DiffDialogHints dialogHints = new DiffDialogHints(WindowWrapper.Mode.MODAL);
|
||||
dialogHints.setCancelAction(new BooleanGetter() {
|
||||
final Ref<Boolean> successRef = new Ref<Boolean>();
|
||||
Consumer<MergeResult> callback = new Consumer<MergeResult>() {
|
||||
@Override
|
||||
public boolean get() {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
document.setText(oldContent);
|
||||
FileDocumentManager.getInstance().saveDocument(document);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
});
|
||||
dialogHints.setOkAction(new BooleanGetter() {
|
||||
@Override
|
||||
public boolean get() {
|
||||
public void consume(MergeResult result) {
|
||||
FileDocumentManager.getInstance().saveDocument(document);
|
||||
return true;
|
||||
successRef.set(true);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
DiffManager.getInstance().showDiff(project, request, dialogHints);
|
||||
MergeRequest request = new ApplyPatchMergeRequest(project, document, file, texts.getLocal().toString(), texts.getPatched(), windowTitle,
|
||||
VcsBundle.message("diff.title.local"), "Patched (with problems)", callback);
|
||||
|
||||
return ApplyPatchStatus.SUCCESS;
|
||||
DiffManager.getInstance().showMerge(project, request);
|
||||
|
||||
return successRef.get() == Boolean.TRUE ? ApplyPatchStatus.SUCCESS : ApplyPatchStatus.FAILURE;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -322,14 +294,8 @@ public class ApplyPatchAction extends DumbAwareAction {
|
||||
final List<DiffContent> contents = ContainerUtil.list(localContent, mergedContent);
|
||||
|
||||
final DiffRequest request = new SimpleDiffRequest(windowTitle, contents, titles);
|
||||
DiffUtil.addNotification(new DiffIsApproximateNotification(), request);
|
||||
DiffUtil.addNotification(new ApplyPatchMergeTool.DiffIsApproximateNotification(), request);
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
private static class DiffIsApproximateNotification extends EditorNotificationPanel {
|
||||
public DiffIsApproximateNotification() {
|
||||
myLabel.setText("<html>Couldn't find context for patch. Some fragments were applied at the best possible place. <b>Please check carefully.</b></html>");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright 2000-2015 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.diff.merge.MergeRequest;
|
||||
import com.intellij.diff.merge.MergeResult;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.Consumer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class ApplyPatchMergeRequest extends MergeRequest {
|
||||
@Nullable private final Project myProject;
|
||||
@NotNull private final Document myDocument;
|
||||
|
||||
@NotNull private final CharSequence myOriginalContent;
|
||||
@NotNull private final String myLocalContent;
|
||||
@NotNull private final String myPatchedContent;
|
||||
|
||||
@NotNull private final String myWindowTitle;
|
||||
@NotNull private final String myLocalTitle;
|
||||
@NotNull private final String myPatchedTitle;
|
||||
|
||||
@Nullable private final Consumer<MergeResult> myCallback;
|
||||
|
||||
public ApplyPatchMergeRequest(@Nullable Project project,
|
||||
@NotNull Document document,
|
||||
@NotNull String localContent,
|
||||
@NotNull String patchedContent,
|
||||
@NotNull String windowTitle,
|
||||
@NotNull String localTitle,
|
||||
@NotNull String patchedTitle,
|
||||
@Nullable Consumer<MergeResult> callback) {
|
||||
myProject = project;
|
||||
myDocument = document;
|
||||
|
||||
myOriginalContent = ApplicationManager.getApplication().runReadAction(new Computable<CharSequence>() {
|
||||
@Override
|
||||
public CharSequence compute() {
|
||||
return myDocument.getImmutableCharSequence();
|
||||
}
|
||||
});
|
||||
myLocalContent = localContent;
|
||||
myPatchedContent = patchedContent;
|
||||
|
||||
myWindowTitle = windowTitle;
|
||||
myLocalTitle = localTitle;
|
||||
myPatchedTitle = patchedTitle;
|
||||
|
||||
myCallback = callback;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Project getProject() {
|
||||
return myProject;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Document getDocument() {
|
||||
return myDocument;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getLocalContent() {
|
||||
return myLocalContent;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getPatchedContent() {
|
||||
return myPatchedContent;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return myWindowTitle;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getLocalTitle() {
|
||||
return myLocalTitle;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getPatchedTitle() {
|
||||
return myPatchedTitle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyResult(@NotNull MergeResult result) {
|
||||
final CharSequence applyContent;
|
||||
switch (result) {
|
||||
case CANCEL:
|
||||
applyContent = myOriginalContent;
|
||||
break;
|
||||
case LEFT:
|
||||
applyContent = myLocalContent;
|
||||
break;
|
||||
case RIGHT:
|
||||
applyContent = myPatchedContent;
|
||||
break;
|
||||
case RESOLVED:
|
||||
applyContent = null;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException(result.name());
|
||||
}
|
||||
|
||||
if (applyContent != null) {
|
||||
new WriteCommandAction.Simple(myProject) {
|
||||
@Override
|
||||
protected void run() throws Throwable {
|
||||
myDocument.setText(applyContent);
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
if (myCallback != null) myCallback.consume(result);
|
||||
}
|
||||
}
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright 2000-2015 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.diff.DiffContentFactory;
|
||||
import com.intellij.diff.FrameDiffTool;
|
||||
import com.intellij.diff.contents.DocumentContent;
|
||||
import com.intellij.diff.merge.*;
|
||||
import com.intellij.diff.requests.SimpleDiffRequest;
|
||||
import com.intellij.diff.tools.simple.SimpleDiffViewer;
|
||||
import com.intellij.diff.util.DiffUtil;
|
||||
import com.intellij.openapi.command.undo.DocumentReference;
|
||||
import com.intellij.openapi.command.undo.DocumentReferenceManager;
|
||||
import com.intellij.openapi.command.undo.UndoManager;
|
||||
import com.intellij.openapi.diff.DiffBundle;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.BooleanGetter;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.EditorNotificationPanel;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
|
||||
public class ApplyPatchMergeTool implements MergeTool {
|
||||
@NotNull
|
||||
@Override
|
||||
public MergeViewer createComponent(@NotNull MergeContext context, @NotNull MergeRequest request) {
|
||||
return new MyViewer(context, (ApplyPatchMergeRequest)request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canShow(@NotNull MergeContext context, @NotNull MergeRequest request) {
|
||||
return request instanceof ApplyPatchMergeRequest;
|
||||
}
|
||||
|
||||
private static class MyViewer implements MergeViewer {
|
||||
@NotNull private final MergeContext myMergeContext;
|
||||
@NotNull private final ApplyPatchMergeRequest myMergeRequest;
|
||||
|
||||
@NotNull private final SimpleDiffViewer myViewer;
|
||||
|
||||
public MyViewer(@NotNull MergeContext context, @NotNull ApplyPatchMergeRequest request) {
|
||||
myMergeContext = context;
|
||||
myMergeRequest = request;
|
||||
|
||||
MergeUtil.ProxyDiffContext diffContext = new MergeUtil.ProxyDiffContext(myMergeContext);
|
||||
|
||||
VirtualFile file = FileDocumentManager.getInstance().getFile(myMergeRequest.getDocument());
|
||||
final DiffContentFactory contentFactory = DiffContentFactory.getInstance();
|
||||
final DocumentContent localContent = contentFactory.create(myMergeRequest.getLocalContent(), file);
|
||||
final DocumentContent mergedContent = contentFactory.create(myMergeRequest.getProject(), myMergeRequest.getDocument());
|
||||
|
||||
SimpleDiffRequest diffRequest = new SimpleDiffRequest(myMergeRequest.getTitle(), localContent, mergedContent,
|
||||
myMergeRequest.getLocalTitle(), myMergeRequest.getPatchedTitle());
|
||||
DiffUtil.addNotification(new DiffIsApproximateNotification(), diffRequest);
|
||||
|
||||
myViewer = new SimpleDiffViewer(diffContext, diffRequest);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JComponent getComponent() {
|
||||
return myViewer.getComponent();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JComponent getPreferredFocusedComponent() {
|
||||
return myViewer.getPreferredFocusedComponent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ToolbarComponents init() {
|
||||
final Project project = myMergeContext.getProject();
|
||||
final Document document = myMergeRequest.getDocument();
|
||||
|
||||
DiffUtil.executeWriteCommand(document, project, "Init merge content", new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
document.setText(myMergeRequest.getPatchedContent());
|
||||
|
||||
UndoManager undoManager = project != null ? UndoManager.getInstance(project) : UndoManager.getGlobalInstance();
|
||||
if (undoManager != null) {
|
||||
DocumentReference ref = DocumentReferenceManager.getInstance().create(document);
|
||||
undoManager.nonundoableActionPerformed(ref, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ToolbarComponents components = new ToolbarComponents();
|
||||
|
||||
FrameDiffTool.ToolbarComponents init = myViewer.init();
|
||||
components.statusPanel = init.statusPanel;
|
||||
components.toolbarActions = init.toolbarActions;
|
||||
|
||||
components.closeHandler = new BooleanGetter() {
|
||||
@Override
|
||||
public boolean get() {
|
||||
return Messages.showYesNoDialog(getComponent().getRootPane(),
|
||||
DiffBundle.message("merge.dialog.exit.without.applying.changes.confirmation.message"),
|
||||
DiffBundle.message("cancel.visual.merge.dialog.title"), Messages.getQuestionIcon()) ==
|
||||
Messages.YES;
|
||||
}
|
||||
};
|
||||
return components;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Action getResolveAction(@NotNull final MergeResult result) {
|
||||
if (result == MergeResult.LEFT || result == MergeResult.RIGHT) return null;
|
||||
|
||||
String caption = MergeUtil.getResolveActionTitle(result, myMergeRequest, myMergeContext);
|
||||
return new AbstractAction(caption) {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (result == MergeResult.CANCEL) {
|
||||
if (Messages.showYesNoDialog(getComponent().getRootPane(),
|
||||
DiffBundle.message("merge.dialog.exit.without.applying.changes.confirmation.message"),
|
||||
DiffBundle.message("cancel.visual.merge.dialog.title"), Messages.getQuestionIcon()) !=
|
||||
Messages.YES) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
myMergeContext.finishMerge(result);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
Disposer.dispose(myViewer);
|
||||
}
|
||||
}
|
||||
|
||||
public static class DiffIsApproximateNotification extends EditorNotificationPanel {
|
||||
public DiffIsApproximateNotification() {
|
||||
myLabel.setText("<html>Couldn't find context for patch. Some fragments were applied at the best possible place. " +
|
||||
"<b>Please check carefully.</b></html>");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user