mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'svn1_8_new'
This commit is contained in:
@@ -330,6 +330,7 @@ progress.text2.exported=Exported {1} files, exporting {0}
|
||||
progress.text2.checked.out.revision=Checked out revision {0}.
|
||||
progress.text2.exported.revision=Exported revision {0}.
|
||||
status.text.checked.out.revision=Checked out revision {0}.
|
||||
message.text.cannot.load.supported.formats=Cannot load supported formats: {0}
|
||||
message.text.cannot.checkout=Cannot checkout from svn: {0}
|
||||
message.text.cannot.export=Cannot export from svn: {0}
|
||||
message.title.check.out=Check Out from Subversion
|
||||
|
||||
@@ -17,12 +17,7 @@ package org.jetbrains.idea.svn;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.util.WaitForProgressToShow;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.svn.dialogs.UpgradeFormatDialog;
|
||||
import org.tmatesoft.svn.core.SVNErrorCode;
|
||||
import org.tmatesoft.svn.core.SVNErrorMessage;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
@@ -136,22 +131,6 @@ public class SvnFormatSelector implements ISVNAdminAreaFactorySelector {
|
||||
return result;
|
||||
}
|
||||
|
||||
public static WorkingCopyFormat showUpgradeDialog(final File path,
|
||||
final Project project,
|
||||
final boolean display13format,
|
||||
@NotNull final WorkingCopyFormat defaultSelection,
|
||||
@NotNull final Ref<Boolean> wasOk) {
|
||||
assert ! ApplicationManager.getApplication().isUnitTestMode();
|
||||
final Ref<WorkingCopyFormat> format = new Ref<WorkingCopyFormat>(defaultSelection);
|
||||
WaitForProgressToShow.runOrInvokeAndWaitAboveProgress(new Runnable() {
|
||||
public void run() {
|
||||
wasOk.set(displayUpgradeDialog(project, path, display13format, format));
|
||||
}
|
||||
});
|
||||
ApplicationManager.getApplication().getMessageBus().syncPublisher(SvnVcs.WC_CONVERTED).run();
|
||||
return format.get();
|
||||
}
|
||||
|
||||
public static WorkingCopyFormat findRootAndGetFormat(final File path) {
|
||||
File root = SvnUtil.getWorkingCopyRootNew(path);
|
||||
|
||||
@@ -189,14 +168,4 @@ public class SvnFormatSelector implements ISVNAdminAreaFactorySelector {
|
||||
|
||||
return WorkingCopyFormat.getInstance(format);
|
||||
}
|
||||
|
||||
private static boolean displayUpgradeDialog(Project project, File path, final boolean dispay13format, Ref<WorkingCopyFormat> format) {
|
||||
UpgradeFormatDialog dialog = new UpgradeFormatDialog(project, path, false);
|
||||
dialog.setData(format.get());
|
||||
dialog.show();
|
||||
if (dialog.isOK()) {
|
||||
format.set(dialog.getUpgradeMode());
|
||||
}
|
||||
return dialog.isOK();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -647,6 +647,7 @@ public class SvnUtil {
|
||||
}
|
||||
|
||||
public static boolean remoteFolderIsEmpty(final SvnVcs vcs, final String url) throws SVNException {
|
||||
// TODO: Implement with command line client
|
||||
SVNRepository repository = null;
|
||||
try {
|
||||
repository = vcs.createRepository(url);
|
||||
|
||||
@@ -100,4 +100,23 @@ public enum WorkingCopyFormat {
|
||||
public int getFormat() {
|
||||
return myFormat;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static WorkingCopyFormat from(@NotNull Version version) {
|
||||
WorkingCopyFormat result = UNKNOWN;
|
||||
|
||||
for (WorkingCopyFormat format : WorkingCopyFormat.values()) {
|
||||
if (format.getVersion().is(version.major, version.minor)) {
|
||||
result = format;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,18 +31,19 @@ import com.intellij.openapi.vcs.AbstractVcs;
|
||||
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.idea.svn.*;
|
||||
import org.jetbrains.idea.svn.api.ClientFactory;
|
||||
import org.jetbrains.idea.svn.checkout.SvnCheckoutProvider;
|
||||
import org.jetbrains.idea.svn.dialogs.ShareDialog;
|
||||
import org.tmatesoft.svn.core.SVNCommitInfo;
|
||||
import org.tmatesoft.svn.core.SVNDepth;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
import org.tmatesoft.svn.core.SVNURL;
|
||||
import org.tmatesoft.svn.core.internal.wc2.SvnWcGeneration;
|
||||
import org.tmatesoft.svn.core.wc.SVNRevision;
|
||||
import org.tmatesoft.svn.core.wc.SVNUpdateClient;
|
||||
import org.tmatesoft.svn.core.wc.SVNWCClient;
|
||||
import org.tmatesoft.svn.core.wc2.SvnTarget;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@@ -104,7 +105,7 @@ public class ShareProjectAction extends BasicAction {
|
||||
final String parent = shareDialog.getSelectedURL();
|
||||
if (shareDialog.isOK() && parent != null) {
|
||||
final Ref<Boolean> actionStarted = new Ref<Boolean>(Boolean.TRUE);
|
||||
final SVNException[] error = new SVNException[1];
|
||||
final Exception[] error = new Exception[1];
|
||||
|
||||
final ShareDialog.ShareTarget shareTarget = shareDialog.getShareTarget();
|
||||
final ProgressManager progressManager = ProgressManager.getInstance();
|
||||
@@ -120,19 +121,23 @@ public class ShareProjectAction extends BasicAction {
|
||||
}
|
||||
}
|
||||
|
||||
final WorkingCopyFormat format = SvnCheckoutProvider.promptForWCopyFormat(VfsUtilCore.virtualToIoFile(file), project);
|
||||
actionStarted.set(format != WorkingCopyFormat.UNKNOWN);
|
||||
// means operation cancelled
|
||||
if (format == WorkingCopyFormat.UNKNOWN) {
|
||||
return true;
|
||||
}
|
||||
|
||||
ExclusiveBackgroundVcsAction.run(project, new Runnable() {
|
||||
public void run() {
|
||||
progressManager.runProcessWithProgressSynchronously(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
|
||||
|
||||
final File path = new File(file.getPath());
|
||||
if (! SvnCheckoutProvider.promptForWCFormatAndSelect(path, project)) {
|
||||
// action cancelled
|
||||
actionStarted.set(Boolean.FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
SvnWorkingCopyFormatHolder.setPresetFormat(format);
|
||||
|
||||
final SVNURL parenUrl = SVNURL.parseURIEncoded(parent);
|
||||
final SVNURL checkoutUrl;
|
||||
final SVNRevision revision;
|
||||
@@ -160,16 +165,17 @@ public class ShareProjectAction extends BasicAction {
|
||||
indicator.checkCanceled();
|
||||
indicator.setText(SvnBundle.message("share.directory.checkout.back.progress.text", checkoutUrl.toString()));
|
||||
}
|
||||
final SVNUpdateClient client = activeVcs.createUpdateClient();
|
||||
if (! WorkingCopyFormat.ONE_DOT_SEVEN.equals(SvnWorkingCopyFormatHolder.getPresetFormat())) {
|
||||
client.getOperationsFactory().setPrimaryWcGeneration(SvnWcGeneration.V16);
|
||||
}
|
||||
client.doCheckout(checkoutUrl, path, SVNRevision.UNDEFINED, revision, SVNDepth.INFINITY, false);
|
||||
SvnWorkingCopyFormatHolder.setPresetFormat(null);
|
||||
|
||||
addRecursively(activeVcs, file);
|
||||
final ClientFactory factory = activeVcs.getFactoryFromSettings();
|
||||
|
||||
factory.createCheckoutClient()
|
||||
.checkout(SvnTarget.fromURL(checkoutUrl), path, revision, SVNDepth.INFINITY, false, false, format, null);
|
||||
addRecursively(activeVcs, factory, file);
|
||||
} catch (SVNException e) {
|
||||
error[0] = e;
|
||||
}
|
||||
catch (VcsException e) {
|
||||
error[0] = e;
|
||||
} finally {
|
||||
activeVcs.invokeRefreshSvnRoots();
|
||||
SvnWorkingCopyFormatHolder.setPresetFormat(null);
|
||||
@@ -226,6 +232,7 @@ public class ShareProjectAction extends BasicAction {
|
||||
indicator.checkCanceled();
|
||||
indicator.setText(SvnBundle.message("share.directory.create.dir.progress.text", urlText));
|
||||
}
|
||||
// TODO: Implement with command line client
|
||||
final SVNCommitInfo info =
|
||||
vcs.createCommitClient().doMkDir(new SVNURL[]{url}, SvnBundle.message("share.directory.commit.message", folderName,
|
||||
ApplicationNamesInfo.getInstance().getFullProductName(), commitText));
|
||||
@@ -237,17 +244,17 @@ public class ShareProjectAction extends BasicAction {
|
||||
VcsDirtyScopeManager.getInstance(project).dirDirtyRecursively(file);
|
||||
}
|
||||
|
||||
private static void addRecursively(final SvnVcs activeVcs, final VirtualFile file) throws SVNException {
|
||||
final SVNWCClient wcClient = activeVcs.createWCClient();
|
||||
private static void addRecursively(@NotNull final SvnVcs activeVcs, @NotNull final ClientFactory factory, final VirtualFile file)
|
||||
throws VcsException {
|
||||
final SvnExcludingIgnoredOperation operation = new SvnExcludingIgnoredOperation(activeVcs.getProject(), new SvnExcludingIgnoredOperation.Operation() {
|
||||
public void doOperation(final VirtualFile virtualFile) throws SVNException {
|
||||
public void doOperation(final VirtualFile virtualFile) throws VcsException {
|
||||
final File ioFile = new File(virtualFile.getPath());
|
||||
final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
|
||||
if (indicator != null) {
|
||||
indicator.checkCanceled();
|
||||
indicator.setText(SvnBundle.message("share.or.import.add.progress.text", virtualFile.getPath()));
|
||||
}
|
||||
wcClient.doAdd(ioFile, true, false, false, SVNDepth.EMPTY, false, false);
|
||||
factory.createAddClient().add(ioFile, SVNDepth.EMPTY, false, false, true, null);
|
||||
}
|
||||
}, SVNDepth.INFINITY);
|
||||
|
||||
|
||||
+7
-7
@@ -20,13 +20,13 @@ import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.FileIndexFacade;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.changes.ChangeListManager;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileVisitor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.tmatesoft.svn.core.SVNDepth;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
|
||||
public class SvnExcludingIgnoredOperation {
|
||||
private final Operation myImportAction;
|
||||
@@ -79,28 +79,28 @@ public class SvnExcludingIgnoredOperation {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean operation(final VirtualFile file) throws SVNException {
|
||||
private boolean operation(final VirtualFile file) throws VcsException {
|
||||
if (! myFilter.accept(file)) return false;
|
||||
|
||||
myImportAction.doOperation(file);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void executeDown(final VirtualFile file) throws SVNException {
|
||||
private void executeDown(final VirtualFile file) throws VcsException {
|
||||
VfsUtilCore.visitChildrenRecursively(file, new VirtualFileVisitor() {
|
||||
@Override
|
||||
public boolean visitFile(@NotNull VirtualFile file) {
|
||||
try {
|
||||
return operation(file);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
catch (VcsException e) {
|
||||
throw new VisitorException(e);
|
||||
}
|
||||
}
|
||||
}, SVNException.class);
|
||||
}, VcsException.class);
|
||||
}
|
||||
|
||||
public void execute(final VirtualFile file) throws SVNException {
|
||||
public void execute(final VirtualFile file) throws VcsException {
|
||||
if (SVNDepth.INFINITY.equals(myDepth)) {
|
||||
executeDown(file);
|
||||
return;
|
||||
@@ -123,6 +123,6 @@ public class SvnExcludingIgnoredOperation {
|
||||
}
|
||||
|
||||
public interface Operation {
|
||||
void doOperation(final VirtualFile file) throws SVNException;
|
||||
void doOperation(final VirtualFile file) throws VcsException;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
package org.jetbrains.idea.svn.api;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.idea.svn.SvnVcs;
|
||||
import org.jetbrains.idea.svn.WorkingCopyFormat;
|
||||
import org.tmatesoft.svn.core.wc2.SvnTarget;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
@@ -44,4 +49,11 @@ public abstract class BaseSvnClient implements SvnClient {
|
||||
throw new IllegalArgumentException("Target should be file " + target);
|
||||
}
|
||||
}
|
||||
|
||||
protected void validateFormat(@NotNull WorkingCopyFormat format, @NotNull Collection<WorkingCopyFormat> supported) throws VcsException {
|
||||
if (!supported.contains(format)) {
|
||||
throw new VcsException(
|
||||
String.format("%s format is not supported. Supported formats are: %s.", format.getName(), StringUtil.join(supported, ",")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import org.tmatesoft.svn.core.wc.SVNRevision;
|
||||
import org.tmatesoft.svn.core.wc2.SvnTarget;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
@@ -22,6 +23,9 @@ public interface CheckoutClient extends SvnClient {
|
||||
@Nullable SVNRevision revision,
|
||||
@Nullable SVNDepth depth,
|
||||
boolean ignoreExternals,
|
||||
@Nullable WorkingCopyFormat format,
|
||||
boolean force,
|
||||
@NotNull WorkingCopyFormat format,
|
||||
@Nullable ISVNEventHandler handler) throws VcsException;
|
||||
|
||||
List<WorkingCopyFormat> getSupportedFormats() throws VcsException;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.jetbrains.idea.svn.checkout;
|
||||
|
||||
import com.intellij.openapi.util.Version;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -27,22 +28,33 @@ public class CmdCheckoutClient extends BaseSvnClient implements CheckoutClient {
|
||||
@Nullable SVNRevision revision,
|
||||
@Nullable SVNDepth depth,
|
||||
boolean ignoreExternals,
|
||||
@Nullable WorkingCopyFormat format,
|
||||
boolean force,
|
||||
@NotNull WorkingCopyFormat format,
|
||||
@Nullable ISVNEventHandler handler) throws VcsException {
|
||||
List<String> parameters = new ArrayList<String>();
|
||||
validateFormat(format, getSupportedFormats());
|
||||
|
||||
// TODO: check format
|
||||
List<String> parameters = new ArrayList<String>();
|
||||
|
||||
CommandUtil.put(parameters, source);
|
||||
CommandUtil.put(parameters, destination, false);
|
||||
CommandUtil.put(parameters, depth);
|
||||
CommandUtil.put(parameters, revision);
|
||||
CommandUtil.put(parameters, ignoreExternals, "--ignore-externals");
|
||||
parameters.add("--force"); // this is to conform to currently used SVNKit behavior - allowUnversionedObstructions
|
||||
CommandUtil.put(parameters, force, "--force"); // corresponds to "allowUnversionedObstructions" in SVNKit
|
||||
|
||||
run(source, destination, handler, parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<WorkingCopyFormat> getSupportedFormats() throws VcsException {
|
||||
ArrayList<WorkingCopyFormat> result = new ArrayList<WorkingCopyFormat>();
|
||||
|
||||
Version version = myFactory.createVersionClient().getVersion();
|
||||
result.add(WorkingCopyFormat.from(version));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void run(@NotNull SvnTarget source,
|
||||
@NotNull File destination,
|
||||
@Nullable ISVNEventHandler handler,
|
||||
|
||||
@@ -17,6 +17,7 @@ package org.jetbrains.idea.svn.checkout;
|
||||
|
||||
import com.intellij.lifecycle.PeriodicalTasksCloser;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
@@ -26,6 +27,7 @@ import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vcs.CalledInAwt;
|
||||
import com.intellij.openapi.vcs.CheckoutProvider;
|
||||
import com.intellij.openapi.vcs.VcsConfiguration;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
@@ -34,6 +36,8 @@ import com.intellij.openapi.vcs.update.RefreshVFsSynchronously;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.wm.StatusBar;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.svn.*;
|
||||
@@ -42,6 +46,7 @@ import org.jetbrains.idea.svn.actions.SvnExcludingIgnoredOperation;
|
||||
import org.jetbrains.idea.svn.checkin.IdeaCommitHandler;
|
||||
import org.jetbrains.idea.svn.commandLine.CommitEventHandler;
|
||||
import org.jetbrains.idea.svn.dialogs.CheckoutDialog;
|
||||
import org.jetbrains.idea.svn.dialogs.UpgradeFormatDialog;
|
||||
import org.tmatesoft.svn.core.SVNCancelException;
|
||||
import org.tmatesoft.svn.core.SVNDepth;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
@@ -51,6 +56,9 @@ import org.tmatesoft.svn.core.wc2.SvnTarget;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public class SvnCheckoutProvider implements CheckoutProvider {
|
||||
|
||||
@@ -84,19 +92,16 @@ public class SvnCheckoutProvider implements CheckoutProvider {
|
||||
final Task.Backgroundable checkoutBackgroundTask = new Task.Backgroundable(project,
|
||||
SvnBundle.message("message.title.check.out"), true, VcsConfiguration.getInstance(project).getCheckoutOption()) {
|
||||
public void run(@NotNull final ProgressIndicator indicator) {
|
||||
SvnWorkingCopyFormatHolder.setPresetFormat(selectedFormat);
|
||||
final WorkingCopyFormat format = selectedFormat == null ? WorkingCopyFormat.UNKNOWN : selectedFormat;
|
||||
|
||||
SvnWorkingCopyFormatHolder.setPresetFormat(format);
|
||||
|
||||
SvnVcs vcs = SvnVcs.getInstance(project);
|
||||
// TODO: made this way to preserve existing logic, but probably this check could be omitted as setPresetFormat(selectedFormat) invoked above
|
||||
WorkingCopyFormat format = !WorkingCopyFormat.ONE_DOT_SEVEN.equals(SvnWorkingCopyFormatHolder.getPresetFormat())
|
||||
? WorkingCopyFormat.ONE_DOT_SIX
|
||||
: selectedFormat;
|
||||
ISVNEventHandler handler = new CheckoutEventHandler(vcs, false, ProgressManager.getInstance().getProgressIndicator());
|
||||
ProgressManager.progress(SvnBundle.message("progress.text.checking.out", target.getAbsolutePath()));
|
||||
try {
|
||||
// TODO: probably rewrite some logic to force ClientFactory provide supported versions (or create special client for that)
|
||||
vcs.getFactoryFromSettings().createCheckoutClient()
|
||||
.checkout(SvnTarget.fromURL(SVNURL.parseURIEncoded(url)), target, revision, depth, ignoreExternals, format, handler);
|
||||
.checkout(SvnTarget.fromURL(SVNURL.parseURIEncoded(url)), target, revision, depth, ignoreExternals, true, format, handler);
|
||||
ProgressManager.checkCanceled();
|
||||
checkoutSuccessful.set(Boolean.TRUE);
|
||||
}
|
||||
@@ -168,22 +173,10 @@ public class SvnCheckoutProvider implements CheckoutProvider {
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean promptForWCFormatAndSelect(final File target, final Project project) {
|
||||
final WorkingCopyFormat result = promptForWCopyFormat(target, project);
|
||||
if (result != WorkingCopyFormat.UNKNOWN) {
|
||||
SvnWorkingCopyFormatHolder.setPresetFormat(result);
|
||||
}
|
||||
return result != WorkingCopyFormat.UNKNOWN;
|
||||
}
|
||||
|
||||
@CalledInAwt
|
||||
@NotNull
|
||||
private static WorkingCopyFormat promptForWCopyFormat(final File target, final Project project) {
|
||||
WorkingCopyFormat format = WorkingCopyFormat.UNKNOWN;
|
||||
final Ref<Boolean> wasOk = new Ref<Boolean>();
|
||||
while ((format == WorkingCopyFormat.UNKNOWN) && (! Boolean.FALSE.equals(wasOk.get()))) {
|
||||
format = SvnFormatSelector.showUpgradeDialog(target, project, true, WorkingCopyFormat.ONE_DOT_SEVEN, wasOk);
|
||||
}
|
||||
return Boolean.TRUE.equals(wasOk.get()) ? format : WorkingCopyFormat.UNKNOWN;
|
||||
public static WorkingCopyFormat promptForWCopyFormat(final File target, final Project project) {
|
||||
return new CheckoutFormatFromUserProvider(project, target).prompt();
|
||||
}
|
||||
|
||||
public static void doExport(final Project project, final File target, final SVNURL url, final SVNDepth depth,
|
||||
@@ -286,6 +279,79 @@ public class SvnCheckoutProvider implements CheckoutProvider {
|
||||
return "_Subversion";
|
||||
}
|
||||
|
||||
}
|
||||
public static class CheckoutFormatFromUserProvider {
|
||||
|
||||
@NotNull private final Project myProject;
|
||||
@NotNull private final SvnVcs myVcs;
|
||||
@NotNull private final File myPath;
|
||||
|
||||
@NotNull private final AtomicReference<String> error;
|
||||
|
||||
public CheckoutFormatFromUserProvider(@NotNull Project project, @NotNull File path) {
|
||||
myProject = project;
|
||||
myVcs = SvnVcs.getInstance(project);
|
||||
myPath = path;
|
||||
|
||||
error = new AtomicReference<String>();
|
||||
}
|
||||
|
||||
@CalledInAwt
|
||||
public WorkingCopyFormat prompt() {
|
||||
assert !ApplicationManager.getApplication().isUnitTestMode();
|
||||
|
||||
final WorkingCopyFormat result = displayUpgradeDialog(WorkingCopyFormat.ONE_DOT_SEVEN);
|
||||
|
||||
ApplicationManager.getApplication().getMessageBus().syncPublisher(SvnVcs.WC_CONVERTED).run();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private WorkingCopyFormat displayUpgradeDialog(@NotNull WorkingCopyFormat defaultSelection) {
|
||||
final UpgradeFormatDialog dialog = new UpgradeFormatDialog(myProject, myPath, false);
|
||||
dialog.startLoading();
|
||||
|
||||
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final List<WorkingCopyFormat> formats = loadSupportedFormats();
|
||||
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final String errorMessage = error.get();
|
||||
|
||||
if (errorMessage != null) {
|
||||
dialog.doCancelAction();
|
||||
Messages.showErrorDialog(SvnBundle.message("message.text.cannot.load.supported.formats", errorMessage),
|
||||
SvnBundle.message("message.title.check.out"));
|
||||
}
|
||||
else {
|
||||
dialog.setSupported(formats);
|
||||
dialog.setData(ContainerUtil.getFirstItem(formats, WorkingCopyFormat.UNKNOWN));
|
||||
dialog.stopLoading();
|
||||
}
|
||||
}
|
||||
}, ModalityState.stateForComponent(dialog.getWindow()));
|
||||
}
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
|
||||
return dialog.isOK() ? dialog.getUpgradeMode() : WorkingCopyFormat.UNKNOWN;
|
||||
}
|
||||
|
||||
private List<WorkingCopyFormat> loadSupportedFormats() {
|
||||
List<WorkingCopyFormat> result;
|
||||
|
||||
try {
|
||||
result = myVcs.getFactoryFromSettings().createCheckoutClient().getSupportedFormats();
|
||||
}
|
||||
catch (VcsException e) {
|
||||
result = Collections.emptyList();
|
||||
error.set(e.getMessage());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,30 +15,41 @@ import org.tmatesoft.svn.core.wc.SVNUpdateClient;
|
||||
import org.tmatesoft.svn.core.wc2.SvnTarget;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kolosovsky.
|
||||
*/
|
||||
public class SvnKitCheckoutClient extends BaseSvnClient implements CheckoutClient {
|
||||
|
||||
private static final List<WorkingCopyFormat> SUPPORTED_FORMATS;
|
||||
|
||||
static {
|
||||
List<WorkingCopyFormat> supportedFormats = new ArrayList<WorkingCopyFormat>();
|
||||
|
||||
supportedFormats.add(WorkingCopyFormat.ONE_DOT_SEVEN);
|
||||
supportedFormats.add(WorkingCopyFormat.ONE_DOT_SIX);
|
||||
|
||||
SUPPORTED_FORMATS = Collections.unmodifiableList(supportedFormats);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkout(@NotNull SvnTarget source,
|
||||
@NotNull File destination,
|
||||
@Nullable SVNRevision revision,
|
||||
@Nullable SVNDepth depth,
|
||||
boolean ignoreExternals,
|
||||
@Nullable WorkingCopyFormat format,
|
||||
boolean force,
|
||||
@NotNull WorkingCopyFormat format,
|
||||
@Nullable ISVNEventHandler handler) throws VcsException {
|
||||
assertUrl(source);
|
||||
|
||||
if (WorkingCopyFormat.ONE_DOT_EIGHT.equals(format)) {
|
||||
throw new IllegalArgumentException("could not check out 1.8 format with SVNKit");
|
||||
}
|
||||
validateFormat(format, getSupportedFormats());
|
||||
|
||||
SVNUpdateClient client = myVcs.createUpdateClient();
|
||||
|
||||
// TODO: most likely we should compare directly with WorkingCopyFormat.ONE_DOT_SIX
|
||||
if (!WorkingCopyFormat.ONE_DOT_SEVEN.equals(format)) {
|
||||
if (WorkingCopyFormat.ONE_DOT_SIX.equals(format)) {
|
||||
client.getOperationsFactory().setPrimaryWcGeneration(SvnWcGeneration.V16);
|
||||
}
|
||||
|
||||
@@ -46,10 +57,15 @@ public class SvnKitCheckoutClient extends BaseSvnClient implements CheckoutClien
|
||||
client.setEventHandler(handler);
|
||||
|
||||
try {
|
||||
client.doCheckout(source.getURL(), destination, source.getPegRevision(), revision, depth, true);
|
||||
client.doCheckout(source.getURL(), destination, source.getPegRevision(), revision, depth, force);
|
||||
}
|
||||
catch (SVNException e) {
|
||||
throw new SvnBindException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<WorkingCopyFormat> getSupportedFormats() throws VcsException {
|
||||
return SUPPORTED_FORMATS;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ public abstract class SvnCommand {
|
||||
private final File myConfigDir;
|
||||
|
||||
private boolean myIsDestroyed;
|
||||
private boolean myNeedsDestroy;
|
||||
private int myExitCode;
|
||||
protected final GeneralCommandLine myCommandLine;
|
||||
private final File myWorkingDirectory;
|
||||
@@ -210,13 +211,31 @@ public abstract class SvnCommand {
|
||||
|
||||
public void destroyProcess() {
|
||||
synchronized (myLock) {
|
||||
if (! myIsDestroyed) {
|
||||
myNeedsDestroy = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ProcessHandler.destroyProcess() implementations could acquire read lock in its implementation - like OSProcessManager.getInstance().
|
||||
* Some commands are called under write lock - which is generally bad idea, but such logic is not refactored yet.
|
||||
* To prevent deadlocks this method should only be called from thread that started the process.
|
||||
*/
|
||||
public void doDestroyProcess() {
|
||||
synchronized (myLock) {
|
||||
if (!myIsDestroyed) {
|
||||
LOG.info("Destroying process by command: " + getCommandText());
|
||||
myIsDestroyed = true;
|
||||
myHandler.destroyProcess();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean needsDestroy() {
|
||||
synchronized (myLock) {
|
||||
return myNeedsDestroy;
|
||||
}
|
||||
}
|
||||
|
||||
public String getCommandText() {
|
||||
synchronized (myLock) {
|
||||
return myCommandLine.getCommandLineString();
|
||||
|
||||
@@ -62,7 +62,8 @@ public class SvnLineCommand extends SvnCommand {
|
||||
public static final String AUTHENTICATION_REALM = "Authentication realm:";
|
||||
public static final String CERTIFICATE_ERROR = "Error validating server certificate for";
|
||||
public static final String PASSPHRASE_FOR = "Passphrase for";
|
||||
public static final String UNABLE_TO_CONNECT = "svn: E170001:";
|
||||
public static final String UNABLE_TO_CONNECT_CODE = "svn: E170001:";
|
||||
public static final String UNABLE_TO_CONNECT_MESSAGE = "Unable to connect to a repository";
|
||||
public static final String CANNOT_AUTHENTICATE_TO_PROXY = "Could not authenticate to proxy server";
|
||||
public static final String AUTHENTICATION_FAILED_MESSAGE = "Authentication failed";
|
||||
|
||||
@@ -216,7 +217,7 @@ public class SvnLineCommand extends SvnCommand {
|
||||
if (errText.startsWith(PASSPHRASE_FOR)) {
|
||||
return new PassphraseCallback(callback, url);
|
||||
}
|
||||
if (errText.startsWith(UNABLE_TO_CONNECT) && errText.contains(CANNOT_AUTHENTICATE_TO_PROXY)) {
|
||||
if (errText.startsWith(UNABLE_TO_CONNECT_CODE) && errText.contains(CANNOT_AUTHENTICATE_TO_PROXY)) {
|
||||
return new ProxyCallback(callback, url);
|
||||
}
|
||||
// http/https protocol invalid credentials
|
||||
@@ -228,6 +229,10 @@ public class SvnLineCommand extends SvnCommand {
|
||||
// svn protocol invalid credentials
|
||||
return new UsernamePasswordCallback(callback, url);
|
||||
}
|
||||
// http/https protocol, svn 1.7, non-interactive
|
||||
if (errText.contains(UNABLE_TO_CONNECT_MESSAGE)) {
|
||||
return new UsernamePasswordCallback(callback, url);
|
||||
}
|
||||
// https one-way protocol untrusted server certificate
|
||||
if (errText.contains(UNTRUSTED_SERVER_CERTIFICATE)) {
|
||||
return new CertificateCallbackCase(callback, url);
|
||||
@@ -469,23 +474,13 @@ public class SvnLineCommand extends SvnCommand {
|
||||
final String trim = text.trim();
|
||||
// should end in 1 second
|
||||
errorReceived.set(true);
|
||||
// TODO: destroy process here is called despite --non-interactive flag (so it is called even for 1.8) and then unnecessary
|
||||
// TODO: cleanup is invoked - fix this
|
||||
if (trim.startsWith(UNABLE_TO_CONNECT)) {
|
||||
// wait for 3 lines of text then
|
||||
if (myErrCnt >= 3) {
|
||||
destroyProcess();
|
||||
}
|
||||
} else if (trim.startsWith(PASSPHRASE_FOR) || myErrCnt >= 2) {
|
||||
destroyProcess();
|
||||
}
|
||||
}
|
||||
super.onTextAvailable(text, outputType);
|
||||
}
|
||||
};
|
||||
|
||||
//command.addParameters("--non-interactive");
|
||||
command.addParameters(parameters);
|
||||
command.addParameters("--non-interactive");
|
||||
final AtomicReference<Throwable> exceptionRef = new AtomicReference<Throwable>();
|
||||
// several threads
|
||||
command.addLineListener(new LineProcessEventListener() {
|
||||
@@ -503,6 +498,7 @@ public class SvnLineCommand extends SvnCommand {
|
||||
}
|
||||
listener.onLineAvailable(line, outputType);
|
||||
if (listener.isCanceled()) {
|
||||
LOG.info("Cancelling command: " + command.getCommandText());
|
||||
command.destroyProcess();
|
||||
return;
|
||||
}
|
||||
@@ -530,9 +526,9 @@ public class SvnLineCommand extends SvnCommand {
|
||||
boolean finished;
|
||||
do {
|
||||
finished = command.waitFor(500);
|
||||
if (!finished && errorReceived.get()) {
|
||||
if (!finished && (errorReceived.get() || command.needsDestroy())) {
|
||||
command.waitFor(1000);
|
||||
command.destroyProcess();
|
||||
command.doDestroyProcess();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.intellij.openapi.application.ApplicationNamesInfo;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.MultiLineLabelUI;
|
||||
import com.intellij.ui.components.JBLoadingPanel;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -30,6 +31,7 @@ import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class UpgradeFormatDialog extends DialogWrapper {
|
||||
@@ -37,6 +39,8 @@ public class UpgradeFormatDialog extends DialogWrapper {
|
||||
private ButtonGroup formatGroup = new ButtonGroup();
|
||||
private List<JRadioButton> formatButtons = new ArrayList<JRadioButton>();
|
||||
|
||||
private JBLoadingPanel myLoadingPanel;
|
||||
|
||||
protected File myPath;
|
||||
|
||||
public UpgradeFormatDialog(Project project, File path, boolean canBeParent) {
|
||||
@@ -64,7 +68,7 @@ public class UpgradeFormatDialog extends DialogWrapper {
|
||||
return "svn.upgradeDialog";
|
||||
}
|
||||
|
||||
public void setData(final WorkingCopyFormat selectedFormat) {
|
||||
public void setData(@NotNull final WorkingCopyFormat selectedFormat) {
|
||||
for (JRadioButton button : formatButtons) {
|
||||
if (selectedFormat == getFormat(button)) {
|
||||
button.setSelected(true);
|
||||
@@ -73,6 +77,29 @@ public class UpgradeFormatDialog extends DialogWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
public void setSupported(@NotNull Collection<WorkingCopyFormat> supported) {
|
||||
for (JRadioButton button : formatButtons) {
|
||||
button.setEnabled(supported.contains(getFormat(button)));
|
||||
}
|
||||
}
|
||||
|
||||
public void startLoading() {
|
||||
enableFormatButtons(false);
|
||||
getOKAction().setEnabled(false);
|
||||
myLoadingPanel.startLoading();
|
||||
}
|
||||
|
||||
private void enableFormatButtons(boolean enabled) {
|
||||
for (JRadioButton button : formatButtons) {
|
||||
button.setEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
public void stopLoading() {
|
||||
getOKAction().setEnabled(true);
|
||||
myLoadingPanel.stopLoading();
|
||||
}
|
||||
|
||||
protected String getTopMessage(final String label) {
|
||||
return SvnBundle.message("label.configure." + label + ".label", ApplicationNamesInfo.getInstance().getFullProductName());
|
||||
}
|
||||
@@ -115,7 +142,10 @@ public class UpgradeFormatDialog extends DialogWrapper {
|
||||
gb.gridy += 1;
|
||||
}
|
||||
|
||||
return panel;
|
||||
myLoadingPanel = new JBLoadingPanel(new BorderLayout(), getDisposable());
|
||||
myLoadingPanel.add(panel, BorderLayout.CENTER);
|
||||
|
||||
return myLoadingPanel;
|
||||
}
|
||||
|
||||
private void registerFormat(@NotNull WorkingCopyFormat format,
|
||||
|
||||
Reference in New Issue
Block a user