diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java index 9dd190c2d32a..b3d760af19d5 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java @@ -189,6 +189,7 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall (instance.USE_HTTP_PROXY || instance.USE_PROXY_PAC); } + // TODO: not used - should be removed. @Override public boolean persistDataToTmpConfig(final SVNURL repositoryUrl) throws IOException { // TODO: Make repositoryUrl @NotNull after SvnLineCommand.runWithAuthenticationAttempt refactored @@ -208,6 +209,16 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall @Nullable public static Proxy getIdeaDefinedProxy(@NotNull final SVNURL url) { + // SVNKit authentication implementation sets repositories as noProxy() to provide custom proxy authentication logic - see for instance, + // SvnAuthenticationManager.getProxyManager(). But noProxy() setting is not cleared correctly in all cases - so if svn command + // (for command line) is executed on thread where repository url was added as noProxy() => proxies are not retrieved for such commands + // and execution logic is incorrect. + + // To prevent such behavior repositoryUrl is manually removed from noProxy() list (for current thread). + // NOTE, that current method is only called from code flows for executing commands through command line client and should not be called + // from SVNKit code flows. + CommonProxy.getInstance().removeNoProxy(url.getProtocol(), url.getHost(), url.getPort()); + final List proxies = CommonProxy.getInstance().select(URI.create(url.toString())); if (proxies != null && ! proxies.isEmpty()) { for (Proxy proxy : proxies) { @@ -253,6 +264,7 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall return authentication; } + // TODO: not used - should be removed. @Override public boolean askProxyCredentials(SVNURL repositoryUrl) { if (repositoryUrl == null) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandExecutor.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandExecutor.java index ec48f728c622..77b5f29280a7 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandExecutor.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandExecutor.java @@ -45,6 +45,7 @@ public class CommandExecutor { private boolean myIsDestroyed; private boolean myNeedsDestroy; private volatile String myDestroyReason; + private volatile boolean myWasCancelled; protected final GeneralCommandLine myCommandLine; protected Process myProcess; protected OSProcessHandler myHandler; @@ -181,7 +182,7 @@ public class CommandExecutor { boolean finished; do { finished = waitFor(500); - if (!finished && (wasError() || needsDestroy() || wasCancelled())) { + if (!finished && (wasError() || needsDestroy() || checkCancelled())) { waitFor(1000); doDestroyProcess(); break; @@ -204,20 +205,22 @@ public class CommandExecutor { } } - private boolean wasCancelled() { - boolean result = false; - - if (myCommand.getCanceller() != null) { + private boolean checkCancelled() { + if (!myWasCancelled && myCommand.getCanceller() != null) { try { myCommand.getCanceller().checkCancelled(); } catch (SVNCancelException e) { // indicates command should be cancelled - result = true; + myWasCancelled = true; } } - return result; + return myWasCancelled; + } + + public boolean wasCancelled() { + return myWasCancelled; } public void destroyProcess() { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandRuntime.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandRuntime.java index 614121e559e5..cf82da3c545a 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandRuntime.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandRuntime.java @@ -105,7 +105,8 @@ public class CommandRuntime { // handle authentication final String errText = executor.getErrorOutput().trim(); final AuthCallbackCase callback = executor instanceof TerminalExecutor ? null : createCallback(errText, command.getRepositoryUrl()); - if (callback != null) { + // do not handle possible authentication errors if command was manually cancelled + if (!executor.wasCancelled() && callback != null) { if (callback.getCredentials(errText)) { if (myAuthCallback.getSpecialConfigDir() != null) { command.setConfigDir(myAuthCallback.getSpecialConfigDir()); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/ProxyCallback.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/ProxyCallback.java index 508205c83b19..340100dcb3a6 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/ProxyCallback.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/ProxyCallback.java @@ -15,6 +15,7 @@ */ package org.jetbrains.idea.svn.commandLine; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.containers.ContainerUtil; @@ -28,6 +29,8 @@ import java.net.PasswordAuthentication; */ public class ProxyCallback extends AuthCallbackCase { + private static final Logger LOG = Logger.getInstance(ProxyCallback.class); + private static final String CANNOT_AUTHENTICATE_TO_PROXY = "Could not authenticate to proxy server"; private static final String PROXY_AUTHENTICATION_FAILED = "Proxy authentication failed"; @@ -53,6 +56,8 @@ public class ProxyCallback extends AuthCallbackCase { if (myUrl == null) { // TODO: We assume that if repository url is null - command is local and do not require repository access // TODO: Check if this is correct for all cases + LOG.info("Proxy callback could handle error text, but repository url is null", new Throwable()); + result = true; // explicit check if proxies are configured in IDEA is used here not to perform "proxy authentication" for proxies manually // specified by users in svn "servers" file diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/ProxyModule.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/ProxyModule.java index 45097befa516..9e28696829dc 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/ProxyModule.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/ProxyModule.java @@ -15,6 +15,7 @@ */ package org.jetbrains.idea.svn.commandLine; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.svn.IdeaSVNConfigFile; @@ -31,6 +32,8 @@ import java.net.Proxy; */ public class ProxyModule extends BaseCommandRuntimeModule { + private static final Logger LOG = Logger.getInstance(ProxyModule.class); + public ProxyModule(@NotNull CommandRuntime runtime) { super(runtime); } @@ -59,6 +62,8 @@ public class ProxyModule extends BaseCommandRuntimeModule { command.put("--config-option"); command.put(String.format("servers:%s:http-proxy-port=%s", hostGroup, address.getPort())); } + } else { + LOG.info("Configured proxy should be used, but repository url is null for command - " + command.getText()); } }