HgCommandExecutor refactoring

* finally block added to stop appropriate socket server in any cases;
* warnings deleted fromHgCommandResult and from PromptCommandExecutor and now considered as non-fatal errors;
* message title changed in PromptCommandExecutor;
* prompthooks extension arguments creation moved to a separate method;
* log command method overrided for remote command execution to not provide password socket information outside
This commit is contained in:
Nadya Zabrodina
2014-05-26 20:21:30 +04:00
parent d215ac2bf1
commit 5298c6bf13
5 changed files with 47 additions and 85 deletions
@@ -147,14 +147,15 @@ public class HgCommandExecutor {
cmdLine.add(HgEncodingUtil.getNameFor(myCharset));
}
HgCommandResult result;
try {
String workingDir = repo != null ? repo.getPath() : null;
ShellCommand shellCommand = new ShellCommand(cmdLine, workingDir, myCharset);
long startTime = System.currentTimeMillis();
LOG.debug(String.format("hg %s started", operation));
result = shellCommand.execute(myShowOutput);
HgCommandResult result = shellCommand.execute(myShowOutput);
LOG.debug(String.format("hg %s finished. Took %s ms", operation, System.currentTimeMillis() - startTime));
logResult(result);
return result;
}
catch (ShellCommandException e) {
if (myVcs.getExecutableValidator().checkExecutableAndNotifyIfNeeded()) {
@@ -168,9 +169,6 @@ public class HgCommandExecutor {
LOG.info(e.getMessage(), e);
return null;
}
logResult(result);
return result;
}
// logging to the Version Control console (without extensions and configs)
@@ -20,7 +20,6 @@ import java.util.List;
public final class HgCommandResult {
public static final HgCommandResult EMPTY = new HgCommandResult(new StringWriter(), new StringWriter(), 0);
public static final HgCommandResult CANCELLED = new HgCommandResult(new StringWriter(), new StringWriter(), 1);
private final StringWriter out;
@@ -29,7 +28,6 @@ public final class HgCommandResult {
private List<String> outLines;
private List<String> errLines;
private String warnings;
public HgCommandResult(StringWriter out, StringWriter err, int exitValue) {
this.out = out;
@@ -54,7 +52,7 @@ public final class HgCommandResult {
public String getRawOutput() {
return out.toString();
}
public String getRawError() {
return err.toString();
}
@@ -62,12 +60,4 @@ public final class HgCommandResult {
public int getExitValue() {
return exitValue;
}
void setWarnings(String warnings) {
this.warnings = warnings;
}
public String getWarnings() {
return warnings;
}
}
@@ -18,6 +18,7 @@ package org.zmlx.hg4idea.execution;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -27,7 +28,6 @@ import java.io.DataOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.Socket;
import java.util.LinkedList;
import java.util.List;
public class HgPromptCommandExecutor extends HgCommandExecutor {
@@ -41,61 +41,32 @@ public class HgPromptCommandExecutor extends HgCommandExecutor {
public HgCommandResult executeInCurrentThread(@Nullable final VirtualFile repo,
@NotNull final String operation,
@Nullable final List<String> arguments) {
final List<String> cmdLine = new LinkedList<String>();
WarningReceiver warningReceiver = new WarningReceiver();
SocketServer promptServer = new SocketServer(new PromptReceiver(new HgDeleteModifyPromptHandler()));
SocketServer warningServer = new SocketServer(warningReceiver);
try {
int promptPort = promptServer.start();
int warningPort = warningServer.start();
cmdLine.add("--config");
cmdLine.add("extensions.hg4ideapromptextension=" + myVcs.getPromptHooksExtensionFile().getAbsolutePath());
cmdLine.add("--config");
cmdLine.add("hg4ideaprompt.port=" + promptPort);
cmdLine.add("--config");
cmdLine.add("hg4ideawarn.port=" + warningPort);
return super.executeInCurrentThread(repo, operation, prepareArguments(arguments, promptPort));
}
catch (IOException e) {
showError(e);
LOG.info("IOException during preparing command", e);
promptServer.stop();
warningServer.stop();
return null;
}
if (arguments != null && arguments.size() != 0) {
cmdLine.addAll(arguments);
finally {
promptServer.stop();
}
HgCommandResult result = super.executeInCurrentThread(repo, operation, cmdLine);
promptServer.stop();
warningServer.stop();
String warnings = warningReceiver.getWarnings();
result.setWarnings(warnings);
return result;
}
private static class WarningReceiver extends SocketServer.Protocol {
private StringBuffer warnings = new StringBuffer();
private List<String> prepareArguments(List<String> arguments, int port) {
List<String> cmdArguments = ContainerUtil.newArrayList();
cmdArguments.add("--config");
cmdArguments.add("extensions.hg4ideapromptextension=" + myVcs.getPromptHooksExtensionFile().getAbsolutePath());
cmdArguments.add("--config");
cmdArguments.add("hg4ideaprompt.port=" + port);
public boolean handleConnection(Socket socket) throws IOException {
//noinspection IOResourceOpenedButNotSafelyClosed
DataInputStream dataInput = new DataInputStream(socket.getInputStream());
int numOfWarnings = dataInput.readInt();
for (int i = 0; i < numOfWarnings; i++) {
warnings.append(new String(readDataBlock(dataInput)));
}
return true;
}
public String getWarnings() {
return warnings.toString();
if (arguments != null && arguments.size() != 0) {
cmdArguments.addAll(arguments);
}
return cmdArguments;
}
private static class PromptReceiver extends SocketServer.Protocol {
@@ -132,7 +103,7 @@ public class HgPromptCommandExecutor extends HgCommandExecutor {
choicePresentationArray[i] = choices[i].toString();
}
index[0] = Messages
.showDialog(message, "Hg4idea",
.showDialog(message, "Mercurial Prompt Message",
choicePresentationArray,
defaultChoice.getChosenIndex(), Messages.getQuestionIcon());
}
@@ -15,6 +15,7 @@ package org.zmlx.hg4idea.execution;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.zmlx.hg4idea.action.HgCommandResultNotifier;
@@ -24,17 +25,12 @@ import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.LinkedList;
import java.util.List;
public class HgRemoteCommandExecutor extends HgCommandExecutor {
@Nullable private ModalityState myState;
public HgRemoteCommandExecutor(@NotNull Project project) {
this(project, null);
}
public HgRemoteCommandExecutor(@NotNull Project project, @Nullable String destination) {
this(project, destination, null);
}
@@ -65,43 +61,49 @@ public class HgRemoteCommandExecutor extends HgCommandExecutor {
}
@Nullable
public HgCommandResult executeInCurrentThread(@Nullable final VirtualFile repo,
private HgCommandResult executeInCurrentThread(@Nullable final VirtualFile repo,
@NotNull final String operation,
@Nullable final List<String> arguments,
boolean forceAuthorization) {
final List<String> cmdLine = new LinkedList<String>();
PassReceiver passReceiver = new PassReceiver(myProject, forceAuthorization, myState);
SocketServer passServer = new SocketServer(passReceiver);
try {
int passPort = passServer.start();
cmdLine.add("--config");
cmdLine.add("extensions.hg4ideapromptextension=" + myVcs.getPromptHooksExtensionFile().getAbsolutePath());
cmdLine.add("--config");
cmdLine.add("hg4ideapass.port=" + passPort);
HgCommandResult result = super.executeInCurrentThread(repo, operation, prepareArguments(arguments, passPort));
if (!HgErrorUtil.isAuthorizationError(result)) {
passReceiver.saveCredentials();
}
return result;
}
catch (IOException e) {
showError(e);
LOG.info("IOException during preparing command", e);
passServer.stop();
return null;
}
if (arguments != null && arguments.size() != 0) {
cmdLine.addAll(arguments);
finally {
passServer.stop();
}
HgCommandResult result;
result = super.executeInCurrentThread(repo, operation, cmdLine);
if (!HgErrorUtil.isAuthorizationError(result)) {
passReceiver.saveCredentials();
}
passServer.stop();
return result;
}
private List<String> prepareArguments(List<String> arguments, int port) {
List<String> cmdArguments = ContainerUtil.newArrayList();
cmdArguments.add("--config");
cmdArguments.add("extensions.hg4ideapromptextension=" + myVcs.getPromptHooksExtensionFile().getAbsolutePath());
cmdArguments.add("--config");
cmdArguments.add("hg4ideapass.port=" + port);
if (arguments != null && arguments.size() != 0) {
cmdArguments.addAll(arguments);
}
return cmdArguments;
}
@Override
protected void logCommand(@NotNull String operation, @Nullable List<String> arguments) {
//do not log arguments for remote command because of internal password port info etc
super.logCommand(operation, null);
}
private static class PassReceiver extends SocketServer.Protocol {
private final Project myProject;
@@ -263,7 +263,8 @@ public class HgRegularUpdater implements HgUpdater {
HgRevisionNumber parentBeforeUpdate = new HgWorkingCopyRevisionsCommand(project).firstParent(repo);
HgUpdateCommand hgUpdateCommand = new HgUpdateCommand(project, repo);
String warningMessages = ensureSuccess(hgUpdateCommand.execute()).getWarnings();
HgCommandResult updateResult = hgUpdateCommand.execute();
String warningMessages = ensureSuccess(updateResult).getRawError();
handlePossibleWarning(warnings, warningMessages);
HgRevisionNumber parentAfterUpdate = new HgWorkingCopyRevisionsCommand(project).firstParent(repo);