From a5820de7deaf879d541c20ff4a4eddc3cccc45c5 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 11 Dec 2013 18:32:23 +0400 Subject: [PATCH 01/38] svn: Fixed conflict reason and conflict action parsing (for info command) --- .../jetbrains/idea/svn/commandLine/SvnInfoStructure.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoStructure.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoStructure.java index 1c44d348059a..696e366490d7 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoStructure.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoStructure.java @@ -119,7 +119,7 @@ public class SvnInfoStructure { private SVNConflictAction parseConflictAction(@NotNull String actionName) { SVNConflictAction action = SVNConflictAction.fromString(actionName); - action = action == null ? ourConflictActions.get(actionName) : null; + action = action != null ? action : ourConflictActions.get(actionName); if (action == null) { throw new IllegalArgumentException("Unknown conflict action " + actionName); @@ -130,10 +130,10 @@ public class SvnInfoStructure { private SVNConflictReason parseConflictReason(@NotNull String reasonName) throws SAXException { SVNConflictReason reason = SVNConflictReason.fromString(reasonName); - reason = reason == null ? ourConflictReasons.get(reasonName) : null; + reason = reason != null ? reason : ourConflictReasons.get(reasonName); if (reason == null) { - throw new SAXException("Can not parse conflict reason: " + reason); + throw new SAXException("Can not parse conflict reason: " + reasonName); } return reason; From 606d6808155c9a8571774583e6be5ed0539aa421 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 18 Dec 2013 15:45:32 +0400 Subject: [PATCH 02/38] svn: Remote revisions caches - added comments, removed unused methods --- .../vcs/changes/LazyRefreshingSelfQueue.java | 33 +++++++++++-------- .../changes/RemoteRevisionsNumbersCache.java | 18 ++++++++++ .../changes/RemoteRevisionsStateCache.java | 17 +++++++++- 3 files changed, 54 insertions(+), 14 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/LazyRefreshingSelfQueue.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/LazyRefreshingSelfQueue.java index 7a7b6a94d433..0f79d570c6a6 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/LazyRefreshingSelfQueue.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/LazyRefreshingSelfQueue.java @@ -32,14 +32,23 @@ import java.util.*; * */ @SomeQueue +// TODO: Used only in RemoteRevisionsNumberCache public class LazyRefreshingSelfQueue { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.changes.LazyRefreshingSelfQueue"); + // provides update interval in milliseconds. private final Getter myUpdateInterval; - // head is old. tail is new + // structure: + // 1) pairs with First == null + // 2) pairs with First != null sorted by First ascending + // pair.First - time when T was last processed + // pair.Second - some item T private final LinkedList> myQueue; + // Set of items that should be processed by myUpdater private final Set myInProgress; + // checks if updateStep should be really performed private final Computable myShouldUpdateOldChecker; + // performs some actions on item T, for instance - updates some data for T in cache private final Consumer myUpdater; private final Object myLock; @@ -52,20 +61,14 @@ public class LazyRefreshingSelfQueue { myLock = new Object(); } + // adds item that should be updated at next updateStep() call public void addRequest(@NotNull final T t) { synchronized (myLock) { myQueue.addFirst(new Pair(null, t)); } } - public void addRequests(final Collection values) { - synchronized (myLock) { - for (T value : values) { - myQueue.addFirst(new Pair(null, value)); - } - } - } - + // unschedules item from update at next updateStep() call public void forceRemove(@NotNull final T t) { synchronized (myLock) { for (Iterator> iterator = myQueue.iterator(); iterator.hasNext();) { @@ -80,11 +83,11 @@ public class LazyRefreshingSelfQueue { // called by outside timer or something public void updateStep() { - final List dirty = new LinkedList(); - final long startTime = System.currentTimeMillis() - myUpdateInterval.get(); boolean onlyAbsolute = true; - // check if we have some old items at all - if not, we would not check if repository latest revision had changed and will save time + // TODO: Actually we could store items with pair.First == null in separate list. + // checks item that has smallest update time - i.e. was not updated by the most time + // if its update time greater than current - interval => we should not update any item with pair.First != null this time (as they are ordered) synchronized (myLock) { for (Pair pair : myQueue) { if (pair.getFirst() != null) { @@ -96,9 +99,10 @@ public class LazyRefreshingSelfQueue { // do not ask under lock final Boolean shouldUpdateOld = onlyAbsolute ? false : myShouldUpdateOldChecker.compute(); + final List dirty = new LinkedList(); synchronized (myLock) { - // get absolute + // adds all pairs with pair.First == null to dirty while (! myQueue.isEmpty()) { final Pair pair = myQueue.get(0); if (pair.getFirst() == null) { @@ -108,6 +112,7 @@ public class LazyRefreshingSelfQueue { } } if (Boolean.TRUE.equals(shouldUpdateOld) && (! myQueue.isEmpty())) { + // adds all pairs with update time (pair.First) < current - interval to dirty while (! myQueue.isEmpty()) { final Pair pair = myQueue.get(0); if (pair.getFirst() < startTime) { @@ -126,6 +131,8 @@ public class LazyRefreshingSelfQueue { for (T t : dirty) { myUpdater.consume(t); synchronized (myLock) { + // output value of remove() is tracked not to process items that were removed from myInProgress in forceRemove() + // TODO: Probably more clear logic should be implemented if (myInProgress.remove(t)) { myQueue.addLast(new Pair(System.currentTimeMillis(), t)); } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/RemoteRevisionsNumbersCache.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/RemoteRevisionsNumbersCache.java index f9b5fda3bd07..30d8f5ef88c0 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/RemoteRevisionsNumbersCache.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/RemoteRevisionsNumbersCache.java @@ -88,11 +88,13 @@ public class RemoteRevisionsNumbersCache implements ChangesOnServerTracker { public boolean updateStep() { mySomethingChanged = false; + // copy under lock final HashMap copyMap; synchronized (myLock) { copyMap = new HashMap(myRefreshingQueues); } + // filter only items for vcs roots that support background operations for (Iterator> iterator = copyMap.entrySet().iterator(); iterator.hasNext();) { final Map.Entry entry = iterator.next(); final VcsRoot key = entry.getKey(); @@ -103,6 +105,7 @@ public class RemoteRevisionsNumbersCache implements ChangesOnServerTracker { } } LOG.debug("queues refresh started, queues: " + copyMap.size()); + // refresh "up to date" info for (LazyRefreshingSelfQueue queue : copyMap.values()) { if (myProject.isDisposed()) throw new ProcessCanceledException(); queue.updateStep(); @@ -111,10 +114,12 @@ public class RemoteRevisionsNumbersCache implements ChangesOnServerTracker { } public void directoryMappingChanged() { + // copy myData under lock HashSet keys; synchronized (myLock) { keys = new HashSet(myData.keySet()); } + // collect new vcs for scheduled files final Map> vFiles = new HashMap>(); for (String key : keys) { final VirtualFile vf = myLfs.refreshAndFindFileByIoFile(new File(key)); @@ -244,6 +249,7 @@ public class RemoteRevisionsNumbersCache implements ChangesOnServerTracker { public void consume(String s) { LOG.debug("update for: " + s); //todo check canceled - check VCS's ready for asynchronous queries + // get last remote revision for file final VirtualFile vf = myLfs.refreshAndFindFileByIoFile(new File(s)); final ItemLatestState state; final DiffProvider diffProvider = myVcsRoot.getVcs().getDiffProvider(); @@ -256,6 +262,7 @@ public class RemoteRevisionsNumbersCache implements ChangesOnServerTracker { final VcsRevisionNumber newNumber = (state == null) || state.isDefaultHead() ? UNKNOWN : state.getNumber(); final Pair oldPair; + // update value in cache synchronized (myLock) { oldPair = myData.get(s); myData.put(s, new Pair(myVcsRoot, newNumber)); @@ -275,6 +282,8 @@ public class RemoteRevisionsNumbersCache implements ChangesOnServerTracker { myVcsRoot = vcsRoot; } + // Check if currently cached vcs root latest revision is less than latest vcs root revision + // => update should be performed in this case public Boolean compute() { final AbstractVcs vcs = myVcsRoot.getVcs(); // won't be called in parallel for same vcs -> just synchronized map is ok @@ -282,6 +291,8 @@ public class RemoteRevisionsNumbersCache implements ChangesOnServerTracker { LOG.debug("should update for: " + vcsName + " root: " + myVcsRoot.getPath().getPath()); final VcsRevisionNumber latestNew = vcs.getDiffProvider().getLatestCommittedRevision(myVcsRoot.getPath()); + // TODO: Why vcsName is used as key and not myVcsRoot.getKey()??? + // TODO: This seems to be invalid logic as we get latest revision for vcs root final VcsRevisionNumber latestKnown = myLatestRevisionsMap.get(vcsName); // not known if (latestNew == null) return true; @@ -307,8 +318,15 @@ public class RemoteRevisionsNumbersCache implements ChangesOnServerTracker { return getRevisionState(change.getBeforeRevision()) && getRevisionState(change.getAfterRevision()); } + /** + * Returns {@code true} if passed revision is up to date, comparing to latest repository revision. + * + * @param revision + * @return + */ private boolean getRevisionState(final ContentRevision revision) { if (revision != null) { + // TODO: Seems peg revision should also be tracked here. final VcsRevisionNumber local = revision.getRevisionNumber(); final String path = revision.getFile().getIOFile().getAbsolutePath(); final VcsRevisionNumber remote = getNumber(path); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/RemoteRevisionsStateCache.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/RemoteRevisionsStateCache.java index adf940b1ec34..d5e197604171 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/RemoteRevisionsStateCache.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/RemoteRevisionsStateCache.java @@ -27,10 +27,14 @@ import java.util.*; public class RemoteRevisionsStateCache implements ChangesOnServerTracker { private final static long DISCRETE = 3600000; - // true -> changed + // All files that were checked during cache update and were not invalidated. + // pair.First - if file is changed (true means changed) + // pair.Second - vcs root where file belongs to private final Map> myChanged; + // All files that needs to be checked during next cache update, grouped by vcs root private final MultiMap myQueries; + // All vcs roots for which cache update was performed with update timestamp private final Map myTs; private final Object myLock; private final ProjectLevelVcsManager myVcsManager; @@ -104,6 +108,7 @@ public class RemoteRevisionsStateCache implements ChangesOnServerTracker { myVcsConfiguration.CHANGED_ON_SERVER_INTERVAL * 60000 : DISCRETE); synchronized (myLock) { + // just copies myQueries MultiMap to dirty MultiMap for (VcsRoot root : myQueries.keySet()) { final Collection collection = myQueries.get(root); for (String s : collection) { @@ -112,15 +117,23 @@ public class RemoteRevisionsStateCache implements ChangesOnServerTracker { } myQueries.clear(); + // collect roots for which cache update should be performed (by timestamp) final Set roots = new HashSet(); for (Map.Entry entry : myTs.entrySet()) { + // ignore timestamp, as still remote changes checking is required + // TODO: why not to add in roots anyway??? - as dirty is still checked when adding myChanged files. if (! dirty.get(entry.getKey()).isEmpty()) continue; + // update only if timeout expired final Long ts = entry.getValue(); if ((ts == null) || (oldPoint > ts)) { roots.add(entry.getKey()); } } + + // Add dirty files from those vcs roots, that + // - needs to be update by timestamp criteria + // - that already contain files for update through manually added requests for (Map.Entry> entry : myChanged.entrySet()) { final VcsRoot vcsRoot = entry.getValue().getSecond(); if ((! dirty.get(vcsRoot).isEmpty()) || roots.contains(vcsRoot)) { @@ -142,6 +155,8 @@ public class RemoteRevisionsStateCache implements ChangesOnServerTracker { final Collection paths = dirty.get(vcsRoot); final Collection remotelyChanged = provider.getRemotelyChanged(vcsRoot.getPath(), paths); for (String path : paths) { + // TODO: Contains invoked for each file - better to use Set (implementations just use List) + // TODO: Why to store boolean for changed or not - why not just remove such values from myChanged??? results.put(path, new Pair(remotelyChanged.contains(path), vcsRoot)); } } From 54ea88ba745e1d2388a756f5a5c54da70a766fba Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 18 Dec 2013 15:53:16 +0400 Subject: [PATCH 03/38] svn: Refactored ReceivedChangeList type checks - used ReceivedChangeList.unwrap() --- .../vcs/changes/committed/ChangeListDetailsAction.java | 8 +------- .../vcs/changes/committed/CommittedChangesCache.java | 5 ++--- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/ChangeListDetailsAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/ChangeListDetailsAction.java index 8c7a32463f0f..b6e7f8be7044 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/ChangeListDetailsAction.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/ChangeListDetailsAction.java @@ -74,13 +74,7 @@ public class ChangeListDetailsAction extends AnAction implements DumbAware { detailsBuilder.append("
"); if (provider != null) { - final CommittedChangeList originalChangeList; - if (changeList instanceof ReceivedChangeList) { - originalChangeList = ((ReceivedChangeList) changeList).getBaseList(); - } - else { - originalChangeList = changeList; - } + final CommittedChangeList originalChangeList = ReceivedChangeList.unwrap(changeList); for(ChangeListColumn column: provider.getColumns()) { if (ChangeListColumn.isCustom(column)) { String value = column.getValue(originalChangeList).toString(); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesCache.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesCache.java index 9155a1a63fd9..4c13ef015123 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesCache.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesCache.java @@ -688,14 +688,13 @@ public class CommittedChangesCache implements PersistentStateComponent baseChanges = new HashSet(); for (CommittedChangeList list : lists) { - baseChanges.addAll(list instanceof ReceivedChangeList ? ((ReceivedChangeList) list).getBaseList().getChanges() : list.getChanges()); + baseChanges.addAll(ReceivedChangeList.unwrap(list).getChanges()); final Collection changes = list.getChanges(); for (Change change : changes) { From ac3960b851317f1ce5b21ce8951e96afac0d7b68 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 18 Dec 2013 20:07:37 +0400 Subject: [PATCH 04/38] svn: Implemented support to get info for several files in batch (for command line) --- .../src/org/jetbrains/idea/svn/SvnVcs.java | 28 +++++++++++++++++ .../commandLine/SvnCommandLineInfoClient.java | 31 +++++++++++++++++-- .../idea/svn/portable/SvnWcClientI.java | 4 +++ .../idea/svn/portable/SvnkitSvnWcClient.java | 6 ++++ 4 files changed, 66 insertions(+), 3 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java index 646363c56a13..108924d9b31a 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java @@ -56,6 +56,7 @@ import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.util.Consumer; import com.intellij.util.Processor; import com.intellij.util.ThreeState; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.Convertor; import com.intellij.util.containers.SoftHashMap; import com.intellij.util.messages.MessageBus; @@ -979,6 +980,33 @@ public class SvnVcs extends AbstractVcs { return result; } + public void collectInfo(@NotNull Collection files, @Nullable ISVNInfoHandler handler) { + File first = ContainerUtil.getFirstItem(files); + + if (first != null) { + ClientFactory factory = getFactory(first); + + try { + if (factory instanceof CmdClientFactory) { + factory.createInfoClient().doInfo(files, handler); + } + else { + // TODO: Generally this should be moved in SvnKit info client implementation. + // TODO: Currently left here to have exception logic as in handleInfoException to be applied for each file separately. + for (File file : files) { + SVNInfo info = getInfo(file); + if (handler != null) { + handler.handleInfo(info); + } + } + } + } + catch (SVNException e) { + handleInfoException(e); + } + } + } + @Nullable public SVNInfo getInfo(@NotNull File ioFile, @NotNull SVNRevision revision) { SVNInfo result = null; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineInfoClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineInfoClient.java index 844835d37bbe..ef4822607e37 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineInfoClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineInfoClient.java @@ -23,6 +23,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.util.Consumer; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnVcs; @@ -124,13 +125,15 @@ public class SvnCommandLineInfoClient extends SvnkitSvnWcClient { final String text = e.getMessage(); final boolean notEmpty = !StringUtil.isEmptyOrSpaces(text); if (notEmpty && text.contains("W155010")) { - // just null - return null; + // if "svn info" is executed for several files at once, then this warning could be printed only for some files, but info for other + // files should be parsed from output + return output.getStdout(); } // not a working copy exception // "E155007: '' is not a working copy" if (notEmpty && text.contains("is not a working copy")) { if (StringUtil.isNotEmpty(output.getStdout())) { + // TODO: Seems not reproducible in 1.8.4 // workaround: as in subversion 1.8 "svn info" on a working copy root outputs such error for parent folder, // if there are files with conflicts. // but the requested info is still in the output except root closing tag @@ -152,7 +155,7 @@ public class SvnCommandLineInfoClient extends SvnkitSvnWcClient { } } - private void parseResult(@NotNull final ISVNInfoHandler handler, @Nullable File base, @Nullable String result) throws SVNException { + private static void parseResult(@NotNull final ISVNInfoHandler handler, @Nullable File base, @Nullable String result) throws SVNException { if (StringUtil.isEmpty(result)) { return; } @@ -246,4 +249,26 @@ public class SvnCommandLineInfoClient extends SvnkitSvnWcClient { }); return infoArr[0]; } + + @Override + public void doInfo(@NotNull Collection paths, @Nullable ISVNInfoHandler handler) throws SVNException { + File base = ContainerUtil.getFirstItem(paths); + + if (base != null) { + base = CommandUtil.correctUpToExistingParent(base); + + List parameters = ContainerUtil.newArrayList(); + for (File file : paths) { + CommandUtil.put(parameters, file); + } + CommandUtil.put(parameters, true, "--xml"); + + // Currently do not handle exceptions here like in SvnVcs.handleInfoException - just continue with parsing in case of warnings for + // some of the requested items + String result = execute(parameters, base); + if (handler != null) { + parseResult(handler, base, result); + } + } + } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnWcClientI.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnWcClientI.java index 036de6b785be..48ba32e5357d 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnWcClientI.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnWcClientI.java @@ -15,6 +15,8 @@ */ package org.jetbrains.idea.svn.portable; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.wc.*; @@ -38,4 +40,6 @@ public interface SvnWcClientI extends SvnMarkerInterface { ISVNInfoHandler handler) throws SVNException; SVNInfo doInfo(File path, SVNRevision revision) throws SVNException; SVNInfo doInfo(SVNURL url, SVNRevision pegRevision, SVNRevision revision) throws SVNException; + + void doInfo(@NotNull Collection paths, @Nullable ISVNInfoHandler handler) throws SVNException; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnkitSvnWcClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnkitSvnWcClient.java index faee8ecc3cb2..44cca7fa26c8 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnkitSvnWcClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnkitSvnWcClient.java @@ -16,6 +16,7 @@ package org.jetbrains.idea.svn.portable; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnVcs; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.wc.*; @@ -83,4 +84,9 @@ public class SvnkitSvnWcClient implements SvnWcClientI { public SVNInfo doInfo(SVNURL url, SVNRevision pegRevision, SVNRevision revision) throws SVNException { return getClient().doInfo(url, pegRevision, revision); } + + @Override + public void doInfo(@NotNull Collection paths, @Nullable ISVNInfoHandler handler) throws SVNException { + throw new UnsupportedOperationException(); + } } From 95c04d18b04648988634e31d5ebacdba3ecf2eac Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 18 Dec 2013 23:03:26 +0400 Subject: [PATCH 05/38] svn: Use common path resolution logic while command output parsing for status, info, commit, update --- .../jetbrains/idea/svn/commandLine/CommandUtil.java | 11 +++++++++++ .../idea/svn/commandLine/SvnCommitRunner.java | 8 +------- .../idea/svn/commandLine/SvnInfoHandler.java | 2 +- .../idea/svn/commandLine/SvnStatusHandler.java | 11 +---------- .../svn/commandLine/UpdateOutputLineConverter.java | 2 +- 5 files changed, 15 insertions(+), 19 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java index 6125ea4c72df..b38d1c914bdf 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java @@ -25,6 +25,17 @@ import java.util.List; */ public class CommandUtil { + @NotNull + public static File resolvePath(@NotNull File base, @NotNull String path) { + File result = new File(path); + + if (!result.isAbsolute()) { + result = ".".equals(path) ? base : new File(base, path); + } + + return result; + } + /** * Puts given value to parameters if condition is satisfied * diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommitRunner.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommitRunner.java index 4780fde090fa..d9b760d8b24a 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommitRunner.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommitRunner.java @@ -213,13 +213,7 @@ public class SvnCommitRunner { @NotNull private File toFile(@NotNull String path) { - File result = new File(path); - - if (!result.isAbsolute()) { - result = new File(myBase, result.getPath()); - } - - return result; + return CommandUtil.resolvePath(myBase, path); } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoHandler.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoHandler.java index f52f120c3217..46372c2a3ec2 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoHandler.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoHandler.java @@ -887,7 +887,7 @@ public class SvnInfoHandler extends DefaultHandler { if (myBase != null) { final String path = attributes.getValue("path"); assertSAX(!StringUtil.isEmptyOrSpaces(path)); - structure.myFile = new File(myBase, path); + structure.myFile = CommandUtil.resolvePath(myBase, path); } final String revision = attributes.getValue("revision"); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnStatusHandler.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnStatusHandler.java index 9ba9f9b81baa..65ca32be58b1 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnStatusHandler.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnStatusHandler.java @@ -739,16 +739,7 @@ public class SvnStatusHandler extends DefaultHandler { protected void updateStatus(Attributes attributes, PortableStatus status, SVNLockWrapper lock) throws SAXException { final String path = attributes.getValue("path"); assertSAX(path != null); - final File file; - if (new File(path).isAbsolute()) { - file = new File(path); - } else { - if (".".equals(path)) { - file = myBase; - } else { - file = new File(myBase, path); - } - } + final File file = CommandUtil.resolvePath(myBase, path); status.setFile(file); final boolean exists = file.exists(); if (exists) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/UpdateOutputLineConverter.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/UpdateOutputLineConverter.java index 6520c6254f65..44d9d7243819 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/UpdateOutputLineConverter.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/UpdateOutputLineConverter.java @@ -169,7 +169,7 @@ public class UpdateOutputLineConverter { } private File createFile(String path) { - return FileUtil.isAbsolute(path) ? new File(path) : new File(myBase, path); + return CommandUtil.resolvePath(myBase, path); } @Nullable From 573e4682d57749cc364cbe2a41f25877679b4a3e Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Fri, 20 Dec 2013 13:27:16 +0400 Subject: [PATCH 06/38] svn: Implemented "Compare with Branch" action for files for command line --- .../svn/actions/CompareWithBranchAction.java | 50 +++++++++++-------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CompareWithBranchAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CompareWithBranchAction.java index 544bbc7beda8..72d353ac7ec4 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CompareWithBranchAction.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CompareWithBranchAction.java @@ -19,7 +19,6 @@ 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; @@ -35,6 +34,7 @@ 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.VcsException; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.openapi.vfs.VirtualFile; @@ -42,6 +42,7 @@ 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.commandLine.SvnBindException; import org.jetbrains.idea.svn.status.SvnDiffEditor; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.internal.util.SVNPathUtil; @@ -55,10 +56,10 @@ 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.core.wc2.SvnTarget; 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; @@ -172,7 +173,7 @@ public class CompareWithBranchAction extends AnAction implements DumbAware { changes.clear(); } catch (SVNException ex) { - reportException(ex, baseUrl); + reportException(new SvnBindException(ex), baseUrl); } } @@ -275,7 +276,7 @@ public class CompareWithBranchAction extends AnAction implements DumbAware { } public void compareFileWithBranch(final String baseUrl, final long revision) { - final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + final Ref content = new Ref(); final StringBuilder remoteTitleBuilder = new StringBuilder(); final Ref success = new Ref(); ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { @@ -292,20 +293,25 @@ public class CompareWithBranchAction extends AnAction implements DumbAware { return; } remoteTitleBuilder.append(svnurl.toString()); - SVNWCClient client = vcs.createWCClient(); - client.doGetFileContents(svnurl, SVNRevision.UNDEFINED, SVNRevision.HEAD, true, baos); + content.set(SvnUtil.getFileContents(vcs, SvnTarget.fromURL(svnurl), SVNRevision.HEAD, SVNRevision.UNDEFINED)); success.set(true); } catch (SVNException ex) { + reportException(new SvnBindException(ex), baseUrl); + } + catch (SvnBindException ex) { reportException(ex, baseUrl); } + catch (VcsException ex) { + reportGeneralException(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())), + 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); @@ -335,25 +341,29 @@ public class CompareWithBranchAction extends AnAction implements DumbAware { 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)) { + private void reportException(final SvnBindException e, final String baseUrl) { + 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(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); + reportGeneralException(e, baseUrl); } } + private void reportGeneralException(final Exception e, final String baseUrl) { + 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(final String baseUrl) { WaitForProgressToShow.runOrInvokeLaterAboveProgress(new Runnable() { public void run() { From e9fde923bb842aa0feea51dbb1d53ce60e4e78b2 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Fri, 20 Dec 2013 16:19:59 +0400 Subject: [PATCH 07/38] svn: Refactored CompareWithBranchAction - method extractions, object extractions, removed unused code --- .../svn/actions/CompareWithBranchAction.java | 481 ++++++++++-------- 1 file changed, 264 insertions(+), 217 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CompareWithBranchAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CompareWithBranchAction.java index 72d353ac7ec4..3b28f2fceab7 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CompareWithBranchAction.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CompareWithBranchAction.java @@ -26,6 +26,7 @@ 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.progress.Task; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; @@ -39,6 +40,7 @@ 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.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.*; import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew; @@ -75,11 +77,8 @@ public class CompareWithBranchAction extends AnAction implements DumbAware { 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")); + SelectBranchPopup + .show(project, virtualFile, new MyBranchSelectedCallback(virtualFile), SvnBundle.message("compare.with.branch.popup.title")); } @Override @@ -100,226 +99,90 @@ public class CompareWithBranchAction extends AnAction implements DumbAware { return true; } + private static class MyBranchSelectedCallback implements SelectBranchPopup.BranchSelectedCallback { - private class CompareWithBranchOperation { - private final Project myProject; - private final VirtualFile myVirtualFile; - private final SvnBranchConfigurationNew myConfiguration; + @NotNull private final VirtualFile myVirtualFile; - public CompareWithBranchOperation(final Project project, final VirtualFile virtualFile, final SvnBranchConfigurationNew config) { - myProject = project; + public MyBranchSelectedCallback(@NotNull VirtualFile virtualFile) { 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 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); - public void compareDirectoryWithBranch(final String baseUrl, final long revision) { - final List changes = new ArrayList(); - ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { - public void run() { + comparer.run(); + } + } + + private static abstract class ElementWithBranchComparer { + + @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; + + protected 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 { - 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); + beforeCompare(); + myElementUrl = resolveElementUrl(); + if (myElementUrl == null) { + reportNotFound(); + } + else { + compare(); } - - /* 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 (SVNCancelException ex) { + ElementWithBranchComparer.this.onCancel(); } catch (SVNException ex) { - reportException(new SvnBindException(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 Ref content = new Ref(); - final StringBuilder remoteTitleBuilder = new StringBuilder(); - final Ref success = new Ref(); - ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { - public void run() { - try { - final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); - if (indicator != null) { - indicator.setIndeterminate(true); - } - final SvnVcs vcs = SvnVcs.getInstance(myProject); - SVNURL svnurl = getURLInBranch(vcs, baseUrl); - if (svnurl == null) { - reportNotFound(baseUrl); - return; - } - remoteTitleBuilder.append(svnurl.toString()); - content.set(SvnUtil.getFileContents(vcs, SvnTarget.fromURL(svnurl), SVNRevision.HEAD, SVNRevision.UNDEFINED)); - success.set(true); - } - catch (SVNException ex) { - reportException(new SvnBindException(ex), baseUrl); + reportException(new SvnBindException(ex)); } catch (SvnBindException ex) { - reportException(ex, baseUrl); + reportException(ex); } catch (VcsException ex) { - reportGeneralException(ex, baseUrl); + reportGeneralException(ex); } } - }, 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(content.get(), myVirtualFile.getCharset())), - new FileContent(myProject, myVirtualFile)); - req.setContentTitles(remoteTitleBuilder.toString(), myVirtualFile.getPresentableUrl()); - DiffManager.getInstance().getDiffTool().show(req); + }.queue(); + showResult(); } + protected void beforeCompare() { + } + + protected abstract void compare() throws SVNException, VcsException; + + protected abstract void showResult(); + + protected void onCancel() { + } + + public abstract String getTitle(); + @Nullable - private SVNURL getURLInBranch(final SvnVcs vcs, final String baseUrl) throws SVNException { - final SvnFileUrlMapping urlMapping = vcs.getSvnFileUrlMapping(); + 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) { @@ -332,29 +195,29 @@ public class CompareWithBranchAction extends AnAction implements DumbAware { return null; } - final SVNURL thisBranchForUrl = SvnUtil.getBranchForUrl(vcs, rootMixed.getVirtualFile(), fileUrlString); + 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(baseUrl, relativePath)); + return SVNURL.parseURIEncoded(SVNPathUtil.append(myBranchUrl, relativePath)); } - private void reportException(final SvnBindException e, final String baseUrl) { + 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(baseUrl); + reportNotFound(); } else { - reportGeneralException(e, baseUrl); + reportGeneralException(e); } } - private void reportGeneralException(final Exception e, final String baseUrl) { + private void reportGeneralException(final Exception e) { WaitForProgressToShow.runOrInvokeLaterAboveProgress(new Runnable() { public void run() { Messages.showMessageDialog(myProject, e.getMessage(), @@ -364,14 +227,198 @@ public class CompareWithBranchAction extends AnAction implements DumbAware { LOG.info(e); } - private void reportNotFound(final String baseUrl) { + private void reportNotFound() { 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()); + 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); + } + } + + public static class FileWithBranchComparer extends ElementWithBranchComparer { + + @NotNull private final Ref content = new Ref(); + @NotNull private final StringBuilder remoteTitleBuilder = new StringBuilder(); + @NotNull private final Ref success = new Ref(); + + public FileWithBranchComparer(@NotNull Project project, + @NotNull VirtualFile virtualFile, + @NotNull String branchUrl, + long branchRevision) { + super(project, virtualFile, branchUrl, branchRevision); + } + + @Override + protected void beforeCompare() { + final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); + if (indicator != null) { + indicator.setIndeterminate(true); + } + } + + @Override + protected void compare() throws SVNException, VcsException { + remoteTitleBuilder.append(myElementUrl); + content.set(SvnUtil.getFileContents(myVcs, SvnTarget.fromURL(myElementUrl), SVNRevision.HEAD, SVNRevision.UNDEFINED)); + success.set(true); + } + + @Override + protected void showResult() { + if (!success.isNull()) { + SimpleDiffRequest req = new SimpleDiffRequest(myProject, SvnBundle.message("compare.with.branch.diff.title")); + req.setContents(new SimpleContent(CharsetToolkit.bytesToString(content.get(), myVirtualFile.getCharset())), + new FileContent(myProject, myVirtualFile)); + req.setContentTitles(remoteTitleBuilder.toString(), myVirtualFile.getPresentableUrl()); + DiffManager.getInstance().getDiffTool().show(req); + } + } + + @Override + public String getTitle() { + return SvnBundle.message("compare.with.branch.progress.loading.content"); + } + } + + public static class DirectoryWithBranchComparer extends ElementWithBranchComparer { + + @NotNull private final StringBuilder titleBuilder = new StringBuilder(); + @NotNull private final List changes = new ArrayList(); + + public DirectoryWithBranchComparer(@NotNull Project project, + @NotNull VirtualFile virtualFile, + @NotNull String branchUrl, + long branchRevision) { + super(project, virtualFile, branchUrl, branchRevision); + } + + @Override + protected void compare() throws SVNException, VcsException { + titleBuilder.append(SvnBundle.message("repository.browser.compare.title", myElementUrl, + FileUtil.toSystemDependentName(myVirtualFile.getPresentableUrl()))); + + final File ioFile = new File(myVirtualFile.getPath()); + if (SvnUtil.is17CopyPart(ioFile)) { + report17DirDiff(); + } + else { + report16DirDiff(); + } + } + + private void report17DirDiff() throws SVNException { + final File ioFile = new File(myVirtualFile.getPath()); + final SVNWCClient wcClient = myVcs.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 { } - }, null, myProject); + + @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"); } } } From b6ed9e4fec07bf947ec934c62969ea159686d2e8 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Tue, 24 Dec 2013 02:55:59 +0400 Subject: [PATCH 08/38] svn: Refactored SvnStatusConvertor - removed unused code, inlined methods, not null --- .../idea/svn/SvnStatusConvertor.java | 32 +++++++------------ 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnStatusConvertor.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnStatusConvertor.java index 184fbab0bc14..970011063eb0 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnStatusConvertor.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnStatusConvertor.java @@ -16,7 +16,8 @@ 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.tmatesoft.svn.core.wc.SVNStatus; import org.tmatesoft.svn.core.wc.SVNStatusType; @@ -24,11 +25,8 @@ public class SvnStatusConvertor { private SvnStatusConvertor() { } - public static FileStatus convertStatus(final SVNStatus status) throws SVNException { - return convertStatus(status, true); - } - - 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 +55,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 +78,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 +108,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; From e16093895bcd381682ebe36136b82a630be3bc8e Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Tue, 24 Dec 2013 03:04:41 +0400 Subject: [PATCH 09/38] svn: Implemented diff client for command line - to compare local/remote directories content --- .../idea/svn/SvnStatusConvertor.java | 11 ++ .../jetbrains/idea/svn/api/ClientFactory.java | 7 + .../idea/svn/api/CmdClientFactory.java | 2 + .../idea/svn/api/SvnKitClientFactory.java | 2 + .../idea/svn/commandLine/SvnCommandName.java | 3 +- .../svn/commandLine/SvnStatusHandler.java | 2 +- .../idea/svn/diff/CmdDiffClient.java | 139 ++++++++++++++++++ .../jetbrains/idea/svn/diff/DiffClient.java | 32 ++++ .../idea/svn/diff/SvnKitDiffClient.java | 35 +++++ 9 files changed, 231 insertions(+), 2 deletions(-) create mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CmdDiffClient.java create mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DiffClient.java create mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/diff/SvnKitDiffClient.java diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnStatusConvertor.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnStatusConvertor.java index 970011063eb0..3c0d396657c7 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnStatusConvertor.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnStatusConvertor.java @@ -18,6 +18,7 @@ package org.jetbrains.idea.svn; import com.intellij.openapi.vcs.FileStatus; 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; @@ -25,6 +26,16 @@ public class SvnStatusConvertor { private SvnStatusConvertor() { } + @NotNull + public static FileStatus convertStatus(@Nullable SVNStatusType itemStatus, @Nullable SVNStatusType propertiesStatus) { + PortableStatus status = new PortableStatus(); + + status.setContentsStatus(itemStatus); + status.setPropertiesStatus(propertiesStatus); + + return convertStatus(status); + } + @NotNull public static FileStatus convertStatus(@Nullable final SVNStatus status) { if (status == null) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java index 22fb76957ac2..9c01217da9f1 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java @@ -14,6 +14,7 @@ import org.jetbrains.idea.svn.conflict.ConflictClient; import org.jetbrains.idea.svn.content.ContentClient; import org.jetbrains.idea.svn.copy.CopyMoveClient; import org.jetbrains.idea.svn.delete.DeleteClient; +import org.jetbrains.idea.svn.diff.DiffClient; import org.jetbrains.idea.svn.history.HistoryClient; import org.jetbrains.idea.svn.integrate.MergeClient; import org.jetbrains.idea.svn.lock.LockClient; @@ -55,6 +56,7 @@ public abstract class ClientFactory { protected ExportClient myExportClient; protected UpgradeClient myUpgradeClient; protected BrowseClient myBrowseClient; + protected DiffClient myDiffClient; protected ClientFactory(@NotNull SvnVcs vcs) { myVcs = vcs; @@ -180,6 +182,11 @@ public abstract class ClientFactory { return prepare(myBrowseClient); } + @NotNull + public DiffClient createDiffClient() { + return prepare(myDiffClient); + } + @NotNull protected T prepare(@NotNull T client) { client.setVcs(myVcs); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java index c99b803c05a2..653852ca3f49 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java @@ -10,6 +10,7 @@ import org.jetbrains.idea.svn.checkin.CmdImportClient; import org.jetbrains.idea.svn.checkout.CmdCheckoutClient; import org.jetbrains.idea.svn.checkout.CmdExportClient; import org.jetbrains.idea.svn.cleanup.CmdCleanupClient; +import org.jetbrains.idea.svn.diff.CmdDiffClient; import org.jetbrains.idea.svn.update.CmdUpdateClient; import org.jetbrains.idea.svn.commandLine.SvnCommandLineInfoClient; import org.jetbrains.idea.svn.commandLine.SvnCommandLineStatusClient; @@ -57,6 +58,7 @@ public class CmdClientFactory extends ClientFactory { myExportClient = new CmdExportClient(); myUpgradeClient = new CmdUpgradeClient(); myBrowseClient = new CmdBrowseClient(); + myDiffClient = new CmdDiffClient(); statusClient = new SvnCommandLineStatusClient(myVcs); infoClient = new SvnCommandLineInfoClient(myVcs); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java index dbe6b0b88989..3fb1d83c159d 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java @@ -14,6 +14,7 @@ import org.jetbrains.idea.svn.conflict.SvnKitConflictClient; import org.jetbrains.idea.svn.content.SvnKitContentClient; import org.jetbrains.idea.svn.copy.SvnKitCopyMoveClient; import org.jetbrains.idea.svn.delete.SvnKitDeleteClient; +import org.jetbrains.idea.svn.diff.SvnKitDiffClient; import org.jetbrains.idea.svn.history.SvnKitHistoryClient; import org.jetbrains.idea.svn.integrate.SvnKitMergeClient; import org.jetbrains.idea.svn.lock.SvnKitLockClient; @@ -57,6 +58,7 @@ public class SvnKitClientFactory extends ClientFactory { myExportClient = new SvnKitExportClient(); myUpgradeClient = new SvnKitUpgradeClient(); myBrowseClient = new SvnKitBrowseClient(); + myDiffClient = new SvnKitDiffClient(); statusClient = new SvnkitSvnStatusClient(myVcs, null); infoClient = new SvnkitSvnWcClient(myVcs); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandName.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandName.java index ac7f958fc059..c31ce2355276 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandName.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandName.java @@ -51,7 +51,8 @@ public enum SvnCommandName { importFolder("import", false), export("export", false), upgrade("upgrade", true), - list("list", false); + list("list", false), + diff("diff", false); private final String myName; private final boolean myWriteable; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnStatusHandler.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnStatusHandler.java index 65ca32be58b1..460f7cde959a 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnStatusHandler.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnStatusHandler.java @@ -67,7 +67,7 @@ public class SvnStatusHandler extends DefaultHandler { } @Nullable - private static SVNStatusType getStatus(@NotNull String code) { + public static SVNStatusType getStatus(@NotNull String code) { SVNStatusType result = ourStatusTypes.get(code); if (result == null) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CmdDiffClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CmdDiffClient.java new file mode 100644 index 000000000000..c4a21ee444fb --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CmdDiffClient.java @@ -0,0 +1,139 @@ +/* + * 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.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.idea.svn.SvnContentRevision; +import org.jetbrains.idea.svn.SvnStatusConvertor; +import org.jetbrains.idea.svn.api.BaseSvnClient; +import org.jetbrains.idea.svn.commandLine.*; +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.util.ArrayList; +import java.util.List; + +/** + * @author Konstantin Kolosovsky. + */ +public class CmdDiffClient extends BaseSvnClient implements DiffClient { + + @Override + public List compare(@NotNull SvnTarget target1, @NotNull SvnTarget target2) throws VcsException { + // TODO: Currently implemented only for "Compare with Branch" action - target1 is assumed to be file, target2 - repository url + // Such combination (file and url) with "--summarize" option is supported only in svn 1.8. + // For svn 1.7 "--summarize" is only supported when both targets are repository urls. + assertFile(target1); + assertUrl(target2); + + List parameters = new ArrayList(); + CommandUtil.put(parameters, target1); + CommandUtil.put(parameters, target2); + parameters.add("--xml"); + parameters.add("--summarize"); + + CommandExecutor executor = CommandUtil.execute(myVcs, target1, SvnCommandName.diff, parameters, null); + return parseOutput(executor); + } + + private List parseOutput(@NotNull CommandExecutor executor) throws SvnBindException { + try { + DiffInfo diffInfo = CommandUtil.parse(executor.getOutput(), DiffInfo.class); + SvnTarget base = SvnTarget.fromFile(executor.getCommand().getWorkingDirectory()); + List result = ContainerUtil.newArrayList(); + + if (diffInfo != null && diffInfo.paths != null) { + for (DiffPath path : diffInfo.paths.diffPaths) { + result.add(createChange(base, path)); + } + } + + return result; + } + catch (JAXBException e) { + throw new SvnBindException(e); + } + } + + private ContentRevision createBeforeRevision(@NotNull SvnTarget target, @NotNull String path) { + return SvnContentRevision.createRemote(myVcs, createFilePath(target, path), SVNRevision.HEAD); + } + + private static ContentRevision createAfterRevision(@NotNull SvnTarget target, @NotNull String path) { + return CurrentContentRevision.create(createFilePath(target, path)); + } + + private static FilePath createFilePath(@NotNull SvnTarget target, @NotNull String path) { + return target.isFile() ? VcsUtil.getFilePath(CommandUtil.resolvePath(target.getFile(), path)) : VcsUtil.getFilePath(path); + } + + @NotNull + private Change createChange(@NotNull SvnTarget target, @NotNull DiffPath diffPath) { + // 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 status is currently not used - SvnStatusConvertor.convertStatus uses properties status only if there are + // TODO: conflicts + FileStatus status = SvnStatusConvertor + .convertStatus(SvnStatusHandler.getStatus(diffPath.itemStatus), SvnStatusHandler.getStatus(diffPath.propertiesStatus)); + + ContentRevision beforeRevision = status == FileStatus.ADDED ? null : createBeforeRevision(target, diffPath.path); + ContentRevision afterRevision = status == FileStatus.DELETED ? null : createAfterRevision(target, diffPath.path); + + return new Change(beforeRevision, afterRevision, status); + } + + @XmlRootElement(name = "diff") + public static class DiffInfo { + + @XmlElement(name = "paths") + public DiffPaths paths; + } + + public static class DiffPaths { + + @XmlElement(name = "path") + public List diffPaths = new ArrayList(); + } + + public static class DiffPath { + + @XmlAttribute(name = "kind") + public String kind; + + @XmlAttribute(name = "props") + public String propertiesStatus; + + @XmlAttribute(name = "item") + public String itemStatus; + + @XmlValue + public String path; + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DiffClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DiffClient.java new file mode 100644 index 000000000000..a9678be33737 --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DiffClient.java @@ -0,0 +1,32 @@ +/* + * 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.SvnClient; +import org.tmatesoft.svn.core.wc2.SvnTarget; + +import java.util.List; + +/** + * @author Konstantin Kolosovsky. + */ +public interface DiffClient extends SvnClient { + + List compare(@NotNull SvnTarget target1, @NotNull SvnTarget target2) throws VcsException; +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/SvnKitDiffClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/SvnKitDiffClient.java new file mode 100644 index 000000000000..07bf6ec77a28 --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/SvnKitDiffClient.java @@ -0,0 +1,35 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.svn.diff; + +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vcs.changes.Change; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.api.BaseSvnClient; +import org.tmatesoft.svn.core.wc2.SvnTarget; + +import java.util.List; + +/** + * @author Konstantin Kolosovsky. + */ +public class SvnKitDiffClient extends BaseSvnClient implements DiffClient { + + @Override + public List compare(@NotNull SvnTarget target1, @NotNull SvnTarget target2) throws VcsException { + throw new UnsupportedOperationException("Diff client is not implemented for SVNKit"); + } +} From 62b3c163f4f42417242e5ac30e4c46d7c243049a Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Tue, 24 Dec 2013 11:28:36 +0400 Subject: [PATCH 10/38] svn: Implemented "Compare with Branch" action for svn 1.8 for command line --- .../svn/actions/CompareWithBranchAction.java | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CompareWithBranchAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CompareWithBranchAction.java index 3b28f2fceab7..a69a755ff3e5 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CompareWithBranchAction.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CompareWithBranchAction.java @@ -57,7 +57,10 @@ 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.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; @@ -302,7 +305,14 @@ public class CompareWithBranchAction extends AnAction implements DumbAware { FileUtil.toSystemDependentName(myVirtualFile.getPresentableUrl()))); final File ioFile = new File(myVirtualFile.getPath()); - if (SvnUtil.is17CopyPart(ioFile)) { + 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 { @@ -310,10 +320,16 @@ public class CompareWithBranchAction extends AnAction implements DumbAware { } } + 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 SVNWCClient wcClient = myVcs.createWCClient(); - final SVNInfo info1 = wcClient.doInfo(ioFile, SVNRevision.HEAD); + final SVNInfo info1 = myVcs.getInfo(ioFile, SVNRevision.HEAD); if (info1 == null) { SVNErrorMessage err = From 11e0f08692c07f7f03c5530c2db58a1ba22be520 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Tue, 24 Dec 2013 12:23:02 +0400 Subject: [PATCH 11/38] svn: Refactored SvnRepositoryContentRevision - removed unnecessary catch blocks --- .../svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java | 2 +- .../svn/history/SvnRepositoryContentRevision.java | 12 ++---------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java index ce734fd683fd..ec1fd8f126a6 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java @@ -743,7 +743,7 @@ public class SvnUtil { } } - public static String appendMultiParts(@NotNull final String base, @NotNull final String subPath) throws SVNException { + public static String appendMultiParts(@NotNull final String base, @NotNull final String subPath) { if (StringUtil.isEmpty(subPath)) return base; final List parts = StringUtil.split(subPath.replace('\\', '/'), "/", true); String result = base; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryContentRevision.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryContentRevision.java index b7a0bb9329b0..177cd69907c4 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryContentRevision.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryContentRevision.java @@ -63,16 +63,8 @@ public class SvnRepositoryContentRevision implements ContentRevision, MarkerVcsC 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; + final String fullPath = SvnUtil.appendMultiParts(repositoryRoot, myPath); + myFilePath = VcsContextFactory.SERVICE.getInstance().createFilePathOnNonLocal(fullPath, false); } myRevision = revision; } From 42c824aca0117ca0dc8ac21028345caa38cecebd Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Tue, 24 Dec 2013 14:26:39 +0400 Subject: [PATCH 12/38] svn: Refactored SvnRepositoryContentRevision not to use explicit repository root path (but just required item path) --- .../SvnRepositoryBinaryContentRevision.java | 4 +-- .../history/SvnRepositoryContentRevision.java | 25 +++++-------------- 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryBinaryContentRevision.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryBinaryContentRevision.java index 49e8c1dd1076..af67d3ae3837 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryBinaryContentRevision.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryBinaryContentRevision.java @@ -27,9 +27,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, final String path, @Nullable final FilePath localPath, final long revision) { - super(vcs, repositoryRoot, path, localPath, revision); + super(vcs, path, localPath, revision); } @Nullable diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryContentRevision.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryContentRevision.java index 177cd69907c4..411fa01654ff 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryContentRevision.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryContentRevision.java @@ -39,7 +39,6 @@ import com.intellij.openapi.vcs.impl.ContentRevisionCache; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.*; -import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; @@ -48,24 +47,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, final String path, @Nullable final FilePath localPath, final long revision) { myVcs = vcs; myPath = path; - myRepositoryRoot = repositoryRoot; - if (localPath != null) { - myFilePath = localPath; - } - else { - final String fullPath = SvnUtil.appendMultiParts(repositoryRoot, myPath); - myFilePath = VcsContextFactory.SERVICE.getInstance().createFilePathOnNonLocal(fullPath, false); - } + myFilePath = localPath != null ? localPath : VcsContextFactory.SERVICE.getInstance().createFilePathOnNonLocal(myPath, false); myRevision = revision; } @@ -117,15 +108,16 @@ 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) { + // TODO: not clear why filename and file type are only checked if path contains '/' 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 SvnRepositoryBinaryContentRevision(vcs, SvnUtil.appendMultiParts(repositoryRoot, path), localPath, revision); } } - return new SvnRepositoryContentRevision(vcs, repositoryRoot, path, localPath, revision); + return new SvnRepositoryContentRevision(vcs, SvnUtil.appendMultiParts(repositoryRoot, path), localPath, revision); } @Override @@ -172,12 +164,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() { From fb9a15129b24f5593ca8192f5a88bc37e5020902 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Tue, 24 Dec 2013 18:24:24 +0400 Subject: [PATCH 13/38] svn: Refactored SvnRepositoryContentRevision to use FilePath for remote path (instead of just String) --- .../src/com/intellij/vcsUtil/VcsUtil.java | 4 ++ .../SvnRepositoryBinaryContentRevision.java | 5 ++- .../history/SvnRepositoryContentRevision.java | 39 +++++++++++-------- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/platform/vcs-api/src/com/intellij/vcsUtil/VcsUtil.java b/platform/vcs-api/src/com/intellij/vcsUtil/VcsUtil.java index 709318330b84..bbeeae9e99f6 100644 --- a/platform/vcs-api/src/com/intellij/vcsUtil/VcsUtil.java +++ b/platform/vcs-api/src/com/intellij/vcsUtil/VcsUtil.java @@ -323,6 +323,10 @@ public class VcsUtil { return getFilePath(new File(path), isDirectory); } + public static FilePath getFilePathOnNonLocal(String path, boolean isDirectory) { + return VcsContextFactory.SERVICE.getInstance().createFilePathOnNonLocal(path, isDirectory); + } + public static FilePath getFilePath(File file, boolean isDirectory) { return VcsContextFactory.SERVICE.getInstance().createFilePathOn(file, isDirectory); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryBinaryContentRevision.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryBinaryContentRevision.java index af67d3ae3837..fb7499cdd38a 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryBinaryContentRevision.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryBinaryContentRevision.java @@ -18,6 +18,7 @@ package org.jetbrains.idea.svn.history; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.changes.BinaryContentRevision; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnVcs; @@ -27,9 +28,9 @@ import org.jetbrains.idea.svn.SvnVcs; public class SvnRepositoryBinaryContentRevision extends SvnRepositoryContentRevision implements BinaryContentRevision { private byte[] myBinaryContent; - public SvnRepositoryBinaryContentRevision(final SvnVcs vcs, final String path, + public SvnRepositoryBinaryContentRevision(final SvnVcs vcs, @NotNull final FilePath remotePath, @Nullable final FilePath localPath, final long revision) { - super(vcs, path, localPath, revision); + super(vcs, remotePath, localPath, revision); } @Nullable diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryContentRevision.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryContentRevision.java index 411fa01654ff..36c80b1caaae 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryContentRevision.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryContentRevision.java @@ -23,22 +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.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; @@ -52,11 +54,11 @@ public class SvnRepositoryContentRevision implements ContentRevision, MarkerVcsC @NotNull private final FilePath myFilePath; private final long myRevision; - public SvnRepositoryContentRevision(final SvnVcs vcs, 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; - myFilePath = localPath != null ? localPath : VcsContextFactory.SERVICE.getInstance().createFilePathOnNonLocal(myPath, false); + myPath = FileUtil.toSystemIndependentName(remotePath.getPath()); + myFilePath = localPath != null ? localPath : remotePath; myRevision = revision; } @@ -108,16 +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) { - // TODO: not clear why filename and file type are only checked if path contains '/' - 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, SvnUtil.appendMultiParts(repositoryRoot, path), localPath, revision); - } - } - return new SvnRepositoryContentRevision(vcs, SvnUtil.appendMultiParts(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 From 6e139b9d278884e1ac189ea75d558670b5277c0c Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Tue, 24 Dec 2013 18:45:00 +0400 Subject: [PATCH 14/38] svn: Fixed CmdDiffClient to create correct ContentRevision and Change instances for retrieved changes - correctly handle directories, non-local files, deleted files --- .../jetbrains/idea/svn/api/BaseSvnClient.java | 7 ++ .../idea/svn/diff/CmdDiffClient.java | 80 ++++++++++++++----- 2 files changed, 67 insertions(+), 20 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java index 4076a729d88a..e140a62db91f 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java @@ -57,6 +57,13 @@ public abstract class BaseSvnClient implements SvnClient { } } + protected void assertDirectory(@NotNull SvnTarget target) { + assertFile(target); + if (!target.getFile().isDirectory()) { + throw new IllegalArgumentException("Target should be directory " + target); + } + } + protected void validateFormat(@NotNull WorkingCopyFormat format, @NotNull Collection supported) throws VcsException { if (!supported.contains(format)) { throw new VcsException( diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CmdDiffClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CmdDiffClient.java index c4a21ee444fb..b774fe6b4aac 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CmdDiffClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CmdDiffClient.java @@ -15,6 +15,7 @@ */ 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; @@ -24,10 +25,13 @@ 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.idea.svn.SvnContentRevision; +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; @@ -36,6 +40,7 @@ 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; @@ -49,7 +54,7 @@ public class CmdDiffClient extends BaseSvnClient implements DiffClient { // 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. - assertFile(target1); + assertDirectory(target1); assertUrl(target2); List parameters = new ArrayList(); @@ -59,18 +64,18 @@ public class CmdDiffClient extends BaseSvnClient implements DiffClient { parameters.add("--summarize"); CommandExecutor executor = CommandUtil.execute(myVcs, target1, SvnCommandName.diff, parameters, null); - return parseOutput(executor); + return parseOutput(target1, target2, executor); } - private List parseOutput(@NotNull CommandExecutor executor) throws SvnBindException { + private List parseOutput(@NotNull SvnTarget target1, @NotNull SvnTarget target2, @NotNull CommandExecutor executor) + throws SvnBindException { try { DiffInfo diffInfo = CommandUtil.parse(executor.getOutput(), DiffInfo.class); - SvnTarget base = SvnTarget.fromFile(executor.getCommand().getWorkingDirectory()); List result = ContainerUtil.newArrayList(); if (diffInfo != null && diffInfo.paths != null) { for (DiffPath path : diffInfo.paths.diffPaths) { - result.add(createChange(base, path)); + result.add(createChange(target1, target2, path)); } } @@ -81,32 +86,63 @@ public class CmdDiffClient extends BaseSvnClient implements DiffClient { } } - private ContentRevision createBeforeRevision(@NotNull SvnTarget target, @NotNull String path) { - return SvnContentRevision.createRemote(myVcs, createFilePath(target, path), SVNRevision.HEAD); + 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 createAfterRevision(@NotNull SvnTarget target, @NotNull String path) { - return CurrentContentRevision.create(createFilePath(target, path)); - } - - private static FilePath createFilePath(@NotNull SvnTarget target, @NotNull String path) { - return target.isFile() ? VcsUtil.getFilePath(CommandUtil.resolvePath(target.getFile(), path)) : VcsUtil.getFilePath(path); + private static ContentRevision createLocalRevision(@NotNull FilePath path) { + return CurrentContentRevision.create(path); } @NotNull - private Change createChange(@NotNull SvnTarget target, @NotNull DiffPath diffPath) { + 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 status is currently not used - SvnStatusConvertor.convertStatus uses properties status only if there are - // TODO: conflicts + // 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 : createBeforeRevision(target, diffPath.path); - ContentRevision afterRevision = status == FileStatus.DELETED ? null : createAfterRevision(target, diffPath.path); + ContentRevision beforeRevision = status == FileStatus.ADDED ? null : createRemoteRevision(remotePath, localPath, status); + ContentRevision afterRevision = status == FileStatus.DELETED ? null : createLocalRevision(localPath); - return new Change(beforeRevision, afterRevision, status); + 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") @@ -135,5 +171,9 @@ public class CmdDiffClient extends BaseSvnClient implements DiffClient { @XmlValue public String path; + + public boolean isDirectory() { + return SVNNodeKind.DIR.equals(SVNNodeKind.parseKind(kind)); + } } } From 47e7518138b7445856071131a1f27651b3951a4f Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Tue, 24 Dec 2013 18:46:58 +0400 Subject: [PATCH 15/38] svn: Fixed CurrentContentRevision handling for properties diff --- .../idea/svn/actions/ShowPropertiesDiffAction.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ShowPropertiesDiffAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ShowPropertiesDiffAction.java index bce62783d92f..d8126a1300f1 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ShowPropertiesDiffAction.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ShowPropertiesDiffAction.java @@ -20,6 +20,7 @@ import com.intellij.openapi.actionSystem.DataKey; import com.intellij.openapi.vcs.VcsDataKeys; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.changes.ContentRevision; +import com.intellij.openapi.vcs.changes.CurrentContentRevision; import org.jetbrains.idea.svn.SvnBundle; import org.jetbrains.idea.svn.SvnRevisionNumber; import org.jetbrains.idea.svn.SvnVcs; @@ -53,7 +54,10 @@ public class ShowPropertiesDiffAction extends AbstractShowPropertiesDiffAction { protected SVNRevision getAfterRevisionValue(final Change change, final SvnVcs vcs) throws SVNException { final ContentRevision afterRevision = change.getAfterRevision(); if (afterRevision != null) { - return ((SvnRevisionNumber) afterRevision.getRevisionNumber()).getRevision(); + // CurrentContentRevision will be here, for instance, if invoked from changes dialog for "Compare with Branch" action + return afterRevision instanceof CurrentContentRevision + ? SVNRevision.WORKING + : ((SvnRevisionNumber)afterRevision.getRevisionNumber()).getRevision(); } else { return SVNRevision.create(((SvnRevisionNumber) change.getBeforeRevision().getRevisionNumber()).getRevision().getNumber() + 1); } From a946a94c0493605437284c096912c40f8588f41f Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Tue, 24 Dec 2013 18:50:24 +0400 Subject: [PATCH 16/38] svn: Moved CompareWithBranchAction to "diff" package --- plugins/svn4idea/src/META-INF/plugin.xml | 2 +- .../idea/svn/{actions => diff}/CompareWithBranchAction.java | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) rename plugins/svn4idea/src/org/jetbrains/idea/svn/{actions => diff}/CompareWithBranchAction.java (99%) diff --git a/plugins/svn4idea/src/META-INF/plugin.xml b/plugins/svn4idea/src/META-INF/plugin.xml index e1a1a0b717ee..1f7edf8936e2 100644 --- a/plugins/svn4idea/src/META-INF/plugin.xml +++ b/plugins/svn4idea/src/META-INF/plugin.xml @@ -72,7 +72,7 @@ - + diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CompareWithBranchAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CompareWithBranchAction.java similarity index 99% rename from plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CompareWithBranchAction.java rename to plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CompareWithBranchAction.java index a69a755ff3e5..08976630dbb4 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CompareWithBranchAction.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CompareWithBranchAction.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.jetbrains.idea.svn.actions; +package org.jetbrains.idea.svn.diff; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; @@ -43,6 +43,7 @@ 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.actions.SelectBranchPopup; import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew; import org.jetbrains.idea.svn.commandLine.SvnBindException; import org.jetbrains.idea.svn.status.SvnDiffEditor; @@ -73,7 +74,7 @@ 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"); + private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.diff.CompareWithBranchAction"); public void actionPerformed(AnActionEvent e) { Project project = e.getData(CommonDataKeys.PROJECT); From 644cc4e38a69e63bcec8b15f82c8bc4a33f7f2d7 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Tue, 24 Dec 2013 18:55:47 +0400 Subject: [PATCH 17/38] svn: Refactored CompareWithBranchAction - inner classes with compare logic extracted to separate classes --- .../svn/diff/CompareWithBranchAction.java | 360 ------------------ .../svn/diff/DirectoryWithBranchComparer.java | 204 ++++++++++ .../svn/diff/ElementWithBranchComparer.java | 163 ++++++++ .../idea/svn/diff/FileWithBranchComparer.java | 82 ++++ 4 files changed, 449 insertions(+), 360 deletions(-) create mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DirectoryWithBranchComparer.java create mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/diff/ElementWithBranchComparer.java create mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/diff/FileWithBranchComparer.java diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CompareWithBranchAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CompareWithBranchAction.java index 08976630dbb4..a8e0ca9e5e7a 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CompareWithBranchAction.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CompareWithBranchAction.java @@ -19,62 +19,20 @@ 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.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.progress.Task; 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.VcsException; -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.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.*; import org.jetbrains.idea.svn.actions.SelectBranchPopup; import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew; -import org.jetbrains.idea.svn.commandLine.SvnBindException; -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.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 yole */ public class CompareWithBranchAction extends AnAction implements DumbAware { - private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.diff.CompareWithBranchAction"); public void actionPerformed(AnActionEvent e) { Project project = e.getData(CommonDataKeys.PROJECT); @@ -120,322 +78,4 @@ public class CompareWithBranchAction extends AnAction implements DumbAware { comparer.run(); } } - - private static abstract class ElementWithBranchComparer { - - @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; - - protected 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); - } - } - - public static class FileWithBranchComparer extends ElementWithBranchComparer { - - @NotNull private final Ref content = new Ref(); - @NotNull private final StringBuilder remoteTitleBuilder = new StringBuilder(); - @NotNull private final Ref success = new Ref(); - - public FileWithBranchComparer(@NotNull Project project, - @NotNull VirtualFile virtualFile, - @NotNull String branchUrl, - long branchRevision) { - super(project, virtualFile, branchUrl, branchRevision); - } - - @Override - protected void beforeCompare() { - final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); - if (indicator != null) { - indicator.setIndeterminate(true); - } - } - - @Override - protected void compare() throws SVNException, VcsException { - remoteTitleBuilder.append(myElementUrl); - content.set(SvnUtil.getFileContents(myVcs, SvnTarget.fromURL(myElementUrl), SVNRevision.HEAD, SVNRevision.UNDEFINED)); - success.set(true); - } - - @Override - protected void showResult() { - if (!success.isNull()) { - SimpleDiffRequest req = new SimpleDiffRequest(myProject, SvnBundle.message("compare.with.branch.diff.title")); - req.setContents(new SimpleContent(CharsetToolkit.bytesToString(content.get(), myVirtualFile.getCharset())), - new FileContent(myProject, myVirtualFile)); - req.setContentTitles(remoteTitleBuilder.toString(), myVirtualFile.getPresentableUrl()); - DiffManager.getInstance().getDiffTool().show(req); - } - } - - @Override - public String getTitle() { - return SvnBundle.message("compare.with.branch.progress.loading.content"); - } - } - - public static class DirectoryWithBranchComparer extends ElementWithBranchComparer { - - @NotNull private final StringBuilder titleBuilder = new StringBuilder(); - @NotNull private final List changes = new ArrayList(); - - public DirectoryWithBranchComparer(@NotNull Project project, - @NotNull VirtualFile virtualFile, - @NotNull String branchUrl, - long branchRevision) { - super(project, virtualFile, branchUrl, branchRevision); - } - - @Override - protected void compare() throws SVNException, VcsException { - titleBuilder.append(SvnBundle.message("repository.browser.compare.title", myElementUrl, - FileUtil.toSystemDependentName(myVirtualFile.getPresentableUrl()))); - - final File ioFile = new File(myVirtualFile.getPath()); - WorkingCopyFormat format = myVcs.getWorkingCopyFormat(ioFile); - - if (WorkingCopyFormat.ONE_DOT_EIGHT.equals(format)) { - // svn 1.7 command line "--summarize" option for "diff" command does not support comparing working copy directories with repository - // directories - that is why command line is only used explicitly for svn 1.8 - compareWithCommandLine(); - } - else if (WorkingCopyFormat.ONE_DOT_SEVEN.equals(format)) { - report17DirDiff(); - } - else { - report16DirDiff(); - } - } - - private void compareWithCommandLine() throws VcsException { - SvnTarget target1 = SvnTarget.fromFile(new File(myVirtualFile.getPath())); - SvnTarget target2 = SvnTarget.fromURL(myElementUrl); - - changes.addAll(myVcs.getFactory(target1).createDiffClient().compare(target1, target2)); - } - - private void report17DirDiff() throws SVNException { - final File ioFile = new File(myVirtualFile.getPath()); - final SVNInfo info1 = myVcs.getInfo(ioFile, SVNRevision.HEAD); - - if (info1 == null) { - SVNErrorMessage err = - SVNErrorMessage.create(SVNErrorCode.ENTRY_NOT_FOUND, "''{0}'' is not under version control", myVirtualFile.getPath()); - SVNErrorManager.error(err, SVNLogType.WC); - } - else if (info1.getURL() == null) { - SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_MISSING_URL, "''{0}'' has no URL", myVirtualFile.getPath()); - SVNErrorManager.error(err, SVNLogType.WC); - } - - final SVNReporter17 reporter17 = - new SVNReporter17(ioFile, new SVNWCContext(SvnConfiguration.getInstance(myProject).getOptions(myProject), new ISVNEventHandler() { - @Override - public void handleEvent(SVNEvent event, double progress) throws SVNException { - } - - @Override - public void checkCancelled() throws SVNCancelException { - } - }), - false, true, SVNDepth.INFINITY, false, false, true, false, - SVNDebugLog.getDefaultLog()); - SVNRepository repository = null; - SVNRepository repository2 = null; - try { - repository = myVcs.createRepository(info1.getURL()); - long rev = repository.getLatestRevision(); - repository2 = myVcs.createRepository(myElementUrl.toString()); - SvnDiffEditor diffEditor = new SvnDiffEditor(myVirtualFile, repository2, rev, true); - repository.diff(myElementUrl, rev, rev, null, true, SVNDepth.INFINITY, false, reporter17, - SVNCancellableEditor.newInstance(diffEditor, new SvnProgressCanceller(), null)); - changes.addAll(diffEditor.getChangesMap().values()); - } - finally { - if (repository != null) { - repository.closeSession(); - } - if (repository2 != null) { - repository2.closeSession(); - } - } - } - - private void report16DirDiff() throws SVNException { - // here there's 1.6 copy so ok to use SVNWCAccess - final SVNWCAccess wcAccess = SVNWCAccess.newInstance(null); - wcAccess.setOptions(myVcs.getSvnOptions()); - SVNRepository repository = null; - SVNRepository repository2 = null; - try { - SVNAdminAreaInfo info = wcAccess.openAnchor(new File(myVirtualFile.getPath()), false, SVNWCAccess.INFINITE_DEPTH); - File anchorPath = info.getAnchor().getRoot(); - String target = "".equals(info.getTargetName()) ? null : info.getTargetName(); - - SVNEntry anchorEntry = info.getAnchor().getEntry("", false); - if (anchorEntry == null) { - SVNErrorMessage err = - SVNErrorMessage.create(SVNErrorCode.ENTRY_NOT_FOUND, "''{0}'' is not under version control", anchorPath); - SVNErrorManager.error(err, SVNLogType.WC); - } - else if (anchorEntry.getURL() == null) { - SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_MISSING_URL, "''{0}'' has no URL", anchorPath); - SVNErrorManager.error(err, SVNLogType.WC); - } - - SVNURL anchorURL = anchorEntry.getSVNURL(); - SVNReporter reporter = new SVNReporter(info, info.getAnchor().getFile(info.getTargetName()), false, true, SVNDepth.INFINITY, - false, false, true, SVNDebugLog.getDefaultLog()); - - repository = myVcs.createRepository(anchorURL.toString()); - long rev = repository.getLatestRevision(); - repository2 = myVcs.createRepository((target == null) ? myElementUrl.toString() : myElementUrl.removePathTail().toString()); - SvnDiffEditor diffEditor = new SvnDiffEditor((target == null) ? myVirtualFile : myVirtualFile.getParent(), - repository2, rev, true); - repository.diff(myElementUrl, rev, rev, target, true, true, false, reporter, - SVNCancellableEditor.newInstance(diffEditor, new SvnProgressCanceller(), null)); - changes.addAll(diffEditor.getChangesMap().values()); - } - finally { - wcAccess.close(); - if (repository != null) { - repository.closeSession(); - } - if (repository2 != null) { - repository2.closeSession(); - } - } - } - - @Override - protected void onCancel() { - changes.clear(); - } - - @Override - protected void showResult() { - if (!changes.isEmpty()) { - AbstractVcsHelper.getInstance(myProject).showWhatDiffersBrowser(null, changes, titleBuilder.toString()); - } - } - - @Override - public String getTitle() { - return SvnBundle.message("progress.computing.difference"); - } - } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DirectoryWithBranchComparer.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DirectoryWithBranchComparer.java new file mode 100644 index 000000000000..48ba029f929d --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DirectoryWithBranchComparer.java @@ -0,0 +1,204 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.svn.diff; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vcs.AbstractVcsHelper; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vcs.changes.Change; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.SvnBundle; +import org.jetbrains.idea.svn.SvnConfiguration; +import org.jetbrains.idea.svn.SvnProgressCanceller; +import org.jetbrains.idea.svn.WorkingCopyFormat; +import org.jetbrains.idea.svn.status.SvnDiffEditor; +import org.tmatesoft.svn.core.*; +import org.tmatesoft.svn.core.internal.wc.SVNCancellableEditor; +import org.tmatesoft.svn.core.internal.wc.SVNErrorManager; +import org.tmatesoft.svn.core.internal.wc.admin.SVNAdminAreaInfo; +import org.tmatesoft.svn.core.internal.wc.admin.SVNEntry; +import org.tmatesoft.svn.core.internal.wc.admin.SVNReporter; +import org.tmatesoft.svn.core.internal.wc.admin.SVNWCAccess; +import org.tmatesoft.svn.core.internal.wc17.SVNReporter17; +import org.tmatesoft.svn.core.internal.wc17.SVNWCContext; +import org.tmatesoft.svn.core.io.SVNRepository; +import org.tmatesoft.svn.core.wc.ISVNEventHandler; +import org.tmatesoft.svn.core.wc.SVNEvent; +import org.tmatesoft.svn.core.wc.SVNInfo; +import org.tmatesoft.svn.core.wc.SVNRevision; +import org.tmatesoft.svn.core.wc2.SvnTarget; +import org.tmatesoft.svn.util.SVNDebugLog; +import org.tmatesoft.svn.util.SVNLogType; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/** +* @author Konstantin Kolosovsky. +*/ +public class DirectoryWithBranchComparer extends ElementWithBranchComparer { + + @NotNull private final StringBuilder titleBuilder = new StringBuilder(); + @NotNull private final List changes = new ArrayList(); + + public DirectoryWithBranchComparer(@NotNull Project project, + @NotNull VirtualFile virtualFile, + @NotNull String branchUrl, + long branchRevision) { + super(project, virtualFile, branchUrl, branchRevision); + } + + @Override + protected void compare() throws SVNException, VcsException { + titleBuilder.append(SvnBundle.message("repository.browser.compare.title", myElementUrl, + FileUtil.toSystemDependentName(myVirtualFile.getPresentableUrl()))); + + final File ioFile = new File(myVirtualFile.getPath()); + WorkingCopyFormat format = myVcs.getWorkingCopyFormat(ioFile); + + if (WorkingCopyFormat.ONE_DOT_EIGHT.equals(format)) { + // svn 1.7 command line "--summarize" option for "diff" command does not support comparing working copy directories with repository + // directories - that is why command line is only used explicitly for svn 1.8 + compareWithCommandLine(); + } + else if (WorkingCopyFormat.ONE_DOT_SEVEN.equals(format)) { + report17DirDiff(); + } + else { + report16DirDiff(); + } + } + + private void compareWithCommandLine() throws VcsException { + SvnTarget target1 = SvnTarget.fromFile(new File(myVirtualFile.getPath())); + SvnTarget target2 = SvnTarget.fromURL(myElementUrl); + + changes.addAll(myVcs.getFactory(target1).createDiffClient().compare(target1, target2)); + } + + private void report17DirDiff() throws SVNException { + final File ioFile = new File(myVirtualFile.getPath()); + final SVNInfo info1 = myVcs.getInfo(ioFile, SVNRevision.HEAD); + + if (info1 == null) { + SVNErrorMessage err = + SVNErrorMessage.create(SVNErrorCode.ENTRY_NOT_FOUND, "''{0}'' is not under version control", myVirtualFile.getPath()); + SVNErrorManager.error(err, SVNLogType.WC); + } + else if (info1.getURL() == null) { + SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_MISSING_URL, "''{0}'' has no URL", myVirtualFile.getPath()); + SVNErrorManager.error(err, SVNLogType.WC); + } + + final SVNReporter17 reporter17 = + new SVNReporter17(ioFile, new SVNWCContext(SvnConfiguration.getInstance(myProject).getOptions(myProject), new ISVNEventHandler() { + @Override + public void handleEvent(SVNEvent event, double progress) throws SVNException { + } + + @Override + public void checkCancelled() throws SVNCancelException { + } + }), + false, true, SVNDepth.INFINITY, false, false, true, false, + SVNDebugLog.getDefaultLog()); + SVNRepository repository = null; + SVNRepository repository2 = null; + try { + repository = myVcs.createRepository(info1.getURL()); + long rev = repository.getLatestRevision(); + repository2 = myVcs.createRepository(myElementUrl.toString()); + SvnDiffEditor diffEditor = new SvnDiffEditor(myVirtualFile, repository2, rev, true); + repository.diff(myElementUrl, rev, rev, null, true, SVNDepth.INFINITY, false, reporter17, + SVNCancellableEditor.newInstance(diffEditor, new SvnProgressCanceller(), null)); + changes.addAll(diffEditor.getChangesMap().values()); + } + finally { + if (repository != null) { + repository.closeSession(); + } + if (repository2 != null) { + repository2.closeSession(); + } + } + } + + private void report16DirDiff() throws SVNException { + // here there's 1.6 copy so ok to use SVNWCAccess + final SVNWCAccess wcAccess = SVNWCAccess.newInstance(null); + wcAccess.setOptions(myVcs.getSvnOptions()); + SVNRepository repository = null; + SVNRepository repository2 = null; + try { + SVNAdminAreaInfo info = wcAccess.openAnchor(new File(myVirtualFile.getPath()), false, SVNWCAccess.INFINITE_DEPTH); + File anchorPath = info.getAnchor().getRoot(); + String target = "".equals(info.getTargetName()) ? null : info.getTargetName(); + + SVNEntry anchorEntry = info.getAnchor().getEntry("", false); + if (anchorEntry == null) { + SVNErrorMessage err = + SVNErrorMessage.create(SVNErrorCode.ENTRY_NOT_FOUND, "''{0}'' is not under version control", anchorPath); + SVNErrorManager.error(err, SVNLogType.WC); + } + else if (anchorEntry.getURL() == null) { + SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_MISSING_URL, "''{0}'' has no URL", anchorPath); + SVNErrorManager.error(err, SVNLogType.WC); + } + + SVNURL anchorURL = anchorEntry.getSVNURL(); + SVNReporter reporter = new SVNReporter(info, info.getAnchor().getFile(info.getTargetName()), false, true, SVNDepth.INFINITY, + false, false, true, SVNDebugLog.getDefaultLog()); + + repository = myVcs.createRepository(anchorURL.toString()); + long rev = repository.getLatestRevision(); + repository2 = myVcs.createRepository((target == null) ? myElementUrl.toString() : myElementUrl.removePathTail().toString()); + SvnDiffEditor diffEditor = new SvnDiffEditor((target == null) ? myVirtualFile : myVirtualFile.getParent(), + repository2, rev, true); + repository.diff(myElementUrl, rev, rev, target, true, true, false, reporter, + SVNCancellableEditor.newInstance(diffEditor, new SvnProgressCanceller(), null)); + changes.addAll(diffEditor.getChangesMap().values()); + } + finally { + wcAccess.close(); + if (repository != null) { + repository.closeSession(); + } + if (repository2 != null) { + repository2.closeSession(); + } + } + } + + @Override + protected void onCancel() { + changes.clear(); + } + + @Override + protected void showResult() { + if (!changes.isEmpty()) { + AbstractVcsHelper.getInstance(myProject).showWhatDiffersBrowser(null, changes, titleBuilder.toString()); + } + } + + @Override + public String getTitle() { + return SvnBundle.message("progress.computing.difference"); + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/ElementWithBranchComparer.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/ElementWithBranchComparer.java new file mode 100644 index 000000000000..2d67ce7e58ad --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/ElementWithBranchComparer.java @@ -0,0 +1,163 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.svn.diff; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.Task; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.WaitForProgressToShow; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.svn.*; +import org.jetbrains.idea.svn.commandLine.SvnBindException; +import org.tmatesoft.svn.core.SVNCancelException; +import org.tmatesoft.svn.core.SVNErrorCode; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNURL; +import org.tmatesoft.svn.core.internal.util.SVNPathUtil; + +import java.io.File; + +/** +* @author Konstantin Kolosovsky. +*/ +public abstract class ElementWithBranchComparer { + + private static final Logger LOG = Logger.getInstance(ElementWithBranchComparer.class); + + @NotNull protected final Project myProject; + @NotNull protected final SvnVcs myVcs; + @NotNull protected final VirtualFile myVirtualFile; + @NotNull protected final String myBranchUrl; + protected final long myBranchRevision; + protected SVNURL myElementUrl; + + ElementWithBranchComparer(@NotNull Project project, + @NotNull VirtualFile virtualFile, + @NotNull String branchUrl, + long branchRevision) { + myProject = project; + myVcs = SvnVcs.getInstance(myProject); + myVirtualFile = virtualFile; + myBranchUrl = branchUrl; + myBranchRevision = branchRevision; + } + + public void run() { + new Task.Modal(myProject, getTitle(), true) { + @Override + public void run(@NotNull ProgressIndicator indicator) { + try { + beforeCompare(); + myElementUrl = resolveElementUrl(); + if (myElementUrl == null) { + reportNotFound(); + } + else { + compare(); + } + } + catch (SVNCancelException ex) { + ElementWithBranchComparer.this.onCancel(); + } + catch (SVNException ex) { + reportException(new SvnBindException(ex)); + } + catch (SvnBindException ex) { + reportException(ex); + } + catch (VcsException ex) { + reportGeneralException(ex); + } + } + }.queue(); + showResult(); + } + + protected void beforeCompare() { + } + + protected abstract void compare() throws SVNException, VcsException; + + protected abstract void showResult(); + + protected void onCancel() { + } + + public abstract String getTitle(); + + @Nullable + protected SVNURL resolveElementUrl() throws SVNException { + final SvnFileUrlMapping urlMapping = myVcs.getSvnFileUrlMapping(); + final File file = new File(myVirtualFile.getPath()); + final SVNURL fileUrl = urlMapping.getUrlForFile(file); + if (fileUrl == null) { + return null; + } + + final String fileUrlString = fileUrl.toString(); + final RootUrlInfo rootMixed = urlMapping.getWcRootForUrl(fileUrlString); + if (rootMixed == null) { + return null; + } + + final SVNURL thisBranchForUrl = SvnUtil.getBranchForUrl(myVcs, rootMixed.getVirtualFile(), fileUrlString); + if (thisBranchForUrl == null) { + return null; + } + + final String relativePath = SVNPathUtil.getRelativePath(thisBranchForUrl.toString(), fileUrlString); + return SVNURL.parseURIEncoded(SVNPathUtil.append(myBranchUrl, relativePath)); + } + + private void reportException(final SvnBindException e) { + if (e.contains(SVNErrorCode.RA_ILLEGAL_URL) || + e.contains(SVNErrorCode.CLIENT_UNRELATED_RESOURCES) || + e.contains(SVNErrorCode.RA_DAV_PATH_NOT_FOUND) || + e.contains(SVNErrorCode.FS_NOT_FOUND) || + e.contains(SVNErrorCode.ILLEGAL_TARGET)) { + reportNotFound(); + } + else { + reportGeneralException(e); + } + } + + private void reportGeneralException(final Exception e) { + WaitForProgressToShow.runOrInvokeLaterAboveProgress(new Runnable() { + public void run() { + Messages.showMessageDialog(myProject, e.getMessage(), + SvnBundle.message("compare.with.branch.error.title"), Messages.getErrorIcon()); + } + }, null, myProject); + LOG.info(e); + } + + private void reportNotFound() { + WaitForProgressToShow.runOrInvokeLaterAboveProgress(new Runnable() { + public void run() { + Messages.showMessageDialog(myProject, + SvnBundle + .message("compare.with.branch.location.error", myVirtualFile.getPresentableUrl(), myBranchUrl), + SvnBundle.message("compare.with.branch.error.title"), Messages.getErrorIcon()); + } + }, null, myProject); + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/FileWithBranchComparer.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/FileWithBranchComparer.java new file mode 100644 index 000000000000..b4b4e3c3c2ea --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/FileWithBranchComparer.java @@ -0,0 +1,82 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.svn.diff; + +import com.intellij.openapi.diff.DiffManager; +import com.intellij.openapi.diff.FileContent; +import com.intellij.openapi.diff.SimpleContent; +import com.intellij.openapi.diff.SimpleDiffRequest; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Ref; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vfs.CharsetToolkit; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.SvnBundle; +import org.jetbrains.idea.svn.SvnUtil; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.wc.SVNRevision; +import org.tmatesoft.svn.core.wc2.SvnTarget; + +/** +* @author Konstantin Kolosovsky. +*/ +public class FileWithBranchComparer extends ElementWithBranchComparer { + + @NotNull private final Ref content = new Ref(); + @NotNull private final StringBuilder remoteTitleBuilder = new StringBuilder(); + @NotNull private final Ref success = new Ref(); + + public FileWithBranchComparer(@NotNull Project project, + @NotNull VirtualFile virtualFile, + @NotNull String branchUrl, + long branchRevision) { + super(project, virtualFile, branchUrl, branchRevision); + } + + @Override + protected void beforeCompare() { + final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); + if (indicator != null) { + indicator.setIndeterminate(true); + } + } + + @Override + protected void compare() throws SVNException, VcsException { + remoteTitleBuilder.append(myElementUrl); + content.set(SvnUtil.getFileContents(myVcs, SvnTarget.fromURL(myElementUrl), SVNRevision.HEAD, SVNRevision.UNDEFINED)); + success.set(true); + } + + @Override + protected void showResult() { + if (!success.isNull()) { + SimpleDiffRequest req = new SimpleDiffRequest(myProject, SvnBundle.message("compare.with.branch.diff.title")); + req.setContents(new SimpleContent(CharsetToolkit.bytesToString(content.get(), myVirtualFile.getCharset())), + new FileContent(myProject, myVirtualFile)); + req.setContentTitles(remoteTitleBuilder.toString(), myVirtualFile.getPresentableUrl()); + DiffManager.getInstance().getDiffTool().show(req); + } + } + + @Override + public String getTitle() { + return SvnBundle.message("compare.with.branch.progress.loading.content"); + } +} From bbae5a3bfc27436db0ca89da55a915b16809de3f Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 25 Dec 2013 13:27:25 +0400 Subject: [PATCH 18/38] svn: Implemented usages collector of svn working copy formats used in project --- plugins/svn4idea/src/META-INF/plugin.xml | 2 + .../SvnWorkingCopyFormatUsagesCollector.java | 65 +++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/statistics/SvnWorkingCopyFormatUsagesCollector.java diff --git a/plugins/svn4idea/src/META-INF/plugin.xml b/plugins/svn4idea/src/META-INF/plugin.xml index 1f7edf8936e2..e831d0550a80 100644 --- a/plugins/svn4idea/src/META-INF/plugin.xml +++ b/plugins/svn4idea/src/META-INF/plugin.xml @@ -139,5 +139,7 @@ + + diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/statistics/SvnWorkingCopyFormatUsagesCollector.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/statistics/SvnWorkingCopyFormatUsagesCollector.java new file mode 100644 index 000000000000..72558d4b2330 --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/statistics/SvnWorkingCopyFormatUsagesCollector.java @@ -0,0 +1,65 @@ +/* + * Copyright 2000-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.svn.statistics; + +import com.intellij.internal.statistic.beans.GroupDescriptor; +import com.intellij.internal.statistic.beans.UsageDescriptor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.vcs.statistics.VcsUsagesCollector; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.NestedCopyType; +import org.jetbrains.idea.svn.RootUrlInfo; +import org.jetbrains.idea.svn.SvnVcs; + +import java.util.List; +import java.util.Set; + +/** + * @author Konstantin Kolosovsky. + */ +public class SvnWorkingCopyFormatUsagesCollector extends VcsUsagesCollector { + + private static final String GROUP_ID = "svn working copy format"; + + @NotNull + public GroupDescriptor getGroupId() { + return GroupDescriptor.create(GROUP_ID, GroupDescriptor.HIGHER_PRIORITY); + } + + @NotNull + public Set getProjectUsages(@NotNull Project project) { + SvnVcs vcs = SvnVcs.getInstance(project); + + // do not track roots with errors (SvnFileUrlMapping.getErrorRoots()) as they are "not usable" until errors are resolved + // skip externals and switched directories as they will have the same format + List roots = ContainerUtil.filter(vcs.getSvnFileUrlMapping().getAllWcInfos(), new Condition() { + @Override + public boolean value(RootUrlInfo info) { + return info.getType() == null || NestedCopyType.inner.equals(info.getType()); + } + }); + + return ContainerUtil.map2Set(roots, new Function() { + @Override + public UsageDescriptor fun(RootUrlInfo info) { + return new UsageDescriptor(info.getFormat().toString(), 1); + } + }); + } +} From f936508f978d8763fa70b84386f5032ac8f07c28 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 25 Dec 2013 14:24:40 +0400 Subject: [PATCH 19/38] svn: Refactored SvnConfiguration - removed unused methods, fixed simple warnings --- .../jetbrains/idea/svn/AuthManagerType.java | 26 ------------- .../jetbrains/idea/svn/SvnConfiguration.java | 37 +++++-------------- 2 files changed, 10 insertions(+), 53 deletions(-) delete mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/AuthManagerType.java diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/AuthManagerType.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/AuthManagerType.java deleted file mode 100644 index b46b7a875b51..000000000000 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/AuthManagerType.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2000-2013 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.idea.svn; - -/** - * Created with IntelliJ IDEA. - * User: Irina.Chernushina - * Date: 2/28/13 - * Time: 10:14 AM - */ -public enum AuthManagerType { - active, passive, usual; -} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java index ee5a589a6080..b1b8d5212ddf 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java @@ -78,7 +78,6 @@ public class SvnConfiguration implements PersistentStateComponent { public static final String CLEANUP_ON_START_RUN = "cleanupOnStartRun"; private final Project myProject; - public String USER = ""; public String PASSWORD = ""; public String[] ADD_PATHS = null; @@ -267,10 +266,6 @@ public class SvnConfiguration implements PersistentStateComponent { private final static long CHANGELIST_SUPPORT = 124; private final static long UPGRADE_TO_16_VERSION_ASKED = 125; - public boolean upgradeTo16Asked() { - return (myVersion != null) && (UPGRADE_TO_16_VERSION_ASKED <= myVersion); - } - public boolean changeListsSynchronized() { return (myVersion != null) && (CHANGELIST_SUPPORT <= myVersion); } @@ -364,17 +359,6 @@ public class SvnConfiguration implements PersistentStateComponent { 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 @@ -439,6 +423,7 @@ public class SvnConfiguration implements PersistentStateComponent { userManager.set(new SvnServerFileManagerImpl(myConfigFile)); } + // TODO: remove unused "myUpgradeMode" from configuration public String getUpgradeMode() { return myUpgradeMode; } @@ -563,15 +548,15 @@ public class SvnConfiguration implements PersistentStateComponent { } 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("maxAnnotateRevisions", String.valueOf(myMaxAnnotateRevisions)); + element.setAttribute("myUseAcceleration", String.valueOf(myUseAcceleration)); + element.setAttribute("myAutoUpdateAfterCommit", String.valueOf(myAutoUpdateAfterCommit)); + element.setAttribute(CLEANUP_ON_START_RUN, String.valueOf(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("TREE_CONFLICT_MERGE_THEIRS_NEW_INTO_OLD_PLACE", String.valueOf(TREE_CONFLICT_MERGE_THEIRS_NEW_INTO_OLD_PLACE)); } } @@ -591,6 +576,7 @@ public class SvnConfiguration implements PersistentStateComponent { myIsKeepLocks = keepLocks; } + // TODO: remove unused "myRemoteStatus" from configuration public boolean isRemoteStatus() { return myRemoteStatus; } @@ -643,6 +629,7 @@ public class SvnConfiguration implements PersistentStateComponent { return myUpdateRootInfos.get(file); } + // TODO: Check why SvnUpdateEnvironment.validationOptions is fully commented and then remove this method if necessary public Map getUpdateInfosMap() { return Collections.unmodifiableMap(myUpdateRootInfos); } @@ -682,10 +669,6 @@ public class SvnConfiguration implements PersistentStateComponent { } } } - - 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 +704,7 @@ public class SvnConfiguration implements PersistentStateComponent { myCleanupRun = cleanupRun; } - public static enum SSLProtocols { + public enum SSLProtocols { sslv3, tlsv1, all } } From ec72d3cf7e5126136815c6caeb706382604540df Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 25 Dec 2013 14:30:25 +0400 Subject: [PATCH 20/38] svn: Removed unused "remoteStatus" and "upgradeMode" configuration parameters --- .../jetbrains/idea/svn/SvnConfiguration.java | 28 ------------------- 1 file changed, 28 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java index b1b8d5212ddf..957234b3ab23 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java @@ -87,11 +87,9 @@ public class SvnConfiguration implements PersistentStateComponent { 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; @@ -423,15 +421,6 @@ public class SvnConfiguration implements PersistentStateComponent { userManager.set(new SvnServerFileManagerImpl(myConfigFile)); } - // TODO: remove unused "myUpgradeMode" from configuration - 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); @@ -466,8 +455,6 @@ public class SvnConfiguration implements PersistentStateComponent { } } 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; @@ -540,12 +527,6 @@ public class SvnConfiguration implements PersistentStateComponent { if (myIsKeepLocks) { element.addContent(new Element("keepLocks")); } - if (myRemoteStatus) { - element.addContent(new Element("remoteStatus")); - } - if (myUpgradeMode != null) { - element.addContent(new Element("upgradeMode").setText(myUpgradeMode)); - } element.addContent(new Element("myIsUseDefaultProxy").setText(myIsUseDefaultProxy ? "true" : "false")); if (mySupportOptions != null) { element.addContent(new Element("supportedVersion").setText(String.valueOf(mySupportOptions.myVersion))); @@ -576,15 +557,6 @@ public class SvnConfiguration implements PersistentStateComponent { myIsKeepLocks = keepLocks; } - // TODO: remove unused "myRemoteStatus" from configuration - public boolean isRemoteStatus() { - return myRemoteStatus; - } - - public void setRemoteStatus(boolean remote) { - myRemoteStatus = remote; - } - public boolean isIsUseDefaultProxy() { return myIsUseDefaultProxy; } From 249a78b3b2cf38631ca4a10d14d9e4eb2019f130 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 25 Dec 2013 16:22:01 +0400 Subject: [PATCH 21/38] svn: Removed unused "addpath" configuration parameter --- .../org/jetbrains/idea/svn/SvnConfiguration.java | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java index 957234b3ab23..a0b288da0005 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java @@ -79,7 +79,6 @@ public class SvnConfiguration implements PersistentStateComponent { private final Project myProject; public String PASSWORD = ""; - public String[] ADD_PATHS = null; private String myConfigurationDirectory; private boolean myIsUseDefaultConfiguration; @@ -424,13 +423,6 @@ public class SvnConfiguration implements PersistentStateComponent { @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(); @@ -511,13 +503,6 @@ public class SvnConfiguration implements PersistentStateComponent { @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); From 20ac89b1a65a533970a4509e9e075ef0c2df060f Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 25 Dec 2013 19:11:50 +0400 Subject: [PATCH 22/38] svn: Refactored SvnConfiguration - fields encapsulated --- .../idea/svn/SvnAuthenticationManager.java | 4 ++-- .../jetbrains/idea/svn/SvnConfigurable.java | 16 +++++++-------- .../jetbrains/idea/svn/SvnConfiguration.java | 20 +++++++++++++++++-- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java index 22f4c5f45350..23b77b31be7f 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java @@ -674,7 +674,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 +683,7 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im public int getConnectTimeout(SVNRepository repository) { String protocol = repository.getLocation().getProtocol(); if (SVN_SSH.equals(protocol)) { - return (int) getConfig().mySSHConnectionTimeout; + return (int)getConfig().getSSHConnectionTimeout(); } final int connectTimeout = super.getConnectTimeout(repository); if ((HTTP.equals(protocol) || HTTPS.equals(protocol)) && (connectTimeout <= 0)) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.java index d46eb28f2a19..8d084391d595 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.java @@ -262,10 +262,10 @@ 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()) { @@ -297,8 +297,8 @@ public class SvnConfigurable implements Configurable { } 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) || @@ -344,8 +344,8 @@ 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(); @@ -381,8 +381,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))); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java index a0b288da0005..1802fc78dfe6 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java @@ -93,8 +93,8 @@ public class SvnConfiguration implements PersistentStateComponent { private boolean myCleanupRun; private int myMaxAnnotateRevisions = ourMaxAnnotateRevisionsDefault; private final static long DEFAULT_SSH_TIMEOUT = 30 * 1000; - public long mySSHConnectionTimeout = DEFAULT_SSH_TIMEOUT; - public long mySSHReadTimeout = DEFAULT_SSH_TIMEOUT; + private long mySSHConnectionTimeout = DEFAULT_SSH_TIMEOUT; + private long mySSHReadTimeout = DEFAULT_SSH_TIMEOUT; public static final AuthStorage RUNTIME_AUTH_CACHE = new AuthStorage(); public String LAST_MERGED_REVISION = null; @@ -245,6 +245,22 @@ public class SvnConfiguration implements PersistentStateComponent { } } + 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 class SvnSupportOptions { /** * version of "support SVN in IDEA". for features tracking. should grow From 591ad7806dec8617558bb08b53a5c390b9a5d9ba Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 25 Dec 2013 19:28:06 +0400 Subject: [PATCH 23/38] svn: Refactored SvnConfiguration - moved config file utility methods to IdeaSVNConfigFile --- .../jetbrains/idea/svn/IdeaSVNConfigFile.java | 61 +++++++++++++++++ .../jetbrains/idea/svn/SvnConfiguration.java | 65 +------------------ ...IdeaSvnkitBasedAuthenticationCallback.java | 9 +-- .../idea/svn/commandLine/ProxyModule.java | 3 +- 4 files changed, 67 insertions(+), 71 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/IdeaSVNConfigFile.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/IdeaSVNConfigFile.java index f5c27c2f9c66..0c0e36f56b1b 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/IdeaSVNConfigFile.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/IdeaSVNConfigFile.java @@ -15,16 +15,24 @@ */ package org.jetbrains.idea.svn; +import com.intellij.openapi.util.text.StringUtil; +import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.svn.config.DefaultProxyGroup; import org.jetbrains.idea.svn.config.ProxyGroup; import org.tmatesoft.svn.core.internal.wc.SVNConfigFile; import java.io.File; +import java.net.InetSocketAddress; +import java.net.PasswordAuthentication; +import java.net.Proxy; import java.util.Collection; import java.util.HashMap; import java.util.Map; public class IdeaSVNConfigFile { + + public final static String SERVERS_FILE_NAME = "servers"; + private final Map myPatternsMap; private final long myLatestUpdate; private final File myFile; @@ -41,6 +49,59 @@ public class IdeaSVNConfigFile { myPatternsMap = new HashMap(); } + public static void putProxyIntoServersFile(final File configDir, final String host, final Proxy proxyInfo) { + final IdeaSVNConfigFile configFile = new IdeaSVNConfigFile(new File(configDir, SERVERS_FILE_NAME)); + configFile.updateGroups(); + + String groupName = ensureHostGroup(host, configFile); + + final HashMap map = new HashMap(); + final InetSocketAddress address = ((InetSocketAddress) proxyInfo.address()); + map.put(SvnAuthenticationManager.HTTP_PROXY_HOST, address.getHostName()); + map.put(SvnAuthenticationManager.HTTP_PROXY_PORT, String.valueOf(address.getPort())); + configFile.addGroup(groupName, host + "*", map); + configFile.save(); + } + + @NotNull + public static String ensureHostGroup(@NotNull String host, @NotNull IdeaSVNConfigFile configFile) { + String groupName = SvnAuthenticationManager.getGroupForHost(host, configFile); + + if (StringUtil.isEmptyOrSpaces(groupName)) { + groupName = getNewGroupName(host, configFile); + } + + return groupName; + } + + @NotNull + public static String getNewGroupName(@NotNull String host, @NotNull IdeaSVNConfigFile configFile) { + String groupName = host; + final Map groups = configFile.getAllGroups(); + while (StringUtil.isEmptyOrSpaces(groupName) || groups.containsKey(groupName)) { + groupName += "1"; + } + return groupName; + } + + public static boolean putProxyCredentialsIntoServerFile(@NotNull final File configDir, @NotNull final String host, + @NotNull final PasswordAuthentication authentication) { + final IdeaSVNConfigFile configFile = new IdeaSVNConfigFile(new File(configDir, SERVERS_FILE_NAME)); + configFile.updateGroups(); + + String groupName = SvnAuthenticationManager.getGroupForHost(host, configFile); + // no proxy defined in group -> no sense in password + if (StringUtil.isEmptyOrSpaces(groupName)) return false; + final Map properties = configFile.getAllGroups().get(groupName).getProperties(); + if (StringUtil.isEmptyOrSpaces(properties.get(SvnAuthenticationManager.HTTP_PROXY_HOST))) return false; + if (StringUtil.isEmptyOrSpaces(properties.get(SvnAuthenticationManager.HTTP_PROXY_PORT))) return false; + + configFile.setValue(groupName, SvnAuthenticationManager.HTTP_PROXY_USERNAME, authentication.getUserName()); + configFile.setValue(groupName, SvnAuthenticationManager.HTTP_PROXY_PASSWORD, String.valueOf(authentication.getPassword())); + configFile.save(); + return true; + } + public void updateGroups() { if (myLatestUpdate != myFile.lastModified()) { myPatternsMap.clear(); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java index 1802fc78dfe6..efbaae787761 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java @@ -27,14 +27,11 @@ 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; @@ -55,9 +52,6 @@ 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,8 +67,6 @@ public class SvnConfiguration implements PersistentStateComponent { private static final Logger LOG = Logger.getInstance("org.jetbrains.idea.svn.SvnConfiguration"); public final static int ourMaxAnnotateRevisionsDefault = 500; - private final static String SERVERS_FILE_NAME = "servers"; - public static final String CLEANUP_ON_START_RUN = "cleanupOnStartRun"; private final Project myProject; @@ -163,7 +155,7 @@ public class SvnConfiguration implements PersistentStateComponent { 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(); } @@ -176,59 +168,6 @@ public class SvnConfiguration implements PersistentStateComponent { myConfigFile.save(); } - public static void putProxyIntoServersFile(final File configDir, final String host, final Proxy proxyInfo) { - final IdeaSVNConfigFile configFile = new IdeaSVNConfigFile(new File(configDir, SERVERS_FILE_NAME)); - configFile.updateGroups(); - - String groupName = ensureHostGroup(host, configFile); - - final HashMap map = new HashMap(); - final InetSocketAddress address = ((InetSocketAddress) proxyInfo.address()); - map.put(SvnAuthenticationManager.HTTP_PROXY_HOST, address.getHostName()); - map.put(SvnAuthenticationManager.HTTP_PROXY_PORT, String.valueOf(address.getPort())); - configFile.addGroup(groupName, host + "*", map); - configFile.save(); - } - - @NotNull - public static String ensureHostGroup(@NotNull String host, @NotNull IdeaSVNConfigFile configFile) { - String groupName = SvnAuthenticationManager.getGroupForHost(host, configFile); - - if (StringUtil.isEmptyOrSpaces(groupName)) { - groupName = getNewGroupName(host, configFile); - } - - return groupName; - } - - @NotNull - public static String getNewGroupName(@NotNull String host, @NotNull IdeaSVNConfigFile configFile) { - String groupName = host; - final Map groups = configFile.getAllGroups(); - while (StringUtil.isEmptyOrSpaces(groupName) || groups.containsKey(groupName)) { - groupName += "1"; - } - return groupName; - } - - public static boolean putProxyCredentialsIntoServerFile(@NotNull final File configDir, @NotNull final String host, - @NotNull final PasswordAuthentication authentication) { - final IdeaSVNConfigFile configFile = new IdeaSVNConfigFile(new File(configDir, SERVERS_FILE_NAME)); - configFile.updateGroups(); - - String groupName = SvnAuthenticationManager.getGroupForHost(host, configFile); - // no proxy defined in group -> no sense in password - if (StringUtil.isEmptyOrSpaces(groupName)) return false; - final Map properties = configFile.getAllGroups().get(groupName).getProperties(); - if (StringUtil.isEmptyOrSpaces(properties.get(SvnAuthenticationManager.HTTP_PROXY_HOST))) return false; - if (StringUtil.isEmptyOrSpaces(properties.get(SvnAuthenticationManager.HTTP_PROXY_PORT))) return false; - - configFile.setValue(groupName, SvnAuthenticationManager.HTTP_PROXY_USERNAME, authentication.getUserName()); - configFile.setValue(groupName, SvnAuthenticationManager.HTTP_PROXY_PASSWORD, String.valueOf(authentication.getPassword())); - configFile.save(); - return true; - } - public static SvnConfiguration getInstance(final Project project) { return ServiceManager.getService(project, SvnConfiguration.class); } @@ -431,7 +370,7 @@ public class SvnConfiguration implements PersistentStateComponent { SVNConfigFile.createDefaultConfiguration(dir); } - systemManager.set(new SvnServerFileManagerImpl(new IdeaSVNConfigFile(new File(SVNFileUtil.getSystemConfigurationDirectory(), SERVERS_FILE_NAME)))); + systemManager.set(new SvnServerFileManagerImpl(new IdeaSVNConfigFile(new File(SVNFileUtil.getSystemConfigurationDirectory(), IdeaSVNConfigFile.SERVERS_FILE_NAME)))); initServers(); userManager.set(new SvnServerFileManagerImpl(myConfigFile)); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java index 57daf70de1fd..4420b32d7f07 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java @@ -33,10 +33,7 @@ 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.tmatesoft.svn.core.*; @@ -221,7 +218,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 +298,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; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/ProxyModule.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/ProxyModule.java index 9e28696829dc..421a7346b6de 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/ProxyModule.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/ProxyModule.java @@ -20,7 +20,6 @@ import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.svn.IdeaSVNConfigFile; import org.jetbrains.idea.svn.SvnAuthenticationManager; -import org.jetbrains.idea.svn.SvnConfiguration; import org.jetbrains.idea.svn.checkin.IdeaSvnkitBasedAuthenticationCallback; import org.tmatesoft.svn.core.SVNURL; @@ -73,7 +72,7 @@ public class ProxyModule extends BaseCommandRuntimeModule { String groupName = SvnAuthenticationManager.getGroupForHost(host, configFile); if (StringUtil.isEmptyOrSpaces(groupName)) { - groupName = SvnConfiguration.getNewGroupName(host, configFile); + groupName = IdeaSVNConfigFile.getNewGroupName(host, configFile); command.put("--config-option"); command.put(String.format("servers:groups:%s=%s*", groupName, host)); From 035b20809073a8c429432567b88cd7aa66864f77 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 25 Dec 2013 20:01:44 +0400 Subject: [PATCH 24/38] svn: Refactored SvnConfigurable - moved "clear auth cache" logic to SvnAuthenticationNotifier --- .../idea/svn/SvnAuthenticationNotifier.java | 22 ++++++++++++++++++- .../jetbrains/idea/svn/SvnConfigurable.java | 22 +------------------ 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationNotifier.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationNotifier.java index 4efcce6f0db6..c2663ed6557b 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationNotifier.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationNotifier.java @@ -23,6 +23,7 @@ import com.intellij.openapi.diagnostic.Logger; 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; @@ -414,7 +415,7 @@ public class SvnAuthenticationNotifier extends GenericNotifierImpl Date: Wed, 25 Dec 2013 20:14:17 +0400 Subject: [PATCH 25/38] svn: Authentication tests refactored - methods extracted, removed duplication --- .../idea/svn/SvnAuthenticationTest.java | 8 ++- .../idea/svn/SvnNativeClientAuthTest.java | 54 ++++++++----------- .../idea/svn16/SvnAuthenticationTest.java | 8 ++- 3 files changed, 34 insertions(+), 36 deletions(-) diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnAuthenticationTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnAuthenticationTest.java index de273690fd73..a551b0877e99 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnAuthenticationTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnAuthenticationTest.java @@ -730,7 +730,7 @@ public class SvnAuthenticationTest extends PlatformTestCase { @Override public void run() { try { - myConfiguration.clearAuthenticationDirectory(getProject()); + clearAuthCache(); } catch (Exception e) { throw new RuntimeException(e); @@ -780,6 +780,10 @@ public class SvnAuthenticationTest extends PlatformTestCase { SVNJNAUtil.setJNAEnabled(true); } + private void clearAuthCache() { + myConfiguration.clearAuthenticationDirectory(getProject()); + } + public void testPlaintextPromptAndSecondPrompt() throws Exception { SVNJNAUtil.setJNAEnabled(false); @@ -875,7 +879,7 @@ public class SvnAuthenticationTest extends PlatformTestCase { @Override public void run() { try { - myConfiguration.clearAuthenticationDirectory(getProject()); + clearAuthCache(); } catch (Exception e) { throw new RuntimeException(e); diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeClientAuthTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeClientAuthTest.java index b6d6ae104bbc..f4e82d565867 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeClientAuthTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeClientAuthTest.java @@ -29,6 +29,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Processor; import com.intellij.util.containers.Convertor; import junit.framework.Assert; +import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.svn.checkout.SvnCheckoutProvider; import org.junit.Before; import org.tmatesoft.svn.core.*; @@ -143,8 +144,7 @@ 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); mySaveCredentials = false; @@ -166,8 +166,7 @@ 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); mySaveCredentials = false; @@ -191,8 +190,7 @@ 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); mySaveCredentials = true; @@ -215,8 +213,7 @@ 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); mySaveCredentials = true; @@ -237,8 +234,7 @@ 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); mySaveCredentials = false; @@ -260,8 +256,7 @@ 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); mySaveCredentials = false; @@ -285,8 +280,7 @@ 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); mySaveCredentials = true; @@ -310,8 +304,7 @@ 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); mySaveCredentials = true; @@ -329,6 +322,11 @@ public class SvnNativeClientAuthTest extends Svn17TestCase { //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount); } + private void clearAuthCache(@NotNull SvnConfiguration instance) { + instance.clearAuthenticationDirectory(myProject); + instance.clearRuntimeStorage(); + } + @Test public void testMixedSSLCommit() throws Exception { final File wc1 = testCheckoutImpl(ourHTTPS_URL); @@ -336,8 +334,7 @@ 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); mySaveCredentials = false; @@ -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,8 +369,7 @@ 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); mySaveCredentials = true; @@ -395,8 +390,7 @@ 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); mySaveCredentials = false; @@ -419,8 +413,7 @@ 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); mySaveCredentials = false; @@ -446,8 +439,7 @@ 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); mySaveCredentials = false; @@ -480,8 +472,7 @@ 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); mySaveCredentials = false; @@ -507,8 +498,7 @@ 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); mySaveCredentials = false; diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnAuthenticationTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnAuthenticationTest.java index b4302105204a..de6511b5312a 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnAuthenticationTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnAuthenticationTest.java @@ -733,7 +733,7 @@ public class SvnAuthenticationTest extends PlatformTestCase { @Override public void run() { try { - myConfiguration.clearAuthenticationDirectory(getProject()); + clearAuthCache(); } catch (Exception e) { throw new RuntimeException(e); @@ -783,6 +783,10 @@ public class SvnAuthenticationTest extends PlatformTestCase { SVNJNAUtil.setJNAEnabled(true); } + private void clearAuthCache() { + myConfiguration.clearAuthenticationDirectory(getProject()); + } + public void testPlaintextPromptAndSecondPrompt() throws Exception { SVNJNAUtil.setJNAEnabled(false); @@ -878,7 +882,7 @@ public class SvnAuthenticationTest extends PlatformTestCase { @Override public void run() { try { - myConfiguration.clearAuthenticationDirectory(getProject()); + clearAuthCache(); } catch (Exception e) { throw new RuntimeException(e); From 3fc6f6f56b91d9f835c76a242a278861a73e503f Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 25 Dec 2013 20:18:49 +0400 Subject: [PATCH 26/38] svn: Refactored SvnConfiguration - moved "clear auth cache" logic to SvnAuthenticationNotifier --- .../idea/svn/SvnAuthenticationNotifier.java | 46 ++++++++++++++++- .../jetbrains/idea/svn/SvnConfiguration.java | 49 ++----------------- .../idea/svn/SvnAuthenticationTest.java | 2 +- .../idea/svn/SvnNativeClientAuthTest.java | 4 +- .../idea/svn16/SvnAuthenticationTest.java | 3 +- 5 files changed, 55 insertions(+), 49 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationNotifier.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationNotifier.java index c2663ed6557b..5b84aa234d38 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationNotifier.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationNotifier.java @@ -16,10 +16,12 @@ 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; @@ -28,6 +30,7 @@ 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; @@ -46,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; @@ -60,6 +66,9 @@ import java.util.Timer; public class SvnAuthenticationNotifier extends GenericNotifierImpl { private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.SvnAuthenticationNotifier"); + private static final List ourAuthKinds = Arrays.asList(ISVNAuthenticationManager.PASSWORD, ISVNAuthenticationManager.SSH, + ISVNAuthenticationManager.SSL, ISVNAuthenticationManager.USERNAME, "svn.ssl.server", "svn.ssh.server"); + private final SvnVcs myVcs; private final RootsToWorkingCopies myRootsToWorkingCopies; private final Map myCopiesPassiveResults; @@ -452,7 +461,42 @@ public class SvnAuthenticationNotifier extends GenericNotifierImpl { 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()); } } @@ -200,6 +193,10 @@ public class SvnConfiguration implements PersistentStateComponent { mySSHReadTimeout = SSHReadTimeout; } + public Project getProject() { + return myProject; + } + public class SvnSupportOptions { /** * version of "support SVN in IDEA". for features tracking. should grow @@ -546,42 +543,6 @@ public class SvnConfiguration implements PersistentStateComponent { return Collections.unmodifiableMap(myUpdateRootInfos); } - private static final List ourAuthKinds = Arrays.asList(ISVNAuthenticationManager.PASSWORD, ISVNAuthenticationManager.SSH, - ISVNAuthenticationManager.SSL, ISVNAuthenticationManager.USERNAME, "svn.ssl.server", "svn.ssh.server"); - - public void clearAuthenticationDirectory(@Nullable Project project) { - final File authDir = new File(getConfigurationDirectory(), "auth"); - if (authDir.exists()) { - final Runnable process = new Runnable() { - public void run() { - final ProgressIndicator ind = ProgressManager.getInstance().getProgressIndicator(); - if (ind != null) { - ind.setIndeterminate(true); - ind.setText("Clearing stored credentials in " + authDir.getAbsolutePath()); - } - final File[] files = authDir.listFiles(new FilenameFilter() { - public boolean accept(File dir, String name) { - return ourAuthKinds.contains(name); - } - }); - - for (File dir : files) { - if (ind != null) { - ind.setText("Deleting " + dir.getAbsolutePath()); - } - FileUtil.delete(dir); - } - } - }; - final Application application = ApplicationManager.getApplication(); - if (application.isUnitTestMode() || ! application.isDispatchThread()) { - process.run(); - } else { - ProgressManager.getInstance().runProcessWithProgressSynchronously(process, "button.text.clear.authentication.cache", false, project); - } - } - } - public void acknowledge(final String kind, final String realm, final Object object) { RUNTIME_AUTH_CACHE.putData(kind, realm, object); } diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnAuthenticationTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnAuthenticationTest.java index a551b0877e99..3700343842e3 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnAuthenticationTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnAuthenticationTest.java @@ -781,7 +781,7 @@ public class SvnAuthenticationTest extends PlatformTestCase { } private void clearAuthCache() { - myConfiguration.clearAuthenticationDirectory(getProject()); + SvnAuthenticationNotifier.clearAuthenticationDirectory(myConfiguration); } public void testPlaintextPromptAndSecondPrompt() throws Exception { diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeClientAuthTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeClientAuthTest.java index f4e82d565867..7d1e0c88169c 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeClientAuthTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeClientAuthTest.java @@ -322,8 +322,8 @@ public class SvnNativeClientAuthTest extends Svn17TestCase { //Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount); } - private void clearAuthCache(@NotNull SvnConfiguration instance) { - instance.clearAuthenticationDirectory(myProject); + private static void clearAuthCache(@NotNull SvnConfiguration instance) { + SvnAuthenticationNotifier.clearAuthenticationDirectory(instance); instance.clearRuntimeStorage(); } diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnAuthenticationTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnAuthenticationTest.java index de6511b5312a..624cfbb25635 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnAuthenticationTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnAuthenticationTest.java @@ -25,6 +25,7 @@ import com.intellij.util.concurrency.Semaphore; import com.intellij.util.ui.UIUtil; import junit.framework.Assert; import org.jetbrains.idea.svn.SvnAuthenticationManager; +import org.jetbrains.idea.svn.SvnAuthenticationNotifier; import org.jetbrains.idea.svn.SvnConfiguration; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.auth.ProviderType; @@ -784,7 +785,7 @@ public class SvnAuthenticationTest extends PlatformTestCase { } private void clearAuthCache() { - myConfiguration.clearAuthenticationDirectory(getProject()); + SvnAuthenticationNotifier.clearAuthenticationDirectory(myConfiguration); } public void testPlaintextPromptAndSecondPrompt() throws Exception { From 851d0f27f59bb8d00776f5025ae014264b5aeb85 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 25 Dec 2013 20:28:57 +0400 Subject: [PATCH 27/38] svn: Refactored SvnConfiguration - "create auth manager for command line" methods inlined to IdeaSvnkitBasedAuthenticationCallback --- .../jetbrains/idea/svn/SvnConfiguration.java | 18 ------------------ .../IdeaSvnkitBasedAuthenticationCallback.java | 8 +++++++- 2 files changed, 7 insertions(+), 19 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java index 24bdecff00b2..de8a1d2ac1a4 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java @@ -26,7 +26,6 @@ import com.intellij.openapi.vcs.changes.VcsAnnotationRefresher; import org.jdom.Attribute; import org.jdom.DataConversionException; import org.jdom.Element; -import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.config.SvnServerFileKeys; import org.jetbrains.idea.svn.dialogs.SvnAuthenticationProvider; import org.jetbrains.idea.svn.dialogs.SvnInteractiveAuthenticationProvider; @@ -291,23 +290,6 @@ public class SvnConfiguration implements PersistentStateComponent { return myOptions; } - public static SvnAuthenticationManager createForTmpDir(final Project project, final File dir) { - return createForTmpDir(project, dir, null); - } - - public static SvnAuthenticationManager createForTmpDir(final Project project, final File dir, - @Nullable final SvnInteractiveAuthenticationProvider provider) { - final SvnVcs vcs = SvnVcs.getInstance(project); - - final SvnAuthenticationManager interactive = new SvnAuthenticationManager(project, dir); - interactive.setRuntimeStorage(RUNTIME_AUTH_CACHE); - final SvnInteractiveAuthenticationProvider interactiveProvider = provider == null ? - new SvnInteractiveAuthenticationProvider(vcs, interactive) : provider; - interactive.setAuthenticationProvider(interactiveProvider); - - return interactive; - } - public SvnAuthenticationManager getAuthenticationManager(final SvnVcs svnVcs) { if (myAuthManager == null) { // reloaded when configuration directory changes diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java index 4420b32d7f07..29d5068073f5 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java @@ -36,6 +36,7 @@ import org.jetbrains.annotations.Nullable; 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; @@ -355,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; From e57aca9b1c471ca4490cae0d72bb96886a3d7d45 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 25 Dec 2013 20:35:13 +0400 Subject: [PATCH 28/38] svn: Removed unused "LAST_MERGED_REVISION" configuration parameter (and related logic) --- .../jetbrains/idea/svn/SvnConfiguration.java | 1 - .../svn/update/SvnIntegrateEnvironment.java | 38 +------------------ 2 files changed, 1 insertion(+), 38 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java index de8a1d2ac1a4..a6d34823e6ab 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java @@ -81,7 +81,6 @@ public class SvnConfiguration implements PersistentStateComponent { private long mySSHReadTimeout = DEFAULT_SSH_TIMEOUT; public static final AuthStorage RUNTIME_AUTH_CACHE = new AuthStorage(); - public String LAST_MERGED_REVISION = null; public SVNDepth UPDATE_DEPTH = SVNDepth.UNKNOWN; public boolean MERGE_DRY_RUN = false; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnIntegrateEnvironment.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnIntegrateEnvironment.java index 7627b1ecc048..a01616e5a89d 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnIntegrateEnvironment.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnIntegrateEnvironment.java @@ -20,15 +20,10 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.update.UpdatedFiles; -import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnBundle; import org.jetbrains.idea.svn.SvnConfiguration; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.integrate.MergeClient; -import org.tmatesoft.svn.core.SVNException; -import org.tmatesoft.svn.core.SVNURL; -import org.tmatesoft.svn.core.io.SVNRepository; -import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; import java.io.File; @@ -69,7 +64,7 @@ public class SvnIntegrateEnvironment extends AbstractSvnUpdateIntegrateEnvironme return SvnConfiguration.getInstance(myVcs.getProject()).MERGE_DRY_RUN; } - private class IntegrateCrawler extends AbstractUpdateIntegrateCrawler { + private static class IntegrateCrawler extends AbstractUpdateIntegrateCrawler { public IntegrateCrawler(SvnVcs vcs, UpdateEventHandler handler, @@ -106,7 +101,6 @@ public class SvnIntegrateEnvironment extends AbstractSvnUpdateIntegrateEnvironme client.merge(source1, source2, root, svnConfig.UPDATE_DEPTH, svnConfig.MERGE_DIFF_USE_ANCESTRY, svnConfig.MERGE_DRY_RUN, false, false, svnConfig.getMergeOptions(), myHandler); - svnConfig.LAST_MERGED_REVISION = getLastMergedRevision(info.getRevision2(), info.getUrl2()); return info.getResultRevision(); } @@ -115,36 +109,6 @@ public class SvnIntegrateEnvironment extends AbstractSvnUpdateIntegrateEnvironme } } - @Nullable - private String getLastMergedRevision(final SVNRevision rev2, final SVNURL svnURL2) { - if (!rev2.isValid() || rev2.isLocal()) { - return null; - } - else { - final long number = rev2.getNumber(); - if (number > 0) { - return String.valueOf(number); - } - else { - - // TODO: Rewrite with command line implementation - SVNRepository repos = null; - try { - repos = myVcs.createRepository(svnURL2.toString()); - final long latestRev = repos.getLatestRevision(); - return String.valueOf(latestRev); - } - catch (SVNException e) { - return null; - } finally { - if (repos != null) { - repos.closeSession(); - } - } - } - } - } - public boolean validateOptions(final Collection roots) { return true; } From 3658903886aa8d78692ba7161b9728284633dac4 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 25 Dec 2013 21:10:21 +0400 Subject: [PATCH 29/38] svn: Refactored SvnConfiguration - encapsulated configuration parameters fields - fields are still public not to break configuration persisting - simple renames --- .../idea/svn/SvnAuthenticationManager.java | 4 +- .../jetbrains/idea/svn/SvnConfigurable.java | 52 +++---- .../jetbrains/idea/svn/SvnConfiguration.java | 136 +++++++++++++++--- .../src/org/jetbrains/idea/svn/SvnVcs.java | 6 +- .../svn/annotate/BaseSvnFileAnnotation.java | 2 +- .../svn/annotate/SvnAnnotationProvider.java | 6 +- .../idea/svn/history/SvnHistoryProvider.java | 2 +- .../idea/svn/integrate/GroupMerger.java | 3 +- .../IntegratedSelectedOptionsDialog.java | 8 +- .../jetbrains/idea/svn/integrate/Merger.java | 2 +- .../idea/svn/integrate/PointMerger.java | 5 +- .../idea/svn/integrate/ResolveWorker.java | 2 +- .../SvnIntegrateChangesActionPerformer.java | 2 +- .../OneRecursiveShotMergeInfoWorker.java | 2 +- .../treeConflict/MergeFromTheirsResolver.java | 8 +- .../svn/update/AbstractSvnUpdatePanel.java | 4 +- .../idea/svn/update/AutoSvnUpdater.java | 6 +- .../svn/update/SvnIntegrateEnvironment.java | 6 +- .../idea/svn/update/SvnIntegratePanel.java | 8 +- .../idea/svn/update/SvnUpdateContext.java | 2 +- .../idea/svn/update/SvnUpdateEnvironment.java | 9 +- .../idea/svn/update/SvnUpdatePanel.java | 12 +- .../jetbrains/idea/svn/SvnMergeInfoTest.java | 2 +- .../idea/svn/SvnNativeClientAuthTest.java | 30 ++-- .../idea/svn16/SvnMergeInfoTest.java | 2 +- 25 files changed, 210 insertions(+), 111 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java index 23b77b31be7f..eafa2a8c9f9f 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java @@ -674,7 +674,7 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im return DEFAULT_READ_TIMEOUT; } if (SVN_SSH.equals(protocol)) { - return (int)getConfig().getSSHReadTimeout(); + return (int)getConfig().getSshReadTimeout(); } return 0; } @@ -683,7 +683,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().getSSHConnectionTimeout(); + return (int)getConfig().getSshConnectionTimeout(); } final int connectTimeout = super.getConnectTimeout(repository); if ((HTTP.equals(protocol) || HTTPS.equals(protocol)) && (connectTimeout <= 0)) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.java index a678bd0ceb45..71709f783055 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.java @@ -219,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()) { @@ -242,16 +242,16 @@ public class SvnConfigurable implements Configurable { return true; } } - if (configuration.getSSHConnectionTimeout() /1000 != ((SpinnerNumberModel) mySSHConnectionTimeout.getModel()).getNumber().longValue()) { + if (configuration.getSshConnectionTimeout() /1000 != ((SpinnerNumberModel) mySSHConnectionTimeout.getModel()).getNumber().longValue()) { return true; } - if (configuration.getSSHReadTimeout() /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()); @@ -268,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.setSSHConnectionTimeout(((SpinnerNumberModel) mySSHConnectionTimeout.getModel()).getNumber().longValue() * 1000); - configuration.setSSHReadTimeout(((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()); @@ -305,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) { @@ -324,16 +324,16 @@ public class SvnConfigurable implements Configurable { myNumRevsInAnnotations.setValue(annotateRevisions); } myNumRevsInAnnotations.setEnabled(myMaximumNumberOfRevisionsCheckBox.isSelected()); - mySSHConnectionTimeout.setValue(Long.valueOf(configuration.getSSHConnectionTimeout() / 1000)); - mySSHReadTimeout.setValue(Long.valueOf(configuration.getSSHReadTimeout() / 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); @@ -361,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.getSSHConnectionTimeout() <= maximum ? configuration.getSSHConnectionTimeout() : maximum; - final long read = configuration.getSSHReadTimeout() <= maximum ? configuration.getSSHReadTimeout() : 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))); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java index a6d34823e6ab..da5d470a4e06 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java @@ -77,8 +77,8 @@ public class SvnConfiguration implements PersistentStateComponent { private boolean myCleanupRun; private int myMaxAnnotateRevisions = ourMaxAnnotateRevisionsDefault; private final static long DEFAULT_SSH_TIMEOUT = 30 * 1000; - private long mySSHConnectionTimeout = DEFAULT_SSH_TIMEOUT; - private long mySSHReadTimeout = DEFAULT_SSH_TIMEOUT; + public long mySSHConnectionTimeout = DEFAULT_SSH_TIMEOUT; + public long mySSHReadTimeout = DEFAULT_SSH_TIMEOUT; public static final AuthStorage RUNTIME_AUTH_CACHE = new AuthStorage(); public SVNDepth UPDATE_DEPTH = SVNDepth.UNKNOWN; @@ -87,7 +87,6 @@ public class SvnConfiguration implements PersistentStateComponent { 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; @@ -105,7 +104,7 @@ public class SvnConfiguration implements PersistentStateComponent { private IdeaSVNConfigFile myConfigFile; public boolean isCommandLine() { - return UseAcceleration.commandLine.equals(myUseAcceleration); + return UseAcceleration.commandLine.equals(getUseAcceleration()); } @Override @@ -141,7 +140,7 @@ public class SvnConfiguration implements PersistentStateComponent { } public SVNDiffOptions getMergeOptions() { - return new SVNDiffOptions(IGNORE_SPACES_IN_MERGE, IGNORE_SPACES_IN_MERGE, IGNORE_SPACES_IN_MERGE); + return new SVNDiffOptions(isIgnoreSpacesInMerge(), isIgnoreSpacesInMerge(), isIgnoreSpacesInMerge()); } private void initServers() { @@ -175,26 +174,126 @@ public class SvnConfiguration implements PersistentStateComponent { } } - public long getSSHConnectionTimeout() { + public long getSshConnectionTimeout() { return mySSHConnectionTimeout; } - public void setSSHConnectionTimeout(long SSHConnectionTimeout) { - mySSHConnectionTimeout = SSHConnectionTimeout; + public void setSshConnectionTimeout(long sshConnectionTimeout) { + mySSHConnectionTimeout = sshConnectionTimeout; } - public long getSSHReadTimeout() { + public long getSshReadTimeout() { return mySSHReadTimeout; } - public void setSSHReadTimeout(long SSHReadTimeout) { - mySSHReadTimeout = SSHReadTimeout; + 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 @@ -405,7 +504,7 @@ public class SvnConfiguration implements PersistentStateComponent { final Attribute acceleration = element.getAttribute("myUseAcceleration"); if (acceleration != null) { try { - myUseAcceleration = UseAcceleration.valueOf(acceleration.getValue()); + setUseAcceleration(UseAcceleration.valueOf(acceleration.getValue())); } catch (IllegalArgumentException e) { // } @@ -423,13 +522,13 @@ public class SvnConfiguration implements PersistentStateComponent { final Attribute protocols = element.getAttribute("SSL_PROTOCOLS"); if (protocols != null) { try { - SSL_PROTOCOLS = SSLProtocols.valueOf(protocols.getValue()); + setSslProtocols(SSLProtocols.valueOf(protocols.getValue())); } catch (IllegalArgumentException e) { // } } if (treeConflictMergeNewFilesPlace != null) { - TREE_CONFLICT_MERGE_THEIRS_NEW_INTO_OLD_PLACE = Boolean.parseBoolean(treeConflictMergeNewFilesPlace.getValue()); + setKeepNewFilesAsIsForTreeConflictMerge(Boolean.parseBoolean(treeConflictMergeNewFilesPlace.getValue())); } } @@ -450,12 +549,13 @@ public class SvnConfiguration implements PersistentStateComponent { element.addContent(new Element("supportedVersion").setText(String.valueOf(mySupportOptions.myVersion))); } element.setAttribute("maxAnnotateRevisions", String.valueOf(myMaxAnnotateRevisions)); - element.setAttribute("myUseAcceleration", String.valueOf(myUseAcceleration)); + 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", SSL_PROTOCOLS.name()); - if (TREE_CONFLICT_MERGE_THEIRS_NEW_INTO_OLD_PLACE != null) { - element.setAttribute("TREE_CONFLICT_MERGE_THEIRS_NEW_INTO_OLD_PLACE", String.valueOf(TREE_CONFLICT_MERGE_THEIRS_NEW_INTO_OLD_PLACE)); + element.setAttribute("SSL_PROTOCOLS", getSslProtocols().name()); + if (isKeepNewFilesAsIsForTreeConflictMerge() != null) { + element.setAttribute("TREE_CONFLICT_MERGE_THEIRS_NEW_INTO_OLD_PLACE", String.valueOf( + isKeepNewFilesAsIsForTreeConflictMerge())); } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java index 108924d9b31a..96dfea9cf4de 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java @@ -1055,11 +1055,11 @@ public class SvnVcs extends AbstractVcs { public void refreshSSLProperty() { if (ourSSLProtocolsExplicitlySet) return; - if (SvnConfiguration.SSLProtocols.all.equals(myConfiguration.SSL_PROTOCOLS)) { + if (SvnConfiguration.SSLProtocols.all.equals(myConfiguration.getSslProtocols())) { System.clearProperty(SVNKIT_HTTP_SSL_PROTOCOLS); - } else if (SvnConfiguration.SSLProtocols.sslv3.equals(myConfiguration.SSL_PROTOCOLS)) { + } else if (SvnConfiguration.SSLProtocols.sslv3.equals(myConfiguration.getSslProtocols())) { System.setProperty(SVNKIT_HTTP_SSL_PROTOCOLS, "SSLv3"); - } else if (SvnConfiguration.SSLProtocols.tlsv1.equals(myConfiguration.SSL_PROTOCOLS)) { + } else if (SvnConfiguration.SSLProtocols.tlsv1.equals(myConfiguration.getSslProtocols())) { System.setProperty(SVNKIT_HTTP_SSL_PROTOCOLS, "TLSv1"); } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/BaseSvnFileAnnotation.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/BaseSvnFileAnnotation.java index f16bfa41c963..f4fa9f950a32 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/BaseSvnFileAnnotation.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/BaseSvnFileAnnotation.java @@ -164,7 +164,7 @@ public abstract class BaseSvnFileAnnotation extends FileAnnotation { myContents = contents; myBaseRevision = baseRevision; myConfiguration = SvnConfiguration.getInstance(vcs.getProject()); - myShowMergeSources = myConfiguration.SHOW_MERGE_SOURCES_IN_ANNOTATE; + myShowMergeSources = myConfiguration.isShowMergeSourcesInAnnotate(); myInfos = new MyPartiallyCreatedInfos(); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnAnnotationProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnAnnotationProvider.java index 18c4b9824631..c51f4dbcdaa3 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnAnnotationProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnAnnotationProvider.java @@ -118,7 +118,7 @@ public class SvnAnnotationProvider implements AnnotationProvider, VcsCacheableAn // ignore mime type=true : IDEA-19562 final ISVNAnnotateHandler annotateHandler = createAnnotationHandler(progress, result); - final boolean calculateMergeinfo = SvnConfiguration.getInstance(myVcs.getProject()).SHOW_MERGE_SOURCES_IN_ANNOTATE && + final boolean calculateMergeinfo = SvnConfiguration.getInstance(myVcs.getProject()).isShowMergeSourcesInAnnotate() && SvnUtil.checkRepositoryVersion15(myVcs, url); final MySteppedLogGetter logGetter = new MySteppedLogGetter( myVcs, ioFile, progress, @@ -248,7 +248,7 @@ public class SvnAnnotationProvider implements AnnotationProvider, VcsCacheableAn pair.getSecond().getPath(), current); final ISVNAnnotateHandler annotateHandler = createAnnotationHandler(ProgressManager.getInstance().getProgressIndicator(), result); - final boolean calculateMergeinfo = SvnConfiguration.getInstance(myVcs.getProject()).SHOW_MERGE_SOURCES_IN_ANNOTATE && + final boolean calculateMergeinfo = SvnConfiguration.getInstance(myVcs.getProject()).isShowMergeSourcesInAnnotate() && SvnUtil.checkRepositoryVersion15(myVcs, wasUrl.toString()); AnnotateClient client = myVcs.getFactory().createAnnotateClient(); client.annotate(SvnTarget.fromURL(wasUrl), SVNRevision.create(1), svnRevision, svnRevision, calculateMergeinfo, @@ -478,6 +478,6 @@ public class SvnAnnotationProvider implements AnnotationProvider, VcsCacheableAn } private static SVNDiffOptions getLogClientOptions(@NotNull SvnVcs vcs) { - return SvnConfiguration.getInstance(vcs.getProject()).IGNORE_SPACES_IN_ANNOTATE ? new SVNDiffOptions(true, true, true) : null; + return SvnConfiguration.getInstance(vcs.getProject()).isIgnoreSpacesInAnnotate() ? new SVNDiffOptions(true, true, true) : null; } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java index a625e5b578ba..b5dfd8ccdbd4 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java @@ -188,7 +188,7 @@ public class SvnHistoryProvider } } - final boolean showMergeSources = SvnConfiguration.getInstance(myVcs.getProject()).SHOW_MERGE_SOURCES_IN_ANNOTATE; + final boolean showMergeSources = SvnConfiguration.getInstance(myVcs.getProject()).isShowMergeSourcesInAnnotate(); final LogLoader logLoader; if (path.isNonLocal()) { logLoader = new RepositoryLoader(myVcs, committedPath, from, to, limit, peg, forceBackwards, showMergeSources); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/GroupMerger.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/GroupMerger.java index 3c4c17ed6ddc..cb62668cbb25 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/GroupMerger.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/GroupMerger.java @@ -31,7 +31,6 @@ import org.jetbrains.idea.svn.update.UpdateEventHandler; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; -import org.tmatesoft.svn.core.wc.SVNDiffOptions; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc.SVNRevisionRange; import org.tmatesoft.svn.core.wc2.SvnTarget; @@ -132,7 +131,7 @@ public class GroupMerger implements IMerger { SvnTarget source = SvnTarget.fromURL(myCurrentBranchUrl); MergeClient client = myVcs.getFactory(myTarget).createMergeClient(); - client.merge(source, createRange(), myTarget, SVNDepth.INFINITY, mySvnConfig.MERGE_DRY_RUN, myDryRun, true, + client.merge(source, createRange(), myTarget, SVNDepth.INFINITY, mySvnConfig.isMergeDryRun(), myDryRun, true, mySvnConfig.getMergeOptions(), myHandler); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/IntegratedSelectedOptionsDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/IntegratedSelectedOptionsDialog.java index 2d2f28502928..47d26335f3f4 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/IntegratedSelectedOptionsDialog.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/IntegratedSelectedOptionsDialog.java @@ -97,8 +97,8 @@ public class IntegratedSelectedOptionsDialog extends DialogWrapper { } SvnConfiguration svnConfig = SvnConfiguration.getInstance(myVcs.getProject()); - myDryRunCheckbox.setSelected(svnConfig.MERGE_DRY_RUN); - myIgnoreWhitespacesCheckBox.setSelected(svnConfig.IGNORE_SPACES_IN_MERGE); + myDryRunCheckbox.setSelected(svnConfig.isMergeDryRun()); + myIgnoreWhitespacesCheckBox.setSelected(svnConfig.isIgnoreSpacesInMerge()); mySourceInfoLabel.setText(SvnBundle.message("action.Subversion.integrate.changes.branch.info.source.label.text", currentBranch)); myTargetInfoLabel.setText(SvnBundle.message("action.Subversion.integrate.changes.branch.info.target.label.text", selectedBranchUrl)); @@ -223,8 +223,8 @@ public class IntegratedSelectedOptionsDialog extends DialogWrapper { public void saveOptions() { SvnConfiguration svnConfig = SvnConfiguration.getInstance(myVcs.getProject()); - svnConfig.MERGE_DRY_RUN = myDryRunCheckbox.isSelected(); - svnConfig.IGNORE_SPACES_IN_MERGE = myIgnoreWhitespacesCheckBox.isSelected(); + svnConfig.setMergeDryRun(myDryRunCheckbox.isSelected()); + svnConfig.setIgnoreSpacesInMerge(myIgnoreWhitespacesCheckBox.isSelected()); } protected JComponent createCenterPanel() { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/Merger.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/Merger.java index 1c50dde706c1..8f534b90bb27 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/Merger.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/Merger.java @@ -128,7 +128,7 @@ public class Merger implements IMerger { SvnTarget source = SvnTarget.fromURL(myCurrentBranchUrl); MergeClient client = myVcs.getFactory(myTarget).createMergeClient(); - client.merge(source, createRange(), myTarget, SVNDepth.INFINITY, mySvnConfig.MERGE_DRY_RUN, isRecordOnly(), true, + client.merge(source, createRange(), myTarget, SVNDepth.INFINITY, mySvnConfig.isMergeDryRun(), isRecordOnly(), true, mySvnConfig.getMergeOptions(), myHandler); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/PointMerger.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/PointMerger.java index 78b8e866129f..1a58a3c80b68 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/PointMerger.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/PointMerger.java @@ -18,7 +18,6 @@ package org.jetbrains.idea.svn.integrate; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnRevisionNumber; import org.jetbrains.idea.svn.SvnUtil; @@ -88,7 +87,7 @@ public class PointMerger extends Merger { SvnTarget source1 = SvnTarget.fromURL(SVNURL.parseURIEncoded(beforeUrl), ((SvnRevisionNumber)before.getRevisionNumber()).getRevision()); SvnTarget source2 = SvnTarget.fromURL(SVNURL.parseURIEncoded(afterUrl), ((SvnRevisionNumber) after.getRevisionNumber()).getRevision()); - client.merge(source1, source2, afterPath, SVNDepth.FILES, true, mySvnConfig.MERGE_DRY_RUN, false, false, mySvnConfig.getMergeOptions(), + client.merge(source1, source2, afterPath, SVNDepth.FILES, true, mySvnConfig.isMergeDryRun(), false, false, mySvnConfig.getMergeOptions(), myHandler); } @@ -99,7 +98,7 @@ public class PointMerger extends Merger { final File beforePath = SvnUtil.fileFromUrl(myTarget, path, beforeUrl); DeleteClient client = myVcs.getFactory(myTarget).createDeleteClient(); - client.delete(beforePath, false, mySvnConfig.MERGE_DRY_RUN, myHandler); + client.delete(beforePath, false, mySvnConfig.isMergeDryRun(), myHandler); } private void add(final Change change) throws SVNException, VcsException { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/ResolveWorker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/ResolveWorker.java index 45558e440d83..f283afa7550a 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/ResolveWorker.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/ResolveWorker.java @@ -75,7 +75,7 @@ public class ResolveWorker { } return ((! myConflictedVirtualFiles.isEmpty()) || (! haveUnresolvedConflicts(updatedFiles))) && - (! SvnConfiguration.getInstance(myProject).MERGE_DRY_RUN); + (!SvnConfiguration.getInstance(myProject).isMergeDryRun()); } public static boolean haveUnresolvedConflicts(final UpdatedFiles updatedFiles) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesActionPerformer.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesActionPerformer.java index a793aae7b10d..e07fac011c9e 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesActionPerformer.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesActionPerformer.java @@ -69,7 +69,7 @@ public class SvnIntegrateChangesActionPerformer implements SelectBranchPopup.Bra return; } final SvnIntegrateChangesTask task = new SvnIntegrateChangesTask(myVcs, info, myMergerFactory, sourceUrl, SvnBundle.message("action.Subversion.integrate.changes.messages.title"), - SvnConfiguration.getInstance(myVcs.getProject()).MERGE_DRY_RUN, name); + SvnConfiguration.getInstance(myVcs.getProject()).isMergeDryRun(), name); ProgressManager.getInstance().run(task); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java index 39d72f5639fd..f492a434a252 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java @@ -63,7 +63,7 @@ public class OneRecursiveShotMergeInfoWorker implements MergeInfoWorker { } public void prepare() throws VcsException { - final SVNDepth depth = SvnConfiguration.getInstance(myProject).CHECK_NESTED_FOR_QUICK_MERGE ? SVNDepth.INFINITY : SVNDepth.EMPTY; + final SVNDepth depth = SvnConfiguration.getInstance(myProject).isCheckNestedForQuickMerge() ? SVNDepth.INFINITY : SVNDepth.EMPTY; ISVNPropertyHandler handler = new ISVNPropertyHandler() { public void handleProperty(File path, SVNPropertyData property) throws SVNException { final String key = keyFromFile(path); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/MergeFromTheirsResolver.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/MergeFromTheirsResolver.java index cfafc6585e92..31b040cd98dd 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/MergeFromTheirsResolver.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/MergeFromTheirsResolver.java @@ -587,8 +587,8 @@ public class MergeFromTheirsResolver { private boolean getAddedFilesPlaceOption() { final SvnConfiguration configuration = SvnConfiguration.getInstance(myVcs.getProject()); - boolean add = Boolean.TRUE.equals(configuration.TREE_CONFLICT_MERGE_THEIRS_NEW_INTO_OLD_PLACE); - if (configuration.TREE_CONFLICT_MERGE_THEIRS_NEW_INTO_OLD_PLACE != null) { + boolean add = Boolean.TRUE.equals(configuration.isKeepNewFilesAsIsForTreeConflictMerge()); + if (configuration.isKeepNewFilesAsIsForTreeConflictMerge() != null) { return add; } if (!containAdditions(myTheirsChanges) && !containAdditions(myTheirsBinaryChanges)) { @@ -606,10 +606,10 @@ public class MergeFromTheirsResolver { if (!value) { if (exitCode == 0) { // yes - configuration.TREE_CONFLICT_MERGE_THEIRS_NEW_INTO_OLD_PLACE = true; + configuration.setKeepNewFilesAsIsForTreeConflictMerge(true); } else { - configuration.TREE_CONFLICT_MERGE_THEIRS_NEW_INTO_OLD_PLACE = false; + configuration.setKeepNewFilesAsIsForTreeConflictMerge(false); } } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AbstractSvnUpdatePanel.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AbstractSvnUpdatePanel.java index 4c24d69d9d92..0cea23ea3988 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AbstractSvnUpdatePanel.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AbstractSvnUpdatePanel.java @@ -85,7 +85,7 @@ public abstract class AbstractSvnUpdatePanel { } public void reset(final SvnConfiguration configuration) { - getDepthBox().setSelectedItem(configuration.UPDATE_DEPTH); + getDepthBox().setSelectedItem(configuration.getUpdateDepth()); for (FilePath filePath : myRootToPanel.keySet()) { myRootToPanel.get(filePath).reset(configuration); @@ -94,7 +94,7 @@ public abstract class AbstractSvnUpdatePanel { } public void apply(final SvnConfiguration configuration) throws ConfigurationException { - configuration.UPDATE_DEPTH = getDepthBox().getDepth(); + configuration.setUpdateDepth(getDepthBox().getDepth()); for (FilePath filePath : myRootToPanel.keySet()) { final SvnPanel svnPanel = myRootToPanel.get(filePath); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AutoSvnUpdater.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AutoSvnUpdater.java index 0c0e836a10b2..cf424af4ef78 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AutoSvnUpdater.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AutoSvnUpdater.java @@ -47,9 +47,9 @@ public class AutoSvnUpdater extends AbstractCommonUpdateAction { @Override protected void actionPerformed(VcsContext context) { final SvnConfiguration configuration17 = SvnConfiguration.getInstance(myProject); - configuration17.FORCE_UPDATE = false; - configuration17.UPDATE_LOCK_ON_DEMAND = false; - configuration17.UPDATE_DEPTH = SVNDepth.INFINITY; + configuration17.setForceUpdate(false); + configuration17.setUpdateLockOnDemand(false); + configuration17.setUpdateDepth(SVNDepth.INFINITY); final SvnVcs vcs = SvnVcs.getInstance(myProject); for (FilePath root : myRoots) { final UpdateRootInfo info = configuration17.getUpdateRootInfo(root.getIOFile(), vcs); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnIntegrateEnvironment.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnIntegrateEnvironment.java index a01616e5a89d..c8a77f6d50d6 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnIntegrateEnvironment.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnIntegrateEnvironment.java @@ -61,7 +61,7 @@ public class SvnIntegrateEnvironment extends AbstractSvnUpdateIntegrateEnvironme @Override protected boolean isDryRun() { - return SvnConfiguration.getInstance(myVcs.getProject()).MERGE_DRY_RUN; + return SvnConfiguration.getInstance(myVcs.getProject()).isMergeDryRun(); } private static class IntegrateCrawler extends AbstractUpdateIntegrateCrawler { @@ -78,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 { @@ -99,7 +99,7 @@ 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); return info.getResultRevision(); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnIntegratePanel.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnIntegratePanel.java index b01b3790e299..b7f5012ef6a4 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnIntegratePanel.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnIntegratePanel.java @@ -65,13 +65,13 @@ public class SvnIntegratePanel extends AbstractSvnUpdatePanel{ public void reset(final SvnConfiguration configuration) { super.reset(configuration); - myDryRunCheckbox.setSelected(configuration.MERGE_DRY_RUN); - myUseAncestry.setSelected(configuration.MERGE_DIFF_USE_ANCESTRY); + myDryRunCheckbox.setSelected(configuration.isMergeDryRun()); + myUseAncestry.setSelected(configuration.isMergeDiffUseAncestry()); } public void apply(final SvnConfiguration configuration) throws ConfigurationException { super.apply(configuration); - configuration.MERGE_DRY_RUN = myDryRunCheckbox.isSelected(); - configuration.MERGE_DIFF_USE_ANCESTRY = myUseAncestry.isSelected(); + configuration.setMergeDryRun(myDryRunCheckbox.isSelected()); + configuration.setMergeDiffUseAncestry(myUseAncestry.isSelected()); } protected JComponent getPanel() { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateContext.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateContext.java index 3da7e90ad98c..42ba2b58c793 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateContext.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateContext.java @@ -67,7 +67,7 @@ public class SvnUpdateContext implements SequentialUpdatesContext { result = false; } else if (NestedCopyType.external.equals(info.getType())) { - result = !myVcs.getSvnConfiguration().IGNORE_EXTERNALS; + result = !myVcs.getSvnConfiguration().isIgnoreExternals(); } } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java index 00b821f003cc..0bb436a428ee 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java @@ -83,10 +83,11 @@ public class SvnUpdateEnvironment extends AbstractSvnUpdateIntegrateEnvironment if (isSwitch) { final UpdateClient updateClient = createUpdateClient(configuration, root, true, sourceUrl); myHandler.addToSwitch(root, sourceUrl); - rev = updateClient.doSwitch(root, rootInfo.getUrl(), SVNRevision.UNDEFINED, updateTo, configuration.UPDATE_DEPTH, configuration.FORCE_UPDATE, false); + rev = updateClient.doSwitch(root, rootInfo.getUrl(), SVNRevision.UNDEFINED, updateTo, configuration.getUpdateDepth(), + configuration.isForceUpdate(), false); } else { final UpdateClient updateClient = createUpdateClient(configuration, root, false, sourceUrl); - rev = updateClient.doUpdate(root, updateTo, configuration.UPDATE_DEPTH, configuration.FORCE_UPDATE, false); + rev = updateClient.doUpdate(root, updateTo, configuration.getUpdateDepth(), configuration.isForceUpdate(), false); } myPostUpdateFiles.setRevisions(root.getAbsolutePath(), myVcs, new SvnRevisionNumber(SVNRevision.create(rev))); @@ -104,10 +105,10 @@ public class SvnUpdateEnvironment extends AbstractSvnUpdateIntegrateEnvironment final UpdateClient updateClient = factory.createUpdateClient(); if (! isSwitch) { - updateClient.setIgnoreExternals(configuration.IGNORE_EXTERNALS); + updateClient.setIgnoreExternals(configuration.isIgnoreExternals()); } updateClient.setEventHandler(myHandler); - updateClient.setUpdateLocksOnDemand(configuration.UPDATE_LOCK_ON_DEMAND); + updateClient.setUpdateLocksOnDemand(configuration.isUpdateLockOnDemand()); return updateClient; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdatePanel.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdatePanel.java index ab66664f0f82..1aef057dd7e2 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdatePanel.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdatePanel.java @@ -52,24 +52,24 @@ public class SvnUpdatePanel extends AbstractSvnUpdatePanel { myDepthLabel.setLabelFor(myDepthCombo); final SvnConfiguration svnConfiguration = SvnConfiguration.getInstance(myVCS.getProject()); - myLockOnDemand.setSelected(svnConfiguration.UPDATE_LOCK_ON_DEMAND); + myLockOnDemand.setSelected(svnConfiguration.isUpdateLockOnDemand()); myLockOnDemand.addActionListener(new ActionListener() { public void actionPerformed(final ActionEvent e) { - svnConfiguration.UPDATE_LOCK_ON_DEMAND = myLockOnDemand.isSelected(); + svnConfiguration.setUpdateLockOnDemand(myLockOnDemand.isSelected()); } }); - myForceBox.setSelected(svnConfiguration.FORCE_UPDATE); - myIgnoreExternalsCheckBox.setSelected(svnConfiguration.IGNORE_EXTERNALS); + myForceBox.setSelected(svnConfiguration.isForceUpdate()); + myIgnoreExternalsCheckBox.setSelected(svnConfiguration.isIgnoreExternals()); myForceBox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - svnConfiguration.FORCE_UPDATE = myForceBox.isSelected(); + svnConfiguration.setForceUpdate(myForceBox.isSelected()); } }); myIgnoreExternalsCheckBox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - svnConfiguration.IGNORE_EXTERNALS = myIgnoreExternalsCheckBox.isSelected(); + svnConfiguration.setIgnoreExternals(myIgnoreExternalsCheckBox.isSelected()); } }); } diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnMergeInfoTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnMergeInfoTest.java index 956c768c0d8c..528ea0f9e2b8 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnMergeInfoTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnMergeInfoTest.java @@ -64,7 +64,7 @@ public class SvnMergeInfoTest extends Svn17TestCase { myWCInfo = new WCInfo(root, true, SVNDepth.INFINITY); myOneShotMergeInfoHelper = new OneShotMergeInfoHelper(myProject, myWCInfo, myRepoUrl + "/trunk"); - SvnConfiguration.getInstance(myProject).CHECK_NESTED_FOR_QUICK_MERGE = true; + SvnConfiguration.getInstance(myProject).setCheckNestedForQuickMerge(true); // AbstractVcs vcsFound = myProjectLevelVcsManager.findVcsByName(SvnVcs.VCS_NAME); // Assert.assertEquals(1, myProjectLevelVcsManager.getRootsUnderVcs(vcsFound).length); } diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeClientAuthTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeClientAuthTest.java index 7d1e0c88169c..1328b94fd7f0 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeClientAuthTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeClientAuthTest.java @@ -146,7 +146,7 @@ public class SvnNativeClientAuthTest extends Svn17TestCase { final SvnConfiguration instance = SvnConfiguration.getInstance(myProject); clearAuthCache(instance); - Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration); + Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration()); mySaveCredentials = false; updateSimple(wc1); @@ -168,7 +168,7 @@ public class SvnNativeClientAuthTest extends Svn17TestCase { final SvnConfiguration instance = SvnConfiguration.getInstance(myProject); clearAuthCache(instance); - Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration); + Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration()); mySaveCredentials = false; updateSimple(wc1); @@ -192,7 +192,7 @@ public class SvnNativeClientAuthTest extends Svn17TestCase { final SvnConfiguration instance = SvnConfiguration.getInstance(myProject); clearAuthCache(instance); - Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration); + Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration()); mySaveCredentials = true; updateSimple(wc1); @@ -215,7 +215,7 @@ public class SvnNativeClientAuthTest extends Svn17TestCase { final SvnConfiguration instance = SvnConfiguration.getInstance(myProject); clearAuthCache(instance); - Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration); + Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration()); mySaveCredentials = true; updateSimple(wc1); @@ -236,7 +236,7 @@ public class SvnNativeClientAuthTest extends Svn17TestCase { final SvnConfiguration instance = SvnConfiguration.getInstance(myProject); clearAuthCache(instance); - Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration); + Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration()); mySaveCredentials = false; testCommitImpl(wc1); @@ -258,7 +258,7 @@ public class SvnNativeClientAuthTest extends Svn17TestCase { final SvnConfiguration instance = SvnConfiguration.getInstance(myProject); clearAuthCache(instance); - Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration); + Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration()); mySaveCredentials = false; testCommitImpl(wc1); @@ -282,7 +282,7 @@ public class SvnNativeClientAuthTest extends Svn17TestCase { final SvnConfiguration instance = SvnConfiguration.getInstance(myProject); clearAuthCache(instance); - Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration); + Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration()); mySaveCredentials = true; testCommitImpl(wc1); @@ -306,7 +306,7 @@ public class SvnNativeClientAuthTest extends Svn17TestCase { final SvnConfiguration instance = SvnConfiguration.getInstance(myProject); clearAuthCache(instance); - Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration); + Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration()); mySaveCredentials = true; myCertificateAnswer = ISVNAuthenticationProvider.ACCEPTED; @@ -336,7 +336,7 @@ public class SvnNativeClientAuthTest extends Svn17TestCase { final SvnConfiguration instance = SvnConfiguration.getInstance(myProject); clearAuthCache(instance); - Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration); + Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration()); mySaveCredentials = false; myCertificateAnswer = ISVNAuthenticationProvider.ACCEPTED; @@ -371,7 +371,7 @@ public class SvnNativeClientAuthTest extends Svn17TestCase { final SvnConfiguration instance = SvnConfiguration.getInstance(myProject); clearAuthCache(instance); - Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration); + Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration()); mySaveCredentials = true; testCommitImpl(wc1); @@ -392,7 +392,7 @@ public class SvnNativeClientAuthTest extends Svn17TestCase { final SvnConfiguration instance = SvnConfiguration.getInstance(myProject); clearAuthCache(instance); - Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration); + Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration()); mySaveCredentials = false; myCredentialsCorrect = false; @@ -415,7 +415,7 @@ public class SvnNativeClientAuthTest extends Svn17TestCase { final SvnConfiguration instance = SvnConfiguration.getInstance(myProject); clearAuthCache(instance); - Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration); + Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration()); mySaveCredentials = false; myCredentialsCorrect = false; @@ -441,7 +441,7 @@ public class SvnNativeClientAuthTest extends Svn17TestCase { final SvnConfiguration instance = SvnConfiguration.getInstance(myProject); clearAuthCache(instance); - Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration); + Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration()); mySaveCredentials = false; myCertificateAnswer = ISVNAuthenticationProvider.REJECTED; @@ -474,7 +474,7 @@ public class SvnNativeClientAuthTest extends Svn17TestCase { final SvnConfiguration instance = SvnConfiguration.getInstance(myProject); clearAuthCache(instance); - Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration); + Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration()); mySaveCredentials = false; myCredentialsCorrect = false; myCancelAuth = true; @@ -500,7 +500,7 @@ public class SvnNativeClientAuthTest extends Svn17TestCase { final SvnConfiguration instance = SvnConfiguration.getInstance(myProject); clearAuthCache(instance); - Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration); + Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration()); mySaveCredentials = false; myCredentialsCorrect = false; myCancelAuth = true; diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnMergeInfoTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnMergeInfoTest.java index ec8f665ecf05..efbb6b99fe1d 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnMergeInfoTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnMergeInfoTest.java @@ -64,7 +64,7 @@ public class SvnMergeInfoTest extends Svn16TestCase { myWCInfo = new WCInfo(root, true, SVNDepth.INFINITY); myOneShotMergeInfoHelper = new OneShotMergeInfoHelper(myProject, myWCInfo, myRepoUrl + "/trunk"); - SvnConfiguration.getInstance(myProject).CHECK_NESTED_FOR_QUICK_MERGE = true; + SvnConfiguration.getInstance(myProject).setCheckNestedForQuickMerge(true); // AbstractVcs vcsFound = myProjectLevelVcsManager.findVcsByName(SvnVcs.VCS_NAME); // Assert.assertEquals(1, myProjectLevelVcsManager.getRootsUnderVcs(vcsFound).length); } From c0c0136d8b8d36d404f22885906240f8de3cad0e Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 25 Dec 2013 21:30:32 +0400 Subject: [PATCH 30/38] svn: Removed unused "PASSWORD" configuration parameter --- .../svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java index da5d470a4e06..76c31ebdd863 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java @@ -62,8 +62,6 @@ public class SvnConfiguration implements PersistentStateComponent { public static final String CLEANUP_ON_START_RUN = "cleanupOnStartRun"; private final Project myProject; - public String PASSWORD = ""; - private String myConfigurationDirectory; private boolean myIsUseDefaultConfiguration; private boolean myIsUseDefaultProxy; @@ -81,6 +79,8 @@ public class SvnConfiguration implements PersistentStateComponent { public long mySSHReadTimeout = DEFAULT_SSH_TIMEOUT; public static final AuthStorage RUNTIME_AUTH_CACHE = new AuthStorage(); + // 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; From 00af757e0d7fc347ee34dd6b35cdbba9e673034e Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 25 Dec 2013 21:42:42 +0400 Subject: [PATCH 31/38] svn: Refactored SvnConfiguration - removed old compatibility logic for "checkout urls" config parameter (which was moved from workspace file to app config) --- .../src/org/jetbrains/idea/svn/SvnConfiguration.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java index 76c31ebdd863..5e0d86fcac98 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java @@ -469,15 +469,6 @@ public class SvnConfiguration implements PersistentStateComponent { else { myIsUseDefaultConfiguration = true; } - // compatibility: this setting was moved from .iws to global settings - List urls = element.getChildren("checkoutURL"); - for (Object url1 : urls) { - Element child = (Element)url1; - String url = child.getText(); - if (url != null) { - SvnApplicationSettings.getInstance().addCheckoutURL(url); - } - } myIsKeepLocks = element.getChild("keepLocks") != null; final Element useProxy = element.getChild("myIsUseDefaultProxy"); if (useProxy == null) { From 8ebc84d9c30854fbc031aa5dba2b773327a2f421 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Fri, 27 Dec 2013 16:19:59 +0400 Subject: [PATCH 32/38] svn: Refactored SvnConfiguration - encapsulated "myUseAcceleration" (in tests) --- .../testSource/org/jetbrains/idea/SvnTestCase.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/SvnTestCase.java b/plugins/svn4idea/testSource/org/jetbrains/idea/SvnTestCase.java index 00d96b882013..17ae6b5ce551 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/SvnTestCase.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/SvnTestCase.java @@ -20,7 +20,6 @@ import com.intellij.ide.startup.impl.StartupManagerImpl; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.DataContext; -import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.actionSystem.Presentation; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.PathManager; @@ -71,9 +70,7 @@ import java.io.File; import java.io.IOException; import java.util.*; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; /** * @author yole @@ -219,7 +216,7 @@ public abstract class SvnTestCase extends AbstractJunitVcsTestCase { @Override protected void projectCreated() { if (isUseNativeAcceleration()) { - SvnConfiguration.getInstance(myProject).myUseAcceleration = SvnConfiguration.UseAcceleration.commandLine; + SvnConfiguration.getInstance(myProject).setUseAcceleration(SvnConfiguration.UseAcceleration.commandLine); SvnApplicationSettings.getInstance().setCommandLinePath(myClientBinaryPath + File.separator + "svn"); } } @@ -618,8 +615,8 @@ public abstract class SvnTestCase extends AbstractJunitVcsTestCase { protected void setNativeAcceleration(final boolean value) { System.out.println("Set native acceleration to " + value); - SvnConfiguration.getInstance(myProject).myUseAcceleration = - value ? SvnConfiguration.UseAcceleration.commandLine : SvnConfiguration.UseAcceleration.nothing; + SvnConfiguration.getInstance(myProject).setUseAcceleration( + value ? SvnConfiguration.UseAcceleration.commandLine : SvnConfiguration.UseAcceleration.nothing); SvnApplicationSettings.getInstance().setCommandLinePath(myClientBinaryPath + File.separator + "svn"); } } From 536608dc3032ad76888243c0d488166cf57c7688 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Fri, 27 Dec 2013 21:06:12 +0400 Subject: [PATCH 33/38] IDEA-54304 svn: Take user name (if any) from repository url when first initializing auth data for SSH protocol --- .../idea/svn/SvnAuthenticationManager.java | 35 +++++++++++++++++++ .../SvnInteractiveAuthenticationProvider.java | 3 +- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java index eafa2a8c9f9f..0597ea1ac91a 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java @@ -32,6 +32,7 @@ import com.intellij.openapi.vcs.CalledInAwt; import com.intellij.openapi.vcs.changes.committed.AbstractCalledLater; import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier; import com.intellij.util.EventDispatcher; +import com.intellij.util.SystemProperties; import com.intellij.util.messages.Topic; import com.intellij.util.net.HttpConfigurable; import com.intellij.util.proxy.CommonProxy; @@ -119,6 +120,40 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im }); } + public String getDefaultUsername(String kind, SVNURL url) { + String result = SystemProperties.getUserName(); + + // USERNAME authentication is also requested in SVNSSHConnector.open() + if (ISVNAuthenticationManager.SSH.equals(kind) || + (ISVNAuthenticationManager.USERNAME.equals(kind) && SVN_SSH.equals(url.getProtocol()))) { + result = url != null && !StringUtil.isEmpty(url.getUserInfo()) ? url.getUserInfo() : getDefaultOptions().getDefaultSSHUserName(); + } + + return result; + } + + @Override + protected SVNSSHAuthentication getDefaultSSHAuthentication(SVNURL url) { + String userName = getDefaultUsername(ISVNAuthenticationManager.SSH, url); + + // This is fully copied from base class - DefaultSVNAuthenticationManager - as there are no setters in Authentication classes + // and there is no url parameter if overriding getDefaultOptions() + String password = getDefaultOptions().getDefaultSSHPassword(); + String keyFile = getDefaultOptions().getDefaultSSHKeyFile(); + int port = getDefaultOptions().getDefaultSSHPortNumber(); + String passphrase = getDefaultOptions().getDefaultSSHPassphrase(); + + if (userName != null && password != null) { + return new SVNSSHAuthentication(userName, password, port, getHostOptionsProvider().getHostOptions(url).isAuthStorageEnabled(), url, + false); + } + else if (userName != null && keyFile != null) { + return new SVNSSHAuthentication(userName, new File(keyFile), passphrase, port, + getHostOptionsProvider().getHostOptions(url).isAuthStorageEnabled(), url, false); + } + return null; + } + private class AuthenticationProviderProxy implements ISVNAuthenticationProvider { private final ISVNAuthenticationProvider myDelegate; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnInteractiveAuthenticationProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnInteractiveAuthenticationProvider.java index 37b4f9d0448a..e82b22c59dbf 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnInteractiveAuthenticationProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnInteractiveAuthenticationProvider.java @@ -23,7 +23,6 @@ import com.intellij.openapi.project.Project; 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.idea.svn.SvnAuthenticationManager; import org.jetbrains.idea.svn.SvnBundle; @@ -81,7 +80,7 @@ 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() { From c08341d8efa58a108bc2f541d2eb5531d522a4c8 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Mon, 30 Dec 2013 14:44:45 +0400 Subject: [PATCH 34/38] svn: Refactored SvnInteractiveAuthenticationProvider - removed duplication (for setting dialog title logic) --- .../SvnInteractiveAuthenticationProvider.java | 37 +++++++------------ 1 file changed, 13 insertions(+), 24 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnInteractiveAuthenticationProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnInteractiveAuthenticationProvider.java index e82b22c59dbf..5be10cf05fbb 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnInteractiveAuthenticationProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnInteractiveAuthenticationProvider.java @@ -20,10 +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.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; @@ -86,12 +89,7 @@ public class SvnInteractiveAuthenticationProvider implements ISVNAuthenticationP 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); @@ -107,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); @@ -124,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(); @@ -157,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()), @@ -183,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; From c6a925275297faea3498268b6384e31c6001b105 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Mon, 30 Dec 2013 16:15:45 +0400 Subject: [PATCH 35/38] IDEA-54304 svn: Do not explicitly save/load port in branch configuration if default port value is specified --- .../idea/svn/SvnBranchConfigurationManager.java | 10 ++++++---- .../src/org/jetbrains/idea/svn/SvnUtil.java | 13 +++++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfigurationManager.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfigurationManager.java index 201a10f004b5..65e9028c8185 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfigurationManager.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfigurationManager.java @@ -295,7 +295,7 @@ public class SvnBranchConfigurationManager implements PersistentStateComponent withUserInfo) { + private static String serializeUrl(final String url, final Ref withUserInfo) { if (Boolean.FALSE.equals(withUserInfo.get())) { return url; } @@ -306,7 +306,8 @@ public class SvnBranchConfigurationManager implements PersistentStateComponent 0)); } if (withUserInfo.get()) { - return SVNURL.create(svnurl.getProtocol(), null, svnurl.getHost(), svnurl.getPort(), svnurl.getURIEncodedPath(), true).toString(); + return SVNURL.create(svnurl.getProtocol(), null, svnurl.getHost(), SvnUtil.resolvePort(svnurl), svnurl.getURIEncodedPath(), true) + .toString(); } } catch (SVNException e) { @@ -321,10 +322,11 @@ public class SvnBranchConfigurationManager implements PersistentStateComponent Date: Mon, 30 Dec 2013 16:59:02 +0400 Subject: [PATCH 36/38] IDEA-54304 svn: Refactored BranchConfigurationDialog - use SVNURL instances for validation (and not just string values) --- .../src/org/jetbrains/idea/svn/SvnUtil.java | 13 +++++ .../dialogs/BranchConfigurationDialog.java | 51 +++++++++++++------ 2 files changed, 49 insertions(+), 15 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java index 5ad0ab3e6070..938176020207 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java @@ -786,6 +786,19 @@ public class SvnUtil { return !hasDefaultPort(url) ? url.getPort() : DEFAULT_PORT_INDICATOR; } + @NotNull + public static SVNURL createUrl(@NotNull String url) throws SVNException { + SVNURL result = SVNURL.parseURIEncoded(url); + + // explicitly check if port corresponds to default port and recreate url specifying default port indicator + if (result.hasPort() && hasDefaultPort(result)) { + result = SVNURL + .create(result.getProtocol(), result.getUserInfo(), result.getHost(), DEFAULT_PORT_INDICATOR, result.getURIEncodedPath(), true); + } + + return result; + } + public static SVNURL parseUrl(@NotNull String url) { try { return SVNURL.parseURIEncoded(url); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java index 221ba2abbce2..32b1dae809ed 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java @@ -35,6 +35,9 @@ import org.jetbrains.idea.svn.branchConfig.InfoStorage; import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigManager; import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew; import org.jetbrains.idea.svn.integrate.SvnBranchItem; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNURL; +import org.tmatesoft.svn.core.internal.util.SVNURLUtil; import javax.swing.*; import javax.swing.event.DocumentEvent; @@ -57,7 +60,11 @@ public class BranchConfigurationDialog extends DialogWrapper { private final SvnBranchConfigManager mySvnBranchConfigManager; private final VirtualFile myRoot; - public BranchConfigurationDialog(@NotNull final Project project, @NotNull final SvnBranchConfigurationNew configuration, final @NotNull String rootUrl, @NotNull final VirtualFile root, @NotNull String url) { + public BranchConfigurationDialog(@NotNull final Project project, + @NotNull final SvnBranchConfigurationNew configuration, + final @NotNull SVNURL rootUrl, + @NotNull final VirtualFile root, + @NotNull String url) { super(project, true); myRoot = root; init(); @@ -95,7 +102,7 @@ public class BranchConfigurationDialog extends DialogWrapper { .setAddAction(new AnActionButtonRunnable() { @Override public void run(AnActionButton button) { - final String selectedUrl = SelectLocationDialog.selectLocation(project, rootUrl); + final String selectedUrl = SelectLocationDialog.selectLocation(project, rootUrl.toDecodedString()); if (selectedUrl != null) { if (!configuration.getBranchUrls().contains(selectedUrl)) { configuration @@ -127,27 +134,41 @@ public class BranchConfigurationDialog extends DialogWrapper { } private class TrunkUrlValidator extends DocumentAdapter { - private final String myRootUrl; - private final String myRootUrlPrefix; + private final SVNURL myRootUrl; private final SvnBranchConfigurationNew myConfiguration; - private TrunkUrlValidator(final String rootUrl, final SvnBranchConfigurationNew configuration) { + private TrunkUrlValidator(final SVNURL rootUrl, final SvnBranchConfigurationNew configuration) { myRootUrl = rootUrl; - myRootUrlPrefix = rootUrl + "/"; myConfiguration = configuration; } protected void textChanged(final DocumentEvent e) { - final String currentValue = myTrunkLocationTextField.getText(); - final boolean valueOk = (currentValue != null) && (currentValue.equals(myRootUrl) || currentValue.startsWith(myRootUrlPrefix)); - final boolean prefixOk = (currentValue != null) && (currentValue.startsWith(myRootUrlPrefix)) && - (currentValue.length() > myRootUrlPrefix.length()); + SVNURL url = parseUrl(myTrunkLocationTextField.getText()); - myTrunkLocationTextField.getButton().setEnabled(valueOk); - if (prefixOk) { - myConfiguration.setTrunkUrl(currentValue.endsWith("/") ? currentValue.substring(0, currentValue.length() - 1) : currentValue); + if (url != null) { + boolean isAncestor = SVNURLUtil.isAncestor(myRootUrl, url); + boolean areNotSame = isAncestor && !url.equals(myRootUrl); + + myTrunkLocationTextField.getButton().setEnabled(isAncestor); + if (areNotSame) { + myConfiguration.setTrunkUrl(url.toDecodedString()); + } + myErrorPrompt.setText(areNotSame ? "" : SvnBundle.message("configure.branches.error.wrong.url", myRootUrl)); } - myErrorPrompt.setText(prefixOk ? "" : SvnBundle.message("configure.branches.error.wrong.url", myRootUrl)); + } + + @Nullable + private SVNURL parseUrl(@NotNull String url) { + SVNURL result = null; + + try { + result = SvnUtil.createUrl(url); + } + catch (SVNException e) { + myErrorPrompt.setText(e.getMessage()); + } + + return result; } } @@ -180,7 +201,7 @@ public class BranchConfigurationDialog extends DialogWrapper { if (wcRoot == null) { return; } - final String rootUrl = wcRoot.getRepositoryUrl(); + final SVNURL rootUrl = wcRoot.getRepositoryUrlUrl(); if (rootUrl == null) { Messages.showErrorDialog(project, SvnBundle.message("configure.branches.error.no.connection.title"), SvnBundle.message("configure.branches.title")); From df5655ccfa9e87a044763cc27b5dae6adbd3088e Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Mon, 30 Dec 2013 18:31:10 +0400 Subject: [PATCH 37/38] IDEA-118908 svn: Fixed url validation for "Merge From" action to use SVNURL instances (instead of just strings) --- .../idea/svn/dialogs/QuickMerge.java | 22 ++++++++++++++++++- .../idea/svn/history/FirstInBranch.java | 3 +++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java index faea29510d79..20077fc42e34 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java @@ -60,6 +60,7 @@ import org.tmatesoft.svn.core.SVNLogEntry; import org.tmatesoft.svn.core.SVNLogEntryPath; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.internal.util.SVNPathUtil; +import org.tmatesoft.svn.core.internal.util.SVNURLUtil; import java.io.File; import java.io.IOException; @@ -115,7 +116,12 @@ public class QuickMerge { @Override public void run(ContinuationContext continuationContext) { - if (SVNPathUtil.isAncestor(mySourceUrl, myWcInfo.getRootUrl()) || SVNPathUtil.isAncestor(myWcInfo.getRootUrl(), mySourceUrl)) { + SVNURL url = parseUrl(continuationContext); + if (url == null) { + return; + } + + if (SVNURLUtil.isAncestor(url, myWcInfo.getUrl()) || SVNURLUtil.isAncestor(myWcInfo.getUrl(), url)) { finishWithError(continuationContext, "Cannot merge from self", true); return; } @@ -124,6 +130,20 @@ public class QuickMerge { continuationContext.cancelEverything(); } } + + @Nullable + private SVNURL parseUrl(ContinuationContext continuationContext) { + SVNURL url = null; + + try { + url = SvnUtil.createUrl(mySourceUrl); + } + catch (SVNException e) { + finishWithError(continuationContext, e.getMessage(), true); + } + + return url; + } } private class CheckRepositorySupportsMergeinfo extends TaskDescriptor { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java index d19ed02f07c1..7fb35d14ca4d 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java @@ -30,6 +30,9 @@ import org.tmatesoft.svn.core.wc.SVNRevision; import java.util.Map; import java.util.Set; +// TODO: This one seem to determine revision in which branch was created - copied from trunk. +// TODO: This could be done in one command "svn log -r 0:HEAD --stop-on-copy --limit 1". +// TODO: Check for 1.7 and rewrite using this approach. public class FirstInBranch implements Runnable { private final SvnVcs myVcs; private final String myBranchUrl; From 6a073c9fffa5f1552c24feaf8808bbba7228c818 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Mon, 30 Dec 2013 20:31:52 +0400 Subject: [PATCH 38/38] xml serialization: Support null values in fields marked as @Attribute (do not add corresponding attribute to output if value is null) --- platform/util/src/com/intellij/util/xmlb/AttributeBinding.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform/util/src/com/intellij/util/xmlb/AttributeBinding.java b/platform/util/src/com/intellij/util/xmlb/AttributeBinding.java index 0206a54e02ea..13c0e80b0be6 100644 --- a/platform/util/src/com/intellij/util/xmlb/AttributeBinding.java +++ b/platform/util/src/com/intellij/util/xmlb/AttributeBinding.java @@ -35,6 +35,8 @@ public class AttributeBinding implements Binding { @Override public Object serialize(@NotNull Object o, Object context, SerializationFilter filter) { final Object v = myAccessor.read(o); + if (v == null) return context; + final Object node = myBinding.serialize(v, context, filter); return new org.jdom.Attribute(myAttribute.value(), ((Content)node).getValue());