mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-64887 Mercurial: change dialog that appears on deleted-modified conflict
This commit is contained in:
@@ -20,6 +20,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.zmlx.hg4idea.HgVcs;
|
||||
import org.zmlx.hg4idea.execution.HgCommandExecutor;
|
||||
import org.zmlx.hg4idea.execution.HgCommandResult;
|
||||
import org.zmlx.hg4idea.execution.HgDeleteModifyPromptHandler;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@@ -66,7 +67,7 @@ public class HgUpdateCommand {
|
||||
|
||||
final HgCommandExecutor executor = new HgCommandExecutor(project);
|
||||
executor.setShowOutput(true);
|
||||
final HgCommandResult result = executor.executeInCurrentThread(repo, "update", arguments);
|
||||
final HgCommandResult result = executor.executeInCurrentThread(repo, "update", arguments,new HgDeleteModifyPromptHandler());
|
||||
project.getMessageBus().syncPublisher(HgVcs.BRANCH_TOPIC).update(project);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
package org.zmlx.hg4idea.execution;
|
||||
|
||||
import com.intellij.execution.ui.ConsoleViewContentType;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.vcsUtil.VcsImplUtil;
|
||||
@@ -28,7 +28,6 @@ import org.zmlx.hg4idea.util.HgEncodingUtil;
|
||||
import org.zmlx.hg4idea.util.HgErrorUtil;
|
||||
import org.zmlx.hg4idea.util.HgUtil;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
@@ -52,7 +51,7 @@ import java.util.List;
|
||||
* </p>
|
||||
*/
|
||||
public final class HgCommandExecutor {
|
||||
|
||||
|
||||
private static final Logger LOG = Logger.getInstance(HgCommandExecutor.class.getName());
|
||||
private static final List<String> DEFAULT_OPTIONS = Arrays.asList("--config", "ui.merge=internal:merge");
|
||||
|
||||
@@ -100,6 +99,12 @@ public final class HgCommandExecutor {
|
||||
@Nullable
|
||||
public HgCommandResult executeInCurrentThread(@Nullable final VirtualFile repo, @NotNull final String operation,
|
||||
@Nullable final List<String> arguments) {
|
||||
return executeInCurrentThread(repo, operation, arguments, null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public HgCommandResult executeInCurrentThread(@Nullable final VirtualFile repo, @NotNull final String operation,
|
||||
@Nullable final List<String> arguments, @Nullable HgPromptHandler handler) {
|
||||
//LOG.assertTrue(!ApplicationManager.getApplication().isDispatchThread()); disabled for release
|
||||
if (myProject == null || myProject.isDisposed() || myVcs == null) {
|
||||
return null;
|
||||
@@ -114,11 +119,11 @@ public final class HgCommandExecutor {
|
||||
|
||||
WarningReceiver warningReceiver = new WarningReceiver();
|
||||
PassReceiver passReceiver = new PassReceiver(myProject);
|
||||
|
||||
SocketServer promptServer = new SocketServer(new PromptReceiver());
|
||||
|
||||
SocketServer promptServer = new SocketServer(new PromptReceiver(handler));
|
||||
SocketServer warningServer = new SocketServer(warningReceiver);
|
||||
SocketServer passServer = new SocketServer(passReceiver);
|
||||
|
||||
|
||||
try {
|
||||
int promptPort = promptServer.start();
|
||||
int warningPort = warningServer.start();
|
||||
@@ -258,37 +263,46 @@ public final class HgCommandExecutor {
|
||||
}
|
||||
|
||||
private static class PromptReceiver extends SocketServer.Protocol {
|
||||
@Nullable HgPromptHandler myHandler;
|
||||
|
||||
public PromptReceiver(@Nullable HgPromptHandler handler) {
|
||||
myHandler = handler;
|
||||
}
|
||||
|
||||
public boolean handleConnection(Socket socket) throws IOException {
|
||||
DataInputStream dataInput = new DataInputStream(socket.getInputStream());
|
||||
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
|
||||
final String message = new String(readDataBlock(dataInput));
|
||||
int numOfChoices = dataInput.readInt();
|
||||
final Choice[] choices = new Choice[numOfChoices];
|
||||
final HgPromptChoice[] choices = new HgPromptChoice[numOfChoices];
|
||||
for (int i = 0; i < numOfChoices; i++) {
|
||||
String choice = new String(readDataBlock(dataInput));
|
||||
choices[i] = new Choice(choice);
|
||||
choices[i] = new HgPromptChoice(i, choice);
|
||||
}
|
||||
int defaultChoiceInt = dataInput.readInt();
|
||||
final Choice defaultChoice = choices[defaultChoiceInt];
|
||||
|
||||
final HgPromptChoice defaultChoice = choices[defaultChoiceInt];
|
||||
if (myHandler != null && myHandler.shouldHandle(message)) {
|
||||
int chosen = myHandler.promptUser(message, choices, defaultChoice).getChosenIndex();
|
||||
sendChoiceToHg(out, chosen);
|
||||
return true;
|
||||
}
|
||||
final int[] index = new int[]{-1};
|
||||
try {
|
||||
EventQueue.invokeAndWait(new Runnable() {
|
||||
public void run() {
|
||||
Window parent = ApplicationManager.getApplication().getComponent(Window.class);
|
||||
index[0] = JOptionPane
|
||||
.showOptionDialog(parent, message, "hg4idea", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, choices,
|
||||
defaultChoice);
|
||||
String[] choicePresentationArray = new String[choices.length];
|
||||
for (int i = 0; i < choices.length; ++i) {
|
||||
choicePresentationArray[i] = choices[i].toString();
|
||||
}
|
||||
index[0] = Messages
|
||||
.showChooseDialog(message, "hg4idea",
|
||||
choicePresentationArray,
|
||||
defaultChoice.toString(), Messages.getQuestionIcon());
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
int chosen = index[0];
|
||||
if (chosen == JOptionPane.CLOSED_OPTION) {
|
||||
out.writeInt(-1);
|
||||
} else {
|
||||
out.writeInt(chosen);
|
||||
}
|
||||
sendChoiceToHg(out, chosen);
|
||||
return true;
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
@@ -301,43 +315,16 @@ public final class HgCommandExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
private static class Choice{
|
||||
private final String fullString;
|
||||
private final String representation;
|
||||
private final String choiceChar;
|
||||
|
||||
private Choice(String fullString) {
|
||||
this.fullString = fullString;
|
||||
this.representation = fullString.replaceAll("&", "");
|
||||
int index = fullString.indexOf("&");
|
||||
this.choiceChar = "" + fullString.charAt(index + 1);
|
||||
|
||||
private static void sendChoiceToHg(@NotNull DataOutputStream outStream, int choice) throws IOException {
|
||||
if (choice == HgPromptChoice.CLOSED_OPTION) {
|
||||
outStream.writeInt(-1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return representation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Choice choice = (Choice) o;
|
||||
|
||||
if (!fullString.equals(choice.fullString)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return fullString.hashCode();
|
||||
else {
|
||||
outStream.writeInt(choice);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class PassReceiver extends SocketServer.Protocol{
|
||||
private final Project myProject;
|
||||
private HgCommandAuthenticator myAuthenticator;
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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 org.zmlx.hg4idea.execution;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.awt.*;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author Nadya Zabrodina
|
||||
*/
|
||||
public class HgDeleteModifyPromptHandler implements HgPromptHandler {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance("#org.zmlx.hg4idea.execution.HgDeleteModifyPromptHandler");
|
||||
|
||||
private static final Pattern LOCAL_DELETE_REMOTE_MODIFIED_CONFLICT_MESSAGE_PATTERN = Pattern.compile(
|
||||
"remote\\schanged(.+)which\\slocal\\sdeleted\\s.+");
|
||||
private static final Pattern REMOTE_DELETE_LOCAL_MODIFIED_CONFLICT_MESSAGE_PATTERN = Pattern.compile(
|
||||
"\\slocal\\schanged(.+)which\\sremote\\sdeleted\\s.+");
|
||||
|
||||
private String myMessage = "";
|
||||
|
||||
public HgPromptChoice promptUser(final String message,
|
||||
@NotNull final HgPromptChoice[] choices,
|
||||
@NotNull final HgPromptChoice defaultChoice) {
|
||||
|
||||
final int[] chosen = new int[]{-1};
|
||||
try {
|
||||
EventQueue.invokeAndWait
|
||||
(new Runnable() {
|
||||
public void run() {
|
||||
String[] choicePresentationArray = new String[choices.length];
|
||||
for (int i = 0; i < choices.length; ++i) {
|
||||
choicePresentationArray[i] = choices[i].toString();
|
||||
}
|
||||
chosen[0] = Messages
|
||||
.showChooseDialog(myMessage, "Delete-Modify Conflict",
|
||||
choicePresentationArray,
|
||||
defaultChoice.toString(), Messages.getQuestionIcon());
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
LOG.error(e);
|
||||
return defaultChoice;
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
LOG.error(e);
|
||||
return defaultChoice;
|
||||
}
|
||||
return chosen[0] >= 0 ? choices[chosen[0]] : HgPromptChoice.ABORT;
|
||||
}
|
||||
|
||||
public boolean shouldHandle(String message) {
|
||||
Matcher localDelMatcher = LOCAL_DELETE_REMOTE_MODIFIED_CONFLICT_MESSAGE_PATTERN.matcher(message);
|
||||
Matcher locaModifMatcher = REMOTE_DELETE_LOCAL_MODIFIED_CONFLICT_MESSAGE_PATTERN.matcher(message);
|
||||
String filename;
|
||||
if (localDelMatcher.matches()) {
|
||||
filename = localDelMatcher.group(1);
|
||||
myMessage =
|
||||
"File " + filename + " is deleted locally, but modified remotely. Do you want to keep the modified version or remove the file?";
|
||||
return true;
|
||||
}
|
||||
else if (locaModifMatcher.matches()) {
|
||||
filename = locaModifMatcher.group(1);
|
||||
myMessage =
|
||||
"File " + filename + " is deleted remotely, but modified locally. Do you want to keep the modified version or remove the file?";
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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 org.zmlx.hg4idea.execution;
|
||||
|
||||
|
||||
public class HgPromptChoice {
|
||||
private final String fullString;
|
||||
private final String representation;
|
||||
private final String choiceChar;
|
||||
private final int chosenIndex;
|
||||
public static final int CLOSED_OPTION = -1;
|
||||
public static final HgPromptChoice ABORT = new HgPromptChoice(-1, "AbortChoice");
|
||||
|
||||
public int getChosenIndex() {
|
||||
return chosenIndex;
|
||||
}
|
||||
|
||||
|
||||
HgPromptChoice(int chosenIndex, String fullString) {
|
||||
this.fullString = fullString;
|
||||
this.representation = fullString.replaceAll("&", "");
|
||||
int index = fullString.indexOf("&");
|
||||
this.choiceChar = String.valueOf(fullString.charAt(index + 1));
|
||||
this.chosenIndex = chosenIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return representation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (null == o) return true;
|
||||
if (getClass() != o.getClass()) return false;
|
||||
|
||||
HgPromptChoice choice = (HgPromptChoice)o;
|
||||
|
||||
if (!fullString.equals(choice.fullString)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return fullString.hashCode();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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 org.zmlx.hg4idea.execution;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* HgPromptHandler is used by {@link HgCommandExecutor}, when you want to change the behavior of standart commands execution in the Mercurial.
|
||||
*
|
||||
* @author Nadya Zabrodina
|
||||
*/
|
||||
public interface HgPromptHandler {
|
||||
|
||||
/**
|
||||
* Checks you need to change the default behavior.
|
||||
*
|
||||
* @param message standart output message from Mercurial
|
||||
* @return
|
||||
*/
|
||||
boolean shouldHandle(String message);
|
||||
|
||||
/**
|
||||
* Change default behavior in commands execution.
|
||||
*
|
||||
*
|
||||
* @param message standard output message from Mercurial
|
||||
* @param choices possible choices
|
||||
* @param defaultChoice
|
||||
* @return
|
||||
*/
|
||||
HgPromptChoice promptUser(final String message,
|
||||
@NotNull final HgPromptChoice[] choices,
|
||||
@NotNull final HgPromptChoice defaultChoice);
|
||||
}
|
||||
Reference in New Issue
Block a user