diff --git a/platform/util/src/com/intellij/util/xmlb/AttributeBinding.java b/platform/util/src/com/intellij/util/xmlb/AttributeBinding.java index 0206a54e02ea..13c0e80b0be6 100644 --- a/platform/util/src/com/intellij/util/xmlb/AttributeBinding.java +++ b/platform/util/src/com/intellij/util/xmlb/AttributeBinding.java @@ -35,6 +35,8 @@ public class AttributeBinding implements Binding { @Override public Object serialize(@NotNull Object o, Object context, SerializationFilter filter) { final Object v = myAccessor.read(o); + if (v == null) return context; + final Object node = myBinding.serialize(v, context, filter); return new org.jdom.Attribute(myAttribute.value(), ((Content)node).getValue()); diff --git a/platform/vcs-api/src/com/intellij/vcsUtil/VcsUtil.java b/platform/vcs-api/src/com/intellij/vcsUtil/VcsUtil.java index 709318330b84..bbeeae9e99f6 100644 --- a/platform/vcs-api/src/com/intellij/vcsUtil/VcsUtil.java +++ b/platform/vcs-api/src/com/intellij/vcsUtil/VcsUtil.java @@ -323,6 +323,10 @@ public class VcsUtil { return getFilePath(new File(path), isDirectory); } + public static FilePath getFilePathOnNonLocal(String path, boolean isDirectory) { + return VcsContextFactory.SERVICE.getInstance().createFilePathOnNonLocal(path, isDirectory); + } + public static FilePath getFilePath(File file, boolean isDirectory) { return VcsContextFactory.SERVICE.getInstance().createFilePathOn(file, isDirectory); } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/LazyRefreshingSelfQueue.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/LazyRefreshingSelfQueue.java index 7a7b6a94d433..0f79d570c6a6 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/LazyRefreshingSelfQueue.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/LazyRefreshingSelfQueue.java @@ -32,14 +32,23 @@ import java.util.*; * */ @SomeQueue +// TODO: Used only in RemoteRevisionsNumberCache public class LazyRefreshingSelfQueue { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.changes.LazyRefreshingSelfQueue"); + // provides update interval in milliseconds. private final Getter myUpdateInterval; - // head is old. tail is new + // structure: + // 1) pairs with First == null + // 2) pairs with First != null sorted by First ascending + // pair.First - time when T was last processed + // pair.Second - some item T private final LinkedList> myQueue; + // Set of items that should be processed by myUpdater private final Set myInProgress; + // checks if updateStep should be really performed private final Computable myShouldUpdateOldChecker; + // performs some actions on item T, for instance - updates some data for T in cache private final Consumer myUpdater; private final Object myLock; @@ -52,20 +61,14 @@ public class LazyRefreshingSelfQueue { myLock = new Object(); } + // adds item that should be updated at next updateStep() call public void addRequest(@NotNull final T t) { synchronized (myLock) { myQueue.addFirst(new Pair(null, t)); } } - public void addRequests(final Collection values) { - synchronized (myLock) { - for (T value : values) { - myQueue.addFirst(new Pair(null, value)); - } - } - } - + // unschedules item from update at next updateStep() call public void forceRemove(@NotNull final T t) { synchronized (myLock) { for (Iterator> iterator = myQueue.iterator(); iterator.hasNext();) { @@ -80,11 +83,11 @@ public class LazyRefreshingSelfQueue { // called by outside timer or something public void updateStep() { - final List dirty = new LinkedList(); - final long startTime = System.currentTimeMillis() - myUpdateInterval.get(); boolean onlyAbsolute = true; - // check if we have some old items at all - if not, we would not check if repository latest revision had changed and will save time + // TODO: Actually we could store items with pair.First == null in separate list. + // checks item that has smallest update time - i.e. was not updated by the most time + // if its update time greater than current - interval => we should not update any item with pair.First != null this time (as they are ordered) synchronized (myLock) { for (Pair pair : myQueue) { if (pair.getFirst() != null) { @@ -96,9 +99,10 @@ public class LazyRefreshingSelfQueue { // do not ask under lock final Boolean shouldUpdateOld = onlyAbsolute ? false : myShouldUpdateOldChecker.compute(); + final List dirty = new LinkedList(); synchronized (myLock) { - // get absolute + // adds all pairs with pair.First == null to dirty while (! myQueue.isEmpty()) { final Pair pair = myQueue.get(0); if (pair.getFirst() == null) { @@ -108,6 +112,7 @@ public class LazyRefreshingSelfQueue { } } if (Boolean.TRUE.equals(shouldUpdateOld) && (! myQueue.isEmpty())) { + // adds all pairs with update time (pair.First) < current - interval to dirty while (! myQueue.isEmpty()) { final Pair pair = myQueue.get(0); if (pair.getFirst() < startTime) { @@ -126,6 +131,8 @@ public class LazyRefreshingSelfQueue { for (T t : dirty) { myUpdater.consume(t); synchronized (myLock) { + // output value of remove() is tracked not to process items that were removed from myInProgress in forceRemove() + // TODO: Probably more clear logic should be implemented if (myInProgress.remove(t)) { myQueue.addLast(new Pair(System.currentTimeMillis(), t)); } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/RemoteRevisionsNumbersCache.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/RemoteRevisionsNumbersCache.java index f9b5fda3bd07..30d8f5ef88c0 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/RemoteRevisionsNumbersCache.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/RemoteRevisionsNumbersCache.java @@ -88,11 +88,13 @@ public class RemoteRevisionsNumbersCache implements ChangesOnServerTracker { public boolean updateStep() { mySomethingChanged = false; + // copy under lock final HashMap copyMap; synchronized (myLock) { copyMap = new HashMap(myRefreshingQueues); } + // filter only items for vcs roots that support background operations for (Iterator> iterator = copyMap.entrySet().iterator(); iterator.hasNext();) { final Map.Entry entry = iterator.next(); final VcsRoot key = entry.getKey(); @@ -103,6 +105,7 @@ public class RemoteRevisionsNumbersCache implements ChangesOnServerTracker { } } LOG.debug("queues refresh started, queues: " + copyMap.size()); + // refresh "up to date" info for (LazyRefreshingSelfQueue queue : copyMap.values()) { if (myProject.isDisposed()) throw new ProcessCanceledException(); queue.updateStep(); @@ -111,10 +114,12 @@ public class RemoteRevisionsNumbersCache implements ChangesOnServerTracker { } public void directoryMappingChanged() { + // copy myData under lock HashSet keys; synchronized (myLock) { keys = new HashSet(myData.keySet()); } + // collect new vcs for scheduled files final Map> vFiles = new HashMap>(); for (String key : keys) { final VirtualFile vf = myLfs.refreshAndFindFileByIoFile(new File(key)); @@ -244,6 +249,7 @@ public class RemoteRevisionsNumbersCache implements ChangesOnServerTracker { public void consume(String s) { LOG.debug("update for: " + s); //todo check canceled - check VCS's ready for asynchronous queries + // get last remote revision for file final VirtualFile vf = myLfs.refreshAndFindFileByIoFile(new File(s)); final ItemLatestState state; final DiffProvider diffProvider = myVcsRoot.getVcs().getDiffProvider(); @@ -256,6 +262,7 @@ public class RemoteRevisionsNumbersCache implements ChangesOnServerTracker { final VcsRevisionNumber newNumber = (state == null) || state.isDefaultHead() ? UNKNOWN : state.getNumber(); final Pair oldPair; + // update value in cache synchronized (myLock) { oldPair = myData.get(s); myData.put(s, new Pair(myVcsRoot, newNumber)); @@ -275,6 +282,8 @@ public class RemoteRevisionsNumbersCache implements ChangesOnServerTracker { myVcsRoot = vcsRoot; } + // Check if currently cached vcs root latest revision is less than latest vcs root revision + // => update should be performed in this case public Boolean compute() { final AbstractVcs vcs = myVcsRoot.getVcs(); // won't be called in parallel for same vcs -> just synchronized map is ok @@ -282,6 +291,8 @@ public class RemoteRevisionsNumbersCache implements ChangesOnServerTracker { LOG.debug("should update for: " + vcsName + " root: " + myVcsRoot.getPath().getPath()); final VcsRevisionNumber latestNew = vcs.getDiffProvider().getLatestCommittedRevision(myVcsRoot.getPath()); + // TODO: Why vcsName is used as key and not myVcsRoot.getKey()??? + // TODO: This seems to be invalid logic as we get latest revision for vcs root final VcsRevisionNumber latestKnown = myLatestRevisionsMap.get(vcsName); // not known if (latestNew == null) return true; @@ -307,8 +318,15 @@ public class RemoteRevisionsNumbersCache implements ChangesOnServerTracker { return getRevisionState(change.getBeforeRevision()) && getRevisionState(change.getAfterRevision()); } + /** + * Returns {@code true} if passed revision is up to date, comparing to latest repository revision. + * + * @param revision + * @return + */ private boolean getRevisionState(final ContentRevision revision) { if (revision != null) { + // TODO: Seems peg revision should also be tracked here. final VcsRevisionNumber local = revision.getRevisionNumber(); final String path = revision.getFile().getIOFile().getAbsolutePath(); final VcsRevisionNumber remote = getNumber(path); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/RemoteRevisionsStateCache.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/RemoteRevisionsStateCache.java index adf940b1ec34..d5e197604171 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/RemoteRevisionsStateCache.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/RemoteRevisionsStateCache.java @@ -27,10 +27,14 @@ import java.util.*; public class RemoteRevisionsStateCache implements ChangesOnServerTracker { private final static long DISCRETE = 3600000; - // true -> changed + // All files that were checked during cache update and were not invalidated. + // pair.First - if file is changed (true means changed) + // pair.Second - vcs root where file belongs to private final Map> myChanged; + // All files that needs to be checked during next cache update, grouped by vcs root private final MultiMap myQueries; + // All vcs roots for which cache update was performed with update timestamp private final Map myTs; private final Object myLock; private final ProjectLevelVcsManager myVcsManager; @@ -104,6 +108,7 @@ public class RemoteRevisionsStateCache implements ChangesOnServerTracker { myVcsConfiguration.CHANGED_ON_SERVER_INTERVAL * 60000 : DISCRETE); synchronized (myLock) { + // just copies myQueries MultiMap to dirty MultiMap for (VcsRoot root : myQueries.keySet()) { final Collection collection = myQueries.get(root); for (String s : collection) { @@ -112,15 +117,23 @@ public class RemoteRevisionsStateCache implements ChangesOnServerTracker { } myQueries.clear(); + // collect roots for which cache update should be performed (by timestamp) final Set roots = new HashSet(); for (Map.Entry entry : myTs.entrySet()) { + // ignore timestamp, as still remote changes checking is required + // TODO: why not to add in roots anyway??? - as dirty is still checked when adding myChanged files. if (! dirty.get(entry.getKey()).isEmpty()) continue; + // update only if timeout expired final Long ts = entry.getValue(); if ((ts == null) || (oldPoint > ts)) { roots.add(entry.getKey()); } } + + // Add dirty files from those vcs roots, that + // - needs to be update by timestamp criteria + // - that already contain files for update through manually added requests for (Map.Entry> entry : myChanged.entrySet()) { final VcsRoot vcsRoot = entry.getValue().getSecond(); if ((! dirty.get(vcsRoot).isEmpty()) || roots.contains(vcsRoot)) { @@ -142,6 +155,8 @@ public class RemoteRevisionsStateCache implements ChangesOnServerTracker { final Collection paths = dirty.get(vcsRoot); final Collection remotelyChanged = provider.getRemotelyChanged(vcsRoot.getPath(), paths); for (String path : paths) { + // TODO: Contains invoked for each file - better to use Set (implementations just use List) + // TODO: Why to store boolean for changed or not - why not just remove such values from myChanged??? results.put(path, new Pair(remotelyChanged.contains(path), vcsRoot)); } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/ChangeListDetailsAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/ChangeListDetailsAction.java index 8c7a32463f0f..b6e7f8be7044 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/ChangeListDetailsAction.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/ChangeListDetailsAction.java @@ -74,13 +74,7 @@ public class ChangeListDetailsAction extends AnAction implements DumbAware { detailsBuilder.append("
"); if (provider != null) { - final CommittedChangeList originalChangeList; - if (changeList instanceof ReceivedChangeList) { - originalChangeList = ((ReceivedChangeList) changeList).getBaseList(); - } - else { - originalChangeList = changeList; - } + final CommittedChangeList originalChangeList = ReceivedChangeList.unwrap(changeList); for(ChangeListColumn column: provider.getColumns()) { if (ChangeListColumn.isCustom(column)) { String value = column.getValue(originalChangeList).toString(); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesCache.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesCache.java index 9155a1a63fd9..4c13ef015123 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesCache.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesCache.java @@ -688,14 +688,13 @@ public class CommittedChangesCache implements PersistentStateComponent baseChanges = new HashSet(); for (CommittedChangeList list : lists) { - baseChanges.addAll(list instanceof ReceivedChangeList ? ((ReceivedChangeList) list).getBaseList().getChanges() : list.getChanges()); + baseChanges.addAll(ReceivedChangeList.unwrap(list).getChanges()); final Collection changes = list.getChanges(); for (Change change : changes) { diff --git a/plugins/svn4idea/src/META-INF/plugin.xml b/plugins/svn4idea/src/META-INF/plugin.xml index e1a1a0b717ee..e831d0550a80 100644 --- a/plugins/svn4idea/src/META-INF/plugin.xml +++ b/plugins/svn4idea/src/META-INF/plugin.xml @@ -72,7 +72,7 @@ - + @@ -139,5 +139,7 @@ + + diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/IdeaSVNConfigFile.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/IdeaSVNConfigFile.java index f5c27c2f9c66..0c0e36f56b1b 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/IdeaSVNConfigFile.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/IdeaSVNConfigFile.java @@ -15,16 +15,24 @@ */ package org.jetbrains.idea.svn; +import com.intellij.openapi.util.text.StringUtil; +import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.svn.config.DefaultProxyGroup; import org.jetbrains.idea.svn.config.ProxyGroup; import org.tmatesoft.svn.core.internal.wc.SVNConfigFile; import java.io.File; +import java.net.InetSocketAddress; +import java.net.PasswordAuthentication; +import java.net.Proxy; import java.util.Collection; import java.util.HashMap; import java.util.Map; public class IdeaSVNConfigFile { + + public final static String SERVERS_FILE_NAME = "servers"; + private final Map myPatternsMap; private final long myLatestUpdate; private final File myFile; @@ -41,6 +49,59 @@ public class IdeaSVNConfigFile { myPatternsMap = new HashMap(); } + public static void putProxyIntoServersFile(final File configDir, final String host, final Proxy proxyInfo) { + final IdeaSVNConfigFile configFile = new IdeaSVNConfigFile(new File(configDir, SERVERS_FILE_NAME)); + configFile.updateGroups(); + + String groupName = ensureHostGroup(host, configFile); + + final HashMap map = new HashMap(); + final InetSocketAddress address = ((InetSocketAddress) proxyInfo.address()); + map.put(SvnAuthenticationManager.HTTP_PROXY_HOST, address.getHostName()); + map.put(SvnAuthenticationManager.HTTP_PROXY_PORT, String.valueOf(address.getPort())); + configFile.addGroup(groupName, host + "*", map); + configFile.save(); + } + + @NotNull + public static String ensureHostGroup(@NotNull String host, @NotNull IdeaSVNConfigFile configFile) { + String groupName = SvnAuthenticationManager.getGroupForHost(host, configFile); + + if (StringUtil.isEmptyOrSpaces(groupName)) { + groupName = getNewGroupName(host, configFile); + } + + return groupName; + } + + @NotNull + public static String getNewGroupName(@NotNull String host, @NotNull IdeaSVNConfigFile configFile) { + String groupName = host; + final Map groups = configFile.getAllGroups(); + while (StringUtil.isEmptyOrSpaces(groupName) || groups.containsKey(groupName)) { + groupName += "1"; + } + return groupName; + } + + public static boolean putProxyCredentialsIntoServerFile(@NotNull final File configDir, @NotNull final String host, + @NotNull final PasswordAuthentication authentication) { + final IdeaSVNConfigFile configFile = new IdeaSVNConfigFile(new File(configDir, SERVERS_FILE_NAME)); + configFile.updateGroups(); + + String groupName = SvnAuthenticationManager.getGroupForHost(host, configFile); + // no proxy defined in group -> no sense in password + if (StringUtil.isEmptyOrSpaces(groupName)) return false; + final Map properties = configFile.getAllGroups().get(groupName).getProperties(); + if (StringUtil.isEmptyOrSpaces(properties.get(SvnAuthenticationManager.HTTP_PROXY_HOST))) return false; + if (StringUtil.isEmptyOrSpaces(properties.get(SvnAuthenticationManager.HTTP_PROXY_PORT))) return false; + + configFile.setValue(groupName, SvnAuthenticationManager.HTTP_PROXY_USERNAME, authentication.getUserName()); + configFile.setValue(groupName, SvnAuthenticationManager.HTTP_PROXY_PASSWORD, String.valueOf(authentication.getPassword())); + configFile.save(); + return true; + } + public void updateGroups() { if (myLatestUpdate != myFile.lastModified()) { myPatternsMap.clear(); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java index 22f4c5f45350..0597ea1ac91a 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java @@ -32,6 +32,7 @@ import com.intellij.openapi.vcs.CalledInAwt; import com.intellij.openapi.vcs.changes.committed.AbstractCalledLater; import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier; import com.intellij.util.EventDispatcher; +import com.intellij.util.SystemProperties; import com.intellij.util.messages.Topic; import com.intellij.util.net.HttpConfigurable; import com.intellij.util.proxy.CommonProxy; @@ -119,6 +120,40 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im }); } + public String getDefaultUsername(String kind, SVNURL url) { + String result = SystemProperties.getUserName(); + + // USERNAME authentication is also requested in SVNSSHConnector.open() + if (ISVNAuthenticationManager.SSH.equals(kind) || + (ISVNAuthenticationManager.USERNAME.equals(kind) && SVN_SSH.equals(url.getProtocol()))) { + result = url != null && !StringUtil.isEmpty(url.getUserInfo()) ? url.getUserInfo() : getDefaultOptions().getDefaultSSHUserName(); + } + + return result; + } + + @Override + protected SVNSSHAuthentication getDefaultSSHAuthentication(SVNURL url) { + String userName = getDefaultUsername(ISVNAuthenticationManager.SSH, url); + + // This is fully copied from base class - DefaultSVNAuthenticationManager - as there are no setters in Authentication classes + // and there is no url parameter if overriding getDefaultOptions() + String password = getDefaultOptions().getDefaultSSHPassword(); + String keyFile = getDefaultOptions().getDefaultSSHKeyFile(); + int port = getDefaultOptions().getDefaultSSHPortNumber(); + String passphrase = getDefaultOptions().getDefaultSSHPassphrase(); + + if (userName != null && password != null) { + return new SVNSSHAuthentication(userName, password, port, getHostOptionsProvider().getHostOptions(url).isAuthStorageEnabled(), url, + false); + } + else if (userName != null && keyFile != null) { + return new SVNSSHAuthentication(userName, new File(keyFile), passphrase, port, + getHostOptionsProvider().getHostOptions(url).isAuthStorageEnabled(), url, false); + } + return null; + } + private class AuthenticationProviderProxy implements ISVNAuthenticationProvider { private final ISVNAuthenticationProvider myDelegate; @@ -674,7 +709,7 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im return DEFAULT_READ_TIMEOUT; } if (SVN_SSH.equals(protocol)) { - return (int) getConfig().mySSHReadTimeout; + return (int)getConfig().getSshReadTimeout(); } return 0; } @@ -683,7 +718,7 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im public int getConnectTimeout(SVNRepository repository) { String protocol = repository.getLocation().getProtocol(); if (SVN_SSH.equals(protocol)) { - return (int) getConfig().mySSHConnectionTimeout; + return (int)getConfig().getSshConnectionTimeout(); } final int connectTimeout = super.getConnectTimeout(repository); if ((HTTP.equals(protocol) || HTTPS.equals(protocol)) && (connectTimeout <= 0)) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationNotifier.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationNotifier.java index 4efcce6f0db6..5b84aa234d38 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationNotifier.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationNotifier.java @@ -16,17 +16,21 @@ package org.jetbrains.idea.svn; import com.intellij.notification.NotificationType; +import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.application.ex.ApplicationEx; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.MessageType; +import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.popup.Balloon; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.util.NamedRunnable; import com.intellij.openapi.util.Ref; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.impl.GenericNotifierImpl; import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier; @@ -45,12 +49,15 @@ import org.tmatesoft.svn.core.SVNAuthenticationException; import org.tmatesoft.svn.core.SVNCancelException; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; +import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager; import org.tmatesoft.svn.core.auth.SVNAuthentication; import org.tmatesoft.svn.core.internal.util.SVNURLUtil; import org.tmatesoft.svn.core.wc.SVNRevision; import javax.swing.*; import java.awt.*; +import java.io.File; +import java.io.FilenameFilter; import java.net.*; import java.util.*; import java.util.List; @@ -59,6 +66,9 @@ import java.util.Timer; public class SvnAuthenticationNotifier extends GenericNotifierImpl { private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.SvnAuthenticationNotifier"); + private static final List ourAuthKinds = Arrays.asList(ISVNAuthenticationManager.PASSWORD, ISVNAuthenticationManager.SSH, + ISVNAuthenticationManager.SSL, ISVNAuthenticationManager.USERNAME, "svn.ssl.server", "svn.ssh.server"); + private final SvnVcs myVcs; private final RootsToWorkingCopies myRootsToWorkingCopies; private final Map myCopiesPassiveResults; @@ -414,7 +424,7 @@ public class SvnAuthenticationNotifier extends GenericNotifierImpl withUserInfo) { + private static String serializeUrl(final String url, final Ref withUserInfo) { if (Boolean.FALSE.equals(withUserInfo.get())) { return url; } @@ -306,7 +306,8 @@ public class SvnBranchConfigurationManager implements PersistentStateComponent 0)); } if (withUserInfo.get()) { - return SVNURL.create(svnurl.getProtocol(), null, svnurl.getHost(), svnurl.getPort(), svnurl.getURIEncodedPath(), true).toString(); + return SVNURL.create(svnurl.getProtocol(), null, svnurl.getHost(), SvnUtil.resolvePort(svnurl), svnurl.getURIEncodedPath(), true) + .toString(); } } catch (SVNException e) { @@ -321,10 +322,11 @@ public class SvnBranchConfigurationManager implements PersistentStateComponent { private static final Logger LOG = Logger.getInstance("org.jetbrains.idea.svn.SvnConfiguration"); public final static int ourMaxAnnotateRevisionsDefault = 500; - private final static String SERVERS_FILE_NAME = "servers"; - public static final String CLEANUP_ON_START_RUN = "cleanupOnStartRun"; private final Project myProject; - public String USER = ""; - public String PASSWORD = ""; - public String[] ADD_PATHS = null; - private String myConfigurationDirectory; private boolean myIsUseDefaultConfiguration; private boolean myIsUseDefaultProxy; private ISVNOptions myOptions; private boolean myIsKeepLocks; private boolean myAutoUpdateAfterCommit; - private boolean myRemoteStatus; private SvnAuthenticationManager myAuthManager; private SvnAuthenticationManager myPassiveAuthManager; private SvnAuthenticationManager myInteractiveManager; - private String myUpgradeMode; private SvnSupportOptions mySupportOptions; private boolean myCleanupRun; private int myMaxAnnotateRevisions = ourMaxAnnotateRevisionsDefault; @@ -101,14 +79,14 @@ public class SvnConfiguration implements PersistentStateComponent { public long mySSHReadTimeout = DEFAULT_SSH_TIMEOUT; public static final AuthStorage RUNTIME_AUTH_CACHE = new AuthStorage(); - public String LAST_MERGED_REVISION = null; + // TODO: update depth is not stored in configuration as SVNDepth has wrong type for DefaultJDOMExternalizer + // TODO: check if it should be stored public SVNDepth UPDATE_DEPTH = SVNDepth.UNKNOWN; public boolean MERGE_DRY_RUN = false; public boolean MERGE_DIFF_USE_ANCESTRY = true; public boolean UPDATE_LOCK_ON_DEMAND = false; public boolean IGNORE_SPACES_IN_MERGE = false; - //public boolean DETECT_NESTED_COPIES = true; public boolean CHECK_NESTED_FOR_QUICK_MERGE = false; public boolean IGNORE_SPACES_IN_ANNOTATE = true; public boolean SHOW_MERGE_SOURCES_IN_ANNOTATE = true; @@ -126,7 +104,7 @@ public class SvnConfiguration implements PersistentStateComponent { private IdeaSVNConfigFile myConfigFile; public boolean isCommandLine() { - return UseAcceleration.commandLine.equals(myUseAcceleration); + return UseAcceleration.commandLine.equals(getUseAcceleration()); } @Override @@ -162,12 +140,12 @@ public class SvnConfiguration implements PersistentStateComponent { } public SVNDiffOptions getMergeOptions() { - return new SVNDiffOptions(IGNORE_SPACES_IN_MERGE, IGNORE_SPACES_IN_MERGE, IGNORE_SPACES_IN_MERGE); + return new SVNDiffOptions(isIgnoreSpacesInMerge(), isIgnoreSpacesInMerge(), isIgnoreSpacesInMerge()); } private void initServers() { if (myConfigFile == null) { - myConfigFile = new IdeaSVNConfigFile(new File(getConfigurationDirectory(), SERVERS_FILE_NAME)); + myConfigFile = new IdeaSVNConfigFile(new File(getConfigurationDirectory(), IdeaSVNConfigFile.SERVERS_FILE_NAME)); } myConfigFile.updateGroups(); } @@ -180,59 +158,6 @@ public class SvnConfiguration implements PersistentStateComponent { myConfigFile.save(); } - public static void putProxyIntoServersFile(final File configDir, final String host, final Proxy proxyInfo) { - final IdeaSVNConfigFile configFile = new IdeaSVNConfigFile(new File(configDir, SERVERS_FILE_NAME)); - configFile.updateGroups(); - - String groupName = ensureHostGroup(host, configFile); - - final HashMap map = new HashMap(); - final InetSocketAddress address = ((InetSocketAddress) proxyInfo.address()); - map.put(SvnAuthenticationManager.HTTP_PROXY_HOST, address.getHostName()); - map.put(SvnAuthenticationManager.HTTP_PROXY_PORT, String.valueOf(address.getPort())); - configFile.addGroup(groupName, host + "*", map); - configFile.save(); - } - - @NotNull - public static String ensureHostGroup(@NotNull String host, @NotNull IdeaSVNConfigFile configFile) { - String groupName = SvnAuthenticationManager.getGroupForHost(host, configFile); - - if (StringUtil.isEmptyOrSpaces(groupName)) { - groupName = getNewGroupName(host, configFile); - } - - return groupName; - } - - @NotNull - public static String getNewGroupName(@NotNull String host, @NotNull IdeaSVNConfigFile configFile) { - String groupName = host; - final Map groups = configFile.getAllGroups(); - while (StringUtil.isEmptyOrSpaces(groupName) || groups.containsKey(groupName)) { - groupName += "1"; - } - return groupName; - } - - public static boolean putProxyCredentialsIntoServerFile(@NotNull final File configDir, @NotNull final String host, - @NotNull final PasswordAuthentication authentication) { - final IdeaSVNConfigFile configFile = new IdeaSVNConfigFile(new File(configDir, SERVERS_FILE_NAME)); - configFile.updateGroups(); - - String groupName = SvnAuthenticationManager.getGroupForHost(host, configFile); - // no proxy defined in group -> no sense in password - if (StringUtil.isEmptyOrSpaces(groupName)) return false; - final Map properties = configFile.getAllGroups().get(groupName).getProperties(); - if (StringUtil.isEmptyOrSpaces(properties.get(SvnAuthenticationManager.HTTP_PROXY_HOST))) return false; - if (StringUtil.isEmptyOrSpaces(properties.get(SvnAuthenticationManager.HTTP_PROXY_PORT))) return false; - - configFile.setValue(groupName, SvnAuthenticationManager.HTTP_PROXY_USERNAME, authentication.getUserName()); - configFile.setValue(groupName, SvnAuthenticationManager.HTTP_PROXY_PASSWORD, String.valueOf(authentication.getPassword())); - configFile.save(); - return true; - } - public static SvnConfiguration getInstance(final Project project) { return ServiceManager.getService(project, SvnConfiguration.class); } @@ -245,10 +170,130 @@ public class SvnConfiguration implements PersistentStateComponent { final boolean changed = IGNORE_SPACES_IN_ANNOTATE != value; IGNORE_SPACES_IN_ANNOTATE = value; if (changed) { - myProject.getMessageBus().syncPublisher(VcsAnnotationRefresher.LOCAL_CHANGES_CHANGED).configurationChanged(SvnVcs.getKey()); + getProject().getMessageBus().syncPublisher(VcsAnnotationRefresher.LOCAL_CHANGES_CHANGED).configurationChanged(SvnVcs.getKey()); } } + public long getSshConnectionTimeout() { + return mySSHConnectionTimeout; + } + + public void setSshConnectionTimeout(long sshConnectionTimeout) { + mySSHConnectionTimeout = sshConnectionTimeout; + } + + public long getSshReadTimeout() { + return mySSHReadTimeout; + } + + public void setSshReadTimeout(long sshReadTimeout) { + mySSHReadTimeout = sshReadTimeout; + } + + public Project getProject() { + return myProject; + } + + public Boolean isKeepNewFilesAsIsForTreeConflictMerge() { + return TREE_CONFLICT_MERGE_THEIRS_NEW_INTO_OLD_PLACE; + } + + public void setKeepNewFilesAsIsForTreeConflictMerge(Boolean keepNewFilesAsIsForTreeConflictMerge) { + this.TREE_CONFLICT_MERGE_THEIRS_NEW_INTO_OLD_PLACE = keepNewFilesAsIsForTreeConflictMerge; + } + + public SSLProtocols getSslProtocols() { + return SSL_PROTOCOLS; + } + + public void setSslProtocols(SSLProtocols sslProtocols) { + this.SSL_PROTOCOLS = sslProtocols; + } + + public SVNDepth getUpdateDepth() { + return UPDATE_DEPTH; + } + + public void setUpdateDepth(SVNDepth updateDepth) { + this.UPDATE_DEPTH = updateDepth; + } + + public UseAcceleration getUseAcceleration() { + return myUseAcceleration; + } + + public void setUseAcceleration(UseAcceleration useAcceleration) { + myUseAcceleration = useAcceleration; + } + + public boolean isIgnoreExternals() { + return IGNORE_EXTERNALS; + } + + public void setIgnoreExternals(boolean ignoreExternals) { + this.IGNORE_EXTERNALS = ignoreExternals; + } + + public boolean isMergeDryRun() { + return MERGE_DRY_RUN; + } + + public void setMergeDryRun(boolean mergeDryRun) { + this.MERGE_DRY_RUN = mergeDryRun; + } + + public boolean isMergeDiffUseAncestry() { + return MERGE_DIFF_USE_ANCESTRY; + } + + public void setMergeDiffUseAncestry(boolean mergeDiffUseAncestry) { + this.MERGE_DIFF_USE_ANCESTRY = mergeDiffUseAncestry; + } + + public boolean isUpdateLockOnDemand() { + return UPDATE_LOCK_ON_DEMAND; + } + + public void setUpdateLockOnDemand(boolean updateLockOnDemand) { + this.UPDATE_LOCK_ON_DEMAND = updateLockOnDemand; + } + + public boolean isIgnoreSpacesInMerge() { + return IGNORE_SPACES_IN_MERGE; + } + + public void setIgnoreSpacesInMerge(boolean ignoreSpacesInMerge) { + this.IGNORE_SPACES_IN_MERGE = ignoreSpacesInMerge; + } + + public boolean isCheckNestedForQuickMerge() { + return CHECK_NESTED_FOR_QUICK_MERGE; + } + + public void setCheckNestedForQuickMerge(boolean checkNestedForQuickMerge) { + this.CHECK_NESTED_FOR_QUICK_MERGE = checkNestedForQuickMerge; + } + + public boolean isIgnoreSpacesInAnnotate() { + return IGNORE_SPACES_IN_ANNOTATE; + } + + public boolean isShowMergeSourcesInAnnotate() { + return SHOW_MERGE_SOURCES_IN_ANNOTATE; + } + + public void setShowMergeSourcesInAnnotate(boolean showMergeSourcesInAnnotate) { + this.SHOW_MERGE_SOURCES_IN_ANNOTATE = showMergeSourcesInAnnotate; + } + + public boolean isForceUpdate() { + return FORCE_UPDATE; + } + + public void setForceUpdate(boolean forceUpdate) { + this.FORCE_UPDATE = forceUpdate; + } + public class SvnSupportOptions { /** * version of "support SVN in IDEA". for features tracking. should grow @@ -267,10 +312,6 @@ public class SvnConfiguration implements PersistentStateComponent { private final static long CHANGELIST_SUPPORT = 124; private final static long UPGRADE_TO_16_VERSION_ASKED = 125; - public boolean upgradeTo16Asked() { - return (myVersion != null) && (UPGRADE_TO_16_VERSION_ASKED <= myVersion); - } - public boolean changeListsSynchronized() { return (myVersion != null) && (CHANGELIST_SUPPORT <= myVersion); } @@ -347,34 +388,6 @@ public class SvnConfiguration implements PersistentStateComponent { return myOptions; } - public static SvnAuthenticationManager createForTmpDir(final Project project, final File dir) { - return createForTmpDir(project, dir, null); - } - - public static SvnAuthenticationManager createForTmpDir(final Project project, final File dir, - @Nullable final SvnInteractiveAuthenticationProvider provider) { - final SvnVcs vcs = SvnVcs.getInstance(project); - - final SvnAuthenticationManager interactive = new SvnAuthenticationManager(project, dir); - interactive.setRuntimeStorage(RUNTIME_AUTH_CACHE); - final SvnInteractiveAuthenticationProvider interactiveProvider = provider == null ? - new SvnInteractiveAuthenticationProvider(vcs, interactive) : provider; - interactive.setAuthenticationProvider(interactiveProvider); - - return interactive; - } - - public SvnAuthenticationManager getManager(final AuthManagerType type, final SvnVcs vcs) { - if (AuthManagerType.active.equals(type)) { - return getInteractiveManager(vcs); - } else if (AuthManagerType.passive.equals(type)) { - return getPassiveAuthenticationManager(vcs.getProject()); - } else if (AuthManagerType.usual.equals(type)) { - return getAuthenticationManager(vcs); - } - throw new IllegalArgumentException(); - } - public SvnAuthenticationManager getAuthenticationManager(final SvnVcs svnVcs) { if (myAuthManager == null) { // reloaded when configuration directory changes @@ -434,29 +447,14 @@ public class SvnConfiguration implements PersistentStateComponent { SVNConfigFile.createDefaultConfiguration(dir); } - systemManager.set(new SvnServerFileManagerImpl(new IdeaSVNConfigFile(new File(SVNFileUtil.getSystemConfigurationDirectory(), SERVERS_FILE_NAME)))); + systemManager.set(new SvnServerFileManagerImpl(new IdeaSVNConfigFile(new File(SVNFileUtil.getSystemConfigurationDirectory(), IdeaSVNConfigFile.SERVERS_FILE_NAME)))); initServers(); userManager.set(new SvnServerFileManagerImpl(myConfigFile)); } - public String getUpgradeMode() { - return myUpgradeMode; - } - - public void setUpgradeMode(String upgradeMode) { - myUpgradeMode = upgradeMode; - } - @SuppressWarnings({"HardCodedStringLiteral"}) public void readExternal(Element element) throws InvalidDataException { DefaultJDOMExternalizer.readExternal(this, element); - List elems = element.getChildren("addpath"); - LOG.debug(elems.toString()); - ADD_PATHS = new String[elems.size()]; - for (int i = 0; i < elems.size(); i++) { - Element elem = (Element)elems.get(i); - ADD_PATHS[i] = elem.getAttributeValue("path"); - } Element configurationDirectory = element.getChild("configuration"); if (configurationDirectory != null) { myConfigurationDirectory = configurationDirectory.getText(); @@ -471,18 +469,7 @@ public class SvnConfiguration implements PersistentStateComponent { else { myIsUseDefaultConfiguration = true; } - // compatibility: this setting was moved from .iws to global settings - List urls = element.getChildren("checkoutURL"); - for (Object url1 : urls) { - Element child = (Element)url1; - String url = child.getText(); - if (url != null) { - SvnApplicationSettings.getInstance().addCheckoutURL(url); - } - } myIsKeepLocks = element.getChild("keepLocks") != null; - myRemoteStatus = element.getChild("remoteStatus") != null; - myUpgradeMode = element.getChild("upgradeMode") != null ? element.getChild("upgradeMode").getText() : null; final Element useProxy = element.getChild("myIsUseDefaultProxy"); if (useProxy == null) { myIsUseDefaultProxy = false; @@ -508,7 +495,7 @@ public class SvnConfiguration implements PersistentStateComponent { final Attribute acceleration = element.getAttribute("myUseAcceleration"); if (acceleration != null) { try { - myUseAcceleration = UseAcceleration.valueOf(acceleration.getValue()); + setUseAcceleration(UseAcceleration.valueOf(acceleration.getValue())); } catch (IllegalArgumentException e) { // } @@ -526,26 +513,19 @@ public class SvnConfiguration implements PersistentStateComponent { final Attribute protocols = element.getAttribute("SSL_PROTOCOLS"); if (protocols != null) { try { - SSL_PROTOCOLS = SSLProtocols.valueOf(protocols.getValue()); + setSslProtocols(SSLProtocols.valueOf(protocols.getValue())); } catch (IllegalArgumentException e) { // } } if (treeConflictMergeNewFilesPlace != null) { - TREE_CONFLICT_MERGE_THEIRS_NEW_INTO_OLD_PLACE = Boolean.parseBoolean(treeConflictMergeNewFilesPlace.getValue()); + setKeepNewFilesAsIsForTreeConflictMerge(Boolean.parseBoolean(treeConflictMergeNewFilesPlace.getValue())); } } @SuppressWarnings({"HardCodedStringLiteral"}) public void writeExternal(Element element) throws WriteExternalException { DefaultJDOMExternalizer.writeExternal(this, element); - if (ADD_PATHS != null) { - for (String aADD_PATHS : ADD_PATHS) { - Element elem = new Element("addpath"); - elem.setAttribute("path", aADD_PATHS); - element.addContent(elem); - } - } if (myConfigurationDirectory != null) { Element configurationDirectory = new Element("configuration"); configurationDirectory.setText(myConfigurationDirectory); @@ -555,23 +535,18 @@ public class SvnConfiguration implements PersistentStateComponent { if (myIsKeepLocks) { element.addContent(new Element("keepLocks")); } - if (myRemoteStatus) { - element.addContent(new Element("remoteStatus")); - } - if (myUpgradeMode != null) { - element.addContent(new Element("upgradeMode").setText(myUpgradeMode)); - } element.addContent(new Element("myIsUseDefaultProxy").setText(myIsUseDefaultProxy ? "true" : "false")); if (mySupportOptions != null) { - element.addContent(new Element("supportedVersion").setText("" + mySupportOptions.myVersion)); + element.addContent(new Element("supportedVersion").setText(String.valueOf(mySupportOptions.myVersion))); } - element.setAttribute("maxAnnotateRevisions", "" + myMaxAnnotateRevisions); - element.setAttribute("myUseAcceleration", "" + myUseAcceleration); - element.setAttribute("myAutoUpdateAfterCommit", "" + myAutoUpdateAfterCommit); - element.setAttribute(CLEANUP_ON_START_RUN, "" + myCleanupRun); - element.setAttribute("SSL_PROTOCOLS", SSL_PROTOCOLS.name()); - if (TREE_CONFLICT_MERGE_THEIRS_NEW_INTO_OLD_PLACE != null) { - element.setAttribute("TREE_CONFLICT_MERGE_THEIRS_NEW_INTO_OLD_PLACE", "" + TREE_CONFLICT_MERGE_THEIRS_NEW_INTO_OLD_PLACE); + element.setAttribute("maxAnnotateRevisions", String.valueOf(myMaxAnnotateRevisions)); + element.setAttribute("myUseAcceleration", String.valueOf(getUseAcceleration())); + element.setAttribute("myAutoUpdateAfterCommit", String.valueOf(myAutoUpdateAfterCommit)); + element.setAttribute(CLEANUP_ON_START_RUN, String.valueOf(myCleanupRun)); + element.setAttribute("SSL_PROTOCOLS", getSslProtocols().name()); + if (isKeepNewFilesAsIsForTreeConflictMerge() != null) { + element.setAttribute("TREE_CONFLICT_MERGE_THEIRS_NEW_INTO_OLD_PLACE", String.valueOf( + isKeepNewFilesAsIsForTreeConflictMerge())); } } @@ -591,14 +566,6 @@ public class SvnConfiguration implements PersistentStateComponent { myIsKeepLocks = keepLocks; } - public boolean isRemoteStatus() { - return myRemoteStatus; - } - - public void setRemoteStatus(boolean remote) { - myRemoteStatus = remote; - } - public boolean isIsUseDefaultProxy() { return myIsUseDefaultProxy; } @@ -643,50 +610,11 @@ public class SvnConfiguration implements PersistentStateComponent { return myUpdateRootInfos.get(file); } + // TODO: Check why SvnUpdateEnvironment.validationOptions is fully commented and then remove this method if necessary public Map getUpdateInfosMap() { return Collections.unmodifiableMap(myUpdateRootInfos); } - private static final List ourAuthKinds = Arrays.asList(ISVNAuthenticationManager.PASSWORD, ISVNAuthenticationManager.SSH, - ISVNAuthenticationManager.SSL, ISVNAuthenticationManager.USERNAME, "svn.ssl.server", "svn.ssh.server"); - - public void clearAuthenticationDirectory(@Nullable Project project) { - final File authDir = new File(getConfigurationDirectory(), "auth"); - if (authDir.exists()) { - final Runnable process = new Runnable() { - public void run() { - final ProgressIndicator ind = ProgressManager.getInstance().getProgressIndicator(); - if (ind != null) { - ind.setIndeterminate(true); - ind.setText("Clearing stored credentials in " + authDir.getAbsolutePath()); - } - final File[] files = authDir.listFiles(new FilenameFilter() { - public boolean accept(File dir, String name) { - return ourAuthKinds.contains(name); - } - }); - - for (File dir : files) { - if (ind != null) { - ind.setText("Deleting " + dir.getAbsolutePath()); - } - FileUtil.delete(dir); - } - } - }; - final Application application = ApplicationManager.getApplication(); - if (application.isUnitTestMode() || ! application.isDispatchThread()) { - process.run(); - } else { - ProgressManager.getInstance().runProcessWithProgressSynchronously(process, "button.text.clear.authentication.cache", false, project); - } - } - } - - public boolean haveCredentialsFor(final String kind, final String realm) { - return RUNTIME_AUTH_CACHE.getData(kind, realm) != null; - } - public void acknowledge(final String kind, final String realm, final Object object) { RUNTIME_AUTH_CACHE.putData(kind, realm, object); } @@ -721,7 +649,7 @@ public class SvnConfiguration implements PersistentStateComponent { myCleanupRun = cleanupRun; } - public static enum SSLProtocols { + public enum SSLProtocols { sslv3, tlsv1, all } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnStatusConvertor.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnStatusConvertor.java index 184fbab0bc14..3c0d396657c7 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnStatusConvertor.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnStatusConvertor.java @@ -16,7 +16,9 @@ package org.jetbrains.idea.svn; import com.intellij.openapi.vcs.FileStatus; -import org.tmatesoft.svn.core.SVNException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.svn.portable.PortableStatus; import org.tmatesoft.svn.core.wc.SVNStatus; import org.tmatesoft.svn.core.wc.SVNStatusType; @@ -24,11 +26,18 @@ public class SvnStatusConvertor { private SvnStatusConvertor() { } - public static FileStatus convertStatus(final SVNStatus status) throws SVNException { - return convertStatus(status, true); + @NotNull + public static FileStatus convertStatus(@Nullable SVNStatusType itemStatus, @Nullable SVNStatusType propertiesStatus) { + PortableStatus status = new PortableStatus(); + + status.setContentsStatus(itemStatus); + status.setPropertiesStatus(propertiesStatus); + + return convertStatus(status); } - public static FileStatus convertStatus(final SVNStatus status, final boolean noticeProperties) throws SVNException { + @NotNull + public static FileStatus convertStatus(@Nullable final SVNStatus status) { if (status == null) { return FileStatus.UNKNOWN; } @@ -57,17 +66,18 @@ public class SvnStatusConvertor { return SvnFileStatus.REPLACED; } else if (status.getContentsStatus() == SVNStatusType.STATUS_CONFLICTED || - noticeProperties && status.getPropertiesStatus() == SVNStatusType.STATUS_CONFLICTED) { + status.getPropertiesStatus() == SVNStatusType.STATUS_CONFLICTED) { if (status.getContentsStatus() == SVNStatusType.STATUS_CONFLICTED && - noticeProperties && status.getPropertiesStatus() == SVNStatusType.STATUS_CONFLICTED) { + status.getPropertiesStatus() == SVNStatusType.STATUS_CONFLICTED) { return FileStatus.MERGED_WITH_BOTH_CONFLICTS; - } else if (status.getContentsStatus() == SVNStatusType.STATUS_CONFLICTED) { + } + else if (status.getContentsStatus() == SVNStatusType.STATUS_CONFLICTED) { return FileStatus.MERGED_WITH_CONFLICTS; } return FileStatus.MERGED_WITH_PROPERTY_CONFLICTS; } else if (status.getContentsStatus() == SVNStatusType.STATUS_MODIFIED || - noticeProperties && status.getPropertiesStatus() == SVNStatusType.STATUS_MODIFIED) { + status.getPropertiesStatus() == SVNStatusType.STATUS_MODIFIED) { return FileStatus.MODIFIED; } else if (status.isSwitched()) { @@ -79,15 +89,8 @@ public class SvnStatusConvertor { return FileStatus.NOT_CHANGED; } - public static FileStatus convertPropertyStatus(final SVNStatusType status) throws SVNException { - return convertSingleStatus(status, FileStatus.MERGED_WITH_PROPERTY_CONFLICTS); - } - - public static FileStatus convertContentsStatus(final SVNStatus status) throws SVNException { - return convertStatus(status, false); - } - - private static FileStatus convertSingleStatus(final SVNStatusType status, final FileStatus defaultConflictStatus) throws SVNException { + @NotNull + public static FileStatus convertPropertyStatus(final SVNStatusType status) { if (status == null) { return FileStatus.UNKNOWN; } @@ -116,7 +119,7 @@ public class SvnStatusConvertor { return SvnFileStatus.REPLACED; } else if (status == SVNStatusType.STATUS_CONFLICTED) { - return defaultConflictStatus; + return FileStatus.MERGED_WITH_PROPERTY_CONFLICTS; } else if (status == SVNStatusType.STATUS_MODIFIED) { return FileStatus.MODIFIED; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java index ec8ebf71d848..490d8905a7e7 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java @@ -73,6 +73,7 @@ public class SvnUtil { @NonNls public static final String WC_DB_FILE_NAME = "wc.db"; @NonNls public static final String DIR_PROPS_FILE_NAME = "dir-props"; @NonNls public static final String PATH_TO_LOCK_FILE = SVN_ADMIN_DIR_NAME + "/lock"; + public static final int DEFAULT_PORT_INDICATOR = -1; private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.SvnUtil"); public static final Pattern ERROR_PATTERN = Pattern.compile("^svn: (E(\\d+)): (.*)$", Pattern.MULTILINE); @@ -738,7 +739,7 @@ public class SvnUtil { } } - public static String appendMultiParts(@NotNull final String base, @NotNull final String subPath) throws SVNException { + public static String appendMultiParts(@NotNull final String base, @NotNull final String subPath) { if (StringUtil.isEmpty(subPath)) return base; final List parts = StringUtil.split(subPath.replace('\\', '/'), "/", true); String result = base; @@ -768,6 +769,31 @@ public class SvnUtil { return factory.createContentClient().getContent(target, revision, pegRevision); } + public static boolean hasDefaultPort(@NotNull SVNURL result) { + return !result.hasPort() || SVNURL.getDefaultPortNumber(result.getProtocol()) == result.getPort(); + } + + /** + * When creating SVNURL with default port, some negative value should be specified as port number, otherwise specified port value (even + * if equals to default) will occur in toString() result. + */ + public static int resolvePort(@NotNull SVNURL url) { + return !hasDefaultPort(url) ? url.getPort() : DEFAULT_PORT_INDICATOR; + } + + @NotNull + public static SVNURL createUrl(@NotNull String url) throws SVNException { + SVNURL result = SVNURL.parseURIEncoded(url); + + // explicitly check if port corresponds to default port and recreate url specifying default port indicator + if (result.hasPort() && hasDefaultPort(result)) { + result = SVNURL + .create(result.getProtocol(), result.getUserInfo(), result.getHost(), DEFAULT_PORT_INDICATOR, result.getURIEncodedPath(), true); + } + + return result; + } + public static SVNURL parseUrl(@NotNull String url) { try { return SVNURL.parseURIEncoded(url); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java index 646363c56a13..96dfea9cf4de 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java @@ -56,6 +56,7 @@ import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.util.Consumer; import com.intellij.util.Processor; import com.intellij.util.ThreeState; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.Convertor; import com.intellij.util.containers.SoftHashMap; import com.intellij.util.messages.MessageBus; @@ -979,6 +980,33 @@ public class SvnVcs extends AbstractVcs { return result; } + public void collectInfo(@NotNull Collection files, @Nullable ISVNInfoHandler handler) { + File first = ContainerUtil.getFirstItem(files); + + if (first != null) { + ClientFactory factory = getFactory(first); + + try { + if (factory instanceof CmdClientFactory) { + factory.createInfoClient().doInfo(files, handler); + } + else { + // TODO: Generally this should be moved in SvnKit info client implementation. + // TODO: Currently left here to have exception logic as in handleInfoException to be applied for each file separately. + for (File file : files) { + SVNInfo info = getInfo(file); + if (handler != null) { + handler.handleInfo(info); + } + } + } + } + catch (SVNException e) { + handleInfoException(e); + } + } + } + @Nullable public SVNInfo getInfo(@NotNull File ioFile, @NotNull SVNRevision revision) { SVNInfo result = null; @@ -1027,11 +1055,11 @@ public class SvnVcs extends AbstractVcs { public void refreshSSLProperty() { if (ourSSLProtocolsExplicitlySet) return; - if (SvnConfiguration.SSLProtocols.all.equals(myConfiguration.SSL_PROTOCOLS)) { + if (SvnConfiguration.SSLProtocols.all.equals(myConfiguration.getSslProtocols())) { System.clearProperty(SVNKIT_HTTP_SSL_PROTOCOLS); - } else if (SvnConfiguration.SSLProtocols.sslv3.equals(myConfiguration.SSL_PROTOCOLS)) { + } else if (SvnConfiguration.SSLProtocols.sslv3.equals(myConfiguration.getSslProtocols())) { System.setProperty(SVNKIT_HTTP_SSL_PROTOCOLS, "SSLv3"); - } else if (SvnConfiguration.SSLProtocols.tlsv1.equals(myConfiguration.SSL_PROTOCOLS)) { + } else if (SvnConfiguration.SSLProtocols.tlsv1.equals(myConfiguration.getSslProtocols())) { System.setProperty(SVNKIT_HTTP_SSL_PROTOCOLS, "TLSv1"); } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CompareWithBranchAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CompareWithBranchAction.java deleted file mode 100644 index 544bbc7beda8..000000000000 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CompareWithBranchAction.java +++ /dev/null @@ -1,367 +0,0 @@ -/* - * Copyright 2000-2009 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.actions; - -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.actionSystem.PlatformDataKeys; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.diff.DiffManager; -import com.intellij.openapi.diff.FileContent; -import com.intellij.openapi.diff.SimpleContent; -import com.intellij.openapi.diff.SimpleDiffRequest; -import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.progress.ProgressManager; -import com.intellij.openapi.project.DumbAware; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.util.Ref; -import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.vcs.AbstractVcsHelper; -import com.intellij.openapi.vcs.FileStatus; -import com.intellij.openapi.vcs.FileStatusManager; -import com.intellij.openapi.vcs.changes.Change; -import com.intellij.openapi.vfs.CharsetToolkit; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.WaitForProgressToShow; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.svn.*; -import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew; -import org.jetbrains.idea.svn.status.SvnDiffEditor; -import org.tmatesoft.svn.core.*; -import org.tmatesoft.svn.core.internal.util.SVNPathUtil; -import org.tmatesoft.svn.core.internal.wc.SVNCancellableEditor; -import org.tmatesoft.svn.core.internal.wc.SVNErrorManager; -import org.tmatesoft.svn.core.internal.wc.admin.SVNAdminAreaInfo; -import org.tmatesoft.svn.core.internal.wc.admin.SVNEntry; -import org.tmatesoft.svn.core.internal.wc.admin.SVNReporter; -import org.tmatesoft.svn.core.internal.wc.admin.SVNWCAccess; -import org.tmatesoft.svn.core.internal.wc17.SVNReporter17; -import org.tmatesoft.svn.core.internal.wc17.SVNWCContext; -import org.tmatesoft.svn.core.io.SVNRepository; -import org.tmatesoft.svn.core.wc.*; -import org.tmatesoft.svn.util.SVNDebugLog; -import org.tmatesoft.svn.util.SVNLogType; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -/** - * @author yole - */ -public class CompareWithBranchAction extends AnAction implements DumbAware { - private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.actions.CompareWithBranchAction"); - - public void actionPerformed(AnActionEvent e) { - Project project = e.getData(CommonDataKeys.PROJECT); - assert project != null; - final VirtualFile virtualFile = e.getData(CommonDataKeys.VIRTUAL_FILE); - - SelectBranchPopup.show(project, virtualFile, new SelectBranchPopup.BranchSelectedCallback() { - public void branchSelected(final Project project, final SvnBranchConfigurationNew configuration, final String url, final long revision) { - new CompareWithBranchOperation(project, virtualFile, configuration).compareWithBranch(url, revision); - } - }, SvnBundle.message("compare.with.branch.popup.title")); - } - - @Override - public void update(final AnActionEvent e) { - Project project = e.getData(CommonDataKeys.PROJECT); - VirtualFile virtualFile = e.getData(CommonDataKeys.VIRTUAL_FILE); - e.getPresentation().setEnabled(isEnabled(project, virtualFile)); - } - - private static boolean isEnabled(final Project project, final VirtualFile virtualFile) { - if (project == null || virtualFile == null) { - return false; - } - final FileStatus fileStatus = FileStatusManager.getInstance(project).getStatus(virtualFile); - if (fileStatus == FileStatus.UNKNOWN || fileStatus == FileStatus.ADDED || fileStatus == FileStatus.IGNORED) { - return false; - } - return true; - } - - - private class CompareWithBranchOperation { - private final Project myProject; - private final VirtualFile myVirtualFile; - private final SvnBranchConfigurationNew myConfiguration; - - public CompareWithBranchOperation(final Project project, final VirtualFile virtualFile, final SvnBranchConfigurationNew config) { - myProject = project; - myVirtualFile = virtualFile; - myConfiguration = config; - } - - public void compareWithBranch(final String baseUrl, final long revision) { - if (myVirtualFile.isDirectory()) { - compareDirectoryWithBranch(baseUrl, revision); - } - else { - compareFileWithBranch(baseUrl, revision); - } - } - final StringBuilder titleBuilder = new StringBuilder(); - - public void compareDirectoryWithBranch(final String baseUrl, final long revision) { - final List changes = new ArrayList(); - ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { - public void run() { - try { - final SvnVcs vcs = SvnVcs.getInstance(myProject); - final SVNURL url = getURLInBranch(vcs, baseUrl); - if (url == null) return; // todo diagnostics - titleBuilder.append(SvnBundle.message("repository.browser.compare.title", - url.toString(), - FileUtil.toSystemDependentName(myVirtualFile.getPresentableUrl()))); - - final File ioFile = new File(myVirtualFile.getPath()); - if (SvnUtil.is17CopyPart(ioFile)) { - report17DirDiff(vcs, url); - } else { - report16DirDiff(vcs, url); - } - - /* final SVNInfo info1 = vcs.createWCClient().doInfo(new File(myVirtualFile.getPath()), SVNRevision.HEAD); - if (info1 == null) return; - - if (info1 == null) { - SVNErrorMessage err = - SVNErrorMessage.create(SVNErrorCode.ENTRY_NOT_FOUND, "''{0}'' is not under version control", myVirtualFile.getPath()); - SVNErrorManager.error(err, SVNLogType.WC); - } - else if (info1.getURL() == null) { - SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_MISSING_URL, "''{0}'' has no URL", myVirtualFile.getPath()); - SVNErrorManager.error(err, SVNLogType.WC); - } - */ - - // todo - - - /*final SVNDiffClient diffClient = vcs.createDiffClient(); - diffClient.doDiffStatus(info1.getURL(), info1.getRevision(), url, info1.getRevision(), SVNDepth.INFINITY, false, - new ISVNDiffStatusHandler() { - @Override - public void handleDiffStatus(SVNDiffStatus diffStatus) throws SVNException { - diffStatus.getModificationType() - } - });*/ - - /*public void doDiffStatus(File path1, SVNRevision rN, File path2, SVNRevision rM, SVNDepth depth, boolean useAncestry, ISVNDiffStatusHandler handler) throws SVNException {*/ - } - catch(SVNCancelException ex) { - changes.clear(); - } - catch (SVNException ex) { - reportException(ex, baseUrl); - } - } - - private void report17DirDiff(SvnVcs vcs, SVNURL url) throws SVNException { - final File ioFile = new File(myVirtualFile.getPath()); - final SVNWCClient wcClient = vcs.createWCClient(); - final SVNInfo info1 = wcClient.doInfo(ioFile, SVNRevision.HEAD); - - if (info1 == null) { - SVNErrorMessage err = - SVNErrorMessage.create(SVNErrorCode.ENTRY_NOT_FOUND, "''{0}'' is not under version control", myVirtualFile.getPath()); - SVNErrorManager.error(err, SVNLogType.WC); - } - else if (info1.getURL() == null) { - SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_MISSING_URL, "''{0}'' has no URL", myVirtualFile.getPath()); - SVNErrorManager.error(err, SVNLogType.WC); - } - - final SVNReporter17 reporter17 = - new SVNReporter17(ioFile, new SVNWCContext(SvnConfiguration.getInstance(myProject).getOptions(myProject), new ISVNEventHandler() { - @Override - public void handleEvent(SVNEvent event, double progress) throws SVNException { - } - - @Override - public void checkCancelled() throws SVNCancelException { - } - }), - false, true, SVNDepth.INFINITY, false, false, true, false, - SVNDebugLog.getDefaultLog()); - SVNRepository repository = null; - SVNRepository repository2 = null; - try { - repository = vcs.createRepository(info1.getURL()); - long rev = repository.getLatestRevision(); - repository2 = vcs.createRepository(url.toString()); - SvnDiffEditor diffEditor = new SvnDiffEditor(myVirtualFile, repository2, rev, true); - repository.diff(url, rev, rev, null, true, SVNDepth.INFINITY, false, reporter17, - SVNCancellableEditor.newInstance(diffEditor, new SvnProgressCanceller(), null)); - changes.addAll(diffEditor.getChangesMap().values()); - } finally { - if (repository != null) { - repository.closeSession(); - } - if (repository2 != null) { - repository2.closeSession(); - } - } - } - - private void report16DirDiff(SvnVcs vcs, SVNURL url) throws SVNException { - // here there's 1.6 copy so ok to use SVNWCAccess - final SVNWCAccess wcAccess = SVNWCAccess.newInstance(null); - wcAccess.setOptions(vcs.getSvnOptions()); - SVNRepository repository = null; - SVNRepository repository2 = null; - try { - SVNAdminAreaInfo info = wcAccess.openAnchor(new File(myVirtualFile.getPath()), false, SVNWCAccess.INFINITE_DEPTH); - File anchorPath = info.getAnchor().getRoot(); - String target = "".equals(info.getTargetName()) ? null : info.getTargetName(); - - SVNEntry anchorEntry = info.getAnchor().getEntry("", false); - if (anchorEntry == null) { - SVNErrorMessage err = - SVNErrorMessage.create(SVNErrorCode.ENTRY_NOT_FOUND, "''{0}'' is not under version control", anchorPath); - SVNErrorManager.error(err, SVNLogType.WC); - } - else if (anchorEntry.getURL() == null) { - SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_MISSING_URL, "''{0}'' has no URL", anchorPath); - SVNErrorManager.error(err, SVNLogType.WC); - } - - SVNURL anchorURL = anchorEntry.getSVNURL(); - SVNReporter reporter = new SVNReporter(info, info.getAnchor().getFile(info.getTargetName()), false, true, SVNDepth.INFINITY, - false, false, true, SVNDebugLog.getDefaultLog()); - - repository = vcs.createRepository(anchorURL.toString()); - long rev = repository.getLatestRevision(); - repository2 = vcs.createRepository((target == null) ? url.toString() : url.removePathTail().toString()); - SvnDiffEditor diffEditor = new SvnDiffEditor((target == null) ? myVirtualFile : myVirtualFile.getParent(), - repository2, rev, true); - repository.diff(url, rev, rev, target, true, true, false, reporter, - SVNCancellableEditor.newInstance(diffEditor, new SvnProgressCanceller(), null)); - changes.addAll(diffEditor.getChangesMap().values()); - } - finally { - wcAccess.close(); - if (repository != null) { - repository.closeSession(); - } - if (repository2 != null) { - repository2.closeSession(); - } - } - } - }, SvnBundle.message("progress.computing.difference"), true, myProject); - if (!changes.isEmpty()) { - AbstractVcsHelper.getInstance(myProject).showWhatDiffersBrowser(null, changes, titleBuilder.toString()); - } - } - - public void compareFileWithBranch(final String baseUrl, final long revision) { - final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - final StringBuilder remoteTitleBuilder = new StringBuilder(); - final Ref success = new Ref(); - ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { - public void run() { - try { - final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); - if (indicator != null) { - indicator.setIndeterminate(true); - } - final SvnVcs vcs = SvnVcs.getInstance(myProject); - SVNURL svnurl = getURLInBranch(vcs, baseUrl); - if (svnurl == null) { - reportNotFound(baseUrl); - return; - } - remoteTitleBuilder.append(svnurl.toString()); - SVNWCClient client = vcs.createWCClient(); - client.doGetFileContents(svnurl, SVNRevision.UNDEFINED, SVNRevision.HEAD, true, baos); - success.set(true); - } - catch (SVNException ex) { - reportException(ex, baseUrl); - } - } - }, SvnBundle.message("compare.with.branch.progress.loading.content"), true, myProject); - if (success.isNull()) { - return; - } - SimpleDiffRequest req = new SimpleDiffRequest(myProject, SvnBundle.message("compare.with.branch.diff.title")); - req.setContents(new SimpleContent(CharsetToolkit.bytesToString(baos.toByteArray(), myVirtualFile.getCharset())), - new FileContent(myProject, myVirtualFile)); - req.setContentTitles(remoteTitleBuilder.toString(), myVirtualFile.getPresentableUrl()); - DiffManager.getInstance().getDiffTool().show(req); - } - - @Nullable - private SVNURL getURLInBranch(final SvnVcs vcs, final String baseUrl) throws SVNException { - final SvnFileUrlMapping urlMapping = vcs.getSvnFileUrlMapping(); - final File file = new File(myVirtualFile.getPath()); - final SVNURL fileUrl = urlMapping.getUrlForFile(file); - if (fileUrl == null) { - return null; - } - - final String fileUrlString = fileUrl.toString(); - final RootUrlInfo rootMixed = urlMapping.getWcRootForUrl(fileUrlString); - if (rootMixed == null) { - return null; - } - - final SVNURL thisBranchForUrl = SvnUtil.getBranchForUrl(vcs, rootMixed.getVirtualFile(), fileUrlString); - if (thisBranchForUrl == null) { - return null; - } - - final String relativePath = SVNPathUtil.getRelativePath(thisBranchForUrl.toString(), fileUrlString); - return SVNURL.parseURIEncoded(SVNPathUtil.append(baseUrl, relativePath)); - } - - private void reportException(final SVNException ex, final String baseUrl) { - final SVNErrorCode errorCode = ex.getErrorMessage().getErrorCode(); - if (errorCode.equals(SVNErrorCode.RA_ILLEGAL_URL) || - errorCode.equals(SVNErrorCode.CLIENT_UNRELATED_RESOURCES) || - errorCode.equals(SVNErrorCode.RA_DAV_PATH_NOT_FOUND) || - errorCode.equals(SVNErrorCode.FS_NOT_FOUND)) { - reportNotFound(baseUrl); - } - else { - WaitForProgressToShow.runOrInvokeLaterAboveProgress(new Runnable() { - public void run() { - Messages.showMessageDialog(myProject, ex.getMessage(), - SvnBundle.message("compare.with.branch.error.title"), Messages.getErrorIcon()); - } - }, null, myProject); - LOG.info(ex); - } - } - - private void reportNotFound(final String baseUrl) { - WaitForProgressToShow.runOrInvokeLaterAboveProgress(new Runnable() { - public void run() { - Messages.showMessageDialog(myProject, - SvnBundle.message("compare.with.branch.location.error", myVirtualFile.getPresentableUrl(), baseUrl), - SvnBundle.message("compare.with.branch.error.title"), Messages.getErrorIcon()); - } - }, null, myProject); - } - } -} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ShowPropertiesDiffAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ShowPropertiesDiffAction.java index bce62783d92f..d8126a1300f1 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ShowPropertiesDiffAction.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ShowPropertiesDiffAction.java @@ -20,6 +20,7 @@ import com.intellij.openapi.actionSystem.DataKey; import com.intellij.openapi.vcs.VcsDataKeys; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.changes.ContentRevision; +import com.intellij.openapi.vcs.changes.CurrentContentRevision; import org.jetbrains.idea.svn.SvnBundle; import org.jetbrains.idea.svn.SvnRevisionNumber; import org.jetbrains.idea.svn.SvnVcs; @@ -53,7 +54,10 @@ public class ShowPropertiesDiffAction extends AbstractShowPropertiesDiffAction { protected SVNRevision getAfterRevisionValue(final Change change, final SvnVcs vcs) throws SVNException { final ContentRevision afterRevision = change.getAfterRevision(); if (afterRevision != null) { - return ((SvnRevisionNumber) afterRevision.getRevisionNumber()).getRevision(); + // CurrentContentRevision will be here, for instance, if invoked from changes dialog for "Compare with Branch" action + return afterRevision instanceof CurrentContentRevision + ? SVNRevision.WORKING + : ((SvnRevisionNumber)afterRevision.getRevisionNumber()).getRevision(); } else { return SVNRevision.create(((SvnRevisionNumber) change.getBeforeRevision().getRevisionNumber()).getRevision().getNumber() + 1); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/BaseSvnFileAnnotation.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/BaseSvnFileAnnotation.java index f16bfa41c963..f4fa9f950a32 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/BaseSvnFileAnnotation.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/BaseSvnFileAnnotation.java @@ -164,7 +164,7 @@ public abstract class BaseSvnFileAnnotation extends FileAnnotation { myContents = contents; myBaseRevision = baseRevision; myConfiguration = SvnConfiguration.getInstance(vcs.getProject()); - myShowMergeSources = myConfiguration.SHOW_MERGE_SOURCES_IN_ANNOTATE; + myShowMergeSources = myConfiguration.isShowMergeSourcesInAnnotate(); myInfos = new MyPartiallyCreatedInfos(); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnAnnotationProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnAnnotationProvider.java index 18c4b9824631..c51f4dbcdaa3 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnAnnotationProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnAnnotationProvider.java @@ -118,7 +118,7 @@ public class SvnAnnotationProvider implements AnnotationProvider, VcsCacheableAn // ignore mime type=true : IDEA-19562 final ISVNAnnotateHandler annotateHandler = createAnnotationHandler(progress, result); - final boolean calculateMergeinfo = SvnConfiguration.getInstance(myVcs.getProject()).SHOW_MERGE_SOURCES_IN_ANNOTATE && + final boolean calculateMergeinfo = SvnConfiguration.getInstance(myVcs.getProject()).isShowMergeSourcesInAnnotate() && SvnUtil.checkRepositoryVersion15(myVcs, url); final MySteppedLogGetter logGetter = new MySteppedLogGetter( myVcs, ioFile, progress, @@ -248,7 +248,7 @@ public class SvnAnnotationProvider implements AnnotationProvider, VcsCacheableAn pair.getSecond().getPath(), current); final ISVNAnnotateHandler annotateHandler = createAnnotationHandler(ProgressManager.getInstance().getProgressIndicator(), result); - final boolean calculateMergeinfo = SvnConfiguration.getInstance(myVcs.getProject()).SHOW_MERGE_SOURCES_IN_ANNOTATE && + final boolean calculateMergeinfo = SvnConfiguration.getInstance(myVcs.getProject()).isShowMergeSourcesInAnnotate() && SvnUtil.checkRepositoryVersion15(myVcs, wasUrl.toString()); AnnotateClient client = myVcs.getFactory().createAnnotateClient(); client.annotate(SvnTarget.fromURL(wasUrl), SVNRevision.create(1), svnRevision, svnRevision, calculateMergeinfo, @@ -478,6 +478,6 @@ public class SvnAnnotationProvider implements AnnotationProvider, VcsCacheableAn } private static SVNDiffOptions getLogClientOptions(@NotNull SvnVcs vcs) { - return SvnConfiguration.getInstance(vcs.getProject()).IGNORE_SPACES_IN_ANNOTATE ? new SVNDiffOptions(true, true, true) : null; + return SvnConfiguration.getInstance(vcs.getProject()).isIgnoreSpacesInAnnotate() ? new SVNDiffOptions(true, true, true) : null; } } 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 4076a729d88a..e140a62db91f 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java @@ -57,6 +57,13 @@ public abstract class BaseSvnClient implements SvnClient { } } + protected void assertDirectory(@NotNull SvnTarget target) { + assertFile(target); + if (!target.getFile().isDirectory()) { + throw new IllegalArgumentException("Target should be directory " + target); + } + } + protected void validateFormat(@NotNull WorkingCopyFormat format, @NotNull Collection supported) throws VcsException { if (!supported.contains(format)) { throw new VcsException( 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 22fb76957ac2..9c01217da9f1 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java @@ -14,6 +14,7 @@ import org.jetbrains.idea.svn.conflict.ConflictClient; import org.jetbrains.idea.svn.content.ContentClient; 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.integrate.MergeClient; import org.jetbrains.idea.svn.lock.LockClient; @@ -55,6 +56,7 @@ public abstract class ClientFactory { protected ExportClient myExportClient; protected UpgradeClient myUpgradeClient; protected BrowseClient myBrowseClient; + protected DiffClient myDiffClient; protected ClientFactory(@NotNull SvnVcs vcs) { myVcs = vcs; @@ -180,6 +182,11 @@ public abstract class ClientFactory { return prepare(myBrowseClient); } + @NotNull + public DiffClient createDiffClient() { + return prepare(myDiffClient); + } + @NotNull protected T prepare(@NotNull T client) { client.setVcs(myVcs); 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 c99b803c05a2..653852ca3f49 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java @@ -10,6 +10,7 @@ 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.diff.CmdDiffClient; import org.jetbrains.idea.svn.update.CmdUpdateClient; import org.jetbrains.idea.svn.commandLine.SvnCommandLineInfoClient; import org.jetbrains.idea.svn.commandLine.SvnCommandLineStatusClient; @@ -57,6 +58,7 @@ public class CmdClientFactory extends ClientFactory { myExportClient = new CmdExportClient(); myUpgradeClient = new CmdUpgradeClient(); myBrowseClient = new CmdBrowseClient(); + myDiffClient = new CmdDiffClient(); statusClient = new SvnCommandLineStatusClient(myVcs); infoClient = new SvnCommandLineInfoClient(myVcs); } 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 dbe6b0b88989..3fb1d83c159d 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java @@ -14,6 +14,7 @@ import org.jetbrains.idea.svn.conflict.SvnKitConflictClient; import org.jetbrains.idea.svn.content.SvnKitContentClient; import org.jetbrains.idea.svn.copy.SvnKitCopyMoveClient; import org.jetbrains.idea.svn.delete.SvnKitDeleteClient; +import org.jetbrains.idea.svn.diff.SvnKitDiffClient; import org.jetbrains.idea.svn.history.SvnKitHistoryClient; import org.jetbrains.idea.svn.integrate.SvnKitMergeClient; import org.jetbrains.idea.svn.lock.SvnKitLockClient; @@ -57,6 +58,7 @@ public class SvnKitClientFactory extends ClientFactory { myExportClient = new SvnKitExportClient(); myUpgradeClient = new SvnKitUpgradeClient(); myBrowseClient = new SvnKitBrowseClient(); + myDiffClient = new SvnKitDiffClient(); statusClient = new SvnkitSvnStatusClient(myVcs, null); infoClient = new SvnkitSvnWcClient(myVcs); } 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 57daf70de1fd..29d5068073f5 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java @@ -33,12 +33,10 @@ import com.intellij.util.net.HttpConfigurable; import com.intellij.util.proxy.CommonProxy; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.svn.SvnAuthenticationManager; -import org.jetbrains.idea.svn.SvnBundle; -import org.jetbrains.idea.svn.SvnConfiguration; -import org.jetbrains.idea.svn.SvnVcs; +import org.jetbrains.idea.svn.*; import org.jetbrains.idea.svn.commandLine.AuthenticationCallback; import org.jetbrains.idea.svn.dialogs.SimpleCredentialsDialog; +import org.jetbrains.idea.svn.dialogs.SvnInteractiveAuthenticationProvider; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.auth.*; import org.tmatesoft.svn.core.internal.util.SVNBase64; @@ -221,7 +219,7 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall final Proxy proxy = getIdeaDefinedProxy(repositoryUrl); if (proxy != null){ - SvnConfiguration.putProxyIntoServersFile(myTempDirectory, repositoryUrl.getHost(), proxy); + IdeaSVNConfigFile.putProxyIntoServersFile(myTempDirectory, repositoryUrl.getHost(), proxy); } return true; } @@ -301,7 +299,7 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall PopupUtil.showBalloonForActiveComponent("Failed to authenticate to proxy: " + e.getMessage(), MessageType.ERROR); return false; } - return SvnConfiguration.putProxyCredentialsIntoServerFile(myTempDirectory, repositoryUrl.getHost(), authentication); + return IdeaSVNConfigFile.putProxyCredentialsIntoServerFile(myTempDirectory, repositoryUrl.getHost(), authentication); } return false; } @@ -358,7 +356,12 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall } protected SvnAuthenticationManager createTmpManager() { - return SvnConfiguration.createForTmpDir(myVcs.getProject(), myTempDirectory); + final SvnAuthenticationManager interactive = new SvnAuthenticationManager(myVcs.getProject(), myTempDirectory); + + interactive.setRuntimeStorage(SvnConfiguration.RUNTIME_AUTH_CACHE); + interactive.setAuthenticationProvider(new SvnInteractiveAuthenticationProvider(myVcs, interactive)); + + return interactive; } protected abstract T getWithPassive(SvnAuthenticationManager passive) throws SVNException; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java index 6125ea4c72df..b38d1c914bdf 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java @@ -25,6 +25,17 @@ import java.util.List; */ public class CommandUtil { + @NotNull + public static File resolvePath(@NotNull File base, @NotNull String path) { + File result = new File(path); + + if (!result.isAbsolute()) { + result = ".".equals(path) ? base : new File(base, path); + } + + return result; + } + /** * Puts given value to parameters if condition is satisfied * 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 9e28696829dc..421a7346b6de 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/ProxyModule.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/ProxyModule.java @@ -20,7 +20,6 @@ import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.svn.IdeaSVNConfigFile; import org.jetbrains.idea.svn.SvnAuthenticationManager; -import org.jetbrains.idea.svn.SvnConfiguration; import org.jetbrains.idea.svn.checkin.IdeaSvnkitBasedAuthenticationCallback; import org.tmatesoft.svn.core.SVNURL; @@ -73,7 +72,7 @@ public class ProxyModule extends BaseCommandRuntimeModule { String groupName = SvnAuthenticationManager.getGroupForHost(host, configFile); if (StringUtil.isEmptyOrSpaces(groupName)) { - groupName = SvnConfiguration.getNewGroupName(host, configFile); + groupName = IdeaSVNConfigFile.getNewGroupName(host, configFile); command.put("--config-option"); command.put(String.format("servers:groups:%s=%s*", groupName, host)); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineInfoClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineInfoClient.java index 844835d37bbe..ef4822607e37 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineInfoClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineInfoClient.java @@ -23,6 +23,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.util.Consumer; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnVcs; @@ -124,13 +125,15 @@ public class SvnCommandLineInfoClient extends SvnkitSvnWcClient { final String text = e.getMessage(); final boolean notEmpty = !StringUtil.isEmptyOrSpaces(text); if (notEmpty && text.contains("W155010")) { - // just null - return null; + // if "svn info" is executed for several files at once, then this warning could be printed only for some files, but info for other + // files should be parsed from output + return output.getStdout(); } // not a working copy exception // "E155007: '' is not a working copy" if (notEmpty && text.contains("is not a working copy")) { if (StringUtil.isNotEmpty(output.getStdout())) { + // TODO: Seems not reproducible in 1.8.4 // workaround: as in subversion 1.8 "svn info" on a working copy root outputs such error for parent folder, // if there are files with conflicts. // but the requested info is still in the output except root closing tag @@ -152,7 +155,7 @@ public class SvnCommandLineInfoClient extends SvnkitSvnWcClient { } } - private void parseResult(@NotNull final ISVNInfoHandler handler, @Nullable File base, @Nullable String result) throws SVNException { + private static void parseResult(@NotNull final ISVNInfoHandler handler, @Nullable File base, @Nullable String result) throws SVNException { if (StringUtil.isEmpty(result)) { return; } @@ -246,4 +249,26 @@ public class SvnCommandLineInfoClient extends SvnkitSvnWcClient { }); return infoArr[0]; } + + @Override + public void doInfo(@NotNull Collection paths, @Nullable ISVNInfoHandler handler) throws SVNException { + File base = ContainerUtil.getFirstItem(paths); + + if (base != null) { + base = CommandUtil.correctUpToExistingParent(base); + + List parameters = ContainerUtil.newArrayList(); + for (File file : paths) { + CommandUtil.put(parameters, file); + } + CommandUtil.put(parameters, true, "--xml"); + + // Currently do not handle exceptions here like in SvnVcs.handleInfoException - just continue with parsing in case of warnings for + // some of the requested items + String result = execute(parameters, base); + if (handler != null) { + parseResult(handler, base, result); + } + } + } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandName.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandName.java index ac7f958fc059..c31ce2355276 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandName.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandName.java @@ -51,7 +51,8 @@ public enum SvnCommandName { importFolder("import", false), export("export", false), upgrade("upgrade", true), - list("list", false); + list("list", false), + diff("diff", false); private final String myName; private final boolean myWriteable; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommitRunner.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommitRunner.java index 4780fde090fa..d9b760d8b24a 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommitRunner.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommitRunner.java @@ -213,13 +213,7 @@ public class SvnCommitRunner { @NotNull private File toFile(@NotNull String path) { - File result = new File(path); - - if (!result.isAbsolute()) { - result = new File(myBase, result.getPath()); - } - - return result; + return CommandUtil.resolvePath(myBase, path); } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoHandler.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoHandler.java index f52f120c3217..46372c2a3ec2 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoHandler.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoHandler.java @@ -887,7 +887,7 @@ public class SvnInfoHandler extends DefaultHandler { if (myBase != null) { final String path = attributes.getValue("path"); assertSAX(!StringUtil.isEmptyOrSpaces(path)); - structure.myFile = new File(myBase, path); + structure.myFile = CommandUtil.resolvePath(myBase, path); } final String revision = attributes.getValue("revision"); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoStructure.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoStructure.java index 1c44d348059a..696e366490d7 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoStructure.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoStructure.java @@ -119,7 +119,7 @@ public class SvnInfoStructure { private SVNConflictAction parseConflictAction(@NotNull String actionName) { SVNConflictAction action = SVNConflictAction.fromString(actionName); - action = action == null ? ourConflictActions.get(actionName) : null; + action = action != null ? action : ourConflictActions.get(actionName); if (action == null) { throw new IllegalArgumentException("Unknown conflict action " + actionName); @@ -130,10 +130,10 @@ public class SvnInfoStructure { private SVNConflictReason parseConflictReason(@NotNull String reasonName) throws SAXException { SVNConflictReason reason = SVNConflictReason.fromString(reasonName); - reason = reason == null ? ourConflictReasons.get(reasonName) : null; + reason = reason != null ? reason : ourConflictReasons.get(reasonName); if (reason == null) { - throw new SAXException("Can not parse conflict reason: " + reason); + throw new SAXException("Can not parse conflict reason: " + reasonName); } return reason; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnStatusHandler.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnStatusHandler.java index 9ba9f9b81baa..460f7cde959a 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnStatusHandler.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnStatusHandler.java @@ -67,7 +67,7 @@ public class SvnStatusHandler extends DefaultHandler { } @Nullable - private static SVNStatusType getStatus(@NotNull String code) { + public static SVNStatusType getStatus(@NotNull String code) { SVNStatusType result = ourStatusTypes.get(code); if (result == null) { @@ -739,16 +739,7 @@ public class SvnStatusHandler extends DefaultHandler { protected void updateStatus(Attributes attributes, PortableStatus status, SVNLockWrapper lock) throws SAXException { final String path = attributes.getValue("path"); assertSAX(path != null); - final File file; - if (new File(path).isAbsolute()) { - file = new File(path); - } else { - if (".".equals(path)) { - file = myBase; - } else { - file = new File(myBase, path); - } - } + final File file = CommandUtil.resolvePath(myBase, path); status.setFile(file); final boolean exists = file.exists(); if (exists) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/UpdateOutputLineConverter.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/UpdateOutputLineConverter.java index 6520c6254f65..44d9d7243819 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/UpdateOutputLineConverter.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/UpdateOutputLineConverter.java @@ -169,7 +169,7 @@ public class UpdateOutputLineConverter { } private File createFile(String path) { - return FileUtil.isAbsolute(path) ? new File(path) : new File(myBase, path); + return CommandUtil.resolvePath(myBase, path); } @Nullable diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java index 221ba2abbce2..32b1dae809ed 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java @@ -35,6 +35,9 @@ import org.jetbrains.idea.svn.branchConfig.InfoStorage; import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigManager; import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew; import org.jetbrains.idea.svn.integrate.SvnBranchItem; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNURL; +import org.tmatesoft.svn.core.internal.util.SVNURLUtil; import javax.swing.*; import javax.swing.event.DocumentEvent; @@ -57,7 +60,11 @@ public class BranchConfigurationDialog extends DialogWrapper { private final SvnBranchConfigManager mySvnBranchConfigManager; private final VirtualFile myRoot; - public BranchConfigurationDialog(@NotNull final Project project, @NotNull final SvnBranchConfigurationNew configuration, final @NotNull String rootUrl, @NotNull final VirtualFile root, @NotNull String url) { + public BranchConfigurationDialog(@NotNull final Project project, + @NotNull final SvnBranchConfigurationNew configuration, + final @NotNull SVNURL rootUrl, + @NotNull final VirtualFile root, + @NotNull String url) { super(project, true); myRoot = root; init(); @@ -95,7 +102,7 @@ public class BranchConfigurationDialog extends DialogWrapper { .setAddAction(new AnActionButtonRunnable() { @Override public void run(AnActionButton button) { - final String selectedUrl = SelectLocationDialog.selectLocation(project, rootUrl); + final String selectedUrl = SelectLocationDialog.selectLocation(project, rootUrl.toDecodedString()); if (selectedUrl != null) { if (!configuration.getBranchUrls().contains(selectedUrl)) { configuration @@ -127,27 +134,41 @@ public class BranchConfigurationDialog extends DialogWrapper { } private class TrunkUrlValidator extends DocumentAdapter { - private final String myRootUrl; - private final String myRootUrlPrefix; + private final SVNURL myRootUrl; private final SvnBranchConfigurationNew myConfiguration; - private TrunkUrlValidator(final String rootUrl, final SvnBranchConfigurationNew configuration) { + private TrunkUrlValidator(final SVNURL rootUrl, final SvnBranchConfigurationNew configuration) { myRootUrl = rootUrl; - myRootUrlPrefix = rootUrl + "/"; myConfiguration = configuration; } protected void textChanged(final DocumentEvent e) { - final String currentValue = myTrunkLocationTextField.getText(); - final boolean valueOk = (currentValue != null) && (currentValue.equals(myRootUrl) || currentValue.startsWith(myRootUrlPrefix)); - final boolean prefixOk = (currentValue != null) && (currentValue.startsWith(myRootUrlPrefix)) && - (currentValue.length() > myRootUrlPrefix.length()); + SVNURL url = parseUrl(myTrunkLocationTextField.getText()); - myTrunkLocationTextField.getButton().setEnabled(valueOk); - if (prefixOk) { - myConfiguration.setTrunkUrl(currentValue.endsWith("/") ? currentValue.substring(0, currentValue.length() - 1) : currentValue); + if (url != null) { + boolean isAncestor = SVNURLUtil.isAncestor(myRootUrl, url); + boolean areNotSame = isAncestor && !url.equals(myRootUrl); + + myTrunkLocationTextField.getButton().setEnabled(isAncestor); + if (areNotSame) { + myConfiguration.setTrunkUrl(url.toDecodedString()); + } + myErrorPrompt.setText(areNotSame ? "" : SvnBundle.message("configure.branches.error.wrong.url", myRootUrl)); } - myErrorPrompt.setText(prefixOk ? "" : SvnBundle.message("configure.branches.error.wrong.url", myRootUrl)); + } + + @Nullable + private SVNURL parseUrl(@NotNull String url) { + SVNURL result = null; + + try { + result = SvnUtil.createUrl(url); + } + catch (SVNException e) { + myErrorPrompt.setText(e.getMessage()); + } + + return result; } } @@ -180,7 +201,7 @@ public class BranchConfigurationDialog extends DialogWrapper { if (wcRoot == null) { return; } - final String rootUrl = wcRoot.getRepositoryUrl(); + final SVNURL rootUrl = wcRoot.getRepositoryUrlUrl(); if (rootUrl == null) { Messages.showErrorDialog(project, SvnBundle.message("configure.branches.error.no.connection.title"), SvnBundle.message("configure.branches.title")); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java index faea29510d79..20077fc42e34 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java @@ -60,6 +60,7 @@ import org.tmatesoft.svn.core.SVNLogEntry; import org.tmatesoft.svn.core.SVNLogEntryPath; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.internal.util.SVNPathUtil; +import org.tmatesoft.svn.core.internal.util.SVNURLUtil; import java.io.File; import java.io.IOException; @@ -115,7 +116,12 @@ public class QuickMerge { @Override public void run(ContinuationContext continuationContext) { - if (SVNPathUtil.isAncestor(mySourceUrl, myWcInfo.getRootUrl()) || SVNPathUtil.isAncestor(myWcInfo.getRootUrl(), mySourceUrl)) { + SVNURL url = parseUrl(continuationContext); + if (url == null) { + return; + } + + if (SVNURLUtil.isAncestor(url, myWcInfo.getUrl()) || SVNURLUtil.isAncestor(myWcInfo.getUrl(), url)) { finishWithError(continuationContext, "Cannot merge from self", true); return; } @@ -124,6 +130,20 @@ public class QuickMerge { continuationContext.cancelEverything(); } } + + @Nullable + private SVNURL parseUrl(ContinuationContext continuationContext) { + SVNURL url = null; + + try { + url = SvnUtil.createUrl(mySourceUrl); + } + catch (SVNException e) { + finishWithError(continuationContext, e.getMessage(), true); + } + + return url; + } } private class CheckRepositorySupportsMergeinfo extends TaskDescriptor { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnInteractiveAuthenticationProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnInteractiveAuthenticationProvider.java index 37b4f9d0448a..5be10cf05fbb 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnInteractiveAuthenticationProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnInteractiveAuthenticationProvider.java @@ -20,11 +20,13 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier; -import com.intellij.util.SystemProperties; import com.intellij.util.WaitForProgressToShow; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnAuthenticationManager; import org.jetbrains.idea.svn.SvnBundle; import org.jetbrains.idea.svn.SvnConfiguration; @@ -81,18 +83,13 @@ public class SvnInteractiveAuthenticationProvider implements ISVNAuthenticationP final boolean authCredsOn = authMayBeStored && myManager.getHostOptionsProvider().getHostOptions(url).isAuthStorageEnabled(); final String userName = - previousAuth != null && previousAuth.getUserName() != null ? previousAuth.getUserName() : SystemProperties.getUserName(); + previousAuth != null && previousAuth.getUserName() != null ? previousAuth.getUserName() : myManager.getDefaultUsername(kind, url); if (ISVNAuthenticationManager.PASSWORD.equals(kind)) {// || ISVNAuthenticationManager.USERNAME.equals(kind)) { command = new Runnable() { public void run() { SimpleCredentialsDialog dialog = new SimpleCredentialsDialog(myProject); dialog.setup(realm, userName, authCredsOn); - if (errorMessage == null) { - dialog.setTitle(SvnBundle.message("dialog.title.authentication.required")); - } - else { - dialog.setTitle(SvnBundle.message("dialog.title.authentication.required.was.failed")); - } + setTitle(dialog, errorMessage); dialog.show(); if (dialog.isOK()) { result[0] = new SVNPasswordAuthentication(dialog.getUserName(), dialog.getPassword(), dialog.isSaveAllowed(), url, false); @@ -108,12 +105,7 @@ public class SvnInteractiveAuthenticationProvider implements ISVNAuthenticationP public void run() { UserNameCredentialsDialog dialog = new UserNameCredentialsDialog(myProject); dialog.setup(realm, userName, authCredsOn); - if (errorMessage == null) { - dialog.setTitle(SvnBundle.message("dialog.title.authentication.required")); - } - else { - dialog.setTitle(SvnBundle.message("dialog.title.authentication.required.was.failed")); - } + setTitle(dialog, errorMessage); dialog.show(); if (dialog.isOK()) { result[0] = new SVNUserNameAuthentication(dialog.getUserName(), dialog.isSaveAllowed(), url, false); @@ -125,12 +117,7 @@ public class SvnInteractiveAuthenticationProvider implements ISVNAuthenticationP command = new Runnable() { public void run() { SSHCredentialsDialog dialog = new SSHCredentialsDialog(myProject, realm, userName, authCredsOn, url.getPort()); - if (errorMessage == null) { - dialog.setTitle(SvnBundle.message("dialog.title.authentication.required")); - } - else { - dialog.setTitle(SvnBundle.message("dialog.title.authentication.required.was.failed")); - } + setTitle(dialog, errorMessage); dialog.show(); if (dialog.isOK()) { int port = dialog.getPortNumber(); @@ -158,12 +145,7 @@ public class SvnInteractiveAuthenticationProvider implements ISVNAuthenticationP if (!StringUtil.isEmptyOrSpaces(file)) { dialog.setFile(file); } - if (errorMessage == null) { - dialog.setTitle(SvnBundle.message("dialog.title.authentication.required")); - } - else { - dialog.setTitle(SvnBundle.message("dialog.title.authentication.required.was.failed")); - } + setTitle(dialog, errorMessage); dialog.show(); if (dialog.isOK()) { result[0] = new SVNSSLAuthentication(new File(dialog.getCertificatePath()), String.valueOf(dialog.getCertificatePassword()), @@ -184,6 +166,12 @@ public class SvnInteractiveAuthenticationProvider implements ISVNAuthenticationP return result[0]; } + private static void setTitle(@NotNull DialogWrapper dialog, @Nullable SVNErrorMessage errorMessage) { + dialog.setTitle(errorMessage == null + ? SvnBundle.message("dialog.title.authentication.required") + : SvnBundle.message("dialog.title.authentication.required.was.failed")); + } + public int acceptServerAuthentication(final SVNURL url, String realm, final Object certificate, final boolean resultMayBeStored) { final int[] result = new int[1]; Runnable command; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CmdDiffClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CmdDiffClient.java new file mode 100644 index 000000000000..b774fe6b4aac --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CmdDiffClient.java @@ -0,0 +1,179 @@ +/* + * 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.diff; + +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vcs.FilePath; +import com.intellij.openapi.vcs.FileStatus; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vcs.changes.Change; +import com.intellij.openapi.vcs.changes.ContentRevision; +import com.intellij.openapi.vcs.changes.CurrentContentRevision; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.vcsUtil.VcsUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.svn.SvnStatusConvertor; +import org.jetbrains.idea.svn.api.BaseSvnClient; +import org.jetbrains.idea.svn.commandLine.*; +import org.jetbrains.idea.svn.history.SvnRepositoryContentRevision; +import org.tmatesoft.svn.core.SVNNodeKind; +import org.tmatesoft.svn.core.internal.util.SVNPathUtil; +import org.tmatesoft.svn.core.wc.SVNRevision; +import org.tmatesoft.svn.core.wc2.SvnTarget; + +import javax.xml.bind.JAXBException; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlValue; +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Konstantin Kolosovsky. + */ +public class CmdDiffClient extends BaseSvnClient implements DiffClient { + + @Override + public List compare(@NotNull SvnTarget target1, @NotNull SvnTarget target2) throws VcsException { + // TODO: Currently implemented only for "Compare with Branch" action - target1 is assumed to be file, target2 - repository url + // Such combination (file and url) with "--summarize" option is supported only in svn 1.8. + // For svn 1.7 "--summarize" is only supported when both targets are repository urls. + assertDirectory(target1); + assertUrl(target2); + + List parameters = new ArrayList(); + CommandUtil.put(parameters, target1); + CommandUtil.put(parameters, target2); + parameters.add("--xml"); + parameters.add("--summarize"); + + CommandExecutor executor = CommandUtil.execute(myVcs, target1, SvnCommandName.diff, parameters, null); + return parseOutput(target1, target2, executor); + } + + private List parseOutput(@NotNull SvnTarget target1, @NotNull SvnTarget target2, @NotNull CommandExecutor executor) + throws SvnBindException { + try { + DiffInfo diffInfo = CommandUtil.parse(executor.getOutput(), DiffInfo.class); + List result = ContainerUtil.newArrayList(); + + if (diffInfo != null && diffInfo.paths != null) { + for (DiffPath path : diffInfo.paths.diffPaths) { + result.add(createChange(target1, target2, path)); + } + } + + return result; + } + catch (JAXBException e) { + throw new SvnBindException(e); + } + } + + private ContentRevision createRemoteRevision(@NotNull FilePath remotePath, @NotNull FilePath localPath, @NotNull FileStatus status) { + // explicitly use local path for deleted items - so these items will be correctly displayed as deleted under local working copy node + // and not as deleted under remote branch node (in ChangesBrowser) + // NOTE, that content is still retrieved using remotePath. + return SvnRepositoryContentRevision + .create(myVcs, remotePath, status == FileStatus.DELETED ? localPath : null, SVNRevision.HEAD.getNumber()); + } + + private static ContentRevision createLocalRevision(@NotNull FilePath path) { + return CurrentContentRevision.create(path); + } + + @NotNull + private Change createChange(@NotNull SvnTarget target1, @NotNull SvnTarget target2, @NotNull DiffPath diffPath) throws SvnBindException { + // TODO: 1) Unify logic of creating Change instance with SvnDiffEditor and SvnChangeProviderContext + // TODO: 2) If some directory is switched, files inside it are returned as modified in "svn diff --summarize", even if they are equal + // TODO: to branch files by content - possibly add separate processing of all switched files + // TODO: 3) Properties change is currently not added as part of result change like in SvnChangeProviderContext.patchWithPropertyChange + + File oldTarget = CommandUtil.resolvePath(target1.getFile(), diffPath.path); + String relativePath = FileUtil.getRelativePath(target1.getFile(), oldTarget); + + if (relativePath == null) { + throw new SvnBindException("Could not get relative path for " + target1.getFile() + " and " + oldTarget); + } + + FilePath localPath = VcsUtil.getFilePath(oldTarget, diffPath.isDirectory()); + FilePath remotePath = VcsUtil + .getFilePathOnNonLocal(SVNPathUtil.append(target2.getPathOrUrlDecodedString(), FileUtil.toSystemIndependentName(relativePath)), + diffPath.isDirectory()); + + FileStatus status = SvnStatusConvertor + .convertStatus(SvnStatusHandler.getStatus(diffPath.itemStatus), SvnStatusHandler.getStatus(diffPath.propertiesStatus)); + + ContentRevision beforeRevision = status == FileStatus.ADDED ? null : createRemoteRevision(remotePath, localPath, status); + ContentRevision afterRevision = status == FileStatus.DELETED ? null : createLocalRevision(localPath); + + return createChange(status, beforeRevision, afterRevision); + } + + @NotNull + private static Change createChange(@NotNull final FileStatus status, + @Nullable final ContentRevision beforeRevision, + @Nullable final ContentRevision afterRevision) { + // isRenamed() and isMoved() are always false here not to have text like "moved from ..." in changes window - by default different + // paths in before and after revisions are treated as move, but this is not the case for "Compare with Branch" + return new Change(beforeRevision, afterRevision, status) { + @Override + public boolean isRenamed() { + return false; + } + + @Override + public boolean isMoved() { + return false; + } + }; + } + + @XmlRootElement(name = "diff") + public static class DiffInfo { + + @XmlElement(name = "paths") + public DiffPaths paths; + } + + public static class DiffPaths { + + @XmlElement(name = "path") + public List diffPaths = new ArrayList(); + } + + public static class DiffPath { + + @XmlAttribute(name = "kind") + public String kind; + + @XmlAttribute(name = "props") + public String propertiesStatus; + + @XmlAttribute(name = "item") + public String itemStatus; + + @XmlValue + public String path; + + public boolean isDirectory() { + return SVNNodeKind.DIR.equals(SVNNodeKind.parseKind(kind)); + } + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CompareWithBranchAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CompareWithBranchAction.java new file mode 100644 index 000000000000..a8e0ca9e5e7a --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CompareWithBranchAction.java @@ -0,0 +1,81 @@ +/* + * Copyright 2000-2009 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.diff; + +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import com.intellij.openapi.project.DumbAware; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vcs.FileStatus; +import com.intellij.openapi.vcs.FileStatusManager; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.*; +import org.jetbrains.idea.svn.actions.SelectBranchPopup; +import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew; + +/** + * @author yole + */ +public class CompareWithBranchAction extends AnAction implements DumbAware { + + public void actionPerformed(AnActionEvent e) { + Project project = e.getData(CommonDataKeys.PROJECT); + assert project != null; + final VirtualFile virtualFile = e.getData(CommonDataKeys.VIRTUAL_FILE); + + SelectBranchPopup + .show(project, virtualFile, new MyBranchSelectedCallback(virtualFile), SvnBundle.message("compare.with.branch.popup.title")); + } + + @Override + public void update(final AnActionEvent e) { + Project project = e.getData(CommonDataKeys.PROJECT); + VirtualFile virtualFile = e.getData(CommonDataKeys.VIRTUAL_FILE); + e.getPresentation().setEnabled(isEnabled(project, virtualFile)); + } + + private static boolean isEnabled(final Project project, final VirtualFile virtualFile) { + if (project == null || virtualFile == null) { + return false; + } + final FileStatus fileStatus = FileStatusManager.getInstance(project).getStatus(virtualFile); + if (fileStatus == FileStatus.UNKNOWN || fileStatus == FileStatus.ADDED || fileStatus == FileStatus.IGNORED) { + return false; + } + return true; + } + + private static class MyBranchSelectedCallback implements SelectBranchPopup.BranchSelectedCallback { + + @NotNull private final VirtualFile myVirtualFile; + + public MyBranchSelectedCallback(@NotNull VirtualFile virtualFile) { + myVirtualFile = virtualFile; + } + + public void branchSelected(Project project, SvnBranchConfigurationNew configuration, String url, long revision) { + ElementWithBranchComparer comparer = + myVirtualFile.isDirectory() + ? new DirectoryWithBranchComparer(project, myVirtualFile, url, revision) + : new FileWithBranchComparer(project, myVirtualFile, url, revision); + + comparer.run(); + } + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/AuthManagerType.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DiffClient.java similarity index 56% rename from plugins/svn4idea/src/org/jetbrains/idea/svn/AuthManagerType.java rename to plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DiffClient.java index b46b7a875b51..a9678be33737 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/AuthManagerType.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DiffClient.java @@ -13,14 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.svn; +package org.jetbrains.idea.svn.diff; + +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vcs.changes.Change; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.api.SvnClient; +import org.tmatesoft.svn.core.wc2.SvnTarget; + +import java.util.List; /** - * Created with IntelliJ IDEA. - * User: Irina.Chernushina - * Date: 2/28/13 - * Time: 10:14 AM + * @author Konstantin Kolosovsky. */ -public enum AuthManagerType { - active, passive, usual; +public interface DiffClient extends SvnClient { + + List compare(@NotNull SvnTarget target1, @NotNull SvnTarget target2) throws VcsException; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DirectoryWithBranchComparer.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DirectoryWithBranchComparer.java new file mode 100644 index 000000000000..48ba029f929d --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DirectoryWithBranchComparer.java @@ -0,0 +1,204 @@ +/* + * 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.diff; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vcs.AbstractVcsHelper; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vcs.changes.Change; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.SvnBundle; +import org.jetbrains.idea.svn.SvnConfiguration; +import org.jetbrains.idea.svn.SvnProgressCanceller; +import org.jetbrains.idea.svn.WorkingCopyFormat; +import org.jetbrains.idea.svn.status.SvnDiffEditor; +import org.tmatesoft.svn.core.*; +import org.tmatesoft.svn.core.internal.wc.SVNCancellableEditor; +import org.tmatesoft.svn.core.internal.wc.SVNErrorManager; +import org.tmatesoft.svn.core.internal.wc.admin.SVNAdminAreaInfo; +import org.tmatesoft.svn.core.internal.wc.admin.SVNEntry; +import org.tmatesoft.svn.core.internal.wc.admin.SVNReporter; +import org.tmatesoft.svn.core.internal.wc.admin.SVNWCAccess; +import org.tmatesoft.svn.core.internal.wc17.SVNReporter17; +import org.tmatesoft.svn.core.internal.wc17.SVNWCContext; +import org.tmatesoft.svn.core.io.SVNRepository; +import org.tmatesoft.svn.core.wc.ISVNEventHandler; +import org.tmatesoft.svn.core.wc.SVNEvent; +import org.tmatesoft.svn.core.wc.SVNInfo; +import org.tmatesoft.svn.core.wc.SVNRevision; +import org.tmatesoft.svn.core.wc2.SvnTarget; +import org.tmatesoft.svn.util.SVNDebugLog; +import org.tmatesoft.svn.util.SVNLogType; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/** +* @author Konstantin Kolosovsky. +*/ +public class DirectoryWithBranchComparer extends ElementWithBranchComparer { + + @NotNull private final StringBuilder titleBuilder = new StringBuilder(); + @NotNull private final List changes = new ArrayList(); + + public DirectoryWithBranchComparer(@NotNull Project project, + @NotNull VirtualFile virtualFile, + @NotNull String branchUrl, + long branchRevision) { + super(project, virtualFile, branchUrl, branchRevision); + } + + @Override + protected void compare() throws SVNException, VcsException { + titleBuilder.append(SvnBundle.message("repository.browser.compare.title", myElementUrl, + FileUtil.toSystemDependentName(myVirtualFile.getPresentableUrl()))); + + final File ioFile = new File(myVirtualFile.getPath()); + WorkingCopyFormat format = myVcs.getWorkingCopyFormat(ioFile); + + if (WorkingCopyFormat.ONE_DOT_EIGHT.equals(format)) { + // svn 1.7 command line "--summarize" option for "diff" command does not support comparing working copy directories with repository + // directories - that is why command line is only used explicitly for svn 1.8 + compareWithCommandLine(); + } + else if (WorkingCopyFormat.ONE_DOT_SEVEN.equals(format)) { + report17DirDiff(); + } + else { + report16DirDiff(); + } + } + + private void compareWithCommandLine() throws VcsException { + SvnTarget target1 = SvnTarget.fromFile(new File(myVirtualFile.getPath())); + SvnTarget target2 = SvnTarget.fromURL(myElementUrl); + + changes.addAll(myVcs.getFactory(target1).createDiffClient().compare(target1, target2)); + } + + private void report17DirDiff() throws SVNException { + final File ioFile = new File(myVirtualFile.getPath()); + final SVNInfo info1 = myVcs.getInfo(ioFile, SVNRevision.HEAD); + + if (info1 == null) { + SVNErrorMessage err = + SVNErrorMessage.create(SVNErrorCode.ENTRY_NOT_FOUND, "''{0}'' is not under version control", myVirtualFile.getPath()); + SVNErrorManager.error(err, SVNLogType.WC); + } + else if (info1.getURL() == null) { + SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_MISSING_URL, "''{0}'' has no URL", myVirtualFile.getPath()); + SVNErrorManager.error(err, SVNLogType.WC); + } + + final SVNReporter17 reporter17 = + new SVNReporter17(ioFile, new SVNWCContext(SvnConfiguration.getInstance(myProject).getOptions(myProject), new ISVNEventHandler() { + @Override + public void handleEvent(SVNEvent event, double progress) throws SVNException { + } + + @Override + public void checkCancelled() throws SVNCancelException { + } + }), + false, true, SVNDepth.INFINITY, false, false, true, false, + SVNDebugLog.getDefaultLog()); + SVNRepository repository = null; + SVNRepository repository2 = null; + try { + repository = myVcs.createRepository(info1.getURL()); + long rev = repository.getLatestRevision(); + repository2 = myVcs.createRepository(myElementUrl.toString()); + SvnDiffEditor diffEditor = new SvnDiffEditor(myVirtualFile, repository2, rev, true); + repository.diff(myElementUrl, rev, rev, null, true, SVNDepth.INFINITY, false, reporter17, + SVNCancellableEditor.newInstance(diffEditor, new SvnProgressCanceller(), null)); + changes.addAll(diffEditor.getChangesMap().values()); + } + finally { + if (repository != null) { + repository.closeSession(); + } + if (repository2 != null) { + repository2.closeSession(); + } + } + } + + private void report16DirDiff() throws SVNException { + // here there's 1.6 copy so ok to use SVNWCAccess + final SVNWCAccess wcAccess = SVNWCAccess.newInstance(null); + wcAccess.setOptions(myVcs.getSvnOptions()); + SVNRepository repository = null; + SVNRepository repository2 = null; + try { + SVNAdminAreaInfo info = wcAccess.openAnchor(new File(myVirtualFile.getPath()), false, SVNWCAccess.INFINITE_DEPTH); + File anchorPath = info.getAnchor().getRoot(); + String target = "".equals(info.getTargetName()) ? null : info.getTargetName(); + + SVNEntry anchorEntry = info.getAnchor().getEntry("", false); + if (anchorEntry == null) { + SVNErrorMessage err = + SVNErrorMessage.create(SVNErrorCode.ENTRY_NOT_FOUND, "''{0}'' is not under version control", anchorPath); + SVNErrorManager.error(err, SVNLogType.WC); + } + else if (anchorEntry.getURL() == null) { + SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_MISSING_URL, "''{0}'' has no URL", anchorPath); + SVNErrorManager.error(err, SVNLogType.WC); + } + + SVNURL anchorURL = anchorEntry.getSVNURL(); + SVNReporter reporter = new SVNReporter(info, info.getAnchor().getFile(info.getTargetName()), false, true, SVNDepth.INFINITY, + false, false, true, SVNDebugLog.getDefaultLog()); + + repository = myVcs.createRepository(anchorURL.toString()); + long rev = repository.getLatestRevision(); + repository2 = myVcs.createRepository((target == null) ? myElementUrl.toString() : myElementUrl.removePathTail().toString()); + SvnDiffEditor diffEditor = new SvnDiffEditor((target == null) ? myVirtualFile : myVirtualFile.getParent(), + repository2, rev, true); + repository.diff(myElementUrl, rev, rev, target, true, true, false, reporter, + SVNCancellableEditor.newInstance(diffEditor, new SvnProgressCanceller(), null)); + changes.addAll(diffEditor.getChangesMap().values()); + } + finally { + wcAccess.close(); + if (repository != null) { + repository.closeSession(); + } + if (repository2 != null) { + repository2.closeSession(); + } + } + } + + @Override + protected void onCancel() { + changes.clear(); + } + + @Override + protected void showResult() { + if (!changes.isEmpty()) { + AbstractVcsHelper.getInstance(myProject).showWhatDiffersBrowser(null, changes, titleBuilder.toString()); + } + } + + @Override + public String getTitle() { + return SvnBundle.message("progress.computing.difference"); + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/ElementWithBranchComparer.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/ElementWithBranchComparer.java new file mode 100644 index 000000000000..2d67ce7e58ad --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/ElementWithBranchComparer.java @@ -0,0 +1,163 @@ +/* + * 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.diff; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.Task; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.WaitForProgressToShow; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.svn.*; +import org.jetbrains.idea.svn.commandLine.SvnBindException; +import org.tmatesoft.svn.core.SVNCancelException; +import org.tmatesoft.svn.core.SVNErrorCode; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNURL; +import org.tmatesoft.svn.core.internal.util.SVNPathUtil; + +import java.io.File; + +/** +* @author Konstantin Kolosovsky. +*/ +public abstract class ElementWithBranchComparer { + + private static final Logger LOG = Logger.getInstance(ElementWithBranchComparer.class); + + @NotNull protected final Project myProject; + @NotNull protected final SvnVcs myVcs; + @NotNull protected final VirtualFile myVirtualFile; + @NotNull protected final String myBranchUrl; + protected final long myBranchRevision; + protected SVNURL myElementUrl; + + ElementWithBranchComparer(@NotNull Project project, + @NotNull VirtualFile virtualFile, + @NotNull String branchUrl, + long branchRevision) { + myProject = project; + myVcs = SvnVcs.getInstance(myProject); + myVirtualFile = virtualFile; + myBranchUrl = branchUrl; + myBranchRevision = branchRevision; + } + + public void run() { + new Task.Modal(myProject, getTitle(), true) { + @Override + public void run(@NotNull ProgressIndicator indicator) { + try { + beforeCompare(); + myElementUrl = resolveElementUrl(); + if (myElementUrl == null) { + reportNotFound(); + } + else { + compare(); + } + } + catch (SVNCancelException ex) { + ElementWithBranchComparer.this.onCancel(); + } + catch (SVNException ex) { + reportException(new SvnBindException(ex)); + } + catch (SvnBindException ex) { + reportException(ex); + } + catch (VcsException ex) { + reportGeneralException(ex); + } + } + }.queue(); + showResult(); + } + + protected void beforeCompare() { + } + + protected abstract void compare() throws SVNException, VcsException; + + protected abstract void showResult(); + + protected void onCancel() { + } + + public abstract String getTitle(); + + @Nullable + protected SVNURL resolveElementUrl() throws SVNException { + final SvnFileUrlMapping urlMapping = myVcs.getSvnFileUrlMapping(); + final File file = new File(myVirtualFile.getPath()); + final SVNURL fileUrl = urlMapping.getUrlForFile(file); + if (fileUrl == null) { + return null; + } + + final String fileUrlString = fileUrl.toString(); + final RootUrlInfo rootMixed = urlMapping.getWcRootForUrl(fileUrlString); + if (rootMixed == null) { + return null; + } + + final SVNURL thisBranchForUrl = SvnUtil.getBranchForUrl(myVcs, rootMixed.getVirtualFile(), fileUrlString); + if (thisBranchForUrl == null) { + return null; + } + + final String relativePath = SVNPathUtil.getRelativePath(thisBranchForUrl.toString(), fileUrlString); + return SVNURL.parseURIEncoded(SVNPathUtil.append(myBranchUrl, relativePath)); + } + + private void reportException(final SvnBindException e) { + if (e.contains(SVNErrorCode.RA_ILLEGAL_URL) || + e.contains(SVNErrorCode.CLIENT_UNRELATED_RESOURCES) || + e.contains(SVNErrorCode.RA_DAV_PATH_NOT_FOUND) || + e.contains(SVNErrorCode.FS_NOT_FOUND) || + e.contains(SVNErrorCode.ILLEGAL_TARGET)) { + reportNotFound(); + } + else { + reportGeneralException(e); + } + } + + private void reportGeneralException(final Exception e) { + WaitForProgressToShow.runOrInvokeLaterAboveProgress(new Runnable() { + public void run() { + Messages.showMessageDialog(myProject, e.getMessage(), + SvnBundle.message("compare.with.branch.error.title"), Messages.getErrorIcon()); + } + }, null, myProject); + LOG.info(e); + } + + private void reportNotFound() { + WaitForProgressToShow.runOrInvokeLaterAboveProgress(new Runnable() { + public void run() { + Messages.showMessageDialog(myProject, + SvnBundle + .message("compare.with.branch.location.error", myVirtualFile.getPresentableUrl(), myBranchUrl), + SvnBundle.message("compare.with.branch.error.title"), Messages.getErrorIcon()); + } + }, null, myProject); + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/FileWithBranchComparer.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/FileWithBranchComparer.java new file mode 100644 index 000000000000..b4b4e3c3c2ea --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/FileWithBranchComparer.java @@ -0,0 +1,82 @@ +/* + * 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.diff; + +import com.intellij.openapi.diff.DiffManager; +import com.intellij.openapi.diff.FileContent; +import com.intellij.openapi.diff.SimpleContent; +import com.intellij.openapi.diff.SimpleDiffRequest; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Ref; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vfs.CharsetToolkit; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.SvnBundle; +import org.jetbrains.idea.svn.SvnUtil; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.wc.SVNRevision; +import org.tmatesoft.svn.core.wc2.SvnTarget; + +/** +* @author Konstantin Kolosovsky. +*/ +public class FileWithBranchComparer extends ElementWithBranchComparer { + + @NotNull private final Ref content = new Ref(); + @NotNull private final StringBuilder remoteTitleBuilder = new StringBuilder(); + @NotNull private final Ref success = new Ref(); + + public FileWithBranchComparer(@NotNull Project project, + @NotNull VirtualFile virtualFile, + @NotNull String branchUrl, + long branchRevision) { + super(project, virtualFile, branchUrl, branchRevision); + } + + @Override + protected void beforeCompare() { + final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); + if (indicator != null) { + indicator.setIndeterminate(true); + } + } + + @Override + protected void compare() throws SVNException, VcsException { + remoteTitleBuilder.append(myElementUrl); + content.set(SvnUtil.getFileContents(myVcs, SvnTarget.fromURL(myElementUrl), SVNRevision.HEAD, SVNRevision.UNDEFINED)); + success.set(true); + } + + @Override + protected void showResult() { + if (!success.isNull()) { + SimpleDiffRequest req = new SimpleDiffRequest(myProject, SvnBundle.message("compare.with.branch.diff.title")); + req.setContents(new SimpleContent(CharsetToolkit.bytesToString(content.get(), myVirtualFile.getCharset())), + new FileContent(myProject, myVirtualFile)); + req.setContentTitles(remoteTitleBuilder.toString(), myVirtualFile.getPresentableUrl()); + DiffManager.getInstance().getDiffTool().show(req); + } + } + + @Override + public String getTitle() { + return SvnBundle.message("compare.with.branch.progress.loading.content"); + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/SvnKitDiffClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/SvnKitDiffClient.java new file mode 100644 index 000000000000..07bf6ec77a28 --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/SvnKitDiffClient.java @@ -0,0 +1,35 @@ +/* + * 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.diff; + +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vcs.changes.Change; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.api.BaseSvnClient; +import org.tmatesoft.svn.core.wc2.SvnTarget; + +import java.util.List; + +/** + * @author Konstantin Kolosovsky. + */ +public class SvnKitDiffClient extends BaseSvnClient implements DiffClient { + + @Override + public List compare(@NotNull SvnTarget target1, @NotNull SvnTarget target2) throws VcsException { + throw new UnsupportedOperationException("Diff client is not implemented for SVNKit"); + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java index d19ed02f07c1..7fb35d14ca4d 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java @@ -30,6 +30,9 @@ import org.tmatesoft.svn.core.wc.SVNRevision; import java.util.Map; import java.util.Set; +// TODO: This one seem to determine revision in which branch was created - copied from trunk. +// TODO: This could be done in one command "svn log -r 0:HEAD --stop-on-copy --limit 1". +// TODO: Check for 1.7 and rewrite using this approach. public class FirstInBranch implements Runnable { private final SvnVcs myVcs; private final String myBranchUrl; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java index a625e5b578ba..b5dfd8ccdbd4 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java @@ -188,7 +188,7 @@ public class SvnHistoryProvider } } - final boolean showMergeSources = SvnConfiguration.getInstance(myVcs.getProject()).SHOW_MERGE_SOURCES_IN_ANNOTATE; + final boolean showMergeSources = SvnConfiguration.getInstance(myVcs.getProject()).isShowMergeSourcesInAnnotate(); final LogLoader logLoader; if (path.isNonLocal()) { logLoader = new RepositoryLoader(myVcs, committedPath, from, to, limit, peg, forceBackwards, showMergeSources); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryBinaryContentRevision.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryBinaryContentRevision.java index 49e8c1dd1076..fb7499cdd38a 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryBinaryContentRevision.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryBinaryContentRevision.java @@ -18,6 +18,7 @@ package org.jetbrains.idea.svn.history; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.changes.BinaryContentRevision; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnVcs; @@ -27,9 +28,9 @@ import org.jetbrains.idea.svn.SvnVcs; public class SvnRepositoryBinaryContentRevision extends SvnRepositoryContentRevision implements BinaryContentRevision { private byte[] myBinaryContent; - public SvnRepositoryBinaryContentRevision(final SvnVcs vcs, final String repositoryRoot, final String path, + public SvnRepositoryBinaryContentRevision(final SvnVcs vcs, @NotNull final FilePath remotePath, @Nullable final FilePath localPath, final long revision) { - super(vcs, repositoryRoot, path, localPath, revision); + super(vcs, remotePath, localPath, revision); } @Nullable diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryContentRevision.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryContentRevision.java index b7a0bb9329b0..36c80b1caaae 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryContentRevision.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryContentRevision.java @@ -23,23 +23,24 @@ package org.jetbrains.idea.svn.history; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.fileTypes.FileType; -import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.util.Throwable2Computable; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.VcsKey; -import com.intellij.openapi.vcs.actions.VcsContextFactory; import com.intellij.openapi.vcs.changes.ContentRevision; import com.intellij.openapi.vcs.changes.MarkerVcsContentRevision; import com.intellij.openapi.vcs.history.VcsRevisionNumber; import com.intellij.openapi.vcs.impl.ContentRevisionCache; +import com.intellij.vcsUtil.VcsUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.svn.*; -import org.tmatesoft.svn.core.SVNException; +import org.jetbrains.idea.svn.SvnBundle; +import org.jetbrains.idea.svn.SvnRevisionNumber; +import org.jetbrains.idea.svn.SvnUtil; +import org.jetbrains.idea.svn.SvnVcs; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; @@ -48,32 +49,16 @@ import java.io.IOException; import java.io.OutputStream; public class SvnRepositoryContentRevision implements ContentRevision, MarkerVcsContentRevision { - private final String myRepositoryRoot; private final SvnVcs myVcs; private final String myPath; @NotNull private final FilePath myFilePath; private final long myRevision; - SvnRepositoryContentRevision(final SvnVcs vcs, final String repositoryRoot, final String path, @Nullable final FilePath localPath, + public SvnRepositoryContentRevision(final SvnVcs vcs, @NotNull final FilePath remotePath, @Nullable final FilePath localPath, final long revision) { myVcs = vcs; - myPath = path; - myRepositoryRoot = repositoryRoot; - if (localPath != null) { - myFilePath = localPath; - } - else { - FilePath local; - try { - final String fullPath = SvnUtil.appendMultiParts(repositoryRoot, myPath); - local = VcsContextFactory.SERVICE.getInstance().createFilePathOnNonLocal(fullPath, false); - } - catch (SVNException e) { - // todo what to do safely? - local = VcsContextFactory.SERVICE.getInstance().createFilePathOnNonLocal(repositoryRoot, false); - } - myFilePath = local; - } + myPath = FileUtil.toSystemIndependentName(remotePath.getPath()); + myFilePath = localPath != null ? localPath : remotePath; myRevision = revision; } @@ -125,15 +110,19 @@ public class SvnRepositoryContentRevision implements ContentRevision, MarkerVcsC public static SvnRepositoryContentRevision create(final SvnVcs vcs, final String repositoryRoot, final String path, @Nullable final FilePath localPath, final long revision) { - int fileNamePos = path.lastIndexOf('/'); - if (fileNamePos >= 0) { - String fileName = path.substring(fileNamePos); - final FileType fileType = FileTypeManager.getInstance().getFileTypeByFileName(fileName); - if (fileType.isBinary()) { - return new SvnRepositoryBinaryContentRevision(vcs, repositoryRoot, path, localPath, revision); - } - } - return new SvnRepositoryContentRevision(vcs, repositoryRoot, path, localPath, revision); + // TODO: Check if isDirectory = false always true for this method calls + FilePath remotePath = VcsUtil.getFilePathOnNonLocal(SvnUtil.appendMultiParts(repositoryRoot, path), false); + + return create(vcs, remotePath, localPath, revision); + } + + public static SvnRepositoryContentRevision create(@NotNull SvnVcs vcs, + @NotNull FilePath remotePath, + @Nullable FilePath localPath, + long revision) { + return remotePath.getFileType().isBinary() + ? new SvnRepositoryBinaryContentRevision(vcs, remotePath, localPath, revision) + : new SvnRepositoryContentRevision(vcs, remotePath, localPath, revision); } @Override @@ -180,12 +169,7 @@ public class SvnRepositoryContentRevision implements ContentRevision, MarkerVcsC } public String getFullPath() { - String fullPath = myRepositoryRoot; - if (!fullPath.endsWith("/") && !myPath.startsWith("/")) { - fullPath += "/"; - } - fullPath += myPath; - return fullPath; + return myPath; } public String getPath() { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/GroupMerger.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/GroupMerger.java index 3c4c17ed6ddc..cb62668cbb25 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/GroupMerger.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/GroupMerger.java @@ -31,7 +31,6 @@ import org.jetbrains.idea.svn.update.UpdateEventHandler; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; -import org.tmatesoft.svn.core.wc.SVNDiffOptions; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc.SVNRevisionRange; import org.tmatesoft.svn.core.wc2.SvnTarget; @@ -132,7 +131,7 @@ public class GroupMerger implements IMerger { SvnTarget source = SvnTarget.fromURL(myCurrentBranchUrl); MergeClient client = myVcs.getFactory(myTarget).createMergeClient(); - client.merge(source, createRange(), myTarget, SVNDepth.INFINITY, mySvnConfig.MERGE_DRY_RUN, myDryRun, true, + client.merge(source, createRange(), myTarget, SVNDepth.INFINITY, mySvnConfig.isMergeDryRun(), myDryRun, true, mySvnConfig.getMergeOptions(), myHandler); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/IntegratedSelectedOptionsDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/IntegratedSelectedOptionsDialog.java index 2d2f28502928..47d26335f3f4 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/IntegratedSelectedOptionsDialog.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/IntegratedSelectedOptionsDialog.java @@ -97,8 +97,8 @@ public class IntegratedSelectedOptionsDialog extends DialogWrapper { } SvnConfiguration svnConfig = SvnConfiguration.getInstance(myVcs.getProject()); - myDryRunCheckbox.setSelected(svnConfig.MERGE_DRY_RUN); - myIgnoreWhitespacesCheckBox.setSelected(svnConfig.IGNORE_SPACES_IN_MERGE); + myDryRunCheckbox.setSelected(svnConfig.isMergeDryRun()); + myIgnoreWhitespacesCheckBox.setSelected(svnConfig.isIgnoreSpacesInMerge()); mySourceInfoLabel.setText(SvnBundle.message("action.Subversion.integrate.changes.branch.info.source.label.text", currentBranch)); myTargetInfoLabel.setText(SvnBundle.message("action.Subversion.integrate.changes.branch.info.target.label.text", selectedBranchUrl)); @@ -223,8 +223,8 @@ public class IntegratedSelectedOptionsDialog extends DialogWrapper { public void saveOptions() { SvnConfiguration svnConfig = SvnConfiguration.getInstance(myVcs.getProject()); - svnConfig.MERGE_DRY_RUN = myDryRunCheckbox.isSelected(); - svnConfig.IGNORE_SPACES_IN_MERGE = myIgnoreWhitespacesCheckBox.isSelected(); + svnConfig.setMergeDryRun(myDryRunCheckbox.isSelected()); + svnConfig.setIgnoreSpacesInMerge(myIgnoreWhitespacesCheckBox.isSelected()); } protected JComponent createCenterPanel() { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/Merger.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/Merger.java index 1c50dde706c1..8f534b90bb27 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/Merger.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/Merger.java @@ -128,7 +128,7 @@ public class Merger implements IMerger { SvnTarget source = SvnTarget.fromURL(myCurrentBranchUrl); MergeClient client = myVcs.getFactory(myTarget).createMergeClient(); - client.merge(source, createRange(), myTarget, SVNDepth.INFINITY, mySvnConfig.MERGE_DRY_RUN, isRecordOnly(), true, + client.merge(source, createRange(), myTarget, SVNDepth.INFINITY, mySvnConfig.isMergeDryRun(), isRecordOnly(), true, mySvnConfig.getMergeOptions(), myHandler); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/PointMerger.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/PointMerger.java index 78b8e866129f..1a58a3c80b68 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/PointMerger.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/PointMerger.java @@ -18,7 +18,6 @@ package org.jetbrains.idea.svn.integrate; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnRevisionNumber; import org.jetbrains.idea.svn.SvnUtil; @@ -88,7 +87,7 @@ public class PointMerger extends Merger { SvnTarget source1 = SvnTarget.fromURL(SVNURL.parseURIEncoded(beforeUrl), ((SvnRevisionNumber)before.getRevisionNumber()).getRevision()); SvnTarget source2 = SvnTarget.fromURL(SVNURL.parseURIEncoded(afterUrl), ((SvnRevisionNumber) after.getRevisionNumber()).getRevision()); - client.merge(source1, source2, afterPath, SVNDepth.FILES, true, mySvnConfig.MERGE_DRY_RUN, false, false, mySvnConfig.getMergeOptions(), + client.merge(source1, source2, afterPath, SVNDepth.FILES, true, mySvnConfig.isMergeDryRun(), false, false, mySvnConfig.getMergeOptions(), myHandler); } @@ -99,7 +98,7 @@ public class PointMerger extends Merger { final File beforePath = SvnUtil.fileFromUrl(myTarget, path, beforeUrl); DeleteClient client = myVcs.getFactory(myTarget).createDeleteClient(); - client.delete(beforePath, false, mySvnConfig.MERGE_DRY_RUN, myHandler); + client.delete(beforePath, false, mySvnConfig.isMergeDryRun(), myHandler); } private void add(final Change change) throws SVNException, VcsException { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/ResolveWorker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/ResolveWorker.java index 45558e440d83..f283afa7550a 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/ResolveWorker.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/ResolveWorker.java @@ -75,7 +75,7 @@ public class ResolveWorker { } return ((! myConflictedVirtualFiles.isEmpty()) || (! haveUnresolvedConflicts(updatedFiles))) && - (! SvnConfiguration.getInstance(myProject).MERGE_DRY_RUN); + (!SvnConfiguration.getInstance(myProject).isMergeDryRun()); } public static boolean haveUnresolvedConflicts(final UpdatedFiles updatedFiles) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesActionPerformer.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesActionPerformer.java index a793aae7b10d..e07fac011c9e 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesActionPerformer.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesActionPerformer.java @@ -69,7 +69,7 @@ public class SvnIntegrateChangesActionPerformer implements SelectBranchPopup.Bra return; } final SvnIntegrateChangesTask task = new SvnIntegrateChangesTask(myVcs, info, myMergerFactory, sourceUrl, SvnBundle.message("action.Subversion.integrate.changes.messages.title"), - SvnConfiguration.getInstance(myVcs.getProject()).MERGE_DRY_RUN, name); + SvnConfiguration.getInstance(myVcs.getProject()).isMergeDryRun(), name); ProgressManager.getInstance().run(task); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java index 39d72f5639fd..f492a434a252 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java @@ -63,7 +63,7 @@ public class OneRecursiveShotMergeInfoWorker implements MergeInfoWorker { } public void prepare() throws VcsException { - final SVNDepth depth = SvnConfiguration.getInstance(myProject).CHECK_NESTED_FOR_QUICK_MERGE ? SVNDepth.INFINITY : SVNDepth.EMPTY; + final SVNDepth depth = SvnConfiguration.getInstance(myProject).isCheckNestedForQuickMerge() ? SVNDepth.INFINITY : SVNDepth.EMPTY; ISVNPropertyHandler handler = new ISVNPropertyHandler() { public void handleProperty(File path, SVNPropertyData property) throws SVNException { final String key = keyFromFile(path); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnWcClientI.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnWcClientI.java index 036de6b785be..48ba32e5357d 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnWcClientI.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnWcClientI.java @@ -15,6 +15,8 @@ */ package org.jetbrains.idea.svn.portable; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.wc.*; @@ -38,4 +40,6 @@ public interface SvnWcClientI extends SvnMarkerInterface { ISVNInfoHandler handler) throws SVNException; SVNInfo doInfo(File path, SVNRevision revision) throws SVNException; SVNInfo doInfo(SVNURL url, SVNRevision pegRevision, SVNRevision revision) throws SVNException; + + void doInfo(@NotNull Collection paths, @Nullable ISVNInfoHandler handler) throws SVNException; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnkitSvnWcClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnkitSvnWcClient.java index faee8ecc3cb2..44cca7fa26c8 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnkitSvnWcClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnkitSvnWcClient.java @@ -16,6 +16,7 @@ package org.jetbrains.idea.svn.portable; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnVcs; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.wc.*; @@ -83,4 +84,9 @@ public class SvnkitSvnWcClient implements SvnWcClientI { public SVNInfo doInfo(SVNURL url, SVNRevision pegRevision, SVNRevision revision) throws SVNException { return getClient().doInfo(url, pegRevision, revision); } + + @Override + public void doInfo(@NotNull Collection paths, @Nullable ISVNInfoHandler handler) throws SVNException { + throw new UnsupportedOperationException(); + } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/statistics/SvnWorkingCopyFormatUsagesCollector.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/statistics/SvnWorkingCopyFormatUsagesCollector.java new file mode 100644 index 000000000000..72558d4b2330 --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/statistics/SvnWorkingCopyFormatUsagesCollector.java @@ -0,0 +1,65 @@ +/* + * 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.statistics; + +import com.intellij.internal.statistic.beans.GroupDescriptor; +import com.intellij.internal.statistic.beans.UsageDescriptor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.vcs.statistics.VcsUsagesCollector; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.NestedCopyType; +import org.jetbrains.idea.svn.RootUrlInfo; +import org.jetbrains.idea.svn.SvnVcs; + +import java.util.List; +import java.util.Set; + +/** + * @author Konstantin Kolosovsky. + */ +public class SvnWorkingCopyFormatUsagesCollector extends VcsUsagesCollector { + + private static final String GROUP_ID = "svn working copy format"; + + @NotNull + public GroupDescriptor getGroupId() { + return GroupDescriptor.create(GROUP_ID, GroupDescriptor.HIGHER_PRIORITY); + } + + @NotNull + public Set getProjectUsages(@NotNull Project project) { + SvnVcs vcs = SvnVcs.getInstance(project); + + // do not track roots with errors (SvnFileUrlMapping.getErrorRoots()) as they are "not usable" until errors are resolved + // skip externals and switched directories as they will have the same format + List roots = ContainerUtil.filter(vcs.getSvnFileUrlMapping().getAllWcInfos(), new Condition() { + @Override + public boolean value(RootUrlInfo info) { + return info.getType() == null || NestedCopyType.inner.equals(info.getType()); + } + }); + + return ContainerUtil.map2Set(roots, new Function() { + @Override + public UsageDescriptor fun(RootUrlInfo info) { + return new UsageDescriptor(info.getFormat().toString(), 1); + } + }); + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/MergeFromTheirsResolver.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/MergeFromTheirsResolver.java index cfafc6585e92..31b040cd98dd 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/MergeFromTheirsResolver.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/MergeFromTheirsResolver.java @@ -587,8 +587,8 @@ public class MergeFromTheirsResolver { private boolean getAddedFilesPlaceOption() { final SvnConfiguration configuration = SvnConfiguration.getInstance(myVcs.getProject()); - boolean add = Boolean.TRUE.equals(configuration.TREE_CONFLICT_MERGE_THEIRS_NEW_INTO_OLD_PLACE); - if (configuration.TREE_CONFLICT_MERGE_THEIRS_NEW_INTO_OLD_PLACE != null) { + boolean add = Boolean.TRUE.equals(configuration.isKeepNewFilesAsIsForTreeConflictMerge()); + if (configuration.isKeepNewFilesAsIsForTreeConflictMerge() != null) { return add; } if (!containAdditions(myTheirsChanges) && !containAdditions(myTheirsBinaryChanges)) { @@ -606,10 +606,10 @@ public class MergeFromTheirsResolver { if (!value) { if (exitCode == 0) { // yes - configuration.TREE_CONFLICT_MERGE_THEIRS_NEW_INTO_OLD_PLACE = true; + configuration.setKeepNewFilesAsIsForTreeConflictMerge(true); } else { - configuration.TREE_CONFLICT_MERGE_THEIRS_NEW_INTO_OLD_PLACE = false; + configuration.setKeepNewFilesAsIsForTreeConflictMerge(false); } } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AbstractSvnUpdatePanel.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AbstractSvnUpdatePanel.java index 4c24d69d9d92..0cea23ea3988 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AbstractSvnUpdatePanel.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AbstractSvnUpdatePanel.java @@ -85,7 +85,7 @@ public abstract class AbstractSvnUpdatePanel { } public void reset(final SvnConfiguration configuration) { - getDepthBox().setSelectedItem(configuration.UPDATE_DEPTH); + getDepthBox().setSelectedItem(configuration.getUpdateDepth()); for (FilePath filePath : myRootToPanel.keySet()) { myRootToPanel.get(filePath).reset(configuration); @@ -94,7 +94,7 @@ public abstract class AbstractSvnUpdatePanel { } public void apply(final SvnConfiguration configuration) throws ConfigurationException { - configuration.UPDATE_DEPTH = getDepthBox().getDepth(); + configuration.setUpdateDepth(getDepthBox().getDepth()); for (FilePath filePath : myRootToPanel.keySet()) { final SvnPanel svnPanel = myRootToPanel.get(filePath); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AutoSvnUpdater.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AutoSvnUpdater.java index 0c0e836a10b2..cf424af4ef78 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AutoSvnUpdater.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AutoSvnUpdater.java @@ -47,9 +47,9 @@ public class AutoSvnUpdater extends AbstractCommonUpdateAction { @Override protected void actionPerformed(VcsContext context) { final SvnConfiguration configuration17 = SvnConfiguration.getInstance(myProject); - configuration17.FORCE_UPDATE = false; - configuration17.UPDATE_LOCK_ON_DEMAND = false; - configuration17.UPDATE_DEPTH = SVNDepth.INFINITY; + configuration17.setForceUpdate(false); + configuration17.setUpdateLockOnDemand(false); + configuration17.setUpdateDepth(SVNDepth.INFINITY); final SvnVcs vcs = SvnVcs.getInstance(myProject); for (FilePath root : myRoots) { final UpdateRootInfo info = configuration17.getUpdateRootInfo(root.getIOFile(), vcs); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnIntegrateEnvironment.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnIntegrateEnvironment.java index 7627b1ecc048..c8a77f6d50d6 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnIntegrateEnvironment.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnIntegrateEnvironment.java @@ -20,15 +20,10 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.update.UpdatedFiles; -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.integrate.MergeClient; -import org.tmatesoft.svn.core.SVNException; -import org.tmatesoft.svn.core.SVNURL; -import org.tmatesoft.svn.core.io.SVNRepository; -import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; import java.io.File; @@ -66,10 +61,10 @@ public class SvnIntegrateEnvironment extends AbstractSvnUpdateIntegrateEnvironme @Override protected boolean isDryRun() { - return SvnConfiguration.getInstance(myVcs.getProject()).MERGE_DRY_RUN; + return SvnConfiguration.getInstance(myVcs.getProject()).isMergeDryRun(); } - private class IntegrateCrawler extends AbstractUpdateIntegrateCrawler { + private static class IntegrateCrawler extends AbstractUpdateIntegrateCrawler { public IntegrateCrawler(SvnVcs vcs, UpdateEventHandler handler, @@ -83,7 +78,7 @@ public class SvnIntegrateEnvironment extends AbstractSvnUpdateIntegrateEnvironme } protected void showProgressMessage(final ProgressIndicator progress, final File root) { - if (SvnConfiguration.getInstance(myVcs.getProject()).MERGE_DRY_RUN) { + if (SvnConfiguration.getInstance(myVcs.getProject()).isMergeDryRun()) { progress.setText(SvnBundle.message("progress.text.merging.dry.run.changes", root.getAbsolutePath())); } else { @@ -104,9 +99,8 @@ public class SvnIntegrateEnvironment extends AbstractSvnUpdateIntegrateEnvironme SvnTarget source1 = SvnTarget.fromURL(info.getUrl1(), info.getRevision1()); SvnTarget source2 = SvnTarget.fromURL(info.getUrl2(), info.getRevision2()); - client.merge(source1, source2, root, svnConfig.UPDATE_DEPTH, svnConfig.MERGE_DIFF_USE_ANCESTRY, svnConfig.MERGE_DRY_RUN, false, false, + client.merge(source1, source2, root, svnConfig.getUpdateDepth(), svnConfig.isMergeDiffUseAncestry(), svnConfig.isMergeDryRun(), false, false, svnConfig.getMergeOptions(), myHandler); - svnConfig.LAST_MERGED_REVISION = getLastMergedRevision(info.getRevision2(), info.getUrl2()); return info.getResultRevision(); } @@ -115,36 +109,6 @@ public class SvnIntegrateEnvironment extends AbstractSvnUpdateIntegrateEnvironme } } - @Nullable - private String getLastMergedRevision(final SVNRevision rev2, final SVNURL svnURL2) { - if (!rev2.isValid() || rev2.isLocal()) { - return null; - } - else { - final long number = rev2.getNumber(); - if (number > 0) { - return String.valueOf(number); - } - else { - - // TODO: Rewrite with command line implementation - SVNRepository repos = null; - try { - repos = myVcs.createRepository(svnURL2.toString()); - final long latestRev = repos.getLatestRevision(); - return String.valueOf(latestRev); - } - catch (SVNException e) { - return null; - } finally { - if (repos != null) { - repos.closeSession(); - } - } - } - } - } - public boolean validateOptions(final Collection roots) { return true; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnIntegratePanel.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnIntegratePanel.java index b01b3790e299..b7f5012ef6a4 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnIntegratePanel.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnIntegratePanel.java @@ -65,13 +65,13 @@ public class SvnIntegratePanel extends AbstractSvnUpdatePanel{ public void reset(final SvnConfiguration configuration) { super.reset(configuration); - myDryRunCheckbox.setSelected(configuration.MERGE_DRY_RUN); - myUseAncestry.setSelected(configuration.MERGE_DIFF_USE_ANCESTRY); + myDryRunCheckbox.setSelected(configuration.isMergeDryRun()); + myUseAncestry.setSelected(configuration.isMergeDiffUseAncestry()); } public void apply(final SvnConfiguration configuration) throws ConfigurationException { super.apply(configuration); - configuration.MERGE_DRY_RUN = myDryRunCheckbox.isSelected(); - configuration.MERGE_DIFF_USE_ANCESTRY = myUseAncestry.isSelected(); + configuration.setMergeDryRun(myDryRunCheckbox.isSelected()); + configuration.setMergeDiffUseAncestry(myUseAncestry.isSelected()); } protected JComponent getPanel() { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateContext.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateContext.java index 3da7e90ad98c..42ba2b58c793 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateContext.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateContext.java @@ -67,7 +67,7 @@ public class SvnUpdateContext implements SequentialUpdatesContext { result = false; } else if (NestedCopyType.external.equals(info.getType())) { - result = !myVcs.getSvnConfiguration().IGNORE_EXTERNALS; + result = !myVcs.getSvnConfiguration().isIgnoreExternals(); } } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java index 00b821f003cc..0bb436a428ee 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java @@ -83,10 +83,11 @@ public class SvnUpdateEnvironment extends AbstractSvnUpdateIntegrateEnvironment if (isSwitch) { final UpdateClient updateClient = createUpdateClient(configuration, root, true, sourceUrl); myHandler.addToSwitch(root, sourceUrl); - rev = updateClient.doSwitch(root, rootInfo.getUrl(), SVNRevision.UNDEFINED, updateTo, configuration.UPDATE_DEPTH, configuration.FORCE_UPDATE, false); + rev = updateClient.doSwitch(root, rootInfo.getUrl(), SVNRevision.UNDEFINED, updateTo, configuration.getUpdateDepth(), + configuration.isForceUpdate(), false); } else { final UpdateClient updateClient = createUpdateClient(configuration, root, false, sourceUrl); - rev = updateClient.doUpdate(root, updateTo, configuration.UPDATE_DEPTH, configuration.FORCE_UPDATE, false); + rev = updateClient.doUpdate(root, updateTo, configuration.getUpdateDepth(), configuration.isForceUpdate(), false); } myPostUpdateFiles.setRevisions(root.getAbsolutePath(), myVcs, new SvnRevisionNumber(SVNRevision.create(rev))); @@ -104,10 +105,10 @@ public class SvnUpdateEnvironment extends AbstractSvnUpdateIntegrateEnvironment final UpdateClient updateClient = factory.createUpdateClient(); if (! isSwitch) { - updateClient.setIgnoreExternals(configuration.IGNORE_EXTERNALS); + updateClient.setIgnoreExternals(configuration.isIgnoreExternals()); } updateClient.setEventHandler(myHandler); - updateClient.setUpdateLocksOnDemand(configuration.UPDATE_LOCK_ON_DEMAND); + updateClient.setUpdateLocksOnDemand(configuration.isUpdateLockOnDemand()); return updateClient; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdatePanel.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdatePanel.java index ab66664f0f82..1aef057dd7e2 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdatePanel.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdatePanel.java @@ -52,24 +52,24 @@ public class SvnUpdatePanel extends AbstractSvnUpdatePanel { myDepthLabel.setLabelFor(myDepthCombo); final SvnConfiguration svnConfiguration = SvnConfiguration.getInstance(myVCS.getProject()); - myLockOnDemand.setSelected(svnConfiguration.UPDATE_LOCK_ON_DEMAND); + myLockOnDemand.setSelected(svnConfiguration.isUpdateLockOnDemand()); myLockOnDemand.addActionListener(new ActionListener() { public void actionPerformed(final ActionEvent e) { - svnConfiguration.UPDATE_LOCK_ON_DEMAND = myLockOnDemand.isSelected(); + svnConfiguration.setUpdateLockOnDemand(myLockOnDemand.isSelected()); } }); - myForceBox.setSelected(svnConfiguration.FORCE_UPDATE); - myIgnoreExternalsCheckBox.setSelected(svnConfiguration.IGNORE_EXTERNALS); + myForceBox.setSelected(svnConfiguration.isForceUpdate()); + myIgnoreExternalsCheckBox.setSelected(svnConfiguration.isIgnoreExternals()); myForceBox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - svnConfiguration.FORCE_UPDATE = myForceBox.isSelected(); + svnConfiguration.setForceUpdate(myForceBox.isSelected()); } }); myIgnoreExternalsCheckBox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - svnConfiguration.IGNORE_EXTERNALS = myIgnoreExternalsCheckBox.isSelected(); + svnConfiguration.setIgnoreExternals(myIgnoreExternalsCheckBox.isSelected()); } }); } diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/SvnTestCase.java b/plugins/svn4idea/testSource/org/jetbrains/idea/SvnTestCase.java index 00d96b882013..17ae6b5ce551 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/SvnTestCase.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/SvnTestCase.java @@ -20,7 +20,6 @@ import com.intellij.ide.startup.impl.StartupManagerImpl; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.DataContext; -import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.actionSystem.Presentation; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.PathManager; @@ -71,9 +70,7 @@ import java.io.File; import java.io.IOException; import java.util.*; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; /** * @author yole @@ -219,7 +216,7 @@ public abstract class SvnTestCase extends AbstractJunitVcsTestCase { @Override protected void projectCreated() { if (isUseNativeAcceleration()) { - SvnConfiguration.getInstance(myProject).myUseAcceleration = SvnConfiguration.UseAcceleration.commandLine; + SvnConfiguration.getInstance(myProject).setUseAcceleration(SvnConfiguration.UseAcceleration.commandLine); SvnApplicationSettings.getInstance().setCommandLinePath(myClientBinaryPath + File.separator + "svn"); } } @@ -618,8 +615,8 @@ public abstract class SvnTestCase extends AbstractJunitVcsTestCase { protected void setNativeAcceleration(final boolean value) { System.out.println("Set native acceleration to " + value); - SvnConfiguration.getInstance(myProject).myUseAcceleration = - value ? SvnConfiguration.UseAcceleration.commandLine : SvnConfiguration.UseAcceleration.nothing; + SvnConfiguration.getInstance(myProject).setUseAcceleration( + value ? SvnConfiguration.UseAcceleration.commandLine : SvnConfiguration.UseAcceleration.nothing); SvnApplicationSettings.getInstance().setCommandLinePath(myClientBinaryPath + File.separator + "svn"); } } diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnAuthenticationTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnAuthenticationTest.java index de273690fd73..3700343842e3 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnAuthenticationTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnAuthenticationTest.java @@ -730,7 +730,7 @@ public class SvnAuthenticationTest extends PlatformTestCase { @Override public void run() { try { - myConfiguration.clearAuthenticationDirectory(getProject()); + clearAuthCache(); } catch (Exception e) { throw new RuntimeException(e); @@ -780,6 +780,10 @@ public class SvnAuthenticationTest extends PlatformTestCase { SVNJNAUtil.setJNAEnabled(true); } + private void clearAuthCache() { + SvnAuthenticationNotifier.clearAuthenticationDirectory(myConfiguration); + } + public void testPlaintextPromptAndSecondPrompt() throws Exception { SVNJNAUtil.setJNAEnabled(false); @@ -875,7 +879,7 @@ public class SvnAuthenticationTest extends PlatformTestCase { @Override public void run() { try { - myConfiguration.clearAuthenticationDirectory(getProject()); + clearAuthCache(); } catch (Exception e) { throw new RuntimeException(e); diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnMergeInfoTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnMergeInfoTest.java index 956c768c0d8c..528ea0f9e2b8 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnMergeInfoTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnMergeInfoTest.java @@ -64,7 +64,7 @@ public class SvnMergeInfoTest extends Svn17TestCase { myWCInfo = new WCInfo(root, true, SVNDepth.INFINITY); myOneShotMergeInfoHelper = new OneShotMergeInfoHelper(myProject, myWCInfo, myRepoUrl + "/trunk"); - SvnConfiguration.getInstance(myProject).CHECK_NESTED_FOR_QUICK_MERGE = true; + SvnConfiguration.getInstance(myProject).setCheckNestedForQuickMerge(true); // AbstractVcs vcsFound = myProjectLevelVcsManager.findVcsByName(SvnVcs.VCS_NAME); // Assert.assertEquals(1, myProjectLevelVcsManager.getRootsUnderVcs(vcsFound).length); } diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeClientAuthTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeClientAuthTest.java index b6d6ae104bbc..1328b94fd7f0 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeClientAuthTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeClientAuthTest.java @@ -29,6 +29,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Processor; import com.intellij.util.containers.Convertor; import junit.framework.Assert; +import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.svn.checkout.SvnCheckoutProvider; import org.junit.Before; import org.tmatesoft.svn.core.*; @@ -143,10 +144,9 @@ public class SvnNativeClientAuthTest extends Svn17TestCase { //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount); final SvnConfiguration instance = SvnConfiguration.getInstance(myProject); - instance.clearAuthenticationDirectory(myProject); - instance.clearRuntimeStorage(); + clearAuthCache(instance); - Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration); + Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration()); mySaveCredentials = false; updateSimple(wc1); @@ -166,10 +166,9 @@ public class SvnNativeClientAuthTest extends Svn17TestCase { //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount); final SvnConfiguration instance = SvnConfiguration.getInstance(myProject); - instance.clearAuthenticationDirectory(myProject); - instance.clearRuntimeStorage(); + clearAuthCache(instance); - Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration); + Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration()); mySaveCredentials = false; updateSimple(wc1); @@ -191,10 +190,9 @@ public class SvnNativeClientAuthTest extends Svn17TestCase { //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount); final SvnConfiguration instance = SvnConfiguration.getInstance(myProject); - instance.clearAuthenticationDirectory(myProject); - instance.clearRuntimeStorage(); + clearAuthCache(instance); - Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration); + Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration()); mySaveCredentials = true; updateSimple(wc1); @@ -215,10 +213,9 @@ public class SvnNativeClientAuthTest extends Svn17TestCase { //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount); final SvnConfiguration instance = SvnConfiguration.getInstance(myProject); - instance.clearAuthenticationDirectory(myProject); - instance.clearRuntimeStorage(); + clearAuthCache(instance); - Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration); + Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration()); mySaveCredentials = true; updateSimple(wc1); @@ -237,10 +234,9 @@ public class SvnNativeClientAuthTest extends Svn17TestCase { //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount); final SvnConfiguration instance = SvnConfiguration.getInstance(myProject); - instance.clearAuthenticationDirectory(myProject); - instance.clearRuntimeStorage(); + clearAuthCache(instance); - Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration); + Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration()); mySaveCredentials = false; testCommitImpl(wc1); @@ -260,10 +256,9 @@ public class SvnNativeClientAuthTest extends Svn17TestCase { //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount); final SvnConfiguration instance = SvnConfiguration.getInstance(myProject); - instance.clearAuthenticationDirectory(myProject); - instance.clearRuntimeStorage(); + clearAuthCache(instance); - Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration); + Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration()); mySaveCredentials = false; testCommitImpl(wc1); @@ -285,10 +280,9 @@ public class SvnNativeClientAuthTest extends Svn17TestCase { //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount); final SvnConfiguration instance = SvnConfiguration.getInstance(myProject); - instance.clearAuthenticationDirectory(myProject); - instance.clearRuntimeStorage(); + clearAuthCache(instance); - Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration); + Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration()); mySaveCredentials = true; testCommitImpl(wc1); @@ -310,10 +304,9 @@ public class SvnNativeClientAuthTest extends Svn17TestCase { //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount); final SvnConfiguration instance = SvnConfiguration.getInstance(myProject); - instance.clearAuthenticationDirectory(myProject); - instance.clearRuntimeStorage(); + clearAuthCache(instance); - Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration); + Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration()); mySaveCredentials = true; myCertificateAnswer = ISVNAuthenticationProvider.ACCEPTED; @@ -329,6 +322,11 @@ public class SvnNativeClientAuthTest extends Svn17TestCase { //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount); } + private static void clearAuthCache(@NotNull SvnConfiguration instance) { + SvnAuthenticationNotifier.clearAuthenticationDirectory(instance); + instance.clearRuntimeStorage(); + } + @Test public void testMixedSSLCommit() throws Exception { final File wc1 = testCheckoutImpl(ourHTTPS_URL); @@ -336,10 +334,9 @@ public class SvnNativeClientAuthTest extends Svn17TestCase { //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount); final SvnConfiguration instance = SvnConfiguration.getInstance(myProject); - instance.clearAuthenticationDirectory(myProject); - instance.clearRuntimeStorage(); + clearAuthCache(instance); - Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration); + Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration()); mySaveCredentials = false; myCertificateAnswer = ISVNAuthenticationProvider.ACCEPTED; @@ -354,8 +351,7 @@ public class SvnNativeClientAuthTest extends Svn17TestCase { //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount); //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount); //------------ - instance.clearAuthenticationDirectory(myProject); - instance.clearRuntimeStorage(); + clearAuthCache(instance); mySaveCredentials = true; myCertificateAnswer = ISVNAuthenticationProvider.ACCEPTED_TEMPORARY; @@ -373,10 +369,9 @@ public class SvnNativeClientAuthTest extends Svn17TestCase { //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount); final SvnConfiguration instance = SvnConfiguration.getInstance(myProject); - instance.clearAuthenticationDirectory(myProject); - instance.clearRuntimeStorage(); + clearAuthCache(instance); - Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration); + Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration()); mySaveCredentials = true; testCommitImpl(wc1); @@ -395,10 +390,9 @@ public class SvnNativeClientAuthTest extends Svn17TestCase { //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount); final SvnConfiguration instance = SvnConfiguration.getInstance(myProject); - instance.clearAuthenticationDirectory(myProject); - instance.clearRuntimeStorage(); + clearAuthCache(instance); - Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration); + Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration()); mySaveCredentials = false; myCredentialsCorrect = false; @@ -419,10 +413,9 @@ public class SvnNativeClientAuthTest extends Svn17TestCase { //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount); final SvnConfiguration instance = SvnConfiguration.getInstance(myProject); - instance.clearAuthenticationDirectory(myProject); - instance.clearRuntimeStorage(); + clearAuthCache(instance); - Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration); + Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration()); mySaveCredentials = false; myCredentialsCorrect = false; @@ -446,10 +439,9 @@ public class SvnNativeClientAuthTest extends Svn17TestCase { //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount); final SvnConfiguration instance = SvnConfiguration.getInstance(myProject); - instance.clearAuthenticationDirectory(myProject); - instance.clearRuntimeStorage(); + clearAuthCache(instance); - Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration); + Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration()); mySaveCredentials = false; myCertificateAnswer = ISVNAuthenticationProvider.REJECTED; @@ -480,10 +472,9 @@ public class SvnNativeClientAuthTest extends Svn17TestCase { //Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount); final SvnConfiguration instance = SvnConfiguration.getInstance(myProject); - instance.clearAuthenticationDirectory(myProject); - instance.clearRuntimeStorage(); + clearAuthCache(instance); - Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration); + Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration()); mySaveCredentials = false; myCredentialsCorrect = false; myCancelAuth = true; @@ -507,10 +498,9 @@ public class SvnNativeClientAuthTest extends Svn17TestCase { //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount); final SvnConfiguration instance = SvnConfiguration.getInstance(myProject); - instance.clearAuthenticationDirectory(myProject); - instance.clearRuntimeStorage(); + clearAuthCache(instance); - Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration); + Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration()); mySaveCredentials = false; myCredentialsCorrect = false; myCancelAuth = true; diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnAuthenticationTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnAuthenticationTest.java index b4302105204a..624cfbb25635 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnAuthenticationTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnAuthenticationTest.java @@ -25,6 +25,7 @@ import com.intellij.util.concurrency.Semaphore; import com.intellij.util.ui.UIUtil; import junit.framework.Assert; import org.jetbrains.idea.svn.SvnAuthenticationManager; +import org.jetbrains.idea.svn.SvnAuthenticationNotifier; import org.jetbrains.idea.svn.SvnConfiguration; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.auth.ProviderType; @@ -733,7 +734,7 @@ public class SvnAuthenticationTest extends PlatformTestCase { @Override public void run() { try { - myConfiguration.clearAuthenticationDirectory(getProject()); + clearAuthCache(); } catch (Exception e) { throw new RuntimeException(e); @@ -783,6 +784,10 @@ public class SvnAuthenticationTest extends PlatformTestCase { SVNJNAUtil.setJNAEnabled(true); } + private void clearAuthCache() { + SvnAuthenticationNotifier.clearAuthenticationDirectory(myConfiguration); + } + public void testPlaintextPromptAndSecondPrompt() throws Exception { SVNJNAUtil.setJNAEnabled(false); @@ -878,7 +883,7 @@ public class SvnAuthenticationTest extends PlatformTestCase { @Override public void run() { try { - myConfiguration.clearAuthenticationDirectory(getProject()); + clearAuthCache(); } catch (Exception e) { throw new RuntimeException(e); diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnMergeInfoTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnMergeInfoTest.java index ec8f665ecf05..efbb6b99fe1d 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnMergeInfoTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnMergeInfoTest.java @@ -64,7 +64,7 @@ public class SvnMergeInfoTest extends Svn16TestCase { myWCInfo = new WCInfo(root, true, SVNDepth.INFINITY); myOneShotMergeInfoHelper = new OneShotMergeInfoHelper(myProject, myWCInfo, myRepoUrl + "/trunk"); - SvnConfiguration.getInstance(myProject).CHECK_NESTED_FOR_QUICK_MERGE = true; + SvnConfiguration.getInstance(myProject).setCheckNestedForQuickMerge(true); // AbstractVcs vcsFound = myProjectLevelVcsManager.findVcsByName(SvnVcs.VCS_NAME); // Assert.assertEquals(1, myProjectLevelVcsManager.getRootsUnderVcs(vcsFound).length); }