IDEA-94774 Creating new project - svn deadlock

This commit is contained in:
irengrig
2012-11-13 16:58:45 +04:00
parent c25302268c
commit d95728d5cf
3 changed files with 90 additions and 56 deletions
@@ -21,17 +21,22 @@ import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.AbstractVcsHelper;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.ChangesUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.wm.impl.status.StatusBarUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.Convertor;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -292,6 +297,50 @@ public class SvnUtil {
return "";
}
public static Collection<List<Change>> splitChangesIntoWc(final SvnVcs vcs, final List<Change> changes) {
return splitIntoWc(vcs, changes, new Convertor<Change, File>() {
@Override
public File convert(Change o) {
return ChangesUtil.getFilePath(o).getIOFile();
}
});
}
public static Collection<List<File>> splitFilesIntoWc(final SvnVcs vcs, final List<File> committables) {
return splitIntoWc(vcs, committables, Convertor.SELF);
}
public static <T> Collection<List<T>> splitIntoWc(final SvnVcs vcs, final List<T> committables,
Convertor<T, File> convertor) {
if (committables.size() == 1) {
return Collections.singletonList(committables);
}
final MultiMap<Pair<SVNURL, WorkingCopyFormat>, T> result = new MultiMap<Pair<SVNURL, WorkingCopyFormat>, T>() {
@Override
protected Collection<T> createCollection() {
return new ArrayList<T>();
}
};
for (T committable : committables) {
final RootUrlInfo path = vcs.getSvnFileUrlMapping().getWcRootForFilePath(convertor.convert(committable));
if (path == null) {
result.putValue(new Pair<SVNURL, WorkingCopyFormat>(null, null), committable);
} else {
result.putValue(new Pair<SVNURL, WorkingCopyFormat>(path.getRepositoryUrlUrl(), path.getFormat()), committable);
}
}
if (result.size() == 1) {
return Collections.singletonList(committables);
}
final Collection<List<T>> result2 = new ArrayList<List<T>>();
for (Map.Entry<Pair<SVNURL, WorkingCopyFormat>, Collection<T>> entry : result.entrySet()) {
result2.add((List<T>)entry.getValue());
}
return result2;
}
private static class LocationsCrawler implements SvnWCRootCrawler {
private final SvnVcs myVcs;
private final Map<String, File> myLocations;
@@ -25,7 +25,6 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vcs.CheckinProjectPanel;
import com.intellij.openapi.vcs.FilePath;
@@ -43,12 +42,17 @@ import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.util.FunctionUtil;
import com.intellij.util.NullableFunction;
import com.intellij.util.PairConsumer;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.*;
import org.tmatesoft.svn.core.*;
import org.jetbrains.idea.svn.SvnBundle;
import org.jetbrains.idea.svn.SvnConfiguration;
import org.jetbrains.idea.svn.SvnUtil;
import org.jetbrains.idea.svn.SvnVcs;
import org.tmatesoft.svn.core.SVNCancelException;
import org.tmatesoft.svn.core.SVNCommitInfo;
import org.tmatesoft.svn.core.SVNDepth;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.wc.*;
import javax.swing.*;
@@ -84,7 +88,7 @@ public class SvnCheckinEnvironment implements CheckinEnvironment {
private List<VcsException> commitInt(List<File> paths, final String comment, final boolean force, final boolean recursive,
final Set<String> feedback) {
final List<VcsException> exception = new ArrayList<VcsException>();
final Collection<File> committables = getCommitables(paths);
final List<File> committables = getCommitables(paths);
final SVNCommitClient committer = mySvnVcs.createCommitClient();
@@ -156,44 +160,19 @@ public class SvnCheckinEnvironment implements CheckinEnvironment {
return exception;
}
private void doCommit(Collection<File> committables,
private void doCommit(List<File> committables,
ProgressIndicator progress,
SVNCommitClient committer,
String comment,
boolean force,
boolean recursive,
List<VcsException> exception, final Set<String> feedback) {
final Collection<Collection<File>> collections = splitIntoWc(committables);
for (Collection<File> collection : collections) {
final Collection<List<File>> collections = SvnUtil.splitFilesIntoWc(mySvnVcs, committables);
for (List<File> collection : collections) {
doCommitOneWc(collection, progress, committer, comment, force, recursive, exception, feedback);
}
}
private Collection<Collection<File>> splitIntoWc(Collection<File> committables) {
if (committables.size() == 1) {
return Collections.singletonList(committables);
}
final MultiMap<Pair<SVNURL, WorkingCopyFormat>, File> result = new MultiMap<Pair<SVNURL, WorkingCopyFormat>, File>();
for (File committable : committables) {
final RootUrlInfo path = mySvnVcs.getSvnFileUrlMapping().getWcRootForFilePath(committable);
if (path == null) {
result.putValue(new Pair<SVNURL, WorkingCopyFormat>(null, null), committable);
} else {
result.putValue(new Pair<SVNURL, WorkingCopyFormat>(path.getRepositoryUrlUrl(), path.getFormat()), committable);
}
}
if (result.size() == 1) {
return Collections.singletonList(committables);
}
final Collection<Collection<File>> result2 = new ArrayList<Collection<File>>();
for (Map.Entry<Pair<SVNURL, WorkingCopyFormat>, Collection<File>> entry : result.entrySet()) {
result2.add(entry.getValue());
}
return result2;
}
private void doCommitOneWc(Collection<File> committables,
ProgressIndicator progress,
SVNCommitClient committer,
@@ -265,7 +244,7 @@ public class SvnCheckinEnvironment implements CheckinEnvironment {
}
private static class Adder {
private final Collection<File> myResult = new ArrayList<File>();
private final List<File> myResult = new ArrayList<File>();
private final Set<String> myDuplicatesControlSet = new HashSet<String>();
public void add(final File file) {
@@ -276,12 +255,12 @@ public class SvnCheckinEnvironment implements CheckinEnvironment {
}
}
public Collection<File> getResult() {
public List<File> getResult() {
return myResult;
}
}
private Collection<File> getCommitables(List<File> paths) {
private List<File> getCommitables(List<File> paths) {
final Adder adder = new Adder();
SVNStatusClient statusClient = mySvnVcs.createStatusClient();
@@ -30,10 +30,7 @@ import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.MoveRenameReplaceCheck;
import org.jetbrains.idea.svn.SvnBundle;
import org.jetbrains.idea.svn.SvnChangeProvider;
import org.jetbrains.idea.svn.SvnVcs;
import org.jetbrains.idea.svn.*;
import org.tmatesoft.svn.core.SVNDepth;
import org.tmatesoft.svn.core.SVNErrorCode;
import org.tmatesoft.svn.core.SVNException;
@@ -62,31 +59,40 @@ public class SvnRollbackEnvironment extends DefaultRollbackEnvironment {
public void rollbackChanges(List<Change> changes, final List<VcsException> exceptions, @NotNull final RollbackProgressListener listener) {
listener.indeterminate();
final SvnChangeProvider changeProvider = (SvnChangeProvider) mySvnVcs.getChangeProvider();
final Collection<List<Change>> collections = SvnUtil.splitChangesIntoWc(mySvnVcs, changes);
for (List<Change> collection : collections) {
rollbackGroupForWc(collection, exceptions, listener, changeProvider);
}
}
private void rollbackGroupForWc(List<Change> changes,
final List<VcsException> exceptions,
final RollbackProgressListener listener,
SvnChangeProvider changeProvider) {
final UnversionedFilesGroupCollector collector = new UnversionedFilesGroupCollector();
final ChangesChecker checker = new ChangesChecker(changeProvider, collector);
checker.gather(changes);
exceptions.addAll(checker.getExceptions());
final SVNWCClient client = mySvnVcs.createWCClient();
client.setEventHandler(new ISVNEventHandler() {
public void handleEvent(SVNEvent event, double progress) {
if (event.getAction() == SVNEventAction.REVERT) {
final File file = event.getFile();
if (file != null) {
listener.accept(file);
}
}
if (event.getAction() == SVNEventAction.FAILED_REVERT) {
exceptions.add(new VcsException("Revert failed"));
final SVNWCClient client = mySvnVcs.createWCClient();
client.setEventHandler(new ISVNEventHandler() {
public void handleEvent(SVNEvent event, double progress) {
if (event.getAction() == SVNEventAction.REVERT) {
final File file = event.getFile();
if (file != null) {
listener.accept(file);
}
}
if (event.getAction() == SVNEventAction.FAILED_REVERT) {
exceptions.add(new VcsException("Revert failed"));
}
}
public void checkCancelled() {
listener.checkCanceled();
}
});
public void checkCancelled() {
listener.checkCanceled();
}
});
final List<Trinity<File, File, File>> fromTo = collector.getFromTo();
final List<Trinity<File, File, File>> fromToModified = new ArrayList<Trinity<File, File, File>>();