diff options
Diffstat (limited to 'plugins/svn4idea')
36 files changed, 312 insertions, 340 deletions
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java index aaf46003c1dd..cd0a321d5a58 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java @@ -790,7 +790,9 @@ public class SvnUtil { e.contains(SVNErrorCode.UNVERSIONED_RESOURCE) || e.contains(SVNErrorCode.WC_NOT_WORKING_COPY) || // thrown when getting info from repository for non-existent item - like HEAD revision for deleted file - e.contains(SVNErrorCode.ILLEGAL_TARGET); + e.contains(SVNErrorCode.ILLEGAL_TARGET) || + // for svn 1.6 + StringUtil.containsIgnoreCase(e.getMessage(), "(not a versioned resource)"); } // TODO: Create custom Target class and implement append there diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java index e5018f3319d5..f4f3ee98f549 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java @@ -32,6 +32,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Trinity; +import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.vcs.*; import com.intellij.openapi.vcs.annotate.AnnotationProvider; import com.intellij.openapi.vcs.changes.*; @@ -63,10 +64,7 @@ import org.jetbrains.idea.svn.actions.CleanupWorker; import org.jetbrains.idea.svn.actions.ShowPropertiesDiffWithLocalAction; import org.jetbrains.idea.svn.actions.SvnMergeProvider; import org.jetbrains.idea.svn.annotate.SvnAnnotationProvider; -import org.jetbrains.idea.svn.api.ClientFactory; -import org.jetbrains.idea.svn.api.CmdClientFactory; -import org.jetbrains.idea.svn.api.Depth; -import org.jetbrains.idea.svn.api.SvnKitClientFactory; +import org.jetbrains.idea.svn.api.*; import org.jetbrains.idea.svn.auth.SvnAuthenticationNotifier; import org.jetbrains.idea.svn.branchConfig.SvnLoadedBranchesStorage; import org.jetbrains.idea.svn.checkin.SvnCheckinEnvironment; @@ -264,13 +262,7 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> { } public boolean checkCommandLineVersion() { - boolean isValid = true; - - if (!isProject16() && (myConfiguration.isCommandLine() || isProject18OrGreater())) { - isValid = myChecker.checkExecutableAndNotifyIfNeeded(); - } - - return isValid; + return getFactory() != cmdClientFactory || myChecker.checkExecutableAndNotifyIfNeeded(); } public void invokeRefreshSvnRoots() { @@ -922,13 +914,9 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> { @Override public boolean isVcsBackgroundOperationsAllowed(@NotNull VirtualFile root) { - // TODO: Currently myAuthNotifier.isAuthenticatedFor directly uses SVNKit to check credentials - so assume for now that background - // TODO: operations are always allowed for command line. As sometimes this leads to errors - for instance, incoming changes are not - // TODO: displayed in "Incoming" tab - incoming changes are collected using command line but not displayed because - // TODO: SvnVcs.isVcsBackgroundOperationsAllowed is false. ClientFactory factory = getFactory(VfsUtilCore.virtualToIoFile(root)); - return factory == cmdClientFactory || ThreeState.YES.equals(myAuthNotifier.isAuthenticatedFor(root)); + return ThreeState.YES.equals(myAuthNotifier.isAuthenticatedFor(root, factory == cmdClientFactory ? factory : null)); } public SvnBranchPointsCalculator getSvnBranchPointsCalculator() { @@ -953,14 +941,6 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> { return svnKitManager; } - public boolean isProject18OrGreater() { - return getProjectRootFormat().isOrGreater(WorkingCopyFormat.ONE_DOT_EIGHT); - } - - public boolean isProject16() { - return WorkingCopyFormat.ONE_DOT_SIX.equals(getProjectRootFormat()); - } - @NotNull private WorkingCopyFormat getProjectRootFormat() { return !getProject().isDefault() ? getWorkingCopyFormat(new File(getProject().getBaseDir().getPath())) : WorkingCopyFormat.UNKNOWN; @@ -1000,12 +980,13 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> { @NotNull private ClientFactory getFactory(@NotNull WorkingCopyFormat format, boolean useProjectRootForUnknown) { boolean is18OrGreater = format.isOrGreater(WorkingCopyFormat.ONE_DOT_EIGHT); - boolean is16 = WorkingCopyFormat.ONE_DOT_SIX.equals(format); boolean isUnknown = WorkingCopyFormat.UNKNOWN.equals(format); return is18OrGreater ? cmdClientFactory - : (is16 ? svnKitClientFactory : (useProjectRootForUnknown && isUnknown ? getFactory() : getFactoryFromSettings())); + : (!isUnknown && !isSupportedByCommandLine(format) + ? svnKitClientFactory + : (useProjectRootForUnknown && isUnknown ? getFactory() : getFactoryFromSettings())); } @NotNull @@ -1037,4 +1018,26 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> { public ClientFactory getSvnKitFactory() { return svnKitClientFactory; } + + @NotNull + public WorkingCopyFormat getLowestSupportedFormatForCommandLine() { + WorkingCopyFormat result; + + try { + result = WorkingCopyFormat.from(CmdVersionClient.parseVersion(Registry.stringValue("svn.lowest.supported.format.for.command.line"))); + } + catch (SvnBindException ignore) { + result = WorkingCopyFormat.ONE_DOT_SEVEN; + } + + return result; + } + + public boolean isSupportedByCommandLine(@NotNull WorkingCopyFormat format) { + return format.isOrGreater(getLowestSupportedFormatForCommandLine()); + } + + public boolean is16SupportedByCommandLine() { + return isSupportedByCommandLine(WorkingCopyFormat.ONE_DOT_SIX); + } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/WorkingCopy.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/WorkingCopy.java index 9b6530e3a914..0a23df56daad 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/WorkingCopy.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/WorkingCopy.java @@ -15,25 +15,29 @@ */ package org.jetbrains.idea.svn; +import org.jetbrains.annotations.NotNull; import org.tmatesoft.svn.core.SVNURL; import java.io.File; public class WorkingCopy { private final boolean myIs17Copy; - private final File myFile; - private final SVNURL myUrl; + @NotNull private final File myFile; + @NotNull private final SVNURL myUrl; - public WorkingCopy(File file, SVNURL url, boolean is17Copy) { + // TODO: is17Copy is currently true in all constructor usages - remove this field and revise is17Copy() usages + public WorkingCopy(@NotNull File file, @NotNull SVNURL url, boolean is17Copy) { myFile = file; myUrl = url; myIs17Copy = is17Copy; } + @NotNull public File getFile() { return myFile; } + @NotNull public SVNURL getUrl() { return myUrl; } 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 0d58355543ba..01689e586f81 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java @@ -6,13 +6,16 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.WorkingCopyFormat; -import org.jetbrains.idea.svn.auth.IdeaSvnkitBasedAuthenticationCallback; +import org.jetbrains.idea.svn.auth.AuthenticationService; import org.jetbrains.idea.svn.commandLine.*; import org.jetbrains.idea.svn.diff.DiffOptions; import org.tmatesoft.svn.core.SVNCancelException; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNException; -import org.tmatesoft.svn.core.wc.*; +import org.tmatesoft.svn.core.wc.ISVNEventHandler; +import org.tmatesoft.svn.core.wc.SVNDiffOptions; +import org.tmatesoft.svn.core.wc.SVNEvent; +import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; import java.io.File; @@ -25,6 +28,7 @@ import java.util.List; public abstract class BaseSvnClient implements SvnClient { protected SvnVcs myVcs; protected ClientFactory myFactory; + protected boolean myIsActive; @NotNull @Override @@ -48,6 +52,11 @@ public abstract class BaseSvnClient implements SvnClient { myFactory = factory; } + @Override + public void setIsActive(boolean isActive) { + myIsActive = isActive; + } + protected void assertUrl(@NotNull SvnTarget target) { if (!target.isURL()) { throw new IllegalArgumentException("Target should be url " + target); @@ -74,31 +83,22 @@ public abstract class BaseSvnClient implements SvnClient { } } - /** - * Utility method for running commands. - * // TODO: Should be replaced with non-static analogue. - * - * @param vcs - * @param target - * @param name - * @param parameters - * @param listener - * @throws com.intellij.openapi.vcs.VcsException - */ - public static CommandExecutor execute(@NotNull SvnVcs vcs, - @NotNull SvnTarget target, - @NotNull SvnCommandName name, - @NotNull List<String> parameters, - @Nullable LineCommandListener listener) throws SvnBindException { + @NotNull + public CommandExecutor execute(@NotNull SvnVcs vcs, + @NotNull SvnTarget target, + @NotNull SvnCommandName name, + @NotNull List<String> parameters, + @Nullable LineCommandListener listener) throws SvnBindException { return execute(vcs, target, null, name, parameters, listener); } - public static CommandExecutor execute(@NotNull SvnVcs vcs, - @NotNull SvnTarget target, - @Nullable File workingDirectory, - @NotNull SvnCommandName name, - @NotNull List<String> parameters, - @Nullable LineCommandListener listener) throws SvnBindException { + @NotNull + public CommandExecutor execute(@NotNull SvnVcs vcs, + @NotNull SvnTarget target, + @Nullable File workingDirectory, + @NotNull SvnCommandName name, + @NotNull List<String> parameters, + @Nullable LineCommandListener listener) throws SvnBindException { Command command = new Command(name); command.setTarget(target); @@ -106,7 +106,7 @@ public abstract class BaseSvnClient implements SvnClient { command.setResultBuilder(listener); command.put(parameters); - CommandRuntime runtime = new CommandRuntime(vcs, new IdeaSvnkitBasedAuthenticationCallback(vcs)); + CommandRuntime runtime = new CommandRuntime(vcs, new AuthenticationService(vcs, myIsActive)); return runtime.runWithAuthenticationAttempt(command); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java index ba3e56de8e63..4eb5f8b0c7b7 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java @@ -1,5 +1,7 @@ package org.jetbrains.idea.svn.api; +import com.intellij.util.ReflectionUtil; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnVcs; @@ -18,17 +20,19 @@ import org.jetbrains.idea.svn.copy.CopyMoveClient; import org.jetbrains.idea.svn.delete.DeleteClient; import org.jetbrains.idea.svn.diff.DiffClient; import org.jetbrains.idea.svn.history.HistoryClient; +import org.jetbrains.idea.svn.info.InfoClient; import org.jetbrains.idea.svn.integrate.MergeClient; import org.jetbrains.idea.svn.lock.LockClient; -import org.jetbrains.idea.svn.info.InfoClient; -import org.jetbrains.idea.svn.status.StatusClient; import org.jetbrains.idea.svn.properties.PropertyClient; import org.jetbrains.idea.svn.revert.RevertClient; +import org.jetbrains.idea.svn.status.StatusClient; import org.jetbrains.idea.svn.update.RelocateClient; import org.jetbrains.idea.svn.update.UpdateClient; import org.jetbrains.idea.svn.upgrade.UpgradeClient; import org.tmatesoft.svn.core.wc.ISVNStatusFileProvider; +import java.util.Map; + /** * @author Konstantin Kolosovsky. */ @@ -63,6 +67,8 @@ public abstract class ClientFactory { protected CheckinClient myCheckinClient; protected RepositoryFeaturesClient myRepositoryFeaturesClient; + @NotNull private final Map<Class, Class> myClientImplementations = ContainerUtil.newHashMap(); + protected ClientFactory(@NotNull SvnVcs vcs) { myVcs = vcs; setup(); @@ -70,6 +76,33 @@ public abstract class ClientFactory { protected abstract void setup(); + protected <T extends SvnClient> void put(@NotNull Class<T> type, @NotNull Class<? extends T> implementation) { + myClientImplementations.put(type, implementation); + } + + @SuppressWarnings("unchecked") + @NotNull + protected <T extends SvnClient> Class<? extends T> get(@NotNull Class<T> type) { + Class<? extends T> implementation = myClientImplementations.get(type); + + if (implementation == null) { + throw new IllegalArgumentException("No implementation registered for " + type); + } + + return implementation; + } + + /** + * TODO: Provide more robust way for the default settings here - probably some default Command instance could be used. + */ + @NotNull + public <T extends SvnClient> T create(@NotNull Class<T> type, boolean isActive) { + T client = prepare(ReflectionUtil.newInstance(get(type))); + client.setIsActive(isActive); + + return client; + } + @NotNull public AddClient createAddClient() { return prepare(addClient); @@ -209,6 +242,7 @@ public abstract class ClientFactory { protected <T extends SvnClient> T prepare(@NotNull T client) { client.setVcs(myVcs); client.setFactory(this); + client.setIsActive(true); return client; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java index 54639b9e120b..6a5b9e8076f2 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java @@ -4,6 +4,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.add.CmdAddClient; import org.jetbrains.idea.svn.annotate.CmdAnnotateClient; +import org.jetbrains.idea.svn.browse.BrowseClient; import org.jetbrains.idea.svn.browse.CmdBrowseClient; import org.jetbrains.idea.svn.change.CmdChangeListClient; import org.jetbrains.idea.svn.checkin.CmdCheckinClient; @@ -11,18 +12,19 @@ import org.jetbrains.idea.svn.checkin.CmdImportClient; import org.jetbrains.idea.svn.checkout.CmdCheckoutClient; import org.jetbrains.idea.svn.checkout.CmdExportClient; import org.jetbrains.idea.svn.cleanup.CmdCleanupClient; -import org.jetbrains.idea.svn.status.CmdStatusClient; -import org.jetbrains.idea.svn.info.CmdInfoClient; import org.jetbrains.idea.svn.conflict.CmdConflictClient; import org.jetbrains.idea.svn.content.CmdContentClient; import org.jetbrains.idea.svn.copy.CmdCopyMoveClient; import org.jetbrains.idea.svn.delete.CmdDeleteClient; import org.jetbrains.idea.svn.diff.CmdDiffClient; import org.jetbrains.idea.svn.history.CmdHistoryClient; +import org.jetbrains.idea.svn.info.CmdInfoClient; +import org.jetbrains.idea.svn.info.InfoClient; import org.jetbrains.idea.svn.integrate.CmdMergeClient; import org.jetbrains.idea.svn.lock.CmdLockClient; import org.jetbrains.idea.svn.properties.CmdPropertyClient; import org.jetbrains.idea.svn.revert.CmdRevertClient; +import org.jetbrains.idea.svn.status.CmdStatusClient; import org.jetbrains.idea.svn.update.CmdRelocateClient; import org.jetbrains.idea.svn.update.CmdUpdateClient; import org.jetbrains.idea.svn.update.UpdateClient; @@ -64,6 +66,9 @@ public class CmdClientFactory extends ClientFactory { statusClient = new CmdStatusClient(); infoClient = new CmdInfoClient(); myRepositoryFeaturesClient = new CmdRepositoryFeaturesClient(); + + put(BrowseClient.class, CmdBrowseClient.class); + put(InfoClient.class, CmdInfoClient.class); } @NotNull diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdVersionClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdVersionClient.java index c3acfdc7c561..5b1484944285 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdVersionClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdVersionClient.java @@ -2,7 +2,6 @@ package org.jetbrains.idea.svn.api; import com.intellij.execution.process.ProcessOutput; import com.intellij.openapi.util.Version; -import com.intellij.openapi.vcs.VcsException; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.svn.SvnApplicationSettings; import org.jetbrains.idea.svn.commandLine.Command; @@ -22,7 +21,7 @@ public class CmdVersionClient extends BaseSvnClient implements VersionClient { @NotNull @Override - public Version getVersion() throws VcsException { + public Version getVersion() throws SvnBindException { return parseVersion(runCommand()); } @@ -38,9 +37,9 @@ public class CmdVersionClient extends BaseSvnClient implements VersionClient { } @NotNull - private static Version parseVersion(@NotNull ProcessOutput output) throws VcsException { + private static Version parseVersion(@NotNull ProcessOutput output) throws SvnBindException { if (output.isTimeout() || (output.getExitCode() != 0) || !output.getStderr().isEmpty()) { - throw new VcsException( + throw new SvnBindException( String.format("Exit code: %d, Error: %s, Timeout: %b", output.getExitCode(), output.getStderr(), output.isTimeout())); } @@ -48,7 +47,7 @@ public class CmdVersionClient extends BaseSvnClient implements VersionClient { } @NotNull - public static Version parseVersion(@NotNull String versionText) throws VcsException { + public static Version parseVersion(@NotNull String versionText) throws SvnBindException { Version result = null; Exception cause = null; @@ -65,7 +64,7 @@ public class CmdVersionClient extends BaseSvnClient implements VersionClient { } if (!found || cause != null) { - throw new VcsException(String.format("Could not parse svn version: %s", versionText), cause); + throw new SvnBindException(String.format("Could not parse svn version: %s", versionText), cause); } return result; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnClient.java index fcf100f62513..14bc054a4127 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnClient.java @@ -17,4 +17,6 @@ public interface SvnClient { void setVcs(@NotNull SvnVcs vcs); void setFactory(@NotNull ClientFactory factory); + + void setIsActive(boolean isActive); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java index f46f5f06ebdb..95b17d95add8 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java @@ -5,6 +5,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.add.SvnKitAddClient; import org.jetbrains.idea.svn.annotate.SvnKitAnnotateClient; +import org.jetbrains.idea.svn.browse.BrowseClient; import org.jetbrains.idea.svn.browse.SvnKitBrowseClient; import org.jetbrains.idea.svn.change.SvnKitChangeListClient; import org.jetbrains.idea.svn.checkin.SvnKitCheckinClient; @@ -67,6 +68,8 @@ public class SvnKitClientFactory extends ClientFactory { statusClient = new SvnKitStatusClient(); infoClient = new SvnKitInfoClient(); myRepositoryFeaturesClient = new SvnKitRepositoryFeaturesClient(); + + put(BrowseClient.class, SvnKitBrowseClient.class); } @NotNull diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitVersionClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitVersionClient.java index 084f7f79d946..d0f5da5ad491 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitVersionClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitVersionClient.java @@ -1,7 +1,6 @@ package org.jetbrains.idea.svn.api; import com.intellij.openapi.util.Version; -import com.intellij.openapi.vcs.VcsException; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.svn.WorkingCopyFormat; @@ -12,7 +11,7 @@ public class SvnKitVersionClient extends BaseSvnClient implements VersionClient @NotNull @Override - public Version getVersion() throws VcsException { + public Version getVersion() { return WorkingCopyFormat.ONE_DOT_SEVEN.getVersion(); } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/VersionClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/VersionClient.java index bbd70921d7a0..a37cbc17b13a 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/VersionClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/VersionClient.java @@ -1,8 +1,8 @@ package org.jetbrains.idea.svn.api; import com.intellij.openapi.util.Version; -import com.intellij.openapi.vcs.VcsException; import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.commandLine.SvnBindException; /** * @author Konstantin Kolosovsky. @@ -10,5 +10,5 @@ import org.jetbrains.annotations.NotNull; public interface VersionClient extends SvnClient { @NotNull - Version getVersion() throws VcsException; + Version getVersion() throws SvnBindException; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/AbstractAuthenticator.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/AbstractAuthenticator.java index 203265dea263..0c11d5a488e6 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/AbstractAuthenticator.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/AbstractAuthenticator.java @@ -39,16 +39,16 @@ abstract class AbstractAuthenticator { private static final Logger LOG = Logger.getInstance(AbstractAuthenticator.class); - @NotNull protected final IdeaSvnkitBasedAuthenticationCallback myAuthService; + @NotNull protected final AuthenticationService myAuthenticationService; @NotNull protected final SvnVcs myVcs; @NotNull protected final SVNURL myUrl; protected final String myRealm; protected boolean myStoreInUsual; protected SvnAuthenticationManager myTmpDirManager; - AbstractAuthenticator(@NotNull IdeaSvnkitBasedAuthenticationCallback authService, @NotNull SVNURL url, String realm) { - myAuthService = authService; - myVcs = myAuthService.getVcs(); + AbstractAuthenticator(@NotNull AuthenticationService authenticationService, @NotNull SVNURL url, String realm) { + myAuthenticationService = authenticationService; + myVcs = myAuthenticationService.getVcs(); myUrl = url; myRealm = realm; } @@ -58,7 +58,7 @@ abstract class AbstractAuthenticator { final SvnAuthenticationManager active = myVcs.getSvnConfiguration().getAuthenticationManager(myVcs); try { - boolean authenticated = getWithPassive(passive) || getWithActive(active); + boolean authenticated = getWithPassive(passive) || (myAuthenticationService.isActive() && getWithActive(active)); if (!authenticated) return false; SvnAuthenticationManager manager = myStoreInUsual ? active : createTmpManager(); @@ -80,8 +80,8 @@ abstract class AbstractAuthenticator { @NotNull protected SvnAuthenticationManager createTmpManager() throws IOException { if (myTmpDirManager == null) { - myAuthService.initTmpDir(myVcs.getSvnConfiguration()); - myTmpDirManager = new SvnAuthenticationManager(myVcs.getProject(), myAuthService.getTempDirectory()); + myAuthenticationService.initTmpDir(myVcs.getSvnConfiguration()); + myTmpDirManager = new SvnAuthenticationManager(myVcs.getProject(), myAuthenticationService.getTempDirectory()); myTmpDirManager.setRuntimeStorage(SvnConfiguration.RUNTIME_AUTH_CACHE); myTmpDirManager.setAuthenticationProvider(new SvnInteractiveAuthenticationProvider(myVcs, myTmpDirManager)); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/IdeaSvnkitBasedAuthenticationCallback.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/AuthenticationService.java index 5b77f78aa7e1..9fb377e1dafe 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/IdeaSvnkitBasedAuthenticationCallback.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/AuthenticationService.java @@ -20,7 +20,6 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.ui.popup.util.PopupUtil; import com.intellij.openapi.util.Getter; -import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.io.FileUtil; import com.intellij.util.WaitForProgressToShow; @@ -32,7 +31,6 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnBundle; import org.jetbrains.idea.svn.SvnConfiguration; import org.jetbrains.idea.svn.SvnVcs; -import org.jetbrains.idea.svn.commandLine.AuthenticationCallback; import org.jetbrains.idea.svn.dialogs.SimpleCredentialsDialog; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager; @@ -52,16 +50,19 @@ import java.util.Set; * Date: 2/26/13 * Time: 1:27 PM */ -public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCallback { +public class AuthenticationService { + @NotNull private final SvnVcs myVcs; - private static final Logger LOG = Logger.getInstance(IdeaSvnkitBasedAuthenticationCallback.class); + private final boolean myIsActive; + private static final Logger LOG = Logger.getInstance(AuthenticationService.class); private File myTempDirectory; private boolean myProxyCredentialsWereReturned; private SvnConfiguration myConfiguration; private final Set<String> myRequestedCredentials; - public IdeaSvnkitBasedAuthenticationCallback(@NotNull SvnVcs vcs) { + public AuthenticationService(@NotNull SvnVcs vcs, boolean isActive) { myVcs = vcs; + myIsActive = isActive; myConfiguration = SvnConfiguration.getInstance(myVcs.getProject()); myRequestedCredentials = ContainerUtil.newHashSet(); } @@ -76,8 +77,11 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall return myTempDirectory; } - @Override - public boolean authenticateFor(String realm, SVNURL repositoryUrl, boolean previousFailed, boolean passwordRequest) { + public boolean isActive() { + return myIsActive; + } + + public boolean authenticateFor(@Nullable String realm, SVNURL repositoryUrl, boolean passwordRequest) { if (repositoryUrl == null) { return false; } @@ -85,20 +89,17 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall } @Nullable - @Override public SVNAuthentication requestCredentials(final SVNURL repositoryUrl, final String type) { SVNAuthentication authentication = null; if (repositoryUrl != null) { final String realm = repositoryUrl.toDecodedString(); - authentication = requestCredentials(realm, type, new Getter<Pair<SVNAuthentication, Boolean>>() { + authentication = requestCredentials(realm, type, new Getter<SVNAuthentication>() { @Override - public Pair<SVNAuthentication, Boolean> get() { - SVNAuthentication result = myVcs.getSvnConfiguration().getInteractiveManager(myVcs).getInnerProvider() + public SVNAuthentication get() { + return myVcs.getSvnConfiguration().getInteractiveManager(myVcs).getInnerProvider() .requestClientAuthentication(type, repositoryUrl, realm, null, null, true); - - return new Pair<SVNAuthentication, Boolean>(result, true); } }); } @@ -111,8 +112,8 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall } @Nullable - private <T> T requestCredentials(@NotNull String realm, @NotNull String type, @NotNull Getter<Pair<T, Boolean>> fromUserProvider) { - T result; + private <T> T requestCredentials(@NotNull String realm, @NotNull String type, @NotNull Getter<T> fromUserProvider) { + T result = null; // Search for stored credentials not only by key but also by "parent" keys. This is useful when we work just with URLs // (not working copy) and can't detect repository url beforehand because authentication is required. If found credentials of "parent" // are not correct then current key will already be stored in myRequestedCredentials - thus user will be asked for credentials and @@ -126,12 +127,10 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall result = (T)data; myRequestedCredentials.add(key); } - else { + else if (myIsActive) { // ask user for credentials - Pair<T, Boolean> userData = fromUserProvider.get(); - result = userData.first; - - if (result != null && userData.second) { + result = fromUserProvider.get(); + if (result != null) { // save user credentials to memory cache myVcs.getSvnConfiguration().acknowledge(type, realm, result); myRequestedCredentials.add(key); @@ -141,14 +140,13 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall return result; } - @Override @Nullable public String requestSshCredentials(@NotNull final String realm, @NotNull final SimpleCredentialsDialog.Mode mode, @NotNull final String key) { - return requestCredentials(realm, ISVNAuthenticationManager.SSH, new Getter<Pair<String, Boolean>>() { + return requestCredentials(realm, ISVNAuthenticationManager.SSH, new Getter<String>() { @Override - public Pair<String, Boolean> get() { + public String get() { final Ref<String> answer = new Ref<String>(); Runnable command = new Runnable() { @@ -169,12 +167,11 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall // the thread that started progress WaitForProgressToShow.runOrInvokeAndWaitAboveProgress(command, ModalityState.any()); - return new Pair<String, Boolean>(answer.get(), true); + return answer.get(); } }); } - @Override public boolean acceptSSLServerCertificate(final SVNURL repositoryUrl, final String realm) { if (repositoryUrl == null) { return false; @@ -183,7 +180,6 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall return new SSLServerCertificateAuthenticator(this, repositoryUrl, realm).tryAuthenticate(); } - @Override public void clearPassiveCredentials(String realm, SVNURL repositoryUrl, boolean password) { if (repositoryUrl == null) { return; @@ -197,7 +193,6 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall } } - @Override public boolean haveDataForTmpConfig() { final HttpConfigurable instance = HttpConfigurable.getInstance(); return SvnConfiguration.getInstance(myVcs.getProject()).isIsUseDefaultProxy() && @@ -227,7 +222,6 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall return null; } - @Override @Nullable public PasswordAuthentication getProxyAuthentication(@NotNull SVNURL repositoryUrl) { Proxy proxy = getIdeaDefinedProxy(repositoryUrl); @@ -296,7 +290,6 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall } @Nullable - @Override public File getSpecialConfigDir() { return myTempDirectory != null ? myTempDirectory : new File(myConfiguration.getConfigurationDirectory()); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/CredentialsAuthenticator.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/CredentialsAuthenticator.java index 410cb0997201..9658e2adbba7 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/CredentialsAuthenticator.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/CredentialsAuthenticator.java @@ -37,14 +37,12 @@ class CredentialsAuthenticator extends AbstractAuthenticator { private String myRealm2; private SVNAuthentication myAuthentication; - CredentialsAuthenticator(@NotNull IdeaSvnkitBasedAuthenticationCallback authService, - @NotNull SVNURL url, - @Nullable String realm) { - super(authService, url, realm == null ? url.getHost() : realm); + CredentialsAuthenticator(@NotNull AuthenticationService authenticationService, @NotNull SVNURL url, @Nullable String realm) { + super(authenticationService, url, realm == null ? url.getHost() : realm); } public boolean tryAuthenticate(boolean passwordRequest) { - final List<String> kinds = IdeaSvnkitBasedAuthenticationCallback.getKinds(myUrl, passwordRequest); + final List<String> kinds = AuthenticationService.getKinds(myUrl, passwordRequest); for (String kind : kinds) { myKind = kind; if (!tryAuthenticate()) { @@ -58,8 +56,8 @@ class CredentialsAuthenticator extends AbstractAuthenticator { protected boolean getWithPassive(SvnAuthenticationManager passive) throws SVNException { myAuthentication = getWithPassiveImpl(passive); if (myAuthentication != null && !checkAuthOk(myAuthentication)) { - myAuthService.clearPassiveCredentials(myRealm, myUrl, - myAuthentication instanceof SVNPasswordAuthentication); //clear passive also take into acconut ssl filepath + //clear passive also take into account ssl file path + myAuthenticationService.clearPassiveCredentials(myRealm, myUrl, myAuthentication instanceof SVNPasswordAuthentication); myAuthentication = null; } return myAuthentication != null; @@ -88,7 +86,7 @@ class CredentialsAuthenticator extends AbstractAuthenticator { if (super.getWithActive(active)) return true; } myAuthentication = active.getProvider().requestClientAuthentication(myKind, myUrl, myRealm, null, null, true); - myStoreInUsual = myAuthService.getTempDirectory() == null && myAuthentication != null && myAuthentication.isStorageAllowed(); + myStoreInUsual = myAuthenticationService.getTempDirectory() == null && myAuthentication != null && myAuthentication.isStorageAllowed(); return myAuthentication != null; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/SSLServerCertificateAuthenticator.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/SSLServerCertificateAuthenticator.java index 3b78aa55d867..7d76a1fa0536 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/SSLServerCertificateAuthenticator.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/SSLServerCertificateAuthenticator.java @@ -41,10 +41,8 @@ class SSLServerCertificateAuthenticator extends AbstractAuthenticator { private int myResult; private SVNAuthentication myAuthentication; - SSLServerCertificateAuthenticator(@NotNull IdeaSvnkitBasedAuthenticationCallback authService, - @NotNull SVNURL url, - String realm) { - super(authService, url, realm); + SSLServerCertificateAuthenticator(@NotNull AuthenticationService authenticationService, @NotNull SVNURL url, String realm) { + super(authenticationService, url, realm); } @Override @@ -102,7 +100,7 @@ class SSLServerCertificateAuthenticator extends AbstractAuthenticator { myCertificate = createCertificate(stored); myCertificateRealm = myRealm; } - if (myAuthService.getTempDirectory() != null && myCertificate != null) { + if (myAuthenticationService.getTempDirectory() != null && myCertificate != null) { storeServerCertificate(); if (myAuthentication != null) { @@ -142,7 +140,7 @@ class SSLServerCertificateAuthenticator extends AbstractAuthenticator { } int failures = SVNSSLUtil.getServerCertificateFailures(x509Certificate, myUrl.getHost()); - storeServerCertificate(myAuthService.getTempDirectory(), myCertificateRealm, stored, failures); + storeServerCertificate(myAuthenticationService.getTempDirectory(), myCertificateRealm, stored, failures); } private void storeServerCertificate(final File configDir, String realm, String data, int failures) throws SVNException { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/SvnAuthenticationNotifier.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/SvnAuthenticationNotifier.java index ffc21a011334..29f15423e581 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/SvnAuthenticationNotifier.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/SvnAuthenticationNotifier.java @@ -44,6 +44,10 @@ import com.intellij.util.proxy.CommonProxy; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.*; +import org.jetbrains.idea.svn.api.ClientFactory; +import org.jetbrains.idea.svn.commandLine.SvnBindException; +import org.jetbrains.idea.svn.info.Info; +import org.jetbrains.idea.svn.info.InfoClient; import org.tmatesoft.svn.core.SVNAuthenticationException; import org.tmatesoft.svn.core.SVNCancelException; import org.tmatesoft.svn.core.SVNException; @@ -172,6 +176,7 @@ public class SvnAuthenticationNotifier extends GenericNotifierImpl<SvnAuthentica } log("on state changed "); ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override public void run() { for (SVNURL key : outdatedRequests) { removeLazyNotificationByKey(key); @@ -223,7 +228,7 @@ public class SvnAuthenticationNotifier extends GenericNotifierImpl<SvnAuthentica /** * Bases on presence of notifications! */ - public ThreeState isAuthenticatedFor(@NotNull VirtualFile vf) { + public ThreeState isAuthenticatedFor(@NotNull VirtualFile vf, @Nullable ClientFactory factory) { final WorkingCopy wcCopy = myRootsToWorkingCopies.getWcRoot(vf); if (wcCopy == null) return ThreeState.UNSURE; @@ -236,11 +241,24 @@ public class SvnAuthenticationNotifier extends GenericNotifierImpl<SvnAuthentica if (Boolean.FALSE.equals(keptResult)) return ThreeState.NO; // check have credentials - final boolean calculatedResult = passiveValidation(myVcs.getProject(), wcCopy.getUrl()); + final boolean calculatedResult = + factory == null ? passiveValidation(myVcs.getProject(), wcCopy.getUrl()) : passiveValidation(factory, wcCopy.getUrl()); myCopiesPassiveResults.put(wcCopy.getUrl(), calculatedResult); return calculatedResult ? ThreeState.YES : ThreeState.NO; } + private static boolean passiveValidation(@NotNull ClientFactory factory, @NotNull SVNURL url) { + Info info = null; + + try { + info = factory.create(InfoClient.class, false).doInfo(url, SVNRevision.UNDEFINED, SVNRevision.UNDEFINED); + } + catch (SvnBindException ignore) { + } + + return info != null; + } + @NotNull @Override protected String getNotificationContent(AuthenticationRequest obj) { @@ -470,6 +488,7 @@ public class SvnAuthenticationNotifier extends GenericNotifierImpl<SvnAuthentica final File authDir = new File(configuration.getConfigurationDirectory(), "auth"); if (authDir.exists()) { final Runnable process = new Runnable() { + @Override public void run() { final ProgressIndicator ind = ProgressManager.getInstance().getProgressIndicator(); if (ind != null) { @@ -477,7 +496,8 @@ public class SvnAuthenticationNotifier extends GenericNotifierImpl<SvnAuthentica ind.setText("Clearing stored credentials in " + authDir.getAbsolutePath()); } final File[] files = authDir.listFiles(new FilenameFilter() { - public boolean accept(File dir, String name) { + @Override + public boolean accept(@NotNull File dir, @NotNull String name) { return ourAuthKinds.contains(name); } }); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchesLoader.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchesLoader.java index ba0288da9699..a51ce8c13629 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchesLoader.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchesLoader.java @@ -21,13 +21,13 @@ import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; -import org.jetbrains.idea.svn.SvnConfiguration; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.api.Depth; +import org.jetbrains.idea.svn.browse.BrowseClient; import org.jetbrains.idea.svn.browse.DirectoryEntry; import org.jetbrains.idea.svn.browse.DirectoryEntryConsumer; -import org.tmatesoft.svn.core.*; -import org.tmatesoft.svn.core.wc.SVNLogClient; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; @@ -75,23 +75,13 @@ public class BranchesLoader implements Runnable { @NotNull public List<SvnBranchItem> loadBranches() throws SVNException, VcsException { - final SvnConfiguration configuration = SvnConfiguration.getInstance(myProject); - final SvnVcs vcs = SvnVcs.getInstance(myProject); + SvnVcs vcs = SvnVcs.getInstance(myProject); SVNURL branchesUrl = SVNURL.parseURIEncoded(myUrl); List<SvnBranchItem> result = new LinkedList<SvnBranchItem>(); SvnTarget target = SvnTarget.fromURL(branchesUrl); + DirectoryEntryConsumer handler = createConsumer(result); - if (!myPassive) { - // TODO: Implement ability to specify interactive/non-interactive auth mode for clients - DirectoryEntryConsumer handler = createConsumer(branchesUrl, result); - vcs.getFactory(target).createBrowseClient().list(target, SVNRevision.HEAD, Depth.IMMEDIATES, handler); - } - else { - ISVNDirEntryHandler handler = createHandler(branchesUrl, result); - SVNLogClient client = vcs.getSvnKitManager().createLogClient(configuration.getPassiveAuthenticationManager(myProject)); - client - .doList(target.getURL(), target.getPegRevision(), SVNRevision.HEAD, false, SVNDepth.IMMEDIATES, SVNDirEntry.DIRENT_ALL, handler); - } + vcs.getFactory(target).create(BrowseClient.class, !myPassive).list(target, SVNRevision.HEAD, Depth.IMMEDIATES, handler); Collections.sort(result); return result; @@ -105,25 +95,12 @@ public class BranchesLoader implements Runnable { } @NotNull - private static ISVNDirEntryHandler createHandler(@NotNull final SVNURL branchesUrl, @NotNull final List<SvnBranchItem> result) { - return new ISVNDirEntryHandler() { - public void handleDirEntry(final SVNDirEntry dirEntry) throws SVNException { - // TODO: Remove equality check with branchesUrl when SVNLogClient will not be used directly, but rather through BrowseClient. - if (!branchesUrl.equals(dirEntry.getURL()) && dirEntry.getDate() != null) { - result.add(new SvnBranchItem(dirEntry.getURL().toDecodedString(), dirEntry.getDate(), dirEntry.getRevision())); - } - } - }; - } - - @NotNull - private static DirectoryEntryConsumer createConsumer(@NotNull final SVNURL branchesUrl, @NotNull final List<SvnBranchItem> result) { + private static DirectoryEntryConsumer createConsumer(@NotNull final List<SvnBranchItem> result) { return new DirectoryEntryConsumer() { @Override public void consume(final DirectoryEntry entry) throws SVNException { - // TODO: Remove equality check with branchesUrl when SVNLogClient will not be used directly, but rather through BrowseClient. - if (!branchesUrl.equals(entry.getUrl()) && entry.getDate() != null) { + if (entry.getDate() != null) { result.add(new SvnBranchItem(entry.getUrl().toDecodedString(), entry.getDate(), entry.getRevision())); } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/browse/SvnKitBrowseClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/browse/SvnKitBrowseClient.java index cdbb1ff1e67b..ac1d4a0486df 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/browse/SvnKitBrowseClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/browse/SvnKitBrowseClient.java @@ -23,6 +23,7 @@ import org.jetbrains.idea.svn.api.BaseSvnClient; import org.jetbrains.idea.svn.api.Depth; import org.jetbrains.idea.svn.commandLine.SvnBindException; import org.tmatesoft.svn.core.*; +import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager; import org.tmatesoft.svn.core.wc.SVNLogClient; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; @@ -38,7 +39,7 @@ public class SvnKitBrowseClient extends BaseSvnClient implements BrowseClient { @Nullable DirectoryEntryConsumer handler) throws VcsException { assertUrl(target); - SVNLogClient client = myVcs.getSvnKitManager().createLogClient(); + SVNLogClient client = getLogClient(); ISVNDirEntryHandler wrappedHandler = wrapHandler(handler); try { @@ -69,6 +70,15 @@ public class SvnKitBrowseClient extends BaseSvnClient implements BrowseClient { } } + @NotNull + private SVNLogClient getLogClient() { + ISVNAuthenticationManager authManager = myIsActive + ? myVcs.getSvnConfiguration().getInteractiveManager(myVcs) + : myVcs.getSvnConfiguration().getPassiveAuthenticationManager(myVcs.getProject()); + + return myVcs.getSvnKitManager().createLogClient(authManager); + } + @Nullable private static ISVNDirEntryHandler wrapHandler(@Nullable DirectoryEntryConsumer handler) { return handler == null ? null : new SkipEmptyNameDirectoriesHandler(handler); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/AuthCallbackCase.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/AuthCallbackCase.java index 8a55a6e89860..77cca02a04fb 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/AuthCallbackCase.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/AuthCallbackCase.java @@ -16,6 +16,7 @@ package org.jetbrains.idea.svn.commandLine; import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.auth.AuthenticationService; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; @@ -25,10 +26,10 @@ import org.tmatesoft.svn.core.SVNURL; public abstract class AuthCallbackCase { protected final SVNURL myUrl; protected boolean myTried = false; - @NotNull protected final AuthenticationCallback myAuthenticationCallback; + @NotNull protected final AuthenticationService myAuthenticationService; - AuthCallbackCase(@NotNull AuthenticationCallback callback, SVNURL url) { - myAuthenticationCallback = callback; + AuthCallbackCase(@NotNull AuthenticationService authenticationService, SVNURL url) { + myAuthenticationService = authenticationService; myUrl = url; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/AuthenticationCallback.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/AuthenticationCallback.java deleted file mode 100644 index 11fb831803bb..000000000000 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/AuthenticationCallback.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2000-2013 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.idea.svn.commandLine; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.svn.dialogs.SimpleCredentialsDialog; -import org.tmatesoft.svn.core.SVNURL; -import org.tmatesoft.svn.core.auth.SVNAuthentication; - -import java.io.File; -import java.net.PasswordAuthentication; - -/** - * Passed for authentication purpose to SvnLineCommand - * Called when svn command indicates that it needs credentials. It also means that credential was not found in standard place - * (Subversion config directory) - * - * Implementations should 1) ask credential from user or take it from any other storage (memory, for instance) - * 2) write credential in Subversion standard form into - * a) standard config directory if user allowed to save *all* credentials - * b) TMP directory and return path to the directory from getSpecialConfigDir() - if user rejected at least one credential storing - * - * Please note that several credentials could be asked during the command and therefore implementation class is used as - * keeping its state, and that TMP directory should be reused for all written credentials - * - * User: Irina.Chernushina - * Date: 2/26/13 - * Time: 1:05 PM - */ -public interface AuthenticationCallback { - /** - * Authenticate for realm and base file belonging to corresponding working copy - * - * @param realm - realm that should be used for credential retrieval/storage. - * @param repositoryUrl - * @param previousFailed - whether previous credentials were correct - * @param passwordRequest - if true, password should be asked. Otherwise that may be a certificate (determined by the protocol) - * @return false if authentication canceled or was unsuccessful - */ - boolean authenticateFor(@Nullable String realm, SVNURL repositoryUrl, boolean previousFailed, boolean passwordRequest); - - /** - * Provides authentication information to access given url by authentication protocol identified by type. - * For instance, username/password for http/svn protocols. SSL client certificate for two way SSL protocol. - * - * @param repositoryUrl - * @param type authentication protocol type with svn specific values, like "svn.simple" for http. - * @return - */ - @Nullable - SVNAuthentication requestCredentials(SVNURL repositoryUrl, String type); - - /** - * @return config directory if TMP was created - */ - @Nullable - File getSpecialConfigDir(); - - @Nullable - String requestSshCredentials(@NotNull String realm, - @NotNull SimpleCredentialsDialog.Mode mode, - @NotNull String key); - - /** - * Ask user or read from memory storage whether server certificate should be accepted - * - * @param repositoryUrl - * @param realm - realm that should be used for credential retrieval/storage. - * @return true is certificate was accepted - */ - boolean acceptSSLServerCertificate(SVNURL repositoryUrl, final String realm); - - /** - * Clear credentials stored anywhere - in case they were not full, wrong or anything else - * - * @param realm - required that credential - * @param repositoryUrl - * @param password - whether password credential should be deleted or certificate, if protocol might demand certificate - */ - void clearPassiveCredentials(String realm, SVNURL repositoryUrl, boolean password); - - /** - * @return true if there's something from IDEA config that should be persisted into Subversion tmp config directory - * for successful call - * (now it's IDEA proxy settings) - */ - boolean haveDataForTmpConfig(); - - @Nullable - PasswordAuthentication getProxyAuthentication(@NotNull SVNURL repositoryUrl); - - void reset(); -} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/BaseCommandRuntimeModule.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/BaseCommandRuntimeModule.java index 1b4235d8ffcf..86a27fa393b7 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/BaseCommandRuntimeModule.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/BaseCommandRuntimeModule.java @@ -17,6 +17,7 @@ package org.jetbrains.idea.svn.commandLine; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.svn.SvnVcs; +import org.jetbrains.idea.svn.auth.AuthenticationService; /** * @author Konstantin Kolosovsky. @@ -24,12 +25,12 @@ import org.jetbrains.idea.svn.SvnVcs; public abstract class BaseCommandRuntimeModule implements CommandRuntimeModule { @NotNull protected final CommandRuntime myRuntime; - @NotNull protected final AuthenticationCallback myAuthCallback; + @NotNull protected final AuthenticationService myAuthenticationService; @NotNull protected final SvnVcs myVcs; public BaseCommandRuntimeModule(@NotNull CommandRuntime runtime) { myRuntime = runtime; - myAuthCallback = runtime.getAuthCallback(); + myAuthenticationService = runtime.getAuthenticationService(); myVcs = runtime.getVcs(); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CertificateCallbackCase.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CertificateCallbackCase.java index a63d4544a5f5..f58a775079ed 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CertificateCallbackCase.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CertificateCallbackCase.java @@ -17,6 +17,7 @@ package org.jetbrains.idea.svn.commandLine; import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.auth.AuthenticationService; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; @@ -31,8 +32,8 @@ public class CertificateCallbackCase extends AuthCallbackCase { private boolean accepted; - CertificateCallbackCase(@NotNull AuthenticationCallback callback, SVNURL url) { - super(callback, url); + CertificateCallbackCase(@NotNull AuthenticationService authenticationService, SVNURL url) { + super(authenticationService, url); } @Override @@ -55,7 +56,7 @@ public class CertificateCallbackCase extends AuthCallbackCase { realm = serverUrl != null ? serverUrl.toString() : realm; } - if (!myTried && myAuthenticationCallback.acceptSSLServerCertificate(myUrl, realm)) { + if (!myTried && myAuthenticationService.acceptSSLServerCertificate(myUrl, realm)) { accepted = true; myTried = true; return true; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandParametersResolutionModule.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandParametersResolutionModule.java index e4883549b0aa..e86fdf388a7f 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandParametersResolutionModule.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandParametersResolutionModule.java @@ -43,7 +43,7 @@ public class CommandParametersResolutionModule extends BaseCommandRuntimeModule if (command.getWorkingDirectory() == null) { command.setWorkingDirectory(resolveWorkingDirectory(command)); } - command.setConfigDir(myAuthCallback.getSpecialConfigDir()); + command.setConfigDir(myAuthenticationService.getSpecialConfigDir()); command.saveOriginalParameters(); } 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 5cc66e0a3983..4902891163d6 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandRuntime.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandRuntime.java @@ -24,6 +24,7 @@ import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.*; +import org.jetbrains.idea.svn.auth.AuthenticationService; import org.jetbrains.idea.svn.auth.SvnAuthenticationManager; import org.tmatesoft.svn.core.SVNURL; @@ -37,14 +38,14 @@ public class CommandRuntime { private static final Logger LOG = Logger.getInstance(CommandRuntime.class); - @NotNull private final AuthenticationCallback myAuthCallback; + @NotNull private final AuthenticationService myAuthenticationService; @NotNull private final SvnVcs myVcs; @NotNull private final List<CommandRuntimeModule> myModules; private final String exePath; - public CommandRuntime(@NotNull SvnVcs vcs, @NotNull AuthenticationCallback authCallback) { + public CommandRuntime(@NotNull SvnVcs vcs, @NotNull AuthenticationService authenticationService) { myVcs = vcs; - myAuthCallback = authCallback; + myAuthenticationService = authenticationService; exePath = SvnApplicationSettings.getInstance().getCommandLinePath(); myModules = ContainerUtil.newArrayList(); @@ -130,8 +131,8 @@ public class CommandRuntime { // "infinite" times despite it was cancelled. if (!executor.checkCancelled() && callback != null) { if (callback.getCredentials(errText)) { - if (myAuthCallback.getSpecialConfigDir() != null) { - command.setConfigDir(myAuthCallback.getSpecialConfigDir()); + if (myAuthenticationService.getSpecialConfigDir() != null) { + command.setConfigDir(myAuthenticationService.getSpecialConfigDir()); } callback.updateParameters(command); return true; @@ -153,7 +154,7 @@ public class CommandRuntime { } private void onFinish() { - myAuthCallback.reset(); + myAuthenticationService.reset(); } private static void logNullExitCode(@NotNull CommandExecutor executor, @Nullable Integer exitCode) { @@ -166,12 +167,12 @@ public class CommandRuntime { private AuthCallbackCase createCallback(@NotNull final String errText, @Nullable final SVNURL url) { List<AuthCallbackCase> authCases = ContainerUtil.newArrayList(); - authCases.add(new CertificateCallbackCase(myAuthCallback, url)); - authCases.add(new CredentialsCallback(myAuthCallback, url)); - authCases.add(new PassphraseCallback(myAuthCallback, url)); - authCases.add(new ProxyCallback(myAuthCallback, url)); - authCases.add(new TwoWaySslCallback(myAuthCallback, url)); - authCases.add(new UsernamePasswordCallback(myAuthCallback, url)); + authCases.add(new CertificateCallbackCase(myAuthenticationService, url)); + authCases.add(new CredentialsCallback(myAuthenticationService, url)); + authCases.add(new PassphraseCallback(myAuthenticationService, url)); + authCases.add(new ProxyCallback(myAuthenticationService, url)); + authCases.add(new TwoWaySslCallback(myAuthenticationService, url)); + authCases.add(new UsernamePasswordCallback(myAuthenticationService, url)); return ContainerUtil.find(authCases, new Condition<AuthCallbackCase>() { @Override @@ -242,8 +243,8 @@ public class CommandRuntime { } @NotNull - public AuthenticationCallback getAuthCallback() { - return myAuthCallback; + public AuthenticationService getAuthenticationService() { + return myAuthenticationService; } @NotNull diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CredentialsCallback.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CredentialsCallback.java index 15f3a78aff5d..5304dff13e01 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CredentialsCallback.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CredentialsCallback.java @@ -17,6 +17,7 @@ package org.jetbrains.idea.svn.commandLine; import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.auth.AuthenticationService; import org.tmatesoft.svn.core.SVNURL; /** @@ -26,8 +27,8 @@ public class CredentialsCallback extends AuthCallbackCase { private static final String AUTHENTICATION_REALM = "Authentication realm:"; - CredentialsCallback(@NotNull AuthenticationCallback callback, SVNURL url) { - super(callback, url); + CredentialsCallback(@NotNull AuthenticationService authenticationService, SVNURL url) { + super(authenticationService, url); } @Override @@ -43,10 +44,10 @@ public class CredentialsCallback extends AuthCallbackCase { : null; final boolean isPassword = StringUtil.containsIgnoreCase(errText, "password"); if (myTried) { - myAuthenticationCallback.clearPassiveCredentials(realm, myUrl, isPassword); + myAuthenticationService.clearPassiveCredentials(realm, myUrl, isPassword); } myTried = true; - if (myAuthenticationCallback.authenticateFor(realm, myUrl, myAuthenticationCallback.getSpecialConfigDir() != null, isPassword)) { + if (myAuthenticationService.authenticateFor(realm, myUrl, isPassword)) { return true; } throw new SvnBindException("Authentication canceled for realm: " + realm); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/PassphraseCallback.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/PassphraseCallback.java index 70e3d245329b..fe793c05fb31 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/PassphraseCallback.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/PassphraseCallback.java @@ -16,6 +16,7 @@ package org.jetbrains.idea.svn.commandLine; import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.auth.AuthenticationService; import org.tmatesoft.svn.core.SVNURL; /** @@ -25,8 +26,8 @@ public class PassphraseCallback extends AuthCallbackCase { private static final String PASSPHRASE_FOR = "Passphrase for"; - PassphraseCallback(@NotNull AuthenticationCallback callback, SVNURL url) { - super(callback, url); + PassphraseCallback(@NotNull AuthenticationService authenticationService, SVNURL url) { + super(authenticationService, url); } @Override @@ -38,10 +39,10 @@ public class PassphraseCallback extends AuthCallbackCase { boolean getCredentials(String errText) throws SvnBindException { // try to get from file /*if (myTried) { - myAuthenticationCallback.clearPassiveCredentials(null, myBase); + myAuthenticationService.clearPassiveCredentials(null, myBase); }*/ myTried = true; - if (myAuthenticationCallback.authenticateFor(null, myUrl, myAuthenticationCallback.getSpecialConfigDir() != null, false)) { + if (myAuthenticationService.authenticateFor(null, myUrl, false)) { return true; } throw new SvnBindException("Authentication canceled for : " + errText.substring(PASSPHRASE_FOR.length())); 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 340100dcb3a6..a3afaf9a5c0c 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/ProxyCallback.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/ProxyCallback.java @@ -20,6 +20,7 @@ import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.auth.AuthenticationService; import org.tmatesoft.svn.core.SVNURL; import java.net.PasswordAuthentication; @@ -36,8 +37,8 @@ public class ProxyCallback extends AuthCallbackCase { private PasswordAuthentication myProxyAuthentication; - ProxyCallback(@NotNull AuthenticationCallback callback, SVNURL url) { - super(callback, url); + ProxyCallback(@NotNull AuthenticationService authenticationService, SVNURL url) { + super(authenticationService, url); } @Override @@ -61,8 +62,8 @@ public class ProxyCallback extends AuthCallbackCase { 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 - } else if (myAuthenticationCallback.haveDataForTmpConfig()) { - myProxyAuthentication = myAuthenticationCallback.getProxyAuthentication(myUrl); + } else if (myAuthenticationService.haveDataForTmpConfig()) { + myProxyAuthentication = myAuthenticationService.getProxyAuthentication(myUrl); result = myProxyAuthentication != null; } 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 11bb9b654523..bdfdd55ed6e1 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/ProxyModule.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/ProxyModule.java @@ -19,8 +19,8 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.svn.IdeaSVNConfigFile; +import org.jetbrains.idea.svn.auth.AuthenticationService; import org.jetbrains.idea.svn.auth.SvnAuthenticationManager; -import org.jetbrains.idea.svn.auth.IdeaSvnkitBasedAuthenticationCallback; import org.tmatesoft.svn.core.SVNURL; import java.net.InetSocketAddress; @@ -39,7 +39,7 @@ public class ProxyModule extends BaseCommandRuntimeModule { @Override public void onStart(@NotNull Command command) throws SvnBindException { - if (myAuthCallback.haveDataForTmpConfig()) { + if (myAuthenticationService.haveDataForTmpConfig()) { setupProxy(command); } } @@ -50,7 +50,7 @@ public class ProxyModule extends BaseCommandRuntimeModule { SVNURL repositoryUrl = command.getRepositoryUrl(); if (repositoryUrl != null) { - Proxy proxy = IdeaSvnkitBasedAuthenticationCallback.getIdeaDefinedProxy(repositoryUrl); + Proxy proxy = AuthenticationService.getIdeaDefinedProxy(repositoryUrl); if (proxy != null) { String hostGroup = ensureGroupForHost(command, repositoryUrl.getHost()); @@ -68,7 +68,7 @@ public class ProxyModule extends BaseCommandRuntimeModule { @NotNull private String ensureGroupForHost(@NotNull Command command, @NotNull String host) { - IdeaSVNConfigFile configFile = new IdeaSVNConfigFile(myAuthCallback.getSpecialConfigDir()); + IdeaSVNConfigFile configFile = new IdeaSVNConfigFile(myAuthenticationService.getSpecialConfigDir()); String groupName = SvnAuthenticationManager.getGroupForHost(host, configFile); if (StringUtil.isEmptyOrSpaces(groupName)) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnBindException.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnBindException.java index 6694083b4d81..f4b4f0d4b0fc 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnBindException.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnBindException.java @@ -21,6 +21,7 @@ import com.intellij.openapi.vcs.VcsException; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnUtil; import org.tmatesoft.svn.core.SVNErrorCode; import org.tmatesoft.svn.core.SVNErrorMessage; @@ -52,18 +53,22 @@ public class SvnBindException extends VcsException { errors.putValue(code.getCode(), getMessage()); } - public SvnBindException(String message) { - super(message); + public SvnBindException(@Nullable String message) { + this(message, null); + } - if (!StringUtil.isEmpty(message)) { - parse(message, SvnUtil.ERROR_PATTERN, errors); - parse(message, SvnUtil.WARNING_PATTERN, warnings); - } + public SvnBindException(@Nullable Throwable cause) { + this(null, cause); } - public SvnBindException(Throwable throwable) { - super(throwable); + public SvnBindException(@Nullable String message, @Nullable Throwable cause) { + super(message, cause); + + init(message); + init(cause); + } + private void init(@Nullable Throwable throwable) { if (throwable instanceof SVNException) { SVNException e = (SVNException)throwable; int code = e.getErrorMessage().getErrorCode().getCode(); @@ -73,6 +78,13 @@ public class SvnBindException extends VcsException { } } + private void init(@Nullable String message) { + if (!StringUtil.isEmpty(message)) { + parse(message, SvnUtil.ERROR_PATTERN, errors); + parse(message, SvnUtil.WARNING_PATTERN, warnings); + } + } + public boolean contains(int code) { return errors.containsKey(code) || warnings.containsKey(code); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnExecutableChecker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnExecutableChecker.java index 4a5183ac5e4c..1add2022074a 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnExecutableChecker.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnExecutableChecker.java @@ -26,6 +26,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnApplicationSettings; import org.jetbrains.idea.svn.SvnBundle; import org.jetbrains.idea.svn.SvnVcs; +import org.jetbrains.idea.svn.WorkingCopyFormat; /** * Created with IntelliJ IDEA. @@ -82,7 +83,7 @@ public class SvnExecutableChecker extends ExecutableValidator { } private boolean validateVersion(@NotNull Version version) { - if (version.lessThan(1, 7)) { + if (!getVcs().isSupportedByCommandLine(WorkingCopyFormat.from(version))) { setNotificationErrorDescription(getOldExecutableMessage(version)); return false; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/TerminalSshModule.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/TerminalSshModule.java index 5a624e9d3414..ca4fce9d910b 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/TerminalSshModule.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/TerminalSshModule.java @@ -130,7 +130,7 @@ public class TerminalSshModule extends LineCommandAdapter implements CommandRunt // TODO: authentication (like "svn info <file> -r HEAD"), if it is invoked before all working copy roots are resolved. // TODO: resolving repositoryUrl logic should be updated so that repositoryUrl is not null here. String auth = - myRuntime.getAuthCallback().requestSshCredentials(repositoryUrl != null ? repositoryUrl.toDecodedString() : "", mode, key); + myRuntime.getAuthenticationService().requestSshCredentials(repositoryUrl != null ? repositoryUrl.toDecodedString() : "", mode, key); if (!StringUtil.isEmpty(auth)) { sendAnswer(auth); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/TwoWaySslCallback.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/TwoWaySslCallback.java index e9df472b65c2..fe8ad9208e5f 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/TwoWaySslCallback.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/TwoWaySslCallback.java @@ -16,6 +16,7 @@ package org.jetbrains.idea.svn.commandLine; import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.auth.AuthenticationService; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager; import org.tmatesoft.svn.core.auth.SVNSSLAuthentication; @@ -28,8 +29,8 @@ public class TwoWaySslCallback extends UsernamePasswordCallback { private static final String ACCESS_TO_PREFIX = "Access to "; private static final String FORBIDDEN_STATUS = "forbidden"; - TwoWaySslCallback(AuthenticationCallback callback, SVNURL url) { - super(callback, url); + TwoWaySslCallback(@NotNull AuthenticationService authenticationService, SVNURL url) { + super(authenticationService, url); } @Override diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/UsernamePasswordCallback.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/UsernamePasswordCallback.java index caeb92f1d734..ad908b213ab3 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/UsernamePasswordCallback.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/UsernamePasswordCallback.java @@ -15,7 +15,9 @@ */ package org.jetbrains.idea.svn.commandLine; +import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.auth.AuthenticationService; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager; import org.tmatesoft.svn.core.auth.SVNAuthentication; @@ -32,6 +34,7 @@ import java.util.regex.Pattern; */ public class UsernamePasswordCallback extends AuthCallbackCase { + private static final String COULD_NOT_AUTHENTICATE_TO_SERVER_MESSAGE = "could not authenticate to server"; private static final String UNABLE_TO_CONNECT_MESSAGE = "Unable to connect to a repository"; private static final String AUTHENTICATION_FAILED_MESSAGE = "Authentication failed"; private static final String INVALID_CREDENTIALS_FOR_SVN_PROTOCOL = "svn: E170001: Can't get"; @@ -40,8 +43,8 @@ public class UsernamePasswordCallback extends AuthCallbackCase { protected SVNAuthentication myAuthentication; - UsernamePasswordCallback(@NotNull AuthenticationCallback callback, SVNURL url) { - super(callback, url); + UsernamePasswordCallback(@NotNull AuthenticationService authenticationService, SVNURL url) { + super(authenticationService, url); } @Override @@ -52,13 +55,14 @@ public class UsernamePasswordCallback extends AuthCallbackCase { // svn protocol invalid credentials - messages could be "Can't get password", "Can't get username or password" error.contains(INVALID_CREDENTIALS_FOR_SVN_PROTOCOL) && error.contains(PASSWORD_STRING) || // http/https protocol, svn 1.7, non-interactive - error.contains(UNABLE_TO_CONNECT_MESSAGE); + error.contains(UNABLE_TO_CONNECT_MESSAGE) || + // http, svn 1.6, non-interactive + StringUtil.containsIgnoreCase(error, COULD_NOT_AUTHENTICATE_TO_SERVER_MESSAGE); } @Override boolean getCredentials(String errText) throws SvnBindException { - myAuthentication = myAuthenticationCallback.requestCredentials(myUrl != null ? myUrl : parseUrlFromError(errText), - getType()); + myAuthentication = myAuthenticationService.requestCredentials(myUrl != null ? myUrl : parseUrlFromError(errText), getType()); return myAuthentication != null; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/CmdUpdateClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/CmdUpdateClient.java index 61b0592af085..8406f1ecec5b 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/CmdUpdateClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/CmdUpdateClient.java @@ -18,6 +18,7 @@ package org.jetbrains.idea.svn.update; import com.intellij.openapi.util.io.FileUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.svn.WorkingCopyFormat; import org.jetbrains.idea.svn.api.Depth; import org.jetbrains.idea.svn.api.EventAction; import org.jetbrains.idea.svn.api.ProgressEvent; @@ -26,7 +27,10 @@ import org.jetbrains.idea.svn.commandLine.CommandUtil; import org.jetbrains.idea.svn.commandLine.SvnBindException; import org.jetbrains.idea.svn.commandLine.SvnCommandName; import org.jetbrains.idea.svn.info.Info; -import org.tmatesoft.svn.core.*; +import org.tmatesoft.svn.core.SVNErrorCode; +import org.tmatesoft.svn.core.SVNErrorMessage; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; @@ -163,7 +167,10 @@ public class CmdUpdateClient extends SvnKitUpdateClient { CommandUtil.put(parameters, SvnTarget.fromURL(url, pegRevision)); CommandUtil.put(parameters, path, false); fillParameters(parameters, revision, depth, depthIsSticky, allowUnversionedObstructions); - parameters.add("--ignore-ancestry"); + if (!myVcs.is16SupportedByCommandLine() || + WorkingCopyFormat.from(myFactory.createVersionClient().getVersion()).isOrGreater(WorkingCopyFormat.ONE_DOT_SEVEN)) { + parameters.add("--ignore-ancestry"); + } long[] revisions = run(path, parameters, SvnCommandName.switchCopy); diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnCachingRepositoryPoolTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnCachingRepositoryPoolTest.java index e2475e020950..ecad58e2b20d 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnCachingRepositoryPoolTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnCachingRepositoryPoolTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -107,13 +107,7 @@ public class SvnCachingRepositoryPoolTest extends FileBasedTest { } } }; - final EmptyProgressIndicator indicator = new EmptyProgressIndicator() { - @Override - public void cancel() { - super.cancel(); - ProgressManagerImpl.canceled(); - } - }; + final EmptyProgressIndicator indicator = new EmptyProgressIndicator(); Thread thread = new Thread(new Runnable() { @Override public void run() { diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnCommandLineStabilityTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnCommandLineStabilityTest.java index 76cc3c8ce9af..4918ef06eb39 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnCommandLineStabilityTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnCommandLineStabilityTest.java @@ -1,16 +1,15 @@ package org.jetbrains.idea.svn; import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vfs.VfsUtilCore; import junit.framework.Assert; -import org.jetbrains.idea.svn.api.BaseSvnClient; -import org.jetbrains.idea.svn.commandLine.CommandExecutor; -import org.jetbrains.idea.svn.commandLine.SvnCommandName; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.auth.AuthenticationService; +import org.jetbrains.idea.svn.commandLine.*; import org.junit.Test; import org.tmatesoft.svn.core.wc2.SvnTarget; import java.io.File; -import java.util.ArrayList; -import java.util.List; /** * Created with IntelliJ IDEA. @@ -30,15 +29,22 @@ public class SvnCommandLineStabilityTest extends Svn17TestCase { } private void call() throws VcsException { - List<String> parameters = new ArrayList<String>(); - parameters.add("--xml"); - - SvnVcs vcs = SvnVcs.getInstance(myProject); - File workingDirectory = new File(myWorkingCopyDir.getPath()); - CommandExecutor command = - BaseSvnClient.execute(vcs, SvnTarget.fromFile(workingDirectory), workingDirectory, SvnCommandName.info, parameters, null); - final String result = command.getOutput(); + String result = runInfo().getOutput(); System.out.println(result); Assert.assertNotNull(result); } + + @NotNull + private CommandExecutor runInfo() throws SvnBindException { + SvnVcs vcs = SvnVcs.getInstance(myProject); + File workingDirectory = VfsUtilCore.virtualToIoFile(myWorkingCopyDir); + Command command = new Command(SvnCommandName.info); + + command.setTarget(SvnTarget.fromFile(workingDirectory)); + command.setWorkingDirectory(workingDirectory); + command.put("--xml"); + + CommandRuntime runtime = new CommandRuntime(vcs, new AuthenticationService(vcs, true)); + return runtime.runWithAuthenticationAttempt(command); + } } |