From 5c315971ca8b61c0865890cffe69a56d4667930d Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 25 Sep 2013 16:19:03 +0400 Subject: [PATCH 01/15] svn: Removed unused parameters from checkout dialog logic --- .../src/org/jetbrains/idea/svn/SvnFormatSelector.java | 5 ++--- .../org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java index 2595631bac4b..0202cb521935 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java @@ -138,14 +138,13 @@ public class SvnFormatSelector implements ISVNAdminAreaFactorySelector { public static WorkingCopyFormat showUpgradeDialog(final File path, final Project project, - final boolean display13format, @NotNull final WorkingCopyFormat defaultSelection, @NotNull final Ref wasOk) { assert ! ApplicationManager.getApplication().isUnitTestMode(); final Ref format = new Ref(defaultSelection); WaitForProgressToShow.runOrInvokeAndWaitAboveProgress(new Runnable() { public void run() { - wasOk.set(displayUpgradeDialog(project, path, display13format, format)); + wasOk.set(displayUpgradeDialog(project, path, format)); } }); ApplicationManager.getApplication().getMessageBus().syncPublisher(SvnVcs.WC_CONVERTED).run(); @@ -190,7 +189,7 @@ public class SvnFormatSelector implements ISVNAdminAreaFactorySelector { return WorkingCopyFormat.getInstance(format); } - private static boolean displayUpgradeDialog(Project project, File path, final boolean dispay13format, Ref format) { + private static boolean displayUpgradeDialog(Project project, File path, Ref format) { UpgradeFormatDialog dialog = new UpgradeFormatDialog(project, path, false); dialog.setData(format.get()); dialog.show(); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java index ff415a0c116f..a748e3f00801 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java @@ -181,7 +181,7 @@ public class SvnCheckoutProvider implements CheckoutProvider { WorkingCopyFormat format = WorkingCopyFormat.UNKNOWN; final Ref wasOk = new Ref(); while ((format == WorkingCopyFormat.UNKNOWN) && (! Boolean.FALSE.equals(wasOk.get()))) { - format = SvnFormatSelector.showUpgradeDialog(target, project, true, WorkingCopyFormat.ONE_DOT_SEVEN, wasOk); + format = SvnFormatSelector.showUpgradeDialog(target, project, WorkingCopyFormat.ONE_DOT_SEVEN, wasOk); } return Boolean.TRUE.equals(wasOk.get()) ? format : WorkingCopyFormat.UNKNOWN; } From c70bab6056bf2956fe74a87ad7a618d65a614f5b Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 25 Sep 2013 18:17:34 +0400 Subject: [PATCH 02/15] svn: Refactored "Upgrade format" dialog logic - use instance instead of static methods --- .../jetbrains/idea/svn/SvnFormatSelector.java | 70 +++++++++++++------ .../svn/checkout/SvnCheckoutProvider.java | 7 +- 2 files changed, 49 insertions(+), 28 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java index 0202cb521935..e9f44d66eee1 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java @@ -136,21 +136,6 @@ public class SvnFormatSelector implements ISVNAdminAreaFactorySelector { return result; } - public static WorkingCopyFormat showUpgradeDialog(final File path, - final Project project, - @NotNull final WorkingCopyFormat defaultSelection, - @NotNull final Ref wasOk) { - assert ! ApplicationManager.getApplication().isUnitTestMode(); - final Ref format = new Ref(defaultSelection); - WaitForProgressToShow.runOrInvokeAndWaitAboveProgress(new Runnable() { - public void run() { - wasOk.set(displayUpgradeDialog(project, path, 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,13 +174,54 @@ public class SvnFormatSelector implements ISVNAdminAreaFactorySelector { return WorkingCopyFormat.getInstance(format); } - private static boolean displayUpgradeDialog(Project project, File path, Ref format) { - UpgradeFormatDialog dialog = new UpgradeFormatDialog(project, path, false); - dialog.setData(format.get()); - dialog.show(); - if (dialog.isOK()) { - format.set(dialog.getUpgradeMode()); + public static class CheckoutFormatFromUserProvider { + + @NotNull private final Project myProject; + @NotNull private final File myPath; + + public CheckoutFormatFromUserProvider(@NotNull Project project, @NotNull File path) { + myProject = project; + myPath = path; + } + + public WorkingCopyFormat prompt() { + WorkingCopyFormat format = WorkingCopyFormat.UNKNOWN; + final Ref wasOk = new Ref(); + + while ((format == WorkingCopyFormat.UNKNOWN) && (!Boolean.FALSE.equals(wasOk.get()))) { + format = showUpgradeDialog(WorkingCopyFormat.ONE_DOT_SEVEN, wasOk); + } + + return Boolean.TRUE.equals(wasOk.get()) ? format : WorkingCopyFormat.UNKNOWN; + } + + public WorkingCopyFormat showUpgradeDialog(@NotNull final WorkingCopyFormat defaultSelection, + @NotNull final Ref wasOk) { + assert !ApplicationManager.getApplication().isUnitTestMode(); + + final Ref format = new Ref(defaultSelection); + + WaitForProgressToShow.runOrInvokeAndWaitAboveProgress(new Runnable() { + public void run() { + wasOk.set(displayUpgradeDialog(format)); + } + }); + + ApplicationManager.getApplication().getMessageBus().syncPublisher(SvnVcs.WC_CONVERTED).run(); + + return format.get(); + } + + private boolean displayUpgradeDialog(@NotNull Ref format) { + UpgradeFormatDialog dialog = new UpgradeFormatDialog(myProject, myPath, false); + + dialog.setData(format.get()); + dialog.show(); + if (dialog.isOK()) { + format.set(dialog.getUpgradeMode()); + } + + return dialog.isOK(); } - return dialog.isOK(); } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java index a748e3f00801..0701c21b4922 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java @@ -178,12 +178,7 @@ public class SvnCheckoutProvider implements CheckoutProvider { @NotNull private static WorkingCopyFormat promptForWCopyFormat(final File target, final Project project) { - WorkingCopyFormat format = WorkingCopyFormat.UNKNOWN; - final Ref wasOk = new Ref(); - while ((format == WorkingCopyFormat.UNKNOWN) && (! Boolean.FALSE.equals(wasOk.get()))) { - format = SvnFormatSelector.showUpgradeDialog(target, project, WorkingCopyFormat.ONE_DOT_SEVEN, wasOk); - } - return Boolean.TRUE.equals(wasOk.get()) ? format : WorkingCopyFormat.UNKNOWN; + return new SvnFormatSelector.CheckoutFormatFromUserProvider(project, target).prompt(); } public static void doExport(final Project project, final File target, final SVNURL url, final SVNDepth depth, From b0bccf747ec8896a5183ec10f95faf98de156dcd Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 25 Sep 2013 18:33:07 +0400 Subject: [PATCH 03/15] svn: Refactored "Share Project" action to show "Working Copy Format" directly in AWT thread (before "run progress synchronously") --- .../idea/svn/actions/ShareProjectAction.java | 17 +++++++++++------ .../idea/svn/checkout/SvnCheckoutProvider.java | 12 +++--------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ShareProjectAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ShareProjectAction.java index 975a1641b0c5..77f466ae93f2 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ShareProjectAction.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ShareProjectAction.java @@ -31,6 +31,7 @@ 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.idea.svn.*; import org.jetbrains.idea.svn.checkout.SvnCheckoutProvider; @@ -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; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java index 0701c21b4922..9596b1159f26 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java @@ -26,6 +26,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; @@ -168,16 +169,9 @@ 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) { + public static WorkingCopyFormat promptForWCopyFormat(final File target, final Project project) { return new SvnFormatSelector.CheckoutFormatFromUserProvider(project, target).prompt(); } From 1b49ff3395d1d5996853666a43ff1a992b7028a0 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 25 Sep 2013 18:59:31 +0400 Subject: [PATCH 04/15] svn: Simplified logic for showing "Working Copy Format" dialog for checkout/share project (as dialog is only shown from AWT thread) --- .../jetbrains/idea/svn/SvnFormatSelector.java | 35 ++++--------------- 1 file changed, 7 insertions(+), 28 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java index e9f44d66eee1..0561822236ca 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java @@ -18,8 +18,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 com.intellij.openapi.vcs.CalledInAwt; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.dialogs.UpgradeFormatDialog; @@ -184,44 +183,24 @@ public class SvnFormatSelector implements ISVNAdminAreaFactorySelector { myPath = path; } + @CalledInAwt public WorkingCopyFormat prompt() { - WorkingCopyFormat format = WorkingCopyFormat.UNKNOWN; - final Ref wasOk = new Ref(); - - while ((format == WorkingCopyFormat.UNKNOWN) && (!Boolean.FALSE.equals(wasOk.get()))) { - format = showUpgradeDialog(WorkingCopyFormat.ONE_DOT_SEVEN, wasOk); - } - - return Boolean.TRUE.equals(wasOk.get()) ? format : WorkingCopyFormat.UNKNOWN; - } - - public WorkingCopyFormat showUpgradeDialog(@NotNull final WorkingCopyFormat defaultSelection, - @NotNull final Ref wasOk) { assert !ApplicationManager.getApplication().isUnitTestMode(); - final Ref format = new Ref(defaultSelection); - - WaitForProgressToShow.runOrInvokeAndWaitAboveProgress(new Runnable() { - public void run() { - wasOk.set(displayUpgradeDialog(format)); - } - }); + final WorkingCopyFormat result = displayUpgradeDialog(WorkingCopyFormat.ONE_DOT_SEVEN); ApplicationManager.getApplication().getMessageBus().syncPublisher(SvnVcs.WC_CONVERTED).run(); - return format.get(); + return result; } - private boolean displayUpgradeDialog(@NotNull Ref format) { + private WorkingCopyFormat displayUpgradeDialog(@NotNull WorkingCopyFormat defaultSelection) { UpgradeFormatDialog dialog = new UpgradeFormatDialog(myProject, myPath, false); - dialog.setData(format.get()); + dialog.setData(defaultSelection); dialog.show(); - if (dialog.isOK()) { - format.set(dialog.getUpgradeMode()); - } - return dialog.isOK(); + return dialog.isOK() ? dialog.getUpgradeMode() : WorkingCopyFormat.UNKNOWN; } } } From 15713d4a784b9dfa0cf8609a71446e2ee20d52c8 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 25 Sep 2013 19:03:33 +0400 Subject: [PATCH 05/15] svn: Moved logic to show "Working Copy Format" dialog to SvnCheckoutProvider --- .../jetbrains/idea/svn/SvnFormatSelector.java | 35 ------------------- .../svn/checkout/SvnCheckoutProvider.java | 33 ++++++++++++++++- 2 files changed, 32 insertions(+), 36 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java index 0561822236ca..12513893c5af 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java @@ -17,11 +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.vcs.CalledInAwt; -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; @@ -172,35 +168,4 @@ public class SvnFormatSelector implements ISVNAdminAreaFactorySelector { return WorkingCopyFormat.getInstance(format); } - - public static class CheckoutFormatFromUserProvider { - - @NotNull private final Project myProject; - @NotNull private final File myPath; - - public CheckoutFormatFromUserProvider(@NotNull Project project, @NotNull File path) { - myProject = project; - myPath = path; - } - - @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) { - UpgradeFormatDialog dialog = new UpgradeFormatDialog(myProject, myPath, false); - - dialog.setData(defaultSelection); - dialog.show(); - - return dialog.isOK() ? dialog.getUpgradeMode() : WorkingCopyFormat.UNKNOWN; - } - } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java index 9596b1159f26..8607c037110a 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java @@ -43,6 +43,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; @@ -172,7 +173,7 @@ public class SvnCheckoutProvider implements CheckoutProvider { @CalledInAwt @NotNull public static WorkingCopyFormat promptForWCopyFormat(final File target, final Project project) { - return new SvnFormatSelector.CheckoutFormatFromUserProvider(project, target).prompt(); + return new CheckoutFormatFromUserProvider(project, target).prompt(); } public static void doExport(final Project project, final File target, final SVNURL url, final SVNDepth depth, @@ -275,6 +276,36 @@ public class SvnCheckoutProvider implements CheckoutProvider { return "_Subversion"; } + public static class CheckoutFormatFromUserProvider { + + @NotNull private final Project myProject; + @NotNull private final File myPath; + + public CheckoutFormatFromUserProvider(@NotNull Project project, @NotNull File path) { + myProject = project; + myPath = path; + } + + @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) { + UpgradeFormatDialog dialog = new UpgradeFormatDialog(myProject, myPath, false); + + dialog.setData(defaultSelection); + dialog.show(); + + return dialog.isOK() ? dialog.getUpgradeMode() : WorkingCopyFormat.UNKNOWN; + } + } } From aa86ffad0a4a67cc969b13cc0e02da6fc93d1f0b Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 25 Sep 2013 20:17:44 +0400 Subject: [PATCH 06/15] svn: Made checkout logic show only working copy formats supported by the current client (SVNKit or command line determined from settings) --- .../jetbrains/idea/svn/SvnBundle.properties | 1 + .../jetbrains/idea/svn/WorkingCopyFormat.java | 14 +++++ .../idea/svn/checkout/CheckoutClient.java | 3 + .../idea/svn/checkout/CmdCheckoutClient.java | 11 ++++ .../svn/checkout/SvnCheckoutProvider.java | 58 +++++++++++++++++-- .../svn/checkout/SvnKitCheckoutClient.java | 19 ++++++ .../idea/svn/dialogs/UpgradeFormatDialog.java | 34 ++++++++++- 7 files changed, 133 insertions(+), 7 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBundle.properties b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBundle.properties index bbb8e54c6704..65de1e5bc8d3 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBundle.properties +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBundle.properties @@ -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 diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/WorkingCopyFormat.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/WorkingCopyFormat.java index 041ee2811a63..d4a12e3b08ad 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/WorkingCopyFormat.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/WorkingCopyFormat.java @@ -100,4 +100,18 @@ 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; + } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CheckoutClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CheckoutClient.java index e7aa0299a00d..97099bcf035f 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CheckoutClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CheckoutClient.java @@ -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. @@ -24,4 +25,6 @@ public interface CheckoutClient extends SvnClient { boolean ignoreExternals, @Nullable WorkingCopyFormat format, @Nullable ISVNEventHandler handler) throws VcsException; + + List getSupportedFormats() throws VcsException; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CmdCheckoutClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CmdCheckoutClient.java index fe22fc817182..1bcc559649cc 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CmdCheckoutClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CmdCheckoutClient.java @@ -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; @@ -43,6 +44,16 @@ public class CmdCheckoutClient extends BaseSvnClient implements CheckoutClient { run(source, destination, handler, parameters); } + @Override + public List getSupportedFormats() throws VcsException { + ArrayList result = new ArrayList(); + + Version version = myFactory.createVersionClient().getVersion(); + result.add(WorkingCopyFormat.from(version)); + + return result; + } + private void run(@NotNull SvnTarget source, @NotNull File destination, @Nullable ISVNEventHandler handler, diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java index 8607c037110a..e75e9ba675e8 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java @@ -35,6 +35,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.*; @@ -53,6 +55,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 { @@ -279,11 +284,17 @@ public class SvnCheckoutProvider implements CheckoutProvider { public static class CheckoutFormatFromUserProvider { @NotNull private final Project myProject; + @NotNull private final SvnVcs myVcs; @NotNull private final File myPath; + @NotNull private final AtomicReference error; + public CheckoutFormatFromUserProvider(@NotNull Project project, @NotNull File path) { myProject = project; + myVcs = SvnVcs.getInstance(project); myPath = path; + + error = new AtomicReference(); } @CalledInAwt @@ -298,14 +309,51 @@ public class SvnCheckoutProvider implements CheckoutProvider { } private WorkingCopyFormat displayUpgradeDialog(@NotNull WorkingCopyFormat defaultSelection) { - UpgradeFormatDialog dialog = new UpgradeFormatDialog(myProject, myPath, false); + final UpgradeFormatDialog dialog = new UpgradeFormatDialog(myProject, myPath, false); + dialog.startLoading(); + + ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { + @Override + public void run() { + final List formats = loadSupportedFormats(); + + UIUtil.invokeLaterIfNeeded(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(); + } + } + }); + } + }); - dialog.setData(defaultSelection); dialog.show(); return dialog.isOK() ? dialog.getUpgradeMode() : WorkingCopyFormat.UNKNOWN; } + + private List loadSupportedFormats() { + List result; + + try { + result = myVcs.getFactoryFromSettings().createCheckoutClient().getSupportedFormats(); + } + catch (VcsException e) { + result = Collections.emptyList(); + error.set(e.getMessage()); + } + + return result; + } } -} - - +} \ No newline at end of file diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnKitCheckoutClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnKitCheckoutClient.java index ba46ec832b87..9759c3ebe787 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnKitCheckoutClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnKitCheckoutClient.java @@ -15,12 +15,26 @@ 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 SUPPORTED_FORMATS; + + static { + List supportedFormats = new ArrayList(); + + 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, @@ -52,4 +66,9 @@ public class SvnKitCheckoutClient extends BaseSvnClient implements CheckoutClien throw new SvnBindException(e); } } + + @Override + public List getSupportedFormats() throws VcsException { + return SUPPORTED_FORMATS; + } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/UpgradeFormatDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/UpgradeFormatDialog.java index cb2fcdaba0f1..28645fd623eb 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/UpgradeFormatDialog.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/UpgradeFormatDialog.java @@ -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 formatButtons = new ArrayList(); + 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 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, From 1d16caa8a0d4e5d7caa63a8ee935714642ca07c7 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Thu, 26 Sep 2013 14:37:36 +0400 Subject: [PATCH 07/15] svn: Made working copy format @NotNull in checkout client --- .../src/org/jetbrains/idea/svn/checkout/CheckoutClient.java | 2 +- .../src/org/jetbrains/idea/svn/checkout/CmdCheckoutClient.java | 2 +- .../org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java | 1 + .../org/jetbrains/idea/svn/checkout/SvnKitCheckoutClient.java | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CheckoutClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CheckoutClient.java index 97099bcf035f..71e0d32ba306 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CheckoutClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CheckoutClient.java @@ -23,7 +23,7 @@ public interface CheckoutClient extends SvnClient { @Nullable SVNRevision revision, @Nullable SVNDepth depth, boolean ignoreExternals, - @Nullable WorkingCopyFormat format, + @NotNull WorkingCopyFormat format, @Nullable ISVNEventHandler handler) throws VcsException; List getSupportedFormats() throws VcsException; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CmdCheckoutClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CmdCheckoutClient.java index 1bcc559649cc..b67f8d429b0f 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CmdCheckoutClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CmdCheckoutClient.java @@ -28,7 +28,7 @@ public class CmdCheckoutClient extends BaseSvnClient implements CheckoutClient { @Nullable SVNRevision revision, @Nullable SVNDepth depth, boolean ignoreExternals, - @Nullable WorkingCopyFormat format, + @NotNull WorkingCopyFormat format, @Nullable ISVNEventHandler handler) throws VcsException { List parameters = new ArrayList(); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java index e75e9ba675e8..63e3fb35cb95 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java @@ -98,6 +98,7 @@ public class SvnCheckoutProvider implements CheckoutProvider { WorkingCopyFormat format = !WorkingCopyFormat.ONE_DOT_SEVEN.equals(SvnWorkingCopyFormatHolder.getPresetFormat()) ? WorkingCopyFormat.ONE_DOT_SIX : selectedFormat; + format = format == null ? WorkingCopyFormat.UNKNOWN : format; ISVNEventHandler handler = new CheckoutEventHandler(vcs, false, ProgressManager.getInstance().getProgressIndicator()); ProgressManager.progress(SvnBundle.message("progress.text.checking.out", target.getAbsolutePath())); try { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnKitCheckoutClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnKitCheckoutClient.java index 9759c3ebe787..023b40bff9c4 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnKitCheckoutClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnKitCheckoutClient.java @@ -41,7 +41,7 @@ public class SvnKitCheckoutClient extends BaseSvnClient implements CheckoutClien @Nullable SVNRevision revision, @Nullable SVNDepth depth, boolean ignoreExternals, - @Nullable WorkingCopyFormat format, + @NotNull WorkingCopyFormat format, @Nullable ISVNEventHandler handler) throws VcsException { assertUrl(source); From 0c676b6f85faf1612f9b52acc922117f64042df4 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Thu, 26 Sep 2013 14:44:16 +0400 Subject: [PATCH 08/15] svn: Added supported format validation to checkout clients --- .../org/jetbrains/idea/svn/WorkingCopyFormat.java | 5 +++++ .../org/jetbrains/idea/svn/api/BaseSvnClient.java | 12 ++++++++++++ .../idea/svn/checkout/CmdCheckoutClient.java | 4 ++-- .../idea/svn/checkout/SvnKitCheckoutClient.java | 5 +---- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/WorkingCopyFormat.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/WorkingCopyFormat.java index d4a12e3b08ad..595abe10a83c 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/WorkingCopyFormat.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/WorkingCopyFormat.java @@ -114,4 +114,9 @@ public enum WorkingCopyFormat { return result; } + + @Override + public String toString() { + return getName(); + } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java index 133bc6489c4e..e6bca33d617f 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java @@ -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 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, ","))); + } + } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CmdCheckoutClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CmdCheckoutClient.java index b67f8d429b0f..29eaa8d99958 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CmdCheckoutClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CmdCheckoutClient.java @@ -30,9 +30,9 @@ public class CmdCheckoutClient extends BaseSvnClient implements CheckoutClient { boolean ignoreExternals, @NotNull WorkingCopyFormat format, @Nullable ISVNEventHandler handler) throws VcsException { - List parameters = new ArrayList(); + validateFormat(format, getSupportedFormats()); - // TODO: check format + List parameters = new ArrayList(); CommandUtil.put(parameters, source); CommandUtil.put(parameters, destination, false); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnKitCheckoutClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnKitCheckoutClient.java index 023b40bff9c4..3f330b798bc1 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnKitCheckoutClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnKitCheckoutClient.java @@ -44,10 +44,7 @@ public class SvnKitCheckoutClient extends BaseSvnClient implements CheckoutClien @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(); From b49b08dd244c5c551af74c2695a1010392e0473b Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Thu, 26 Sep 2013 14:56:35 +0400 Subject: [PATCH 09/15] svn: Fixed checkout logic that assumed only 1.6 and 1.7 formats are known --- .../idea/svn/checkout/SvnCheckoutProvider.java | 10 +++------- .../idea/svn/checkout/SvnKitCheckoutClient.java | 3 +-- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java index 63e3fb35cb95..fb1851bbe407 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java @@ -91,18 +91,14 @@ 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; - format = format == null ? WorkingCopyFormat.UNKNOWN : format; 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); ProgressManager.checkCanceled(); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnKitCheckoutClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnKitCheckoutClient.java index 3f330b798bc1..a8caab2310c7 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnKitCheckoutClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnKitCheckoutClient.java @@ -48,8 +48,7 @@ public class SvnKitCheckoutClient extends BaseSvnClient implements CheckoutClien 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); } From ebba545cfe466c5728e1d52a278c6b8c221ef181 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Thu, 26 Sep 2013 15:18:41 +0400 Subject: [PATCH 10/15] svn: Updated invokeLater for checkout dialog to use modality state --- .../org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java index fb1851bbe407..a361f6eb881d 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java @@ -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; @@ -314,7 +315,7 @@ public class SvnCheckoutProvider implements CheckoutProvider { public void run() { final List formats = loadSupportedFormats(); - UIUtil.invokeLaterIfNeeded(new Runnable() { + ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { final String errorMessage = error.get(); @@ -330,7 +331,7 @@ public class SvnCheckoutProvider implements CheckoutProvider { dialog.stopLoading(); } } - }); + }, ModalityState.stateForComponent(dialog.getWindow())); } }); From 052bd9ad66318aee93e441155f67bc0511e232eb Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Thu, 26 Sep 2013 20:14:21 +0400 Subject: [PATCH 11/15] IDEA-113934 Ensure ProcessHandler.destroyProcess() is not called from thread other than started the process (as some code flows lead to deadlock - destroy requires read lock, but command was called under write lock) --- .../idea/svn/commandLine/SvnCommand.java | 21 ++++++++++++++++++- .../idea/svn/commandLine/SvnLineCommand.java | 4 ++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommand.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommand.java index 2f667d363067..8ae61d51df22 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommand.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommand.java @@ -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(); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnLineCommand.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnLineCommand.java index 9cf56bbd5500..6e4c1cf31aa3 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnLineCommand.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnLineCommand.java @@ -530,9 +530,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; } } From 6da60f1dd7dce2bd66f4898d7baa80bc84fa13a6 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Thu, 26 Sep 2013 20:20:49 +0400 Subject: [PATCH 12/15] IDEA-113934 Forced all calls to svn command line be non-interactive (corresponding destroy process logic udpated) --- .../idea/svn/commandLine/SvnLineCommand.java | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnLineCommand.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnLineCommand.java index 6e4c1cf31aa3..d859d58dc040 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnLineCommand.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnLineCommand.java @@ -469,23 +469,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 exceptionRef = new AtomicReference(); // several threads command.addLineListener(new LineProcessEventListener() { @@ -503,6 +493,7 @@ public class SvnLineCommand extends SvnCommand { } listener.onLineAvailable(line, outputType); if (listener.isCanceled()) { + LOG.info("Cancelling command: " + command.getCommandText()); command.destroyProcess(); return; } From 6f46313fa0472c3bfdc2a1a80288d0f4b1e4c318 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Thu, 26 Sep 2013 20:25:28 +0400 Subject: [PATCH 13/15] svn: Fixed http/https authentication for svn 1.7 command line in non-interactive mode --- .../jetbrains/idea/svn/commandLine/SvnLineCommand.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnLineCommand.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnLineCommand.java index d859d58dc040..75ff08525af4 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnLineCommand.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnLineCommand.java @@ -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); From c64c4eca8f54255e4228152c2d316fd6d3c0e341 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Thu, 26 Sep 2013 20:36:22 +0400 Subject: [PATCH 14/15] svn: Added "force" parameter to checkout client --- .../src/org/jetbrains/idea/svn/checkout/CheckoutClient.java | 1 + .../src/org/jetbrains/idea/svn/checkout/CmdCheckoutClient.java | 3 ++- .../org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java | 2 +- .../org/jetbrains/idea/svn/checkout/SvnKitCheckoutClient.java | 3 ++- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CheckoutClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CheckoutClient.java index 71e0d32ba306..b31d0da1dc48 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CheckoutClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CheckoutClient.java @@ -23,6 +23,7 @@ public interface CheckoutClient extends SvnClient { @Nullable SVNRevision revision, @Nullable SVNDepth depth, boolean ignoreExternals, + boolean force, @NotNull WorkingCopyFormat format, @Nullable ISVNEventHandler handler) throws VcsException; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CmdCheckoutClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CmdCheckoutClient.java index 29eaa8d99958..6e151e4a6ae8 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CmdCheckoutClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CmdCheckoutClient.java @@ -28,6 +28,7 @@ public class CmdCheckoutClient extends BaseSvnClient implements CheckoutClient { @Nullable SVNRevision revision, @Nullable SVNDepth depth, boolean ignoreExternals, + boolean force, @NotNull WorkingCopyFormat format, @Nullable ISVNEventHandler handler) throws VcsException { validateFormat(format, getSupportedFormats()); @@ -39,7 +40,7 @@ public class CmdCheckoutClient extends BaseSvnClient implements CheckoutClient { 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); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java index a361f6eb881d..4e703ddee543 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java @@ -101,7 +101,7 @@ public class SvnCheckoutProvider implements CheckoutProvider { ProgressManager.progress(SvnBundle.message("progress.text.checking.out", target.getAbsolutePath())); try { 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); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnKitCheckoutClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnKitCheckoutClient.java index a8caab2310c7..54e9063e1937 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnKitCheckoutClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnKitCheckoutClient.java @@ -41,6 +41,7 @@ public class SvnKitCheckoutClient extends BaseSvnClient implements CheckoutClien @Nullable SVNRevision revision, @Nullable SVNDepth depth, boolean ignoreExternals, + boolean force, @NotNull WorkingCopyFormat format, @Nullable ISVNEventHandler handler) throws VcsException { assertUrl(source); @@ -56,7 +57,7 @@ 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); From 6210db9c82f1d764f60121ebc10db39f1e0c4ef2 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Thu, 26 Sep 2013 21:12:23 +0400 Subject: [PATCH 15/15] svn: Implemented "Share Project" action for command line --- .../src/org/jetbrains/idea/svn/SvnUtil.java | 1 + .../idea/svn/actions/ShareProjectAction.java | 32 ++++++++++--------- .../actions/SvnExcludingIgnoredOperation.java | 14 ++++---- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java index 07301c0829f1..083bb7840cdf 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java @@ -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); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ShareProjectAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ShareProjectAction.java index 77f466ae93f2..99b2e0cc8449 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ShareProjectAction.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ShareProjectAction.java @@ -33,17 +33,17 @@ 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; @@ -105,7 +105,7 @@ public class ShareProjectAction extends BasicAction { final String parent = shareDialog.getSelectedURL(); if (shareDialog.isOK() && parent != null) { final Ref actionStarted = new Ref(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(); @@ -165,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); @@ -231,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)); @@ -242,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); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnExcludingIgnoredOperation.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnExcludingIgnoredOperation.java index f60e553332e3..49fdc0279dd5 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnExcludingIgnoredOperation.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnExcludingIgnoredOperation.java @@ -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; } }