diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandExecutor.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandExecutor.java index 8f3471d38f41..982eb44ce725 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandExecutor.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandExecutor.java @@ -26,16 +26,16 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.util.EventDispatcher; -import com.intellij.util.io.BaseDataReader; -import com.intellij.util.io.BinaryOutputReader; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.tmatesoft.svn.core.SVNCancelException; -import java.io.*; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.OutputStreamWriter; import java.util.List; -import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; @@ -57,7 +57,7 @@ public class CommandExecutor { private volatile boolean myWasCancelled; protected final GeneralCommandLine myCommandLine; protected Process myProcess; - protected OSProcessHandler myHandler; + protected SvnProcessHandler myHandler; private OutputStreamWriter myProcessWriter; // TODO: Try to implement commands in a way that they manually indicate if they need full output - to prevent situations // TODO: when large amount of data needs to be stored instead of just sequential processing. @@ -201,16 +201,18 @@ public class CommandExecutor { } @NotNull - protected OSProcessHandler createProcessHandler() { - return needsBinaryOutput() - ? new BinaryOSProcessHandler(myProcess, myCommandLine.getCommandLineString()) - : new MyOSProcessHandler(myProcess, myCommandLine.getCommandLineString()); + protected SvnProcessHandler createProcessHandler() { + return new SvnProcessHandler(myProcess, myCommandLine.getCommandLineString(), needsUtf8Output(), needsBinaryOutput()); } - private boolean needsBinaryOutput() { + protected boolean needsBinaryOutput() { return SvnCommandName.cat.equals(myCommand.getName()); } + protected boolean needsUtf8Output() { + return myCommand.getParameters().contains("--xml"); + } + @NotNull protected Process createProcess() throws ExecutionException { return myCommandLine.createProcess(); @@ -237,9 +239,9 @@ public class CommandExecutor { return outputAdapter.getOutput(); } - @Nullable + @NotNull public ByteArrayOutputStream getBinaryOutput() { - return myHandler instanceof BinaryOSProcessHandler ? ((BinaryOSProcessHandler)myHandler).myBinaryOutput : null; + return myHandler.getBinaryOutput(); } // TODO: Carefully here - do not modify command from threads other than the one started command execution @@ -463,53 +465,4 @@ public class CommandExecutor { } } } - - private class MyOSProcessHandler extends OSProcessHandler { - - public MyOSProcessHandler(@NotNull Process process, @Nullable String commandLine) { - super(process, commandLine); - } - - @Override - protected Reader createProcessOutReader() { - if (myCommand.getParameters().contains("--xml")) { - return new InputStreamReader(myProcess.getInputStream(), CharsetToolkit.UTF8_CHARSET); - } - return super.createProcessOutReader(); - } - } - - private static class BinaryOSProcessHandler extends OSProcessHandler { - - @NotNull private final ByteArrayOutputStream myBinaryOutput; - - public BinaryOSProcessHandler(@NotNull final Process process, @Nullable final String commandLine) { - super(process, commandLine); - myBinaryOutput = new ByteArrayOutputStream(); - } - - @NotNull - @Override - protected BaseDataReader createOutputDataReader(BaseDataReader.SleepingPolicy sleepingPolicy) { - return new SimpleBinaryOutputReader(myProcess.getInputStream(), sleepingPolicy); - } - - private class SimpleBinaryOutputReader extends BinaryOutputReader { - - public SimpleBinaryOutputReader(@NotNull InputStream stream, SleepingPolicy sleepingPolicy) { - super(stream, sleepingPolicy); - start(); - } - - @Override - protected void onBinaryAvailable(@NotNull byte[] data, int size) { - myBinaryOutput.write(data, 0, size); - } - - @Override - protected Future executeOnPooledThread(Runnable runnable) { - return BinaryOSProcessHandler.this.executeOnPooledThread(runnable); - } - } - } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnProcessHandler.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnProcessHandler.java new file mode 100644 index 000000000000..8bed772d70f9 --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnProcessHandler.java @@ -0,0 +1,91 @@ +/* + * Copyright 2000-2014 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.jetbrains.idea.svn.commandLine; + +import com.intellij.execution.process.OSProcessHandler; +import com.intellij.openapi.vfs.CharsetToolkit; +import com.intellij.util.io.BaseDataReader; +import com.intellij.util.io.BinaryOutputReader; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.util.concurrent.Future; + +/** + * @author Konstantin Kolosovsky. + */ +public class SvnProcessHandler extends OSProcessHandler { + + private final boolean myForceUtf8; + private final boolean myForceBinary; + @NotNull private final ByteArrayOutputStream myBinaryOutput; + + public SvnProcessHandler(@NotNull Process process, boolean forceUtf8, boolean forceBinary) { + this(process, null, forceUtf8, forceBinary); + } + + public SvnProcessHandler(@NotNull Process process, @Nullable String commandLine, boolean forceUtf8, boolean forceBinary) { + super(process, commandLine); + + myForceUtf8 = forceUtf8; + myForceBinary = forceBinary; + myBinaryOutput = new ByteArrayOutputStream(); + } + + @NotNull + public ByteArrayOutputStream getBinaryOutput() { + return myBinaryOutput; + } + + @Override + protected Reader createProcessOutReader() { + if (myForceUtf8) { + return new InputStreamReader(myProcess.getInputStream(), CharsetToolkit.UTF8_CHARSET); + } + return super.createProcessOutReader(); + } + + @NotNull + @Override + protected BaseDataReader createOutputDataReader(BaseDataReader.SleepingPolicy sleepingPolicy) { + if (myForceBinary) { + return new SimpleBinaryOutputReader(myProcess.getInputStream(), sleepingPolicy); + } + return super.createOutputDataReader(sleepingPolicy); + } + + private class SimpleBinaryOutputReader extends BinaryOutputReader { + + public SimpleBinaryOutputReader(@NotNull InputStream stream, SleepingPolicy sleepingPolicy) { + super(stream, sleepingPolicy); + start(); + } + + @Override + protected void onBinaryAvailable(@NotNull byte[] data, int size) { + myBinaryOutput.write(data, 0, size); + } + + @Override + protected Future executeOnPooledThread(Runnable runnable) { + return SvnProcessHandler.this.executeOnPooledThread(runnable); + } + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/TerminalExecutor.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/TerminalExecutor.java index f23a9e092ff1..742cbd2584bc 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/TerminalExecutor.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/TerminalExecutor.java @@ -17,7 +17,6 @@ package org.jetbrains.idea.svn.commandLine; import com.intellij.execution.CommandLineUtil; import com.intellij.execution.ExecutionException; -import com.intellij.execution.process.OSProcessHandler; import com.intellij.util.ArrayUtil; import com.intellij.util.containers.ContainerUtil; import com.pty4j.PtyProcess; @@ -53,8 +52,8 @@ public class TerminalExecutor extends CommandExecutor { @NotNull @Override - protected OSProcessHandler createProcessHandler() { - return new TerminalProcessHandler(myProcess); + protected SvnProcessHandler createProcessHandler() { + return new TerminalProcessHandler(myProcess, needsUtf8Output(), needsBinaryOutput()); } @NotNull diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/TerminalProcessHandler.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/TerminalProcessHandler.java index ee9c0ebab43d..c6f8dd7cc081 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/TerminalProcessHandler.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/TerminalProcessHandler.java @@ -16,7 +16,6 @@ package org.jetbrains.idea.svn.commandLine; import com.intellij.execution.process.CapturingProcessAdapter; -import com.intellij.execution.process.OSProcessHandler; import com.intellij.execution.process.ProcessEvent; import com.intellij.execution.process.ProcessOutputTypes; import com.intellij.openapi.util.Key; @@ -31,7 +30,7 @@ import java.util.regex.Matcher; /** * @author Konstantin Kolosovsky. */ -public class TerminalProcessHandler extends OSProcessHandler { +public class TerminalProcessHandler extends SvnProcessHandler { private final List myInteractiveListeners = ContainerUtil.createLockFreeCopyOnWriteList(); private final CapturingProcessAdapter terminalOutputCapturer = new CapturingProcessAdapter(); @@ -39,8 +38,8 @@ public class TerminalProcessHandler extends OSProcessHandler { private final StringBuilder outputLine = new StringBuilder(); private final StringBuilder errorLine = new StringBuilder(); - public TerminalProcessHandler(@NotNull Process process) { - super(process); + public TerminalProcessHandler(@NotNull Process process, boolean forceUtf8, boolean forceBinary) { + super(process, forceUtf8, forceBinary); } public void addInteractiveListener(@NotNull InteractiveCommandListener listener) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/WinTerminalExecutor.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/WinTerminalExecutor.java index c5002a2dd852..e08594d33c28 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/WinTerminalExecutor.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/WinTerminalExecutor.java @@ -16,7 +16,6 @@ package org.jetbrains.idea.svn.commandLine; import com.intellij.execution.ExecutionException; -import com.intellij.execution.process.OSProcessHandler; import com.intellij.execution.process.ProcessWrapper; import com.intellij.execution.util.ExecUtil; import com.intellij.openapi.util.SystemInfo; @@ -56,8 +55,8 @@ public class WinTerminalExecutor extends TerminalExecutor { @NotNull @Override - protected OSProcessHandler createProcessHandler() { - return new WinTerminalProcessHandler(myProcess); + protected SvnProcessHandler createProcessHandler() { + return new WinTerminalProcessHandler(myProcess, needsUtf8Output(), needsBinaryOutput()); } @Override diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/WinTerminalProcessHandler.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/WinTerminalProcessHandler.java index f7657023ff41..3856b336d07f 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/WinTerminalProcessHandler.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/WinTerminalProcessHandler.java @@ -27,8 +27,8 @@ public class WinTerminalProcessHandler extends TerminalProcessHandler { private static final String NON_CSI_ESCAPE_CODE = "\u001B.[@-_]"; private static final String CSI_ESCAPE_CODE = "\u001B\\[(.*?)[@-~]"; - public WinTerminalProcessHandler(@NotNull Process process) { - super(process); + public WinTerminalProcessHandler(@NotNull Process process, boolean forceUtf8, boolean forceBinary) { + super(process, forceUtf8, forceBinary); } @Override diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/content/CmdContentClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/content/CmdContentClient.java index d654253bf426..17b195eb927e 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/content/CmdContentClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/content/CmdContentClient.java @@ -2,15 +2,15 @@ package org.jetbrains.idea.svn.content; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.impl.ContentRevisionCache; -import com.intellij.openapi.vfs.CharsetToolkit; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.api.BaseSvnClient; -import org.jetbrains.idea.svn.commandLine.*; +import org.jetbrains.idea.svn.commandLine.CommandExecutor; +import org.jetbrains.idea.svn.commandLine.CommandUtil; +import org.jetbrains.idea.svn.commandLine.SvnCommandName; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; -import java.io.ByteArrayOutputStream; import java.util.ArrayList; import java.util.List; @@ -31,9 +31,7 @@ public class CmdContentClient extends BaseSvnClient implements ContentClient { CommandUtil.put(parameters, revision); CommandExecutor command = CommandUtil.execute(myVcs, target, SvnCommandName.cat, parameters, null); - // TODO: currently binary output will be null for terminal mode - use text output in this case - ByteArrayOutputStream output = command.getBinaryOutput(); - byte[] bytes = output != null ? output.toByteArray() : CharsetToolkit.getUtf8Bytes(command.getOutput()); + byte[] bytes = command.getBinaryOutput().toByteArray(); ContentRevisionCache.checkContentsSize(target.getPathOrUrlString(), bytes.length);