IDEA-122217 When "svn commit" command is too long (many files are being committed) pass necessary commit targets to svn command line client through temporary file (using "--targets" parameter) - otherwise corresponding error (indicating command is too long) occurs

This commit is contained in:
Konstantin Kolosovsky
2015-03-24 15:16:33 +03:00
parent bb6c939bc6
commit 249158d456
4 changed files with 68 additions and 13 deletions
@@ -99,16 +99,31 @@ public abstract class BaseSvnClient implements SvnClient {
@NotNull SvnCommandName name,
@NotNull List<String> parameters,
@Nullable LineCommandListener listener) throws SvnBindException {
Command command = new Command(name);
Command command = newCommand(name);
command.put(parameters);
return execute(vcs, target, workingDirectory, command, listener);
}
@NotNull
public CommandExecutor execute(@NotNull SvnVcs vcs,
@NotNull SvnTarget target,
@Nullable File workingDirectory,
@NotNull Command command,
@Nullable LineCommandListener listener) throws SvnBindException {
command.setTarget(target);
command.setWorkingDirectory(workingDirectory);
command.setResultBuilder(listener);
command.put(parameters);
return newRuntime(vcs).runWithAuthenticationAttempt(command);
}
@NotNull
public Command newCommand(@NotNull SvnCommandName name) {
return new Command(name);
}
@NotNull
public CommandRuntime newRuntime(@NotNull SvnVcs vcs) {
return new CommandRuntime(vcs, new AuthenticationService(vcs, myIsActive));
@@ -29,17 +29,13 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.SvnUtil;
import org.jetbrains.idea.svn.api.BaseSvnClient;
import org.jetbrains.idea.svn.api.Depth;
import org.jetbrains.idea.svn.commandLine.CommandUtil;
import org.jetbrains.idea.svn.commandLine.LineCommandAdapter;
import org.jetbrains.idea.svn.commandLine.SvnBindException;
import org.jetbrains.idea.svn.commandLine.SvnCommandName;
import org.jetbrains.idea.svn.commandLine.*;
import org.jetbrains.idea.svn.status.Status;
import org.jetbrains.idea.svn.status.StatusClient;
import org.jetbrains.idea.svn.status.StatusType;
import org.tmatesoft.svn.core.wc2.SvnTarget;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
@@ -73,19 +69,18 @@ public class CmdCheckinClient extends BaseSvnClient implements CheckinClient {
private CommitInfo[] runCommit(@NotNull List<File> paths, @NotNull String message) throws VcsException {
if (ContainerUtil.isEmpty(paths)) return new CommitInfo[]{CommitInfo.EMPTY};
final List<String> parameters = new ArrayList<String>();
Command command = newCommand(SvnCommandName.ci);
CommandUtil.put(parameters, Depth.EMPTY);
parameters.add("-m");
parameters.add(message);
command.put(Depth.EMPTY);
command.put("-m", message);
// TODO: seems that sort is not necessary here
ContainerUtil.sort(paths);
CommandUtil.put(parameters, paths);
command.setTargets(paths);
IdeaCommitHandler handler = new IdeaCommitHandler(ProgressManager.getInstance().getProgressIndicator());
CmdCheckinClient.CommandListener listener = new CommandListener(handler);
listener.setBaseDirectory(CommandUtil.correctUpToExistingParent(paths.get(0)));
execute(myVcs, SvnTarget.fromFile(paths.get(0)), SvnCommandName.ci, parameters, listener);
execute(myVcs, SvnTarget.fromFile(paths.get(0)), null, command, listener);
listener.throwExceptionIfOccurred();
long revision = validateRevisionNumber(listener.getCommittedRevision());
@@ -1,10 +1,12 @@
package org.jetbrains.idea.svn.commandLine;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.api.Depth;
import org.jetbrains.idea.svn.api.ProgressTracker;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.wc.SVNRevision;
@@ -13,6 +15,7 @@ import org.tmatesoft.svn.core.wc2.SvnTarget;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
/**
@@ -30,6 +33,7 @@ public class Command {
@Nullable private LineCommandListener myResultBuilder;
@Nullable private volatile SVNURL myRepositoryUrl;
@NotNull private SvnTarget myTarget;
@Nullable private Collection<File> myTargets;
@Nullable private ProgressTracker myCanceller;
@@ -37,6 +41,10 @@ public class Command {
myName = name;
}
public void put(@Nullable Depth depth) {
CommandUtil.put(myParameters, depth, false);
}
public void put(@NonNls @NotNull String... parameters) {
put(Arrays.asList(parameters));
}
@@ -92,6 +100,16 @@ public class Command {
return myTarget;
}
@Nullable
public List<String> getTargetsPaths() {
return ContainerUtil.isEmpty(myTargets) ? null : ContainerUtil.map(myTargets, new Function<File, String>() {
@Override
public String fun(File file) {
return file.getAbsolutePath();
}
});
}
@NotNull
public SvnCommandName getName() {
return myName;
@@ -117,6 +135,10 @@ public class Command {
myTarget = target;
}
public void setTargets(@Nullable Collection<File> targets) {
myTargets = targets;
}
// TODO: used only to ensure authentication info is not logged to file. Remove when command execution model is refactored
// TODO: - so we could determine if parameter should be logged by the parameter itself.
public void saveOriginalParameters() {
@@ -139,6 +161,11 @@ public class Command {
data.add(myName.getName());
data.addAll(myOriginalParameters);
List<String> targetsPaths = getTargetsPaths();
if (!ContainerUtil.isEmpty(targetsPaths)) {
data.addAll(targetsPaths);
}
return StringUtil.join(data, " ");
}
@@ -26,7 +26,9 @@ 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.SystemProperties;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.vcsUtil.VcsFileUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -158,6 +160,7 @@ public class CommandExecutor {
EncodingEnvironmentUtil.fixDefaultEncodingIfMac(myCommandLine, null);
setupLocale();
ensureMessageFile();
ensureTargetsAdded();
}
private void setupLocale() {
@@ -197,6 +200,21 @@ public class CommandExecutor {
}
}
private void ensureTargetsAdded() throws SvnBindException {
List<String> targetsPaths = myCommand.getTargetsPaths();
if (!ContainerUtil.isEmpty(targetsPaths)) {
String targetsValue = StringUtil.join(targetsPaths, SystemProperties.getLineSeparator());
if (myCommandLine.getCommandLineString().length() + targetsValue.length() > VcsFileUtil.FILE_PATH_LIMIT) {
ensureCommandFile("command-targets", ".txt", targetsValue, "--targets");
}
else {
myCommandLine.addParameters(targetsPaths);
}
}
}
private void deleteTempFiles() {
for (File file : myTempFiles) {
deleteTempFile(file);