Merge branch 'svn_18_2'

This commit is contained in:
Konstantin Kolosovsky
2013-12-30 21:07:09 +04:00
73 changed files with 1598 additions and 950 deletions
@@ -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());
@@ -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);
}
@@ -32,14 +32,23 @@ import java.util.*;
*
*/
@SomeQueue
// TODO: Used only in RemoteRevisionsNumberCache
public class LazyRefreshingSelfQueue<T> {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.changes.LazyRefreshingSelfQueue");
// provides update interval in milliseconds.
private final Getter<Long> 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<Pair<Long, T>> myQueue;
// Set of items that should be processed by myUpdater
private final Set<T> myInProgress;
// checks if updateStep should be really performed
private final Computable<Boolean> myShouldUpdateOldChecker;
// performs some actions on item T, for instance - updates some data for T in cache
private final Consumer<T> myUpdater;
private final Object myLock;
@@ -52,20 +61,14 @@ public class LazyRefreshingSelfQueue<T> {
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<Long,T>(null, t));
}
}
public void addRequests(final Collection<T> values) {
synchronized (myLock) {
for (T value : values) {
myQueue.addFirst(new Pair<Long,T>(null, value));
}
}
}
// unschedules item from update at next updateStep() call
public void forceRemove(@NotNull final T t) {
synchronized (myLock) {
for (Iterator<Pair<Long, T>> iterator = myQueue.iterator(); iterator.hasNext();) {
@@ -80,11 +83,11 @@ public class LazyRefreshingSelfQueue<T> {
// called by outside timer or something
public void updateStep() {
final List<T> dirty = new LinkedList<T>();
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<Long, T> pair : myQueue) {
if (pair.getFirst() != null) {
@@ -96,9 +99,10 @@ public class LazyRefreshingSelfQueue<T> {
// do not ask under lock
final Boolean shouldUpdateOld = onlyAbsolute ? false : myShouldUpdateOldChecker.compute();
final List<T> dirty = new LinkedList<T>();
synchronized (myLock) {
// get absolute
// adds all pairs with pair.First == null to dirty
while (! myQueue.isEmpty()) {
final Pair<Long, T> pair = myQueue.get(0);
if (pair.getFirst() == null) {
@@ -108,6 +112,7 @@ public class LazyRefreshingSelfQueue<T> {
}
}
if (Boolean.TRUE.equals(shouldUpdateOld) && (! myQueue.isEmpty())) {
// adds all pairs with update time (pair.First) < current - interval to dirty
while (! myQueue.isEmpty()) {
final Pair<Long, T> pair = myQueue.get(0);
if (pair.getFirst() < startTime) {
@@ -126,6 +131,8 @@ public class LazyRefreshingSelfQueue<T> {
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<Long,T>(System.currentTimeMillis(), t));
}
@@ -88,11 +88,13 @@ public class RemoteRevisionsNumbersCache implements ChangesOnServerTracker {
public boolean updateStep() {
mySomethingChanged = false;
// copy under lock
final HashMap<VcsRoot, LazyRefreshingSelfQueue> copyMap;
synchronized (myLock) {
copyMap = new HashMap<VcsRoot, LazyRefreshingSelfQueue>(myRefreshingQueues);
}
// filter only items for vcs roots that support background operations
for (Iterator<Map.Entry<VcsRoot, LazyRefreshingSelfQueue>> iterator = copyMap.entrySet().iterator(); iterator.hasNext();) {
final Map.Entry<VcsRoot, LazyRefreshingSelfQueue> 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<String> keys;
synchronized (myLock) {
keys = new HashSet<String>(myData.keySet());
}
// collect new vcs for scheduled files
final Map<String, Pair<VirtualFile, AbstractVcs>> vFiles = new HashMap<String, Pair<VirtualFile, AbstractVcs>>();
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<VcsRoot, VcsRevisionNumber> oldPair;
// update value in cache
synchronized (myLock) {
oldPair = myData.get(s);
myData.put(s, new Pair<VcsRoot, VcsRevisionNumber>(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);
@@ -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<String, Pair<Boolean, VcsRoot>> myChanged;
// All files that needs to be checked during next cache update, grouped by vcs root
private final MultiMap<VcsRoot, String> myQueries;
// All vcs roots for which cache update was performed with update timestamp
private final Map<VcsRoot, Long> 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<String> 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<VcsRoot> roots = new HashSet<VcsRoot>();
for (Map.Entry<VcsRoot, Long> 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<String, Pair<Boolean, VcsRoot>> 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<String> paths = dirty.get(vcsRoot);
final Collection<String> 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<Boolean, VcsRoot>(remotelyChanged.contains(path), vcsRoot));
}
}
@@ -74,13 +74,7 @@ public class ChangeListDetailsAction extends AnAction implements DumbAware {
detailsBuilder.append("<br>");
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();
@@ -688,14 +688,13 @@ public class CommittedChangesCache implements PersistentStateComponent<Committed
if (lists.size() == 1) {
return lists.get(0);
}
final CommittedChangeList victim = lists.get(0) instanceof ReceivedChangeList ? (((ReceivedChangeList) lists.get(0)).getBaseList()) :
lists.get(0);
final CommittedChangeList victim = ReceivedChangeList.unwrap(lists.get(0));
final ReceivedChangeList result = new ReceivedChangeList(victim);
result.setForcePartial(false);
final Set<Change> baseChanges = new HashSet<Change>();
for (CommittedChangeList list : lists) {
baseChanges.addAll(list instanceof ReceivedChangeList ? ((ReceivedChangeList) list).getBaseList().getChanges() : list.getChanges());
baseChanges.addAll(ReceivedChangeList.unwrap(list).getChanges());
final Collection<Change> changes = list.getChanges();
for (Change change : changes) {
+3 -1
View File
@@ -72,7 +72,7 @@
<reference id="Compare.SameVersion" text="Compare with BASE revision"/>
<reference id="Compare.LastVersion" text="Compare with revision at HEAD"/>
<reference id="Compare.Selected"/>
<action id="Subversion.CompareWithBranch" class="org.jetbrains.idea.svn.actions.CompareWithBranchAction"/>
<action id="Subversion.CompareWithBranch" class="org.jetbrains.idea.svn.diff.CompareWithBranchAction"/>
<reference id="Vcs.ShowTabbedFileHistory"/>
<reference id="Vcs.ShowHistoryForBlock"/>
<reference id="Annotate"/>
@@ -139,5 +139,7 @@
<vcs name="svn" vcsClass="org.jetbrains.idea.svn.SvnVcs" displayName="Subversion" administrativeAreaName=".svn, _svn" crawlUpToCheckUnderVcs="true"/>
<vcsPopupProvider implementation="org.jetbrains.idea.svn.actions.SvnQuickListContentProvider"/>
<statistics.usagesCollector implementation="org.jetbrains.idea.svn.statistics.SvnWorkingCopyFormatUsagesCollector"/>
</extensions>
</idea-plugin>
@@ -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<String, String> myPatternsMap;
private final long myLatestUpdate;
private final File myFile;
@@ -41,6 +49,59 @@ public class IdeaSVNConfigFile {
myPatternsMap = new HashMap<String, String>();
}
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<String, String> map = new HashMap<String, String>();
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<String,ProxyGroup> 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<String, String> 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();
@@ -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)) {
@@ -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<SvnAuthenticationNotifier.AuthenticationRequest, SVNURL> {
private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.SvnAuthenticationNotifier");
private static final List<String> 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<SVNURL, Boolean> myCopiesPassiveResults;
@@ -414,7 +424,7 @@ public class SvnAuthenticationNotifier extends GenericNotifierImpl<SvnAuthentica
SvnBundle.message("confirmation.title.clear.authentication.cache")) {
@Override
public void run() {
SvnConfigurable.clearAuthenticationCache(project, null, configuration
clearAuthenticationCache(project, null, configuration
.getConfigurationDirectory());
}
},
@@ -436,4 +446,58 @@ public class SvnAuthenticationNotifier extends GenericNotifierImpl<SvnAuthentica
}
}, ModalityState.NON_MODAL, project.getDisposed());
}
public static void clearAuthenticationCache(@NotNull final Project project, final Component component, final String configDirPath) {
if (configDirPath != null) {
int result;
if (component == null) {
result = Messages.showYesNoDialog(project, SvnBundle.message("confirmation.text.delete.stored.authentication.information"),
SvnBundle.message("confirmation.title.clear.authentication.cache"),
Messages.getWarningIcon());
} else {
result = Messages.showYesNoDialog(component, SvnBundle.message("confirmation.text.delete.stored.authentication.information"),
SvnBundle.message("confirmation.title.clear.authentication.cache"),
Messages.getWarningIcon());
}
if (result == Messages.YES) {
SvnConfiguration.RUNTIME_AUTH_CACHE.clear();
clearAuthenticationDirectory(SvnConfiguration.getInstance(project));
}
}
}
public static void clearAuthenticationDirectory(@NotNull SvnConfiguration configuration) {
final File authDir = new File(configuration.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, configuration.getProject());
}
}
}
}
@@ -295,7 +295,7 @@ public class SvnBranchConfigurationManager implements PersistentStateComponent<S
return result;
}
private String serializeUrl(final String url, final Ref<Boolean> withUserInfo) {
private static String serializeUrl(final String url, final Ref<Boolean> withUserInfo) {
if (Boolean.FALSE.equals(withUserInfo.get())) {
return url;
}
@@ -306,7 +306,8 @@ public class SvnBranchConfigurationManager implements PersistentStateComponent<S
withUserInfo.set((userInfo != null) && (userInfo.length() > 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<S
return svnurl != null ? svnurl.getUserInfo() : null;
}
private String deserializeUrl(final String url, final String userInfo) {
private static String deserializeUrl(final String url, final String userInfo) {
try {
final SVNURL svnurl = SVNURL.parseURIEncoded(url);
return SVNURL.create(svnurl.getProtocol(), userInfo, svnurl.getHost(), svnurl.getPort(), svnurl.getURIEncodedPath(), true).toString();
return SVNURL.create(svnurl.getProtocol(), userInfo, svnurl.getHost(), SvnUtil.resolvePort(svnurl), svnurl.getURIEncodedPath(),
true).toString();
} catch (SVNException e) {
return url;
}
@@ -25,7 +25,6 @@ import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.SystemInfo;
@@ -102,7 +101,7 @@ public class SvnConfigurable implements Configurable {
myClearAuthButton.addActionListener(new ActionListener(){
public void actionPerformed(final ActionEvent e) {
clearAuthenticationCache(myProject, myComponent, myConfigurationDirectoryText.getText());
SvnAuthenticationNotifier.clearAuthenticationCache(myProject, myComponent, myConfigurationDirectoryText.getText());
}
});
@@ -180,25 +179,6 @@ public class SvnConfigurable implements Configurable {
dirConsumer.consume(resultPath);
}
public static void clearAuthenticationCache(@NotNull final Project project, final Component component, final String configDirPath) {
if (configDirPath != null) {
int result;
if (component == null) {
result = Messages.showYesNoDialog(project, SvnBundle.message("confirmation.text.delete.stored.authentication.information"),
SvnBundle.message("confirmation.title.clear.authentication.cache"),
Messages.getWarningIcon());
} else {
result = Messages.showYesNoDialog(component, SvnBundle.message("confirmation.text.delete.stored.authentication.information"),
SvnBundle.message("confirmation.title.clear.authentication.cache"),
Messages.getWarningIcon());
}
if (result == Messages.YES) {
SvnConfiguration.RUNTIME_AUTH_CACHE.clear();
SvnConfiguration.getInstance(project).clearAuthenticationDirectory(project);
}
}
}
private static FileChooserDescriptor createFileDescriptor() {
final FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor();
descriptor.setShowFileSystemRoots(true);
@@ -239,19 +219,19 @@ public class SvnConfigurable implements Configurable {
if (configuration.isIsUseDefaultProxy() != myUseCommonProxy.isSelected()) {
return true;
}
if (configuration.UPDATE_LOCK_ON_DEMAND != myLockOnDemand.isSelected()) {
if (configuration.isUpdateLockOnDemand() != myLockOnDemand.isSelected()) {
return true;
}
if (configuration.CHECK_NESTED_FOR_QUICK_MERGE != myCheckNestedInQuickMerge.isSelected()) {
if (configuration.isCheckNestedForQuickMerge() != myCheckNestedInQuickMerge.isSelected()) {
return true;
}
if (configuration.IGNORE_SPACES_IN_ANNOTATE != myIgnoreWhitespaceDifferenciesInCheckBox.isSelected()) {
if (configuration.isIgnoreSpacesInAnnotate() != myIgnoreWhitespaceDifferenciesInCheckBox.isSelected()) {
return true;
}
if (configuration.SHOW_MERGE_SOURCES_IN_ANNOTATE != myShowMergeSourceInAnnotate.isSelected()) {
if (configuration.isShowMergeSourcesInAnnotate() != myShowMergeSourceInAnnotate.isSelected()) {
return true;
}
if (! configuration.myUseAcceleration.equals(acceleration())) return true;
if (! configuration.getUseAcceleration().equals(acceleration())) return true;
final int annotateRevisions = configuration.getMaxAnnotateRevisions();
final boolean useMaxInAnnot = annotateRevisions != -1;
if (useMaxInAnnot != myMaximumNumberOfRevisionsCheckBox.isSelected()) {
@@ -262,16 +242,16 @@ public class SvnConfigurable implements Configurable {
return true;
}
}
if (configuration.mySSHConnectionTimeout/1000 != ((SpinnerNumberModel) mySSHConnectionTimeout.getModel()).getNumber().longValue()) {
if (configuration.getSshConnectionTimeout() /1000 != ((SpinnerNumberModel) mySSHConnectionTimeout.getModel()).getNumber().longValue()) {
return true;
}
if (configuration.mySSHReadTimeout/1000 != ((SpinnerNumberModel) mySSHReadTimeout.getModel()).getNumber().longValue()) {
if (configuration.getSshReadTimeout() /1000 != ((SpinnerNumberModel) mySSHReadTimeout.getModel()).getNumber().longValue()) {
return true;
}
if (configuration.getHttpTimeout()/1000 != ((SpinnerNumberModel) myHttpTimeout.getModel()).getNumber().longValue()) {
return true;
}
if (! getSelectedSSL().equals(configuration.SSL_PROTOCOLS)) return true;
if (! getSelectedSSL().equals(configuration.getSslProtocols())) return true;
final SvnApplicationSettings applicationSettings17 = SvnApplicationSettings.getInstance();
if (! Comparing.equal(applicationSettings17.getCommandLinePath(), myCommandLineClient.getText().trim())) return true;
return !configuration.getConfigurationDirectory().equals(myConfigurationDirectoryText.getText().trim());
@@ -288,23 +268,23 @@ public class SvnConfigurable implements Configurable {
configuration.setIsUseDefaultProxy(myUseCommonProxy.isSelected());
final SvnVcs vcs17 = SvnVcs.getInstance(myProject);
configuration.CHECK_NESTED_FOR_QUICK_MERGE = myCheckNestedInQuickMerge.isSelected();
configuration.UPDATE_LOCK_ON_DEMAND = myLockOnDemand.isSelected();
configuration.setCheckNestedForQuickMerge(myCheckNestedInQuickMerge.isSelected());
configuration.setUpdateLockOnDemand(myLockOnDemand.isSelected());
configuration.setIgnoreSpacesInAnnotate(myIgnoreWhitespaceDifferenciesInCheckBox.isSelected());
configuration.SHOW_MERGE_SOURCES_IN_ANNOTATE = myShowMergeSourceInAnnotate.isSelected();
configuration.setShowMergeSourcesInAnnotate(myShowMergeSourceInAnnotate.isSelected());
if (! myMaximumNumberOfRevisionsCheckBox.isSelected()) {
configuration.setMaxAnnotateRevisions(-1);
} else {
configuration.setMaxAnnotateRevisions(((SpinnerNumberModel) myNumRevsInAnnotations.getModel()).getNumber().intValue());
}
configuration.mySSHConnectionTimeout = ((SpinnerNumberModel) mySSHConnectionTimeout.getModel()).getNumber().longValue() * 1000;
configuration.mySSHReadTimeout = ((SpinnerNumberModel) mySSHReadTimeout.getModel()).getNumber().longValue() * 1000;
configuration.setSshConnectionTimeout(((SpinnerNumberModel)mySSHConnectionTimeout.getModel()).getNumber().longValue() * 1000);
configuration.setSshReadTimeout(((SpinnerNumberModel)mySSHReadTimeout.getModel()).getNumber().longValue() * 1000);
final SvnApplicationSettings applicationSettings17 = SvnApplicationSettings.getInstance();
boolean reloadWorkingCopies = !acceleration().equals(configuration.myUseAcceleration) ||
boolean reloadWorkingCopies = !acceleration().equals(configuration.getUseAcceleration()) ||
!StringUtil.equals(applicationSettings17.getCommandLinePath(), myCommandLineClient.getText().trim());
configuration.myUseAcceleration = acceleration();
configuration.SSL_PROTOCOLS = getSelectedSSL();
configuration.setUseAcceleration(acceleration());
configuration.setSslProtocols(getSelectedSSL());
SvnVcs.getInstance(myProject).refreshSSLProperty();
applicationSettings17.setCommandLinePath(myCommandLineClient.getText().trim());
@@ -325,15 +305,15 @@ public class SvnConfigurable implements Configurable {
myConfigurationDirectoryText.setText(path);
myUseDefaultCheckBox.setSelected(configuration.isUseDefaultConfiguation());
myUseCommonProxy.setSelected(configuration.isIsUseDefaultProxy());
myCheckNestedInQuickMerge.setSelected(configuration.CHECK_NESTED_FOR_QUICK_MERGE);
myCheckNestedInQuickMerge.setSelected(configuration.isCheckNestedForQuickMerge());
boolean enabled = !myUseDefaultCheckBox.isSelected();
myConfigurationDirectoryText.setEnabled(enabled);
myConfigurationDirectoryText.setEditable(enabled);
myConfigurationDirectoryLabel.setEnabled(enabled);
myLockOnDemand.setSelected(configuration.UPDATE_LOCK_ON_DEMAND);
myIgnoreWhitespaceDifferenciesInCheckBox.setSelected(configuration.IGNORE_SPACES_IN_ANNOTATE);
myShowMergeSourceInAnnotate.setSelected(configuration.SHOW_MERGE_SOURCES_IN_ANNOTATE);
myLockOnDemand.setSelected(configuration.isUpdateLockOnDemand());
myIgnoreWhitespaceDifferenciesInCheckBox.setSelected(configuration.isIgnoreSpacesInAnnotate());
myShowMergeSourceInAnnotate.setSelected(configuration.isShowMergeSourcesInAnnotate());
final int annotateRevisions = configuration.getMaxAnnotateRevisions();
if (annotateRevisions == -1) {
@@ -344,16 +324,16 @@ public class SvnConfigurable implements Configurable {
myNumRevsInAnnotations.setValue(annotateRevisions);
}
myNumRevsInAnnotations.setEnabled(myMaximumNumberOfRevisionsCheckBox.isSelected());
mySSHConnectionTimeout.setValue(Long.valueOf(configuration.mySSHConnectionTimeout / 1000));
mySSHReadTimeout.setValue(Long.valueOf(configuration.mySSHReadTimeout / 1000));
mySSHConnectionTimeout.setValue(Long.valueOf(configuration.getSshConnectionTimeout() / 1000));
mySSHReadTimeout.setValue(Long.valueOf(configuration.getSshReadTimeout() / 1000));
myHttpTimeout.setValue(Long.valueOf(configuration.getHttpTimeout() / 1000));
myWithCommandLineClient.setSelected(configuration.isCommandLine());
final SvnApplicationSettings applicationSettings17 = SvnApplicationSettings.getInstance();
myCommandLineClient.setText(applicationSettings17.getCommandLinePath());
if (SvnConfiguration.SSLProtocols.sslv3.equals(configuration.SSL_PROTOCOLS)) {
if (SvnConfiguration.SSLProtocols.sslv3.equals(configuration.getSslProtocols())) {
mySSLv3RadioButton.setSelected(true);
} else if (SvnConfiguration.SSLProtocols.tlsv1.equals(configuration.SSL_PROTOCOLS)) {
} else if (SvnConfiguration.SSLProtocols.tlsv1.equals(configuration.getSslProtocols())) {
myTLSv1RadioButton.setSelected(true);
} else {
myAllRadioButton.setSelected(true);
@@ -381,8 +361,8 @@ public class SvnConfigurable implements Configurable {
myNumRevsInAnnotations = new JSpinner(new SpinnerNumberModel(value, 10, 100000, 100));
final Long maximum = 30 * 60 * 1000L;
final long connection = configuration.mySSHConnectionTimeout <= maximum ? configuration.mySSHConnectionTimeout : maximum;
final long read = configuration.mySSHReadTimeout <= maximum ? configuration.mySSHReadTimeout : maximum;
final long connection = configuration.getSshConnectionTimeout() <= maximum ? configuration.getSshConnectionTimeout() : maximum;
final long read = configuration.getSshReadTimeout() <= maximum ? configuration.getSshReadTimeout() : maximum;
mySSHConnectionTimeout = new JSpinner(new SpinnerNumberModel(Long.valueOf(connection / 1000), Long.valueOf(0L), maximum, Long.valueOf(10L)));
mySSHReadTimeout = new JSpinner(new SpinnerNumberModel(Long.valueOf(read / 1000), Long.valueOf(0L), maximum, Long.valueOf(10L)));
myHttpTimeout = new JSpinner(new SpinnerNumberModel(Long.valueOf(read / 1000), Long.valueOf(0L), maximum, Long.valueOf(10L)));
@@ -18,23 +18,14 @@
package org.jetbrains.idea.svn;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.*;
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.util.*;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.changes.VcsAnnotationRefresher;
import org.jdom.Attribute;
import org.jdom.DataConversionException;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.config.ProxyGroup;
import org.jetbrains.idea.svn.config.SvnServerFileKeys;
import org.jetbrains.idea.svn.dialogs.SvnAuthenticationProvider;
import org.jetbrains.idea.svn.dialogs.SvnInteractiveAuthenticationProvider;
@@ -43,7 +34,6 @@ import org.jetbrains.idea.svn.update.UpdateRootInfo;
import org.tmatesoft.svn.core.SVNDepth;
import org.tmatesoft.svn.core.SVNErrorMessage;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationProvider;
import org.tmatesoft.svn.core.auth.SVNAuthentication;
import org.tmatesoft.svn.core.internal.wc.ISVNAuthenticationStorage;
@@ -54,10 +44,6 @@ import org.tmatesoft.svn.core.wc.SVNDiffOptions;
import org.tmatesoft.svn.core.wc.SVNWCUtil;
import java.io.File;
import java.io.FilenameFilter;
import java.net.InetSocketAddress;
import java.net.PasswordAuthentication;
import java.net.Proxy;
import java.util.*;
@State(
@@ -73,26 +59,18 @@ public class SvnConfiguration implements PersistentStateComponent<Element> {
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<Element> {
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<Element> {
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<Element> {
}
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<Element> {
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<String, String> map = new HashMap<String, String>();
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<String,ProxyGroup> 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<String, String> 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<Element> {
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<Element> {
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<Element> {
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<Element> {
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<Element> {
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<Element> {
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<Element> {
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<Element> {
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<Element> {
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<Element> {
return myUpdateRootInfos.get(file);
}
// TODO: Check why SvnUpdateEnvironment.validationOptions is fully commented and then remove this method if necessary
public Map<File, UpdateRootInfo> getUpdateInfosMap() {
return Collections.unmodifiableMap(myUpdateRootInfos);
}
private static final List<String> 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<Element> {
myCleanupRun = cleanupRun;
}
public static enum SSLProtocols {
public enum SSLProtocols {
sslv3, tlsv1, all
}
}
@@ -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;
@@ -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<String> 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);
@@ -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<CommittedChangeList> {
return result;
}
public void collectInfo(@NotNull Collection<File> 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<CommittedChangeList> {
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");
}
}
@@ -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<Change> changes = new ArrayList<Change>();
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<Boolean> success = new Ref<Boolean>();
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);
}
}
}
@@ -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);
}
@@ -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();
}
@@ -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;
}
}
@@ -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<WorkingCopyFormat> supported) throws VcsException {
if (!supported.contains(format)) {
throw new VcsException(
@@ -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 extends SvnClient> T prepare(@NotNull T client) {
client.setVcs(myVcs);
@@ -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);
}
@@ -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);
}
@@ -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;
@@ -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
*
@@ -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));
@@ -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<File> paths, @Nullable ISVNInfoHandler handler) throws SVNException {
File base = ContainerUtil.getFirstItem(paths);
if (base != null) {
base = CommandUtil.correctUpToExistingParent(base);
List<String> 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);
}
}
}
}
@@ -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;
@@ -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);
}
}
@@ -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");
@@ -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;
@@ -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) {
@@ -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
@@ -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"));
@@ -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 {
@@ -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;
@@ -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<Change> 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<String> parameters = new ArrayList<String>();
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<Change> parseOutput(@NotNull SvnTarget target1, @NotNull SvnTarget target2, @NotNull CommandExecutor executor)
throws SvnBindException {
try {
DiffInfo diffInfo = CommandUtil.parse(executor.getOutput(), DiffInfo.class);
List<Change> 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<DiffPath> diffPaths = new ArrayList<DiffPath>();
}
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));
}
}
}
@@ -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();
}
}
}
@@ -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<Change> compare(@NotNull SvnTarget target1, @NotNull SvnTarget target2) throws VcsException;
}
@@ -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<Change> changes = new ArrayList<Change>();
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");
}
}
@@ -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);
}
}
@@ -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<byte[]> content = new Ref<byte[]>();
@NotNull private final StringBuilder remoteTitleBuilder = new StringBuilder();
@NotNull private final Ref<Boolean> success = new Ref<Boolean>();
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");
}
}
@@ -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<Change> compare(@NotNull SvnTarget target1, @NotNull SvnTarget target2) throws VcsException {
throw new UnsupportedOperationException("Diff client is not implemented for SVNKit");
}
}
@@ -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 <folder> -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;
@@ -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);
@@ -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
@@ -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() {
@@ -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);
}
@@ -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() {
@@ -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);
}
@@ -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 {
@@ -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) {
@@ -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);
}
@@ -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);
@@ -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<File> paths, @Nullable ISVNInfoHandler handler) throws SVNException;
}
@@ -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<File> paths, @Nullable ISVNInfoHandler handler) throws SVNException {
throw new UnsupportedOperationException();
}
}
@@ -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<UsageDescriptor> 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<RootUrlInfo> roots = ContainerUtil.filter(vcs.getSvnFileUrlMapping().getAllWcInfos(), new Condition<RootUrlInfo>() {
@Override
public boolean value(RootUrlInfo info) {
return info.getType() == null || NestedCopyType.inner.equals(info.getType());
}
});
return ContainerUtil.map2Set(roots, new Function<RootUrlInfo, UsageDescriptor>() {
@Override
public UsageDescriptor fun(RootUrlInfo info) {
return new UsageDescriptor(info.getFormat().toString(), 1);
}
});
}
}
@@ -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);
}
}
}
@@ -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);
@@ -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);
@@ -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<FilePath> roots) {
return true;
}
@@ -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() {
@@ -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();
}
}
}
@@ -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;
}
@@ -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());
}
});
}
@@ -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");
}
}
@@ -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);
@@ -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);
}
@@ -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;
@@ -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);
@@ -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);
}