diff options
Diffstat (limited to 'plugins/svn4idea/src')
47 files changed, 1032 insertions, 490 deletions
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/NestedCopiesBuilder.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/NestedCopiesBuilder.java index d0eafb77bc4b..062666fbd402 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/NestedCopiesBuilder.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/NestedCopiesBuilder.java @@ -86,6 +86,10 @@ public class NestedCopiesBuilder implements StatusReceiver { } } + @Override + public void finish() { + } + public Set<NestedCopyInfo> getCopies() { return mySet; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusReceiver.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusReceiver.java index ac165c48f5c3..f6515de0ebf1 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusReceiver.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusReceiver.java @@ -29,4 +29,5 @@ public interface StatusReceiver extends EventListener { void processUnversioned(final VirtualFile vFile); void processCopyRoot(VirtualFile file, SVNURL url, WorkingCopyFormat format, SVNURL rootURL); void bewareRoot(VirtualFile vf, SVNURL url); + void finish(); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusWalkerPartner.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusWalkerPartner.java index 367ae1bc4619..690eb1e76ee3 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusWalkerPartner.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusWalkerPartner.java @@ -15,12 +15,11 @@ */ package org.jetbrains.idea.svn; -import com.intellij.lifecycle.PeriodicalTasksCloser; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.roots.FileIndexFacade; import com.intellij.openapi.util.Computable; +import com.intellij.openapi.vcs.ProjectLevelVcsManager; import com.intellij.openapi.vcs.changes.ChangeListManager; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; @@ -34,14 +33,14 @@ import org.tmatesoft.svn.core.wc.ISVNStatusFileProvider; public class StatusWalkerPartner { private final SvnVcs myVcs; private final ChangeListManager myClManager; - private final FileIndexFacade myExcludedFileIndex; + private final ProjectLevelVcsManager myVcsManager; private final ProgressIndicator myIndicator; private ISVNStatusFileProvider myFileProvider; public StatusWalkerPartner(final SvnVcs vcs, final ProgressIndicator pi) { myVcs = vcs; myClManager = ChangeListManager.getInstance(myVcs.getProject()); - myExcludedFileIndex = PeriodicalTasksCloser.getInstance().safeGetService(myVcs.getProject(), FileIndexFacade.class); + myVcsManager = ProjectLevelVcsManager.getInstance(myVcs.getProject()); myIndicator = pi; } @@ -75,12 +74,12 @@ public class StatusWalkerPartner { } } - public boolean isExcluded(final VirtualFile vFile) { + public boolean isIgnoredByVcs(final VirtualFile vFile) { return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() { @Override public Boolean compute() { if (myVcs.getProject().isDisposed()) throw new ProcessCanceledException(); - return myExcludedFileIndex.isExcludedFile(vFile); + return myVcsManager.isIgnored(vFile); } }); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java index 073826f6b035..41461ed623c6 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java @@ -95,6 +95,8 @@ public class SvnChangeProvider implements ChangeProvider { walker.go(item.getDir(), Depth.IMMEDIATES); } + statusReceiver.getMulticaster().finish(); + processCopiedAndDeleted(context, dirtyScope); processUnsaved(dirtyScope, addGate, context); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProviderContext.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProviderContext.java index 716abbe1b20b..9ae90c722cb3 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProviderContext.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProviderContext.java @@ -23,6 +23,7 @@ import com.intellij.openapi.vcs.*; import com.intellij.openapi.vcs.changes.*; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.actions.AbstractShowPropertiesDiffAction; @@ -48,6 +49,7 @@ class SvnChangeProviderContext implements StatusReceiver { private Map<FilePath, String> myCopyFromURLs = null; private final SvnVcs myVcs; private final SvnBranchConfigurationManager myBranchConfigurationManager; + private final List<File> filesToRefresh = ContainerUtil.newArrayList(); private final ProgressIndicator myProgress; @@ -79,6 +81,11 @@ class SvnChangeProviderContext implements StatusReceiver { public void bewareRoot(VirtualFile vf, SVNURL url) { } + @Override + public void finish() { + LocalFileSystem.getInstance().refreshIoFiles(filesToRefresh, true, false, null); + } + public ChangelistBuilder getBuilder() { return myChangelistBuilder; } @@ -302,7 +309,7 @@ class SvnChangeProviderContext implements StatusReceiver { * * @param filePath the path of a changed file. */ - private static void loadEntriesFile(final FilePath filePath) { + private void loadEntriesFile(final FilePath filePath) { final FilePath parentPath = filePath.getParentPath(); if (parentPath == null) { return; @@ -313,9 +320,11 @@ class SvnChangeProviderContext implements StatusReceiver { } } - private static void refreshDotSvnAndEntries(FilePath filePath) { + private void refreshDotSvnAndEntries(FilePath filePath) { final File svn = new File(filePath.getPath(), SvnUtil.SVN_ADMIN_DIR_NAME); - LocalFileSystem.getInstance().refreshIoFiles(Arrays.asList(svn, new File(svn, SvnUtil.ENTRIES_FILE_NAME)), true, false, null); + + filesToRefresh.add(svn); + filesToRefresh.add(new File(svn, SvnUtil.ENTRIES_FILE_NAME)); } // seems here we can only have a tree conflict; which can be marked on either path (?) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnDiffProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnDiffProvider.java index 49ea87d44f6e..5f5edd12eea7 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnDiffProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnDiffProvider.java @@ -34,14 +34,14 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.commandLine.SvnBindException; import org.jetbrains.idea.svn.history.LatestExistentSearcher; -import org.jetbrains.idea.svn.info.InfoConsumer; import org.jetbrains.idea.svn.info.Info; +import org.jetbrains.idea.svn.info.InfoConsumer; +import org.jetbrains.idea.svn.properties.PropertyValue; import org.jetbrains.idea.svn.status.Status; import org.jetbrains.idea.svn.status.StatusType; import org.tmatesoft.svn.core.SVNException; -import org.tmatesoft.svn.core.SVNPropertyValue; import org.tmatesoft.svn.core.SVNURL; -import org.tmatesoft.svn.core.wc.*; +import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; import java.io.File; @@ -162,11 +162,12 @@ public class SvnDiffProvider extends DiffProviderEx implements DiffProvider, Dif } } + @Nullable private String getCommitMessage(File path) throws VcsException { - SVNPropertyData property = + PropertyValue property = myVcs.getFactory(path).createPropertyClient().getProperty(SvnTarget.fromFile(path), COMMIT_MESSAGE, true, SVNRevision.BASE); - return property != null ? SVNPropertyValue.getPropertyAsString(property.getValue()) : null; + return PropertyValue.toString(property); } private static ItemLatestState defaultResult() { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnEditFileProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnEditFileProvider.java index 64248892614a..c8b47aa0928e 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnEditFileProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnEditFileProvider.java @@ -19,7 +19,7 @@ import com.intellij.openapi.vcs.EditFileProvider; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.idea.svn.properties.PropertyClient; -import org.tmatesoft.svn.core.wc.SVNPropertyData; +import org.jetbrains.idea.svn.properties.PropertyValue; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; @@ -42,10 +42,10 @@ public class SvnEditFileProvider implements EditFileProvider { ioFiles[i] = new File(files[i].getPath()); PropertyClient client = myVCS.getFactory(ioFiles[i]).createPropertyClient(); - SVNPropertyData property = client.getProperty(SvnTarget.fromFile(ioFiles[i], SVNRevision.WORKING), SvnPropertyKeys.SVN_NEEDS_LOCK, + PropertyValue property = client.getProperty(SvnTarget.fromFile(ioFiles[i], SVNRevision.WORKING), SvnPropertyKeys.SVN_NEEDS_LOCK, false, SVNRevision.WORKING); - if (property == null || property.getValue() == null) { + if (property == null) { throw new VcsException(SvnBundle.message("exception.text.file.miss.svn", ioFiles[i].getName())); } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java index 1719f781a34a..977c6add0c1f 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java @@ -15,122 +15,15 @@ */ package org.jetbrains.idea.svn; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.diagnostic.Logger; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.tmatesoft.svn.core.SVNErrorCode; -import org.tmatesoft.svn.core.SVNErrorMessage; import org.tmatesoft.svn.core.SVNException; -import org.tmatesoft.svn.core.internal.wc.admin.ISVNAdminAreaFactorySelector; import org.tmatesoft.svn.core.internal.wc.admin.SVNAdminAreaFactory; import org.tmatesoft.svn.core.internal.wc2.SvnWcGeneration; import org.tmatesoft.svn.core.wc2.SvnOperationFactory; import java.io.File; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -public class SvnFormatSelector implements ISVNAdminAreaFactorySelector { - - private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.SvnFormatSelector"); - - public Collection getEnabledFactories(File path, Collection factories, boolean writeAccess) throws SVNException { - if (ApplicationManager.getApplication().isUnitTestMode()) { - return factories; - } - - if (! writeAccess) { - return factories; - } - - Collection result = null; - final WorkingCopyFormat presetFormat = SvnWorkingCopyFormatHolder.getPresetFormat(); - if (presetFormat != null) { - result = format2Factories(presetFormat, factories); - } - - if (result == null) { - final WorkingCopyFormat format = getWorkingCopyFormat(path); - result = format2Factories(format, factories); - } - - if (result == null) { - throw new SVNException(SVNErrorMessage.create(SVNErrorCode.WC_NOT_DIRECTORY)); - } - return result; - } - - @Nullable - static Collection format2Factories(final WorkingCopyFormat format, final Collection factories) { - if (WorkingCopyFormat.ONE_DOT_SEVEN.equals(format)) { - return factories; - } else if (WorkingCopyFormat.ONE_DOT_SIX.equals(format)) { - return factoriesFor16(factories); - } else if (WorkingCopyFormat.ONE_DOT_FIVE.equals(format)) { - return factoriesFor15(factories); - } else if (WorkingCopyFormat.ONE_DOT_FOUR.equals(format)) { - return factoriesFor14(factories); - } else if (WorkingCopyFormat.ONE_DOT_THREE.equals(format)) { - return factoriesFor13(factories); - } - return null; - } - - private static Collection<SVNAdminAreaFactory> factoriesFor13(final Collection factories) { - for (Iterator iterator = factories.iterator(); iterator.hasNext();) { - final SVNAdminAreaFactory factory = (SVNAdminAreaFactory) iterator.next(); - final int supportedVersion = factory.getSupportedVersion(); - if (WorkingCopyFormat.ONE_DOT_THREE.getFormat() == supportedVersion) { - return Collections.singletonList(factory); - } - } - return Collections.emptyList(); - } - - private static Collection<SVNAdminAreaFactory> factoriesFor14(final Collection factories) { - final Collection<SVNAdminAreaFactory> result = new ArrayList<SVNAdminAreaFactory>(2); - for (Iterator iterator = factories.iterator(); iterator.hasNext();) { - final SVNAdminAreaFactory factory = (SVNAdminAreaFactory) iterator.next(); - final int supportedVersion = factory.getSupportedVersion(); - if ((WorkingCopyFormat.ONE_DOT_FOUR.getFormat() == supportedVersion) || - (WorkingCopyFormat.ONE_DOT_THREE.getFormat() == supportedVersion)) { - result.add(factory); - } - } - return result; - } - - private static Collection<SVNAdminAreaFactory> factoriesFor15(final Collection factories) { - final Collection<SVNAdminAreaFactory> result = new ArrayList<SVNAdminAreaFactory>(2); - for (Iterator iterator = factories.iterator(); iterator.hasNext();) { - final SVNAdminAreaFactory factory = (SVNAdminAreaFactory) iterator.next(); - final int supportedVersion = factory.getSupportedVersion(); - if ((WorkingCopyFormat.ONE_DOT_FOUR.getFormat() == supportedVersion) || - (WorkingCopyFormat.ONE_DOT_THREE.getFormat() == supportedVersion) || - (WorkingCopyFormat.ONE_DOT_FIVE.getFormat() == supportedVersion)) { - result.add(factory); - } - } - return result; - } - - private static Collection<SVNAdminAreaFactory> factoriesFor16(final Collection factories) { - final Collection<SVNAdminAreaFactory> result = new ArrayList<SVNAdminAreaFactory>(2); - for (Iterator iterator = factories.iterator(); iterator.hasNext();) { - final SVNAdminAreaFactory factory = (SVNAdminAreaFactory) iterator.next(); - final int supportedVersion = factory.getSupportedVersion(); - if ((WorkingCopyFormat.ONE_DOT_FOUR.getFormat() == supportedVersion) || - (WorkingCopyFormat.ONE_DOT_THREE.getFormat() == supportedVersion) || - (WorkingCopyFormat.ONE_DOT_FIVE.getFormat() == supportedVersion) || - (WorkingCopyFormat.ONE_DOT_SIX.getFormat() == supportedVersion)) { - result.add(factory); - } - } - return result; - } +public class SvnFormatSelector { @NotNull public static WorkingCopyFormat findRootAndGetFormat(final File path) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java index 1b1cd00589d0..13c15b23efa8 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java @@ -103,7 +103,7 @@ public class SvnRecursiveStatusWalker { if (e.contains(SVNErrorCode.WC_NOT_DIRECTORY) || e.contains(SVNErrorCode.WC_NOT_FILE)) { final VirtualFile virtualFile = path.getVirtualFile(); if (virtualFile != null) { - if (! myPartner.isExcluded(virtualFile)) { + if (! myPartner.isIgnoredByVcs(virtualFile)) { // self is unversioned myReceiver.processUnversioned(virtualFile); @@ -184,15 +184,20 @@ public class SvnRecursiveStatusWalker { } }; if (Depth.EMPTY.equals(newDepth)) { - directoryFilter = Processor.TRUE; + // just process immediate children - so only root directory itself should satisfy filter + directoryFilter = new Processor<File>() { + @Override + public boolean process(File file) { + return FileUtil.filesEqual(ioFile, file); + } + }; processor = new Processor<File>() { @Override public boolean process(File file) { - // here we deal only with immediate children - so ignored on IDEA level for children is not important - we nevertheless do not go into - // other levels - if (! FileUtil.filesEqual(ioFile, file)) return true; - if (! FileUtil.filesEqual(ioFile, file.getParentFile())) return false; - return checkDirProcessor.process(file); + // TODO: check if we should still call checkDirProcessor() here - or we really could not check ignore settings but just call + // TODO: myReceiver.processUnversioned() for all immediate children + // here we deal only with immediate children - so ignored on IDEA level for children is not important + return FileUtil.filesEqual(ioFile, file) || checkDirProcessor.process(file); } }; } else { @@ -278,7 +283,7 @@ public class SvnRecursiveStatusWalker { @Override public Boolean compute() { if (myProject.isDisposed()) return null; - return myPartner.isExcluded(vFile); + return myPartner.isIgnoredByVcs(vFile); } }); if (Boolean.TRUE.equals(excluded)) return; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java index 5010ac580750..b44fd16f979f 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java @@ -81,6 +81,8 @@ import org.jetbrains.idea.svn.history.SvnHistoryProvider; import org.jetbrains.idea.svn.info.Info; import org.jetbrains.idea.svn.info.InfoConsumer; import org.jetbrains.idea.svn.properties.PropertyClient; +import org.jetbrains.idea.svn.properties.PropertyData; +import org.jetbrains.idea.svn.properties.PropertyValue; import org.jetbrains.idea.svn.rollback.SvnRollbackEnvironment; import org.jetbrains.idea.svn.status.Status; import org.jetbrains.idea.svn.status.StatusType; @@ -89,7 +91,6 @@ import org.jetbrains.idea.svn.update.SvnIntegrateEnvironment; import org.jetbrains.idea.svn.update.SvnUpdateEnvironment; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.internal.wc.SVNAdminUtil; -import org.tmatesoft.svn.core.wc.SVNPropertyData; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; @@ -108,8 +109,8 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> { private static final VcsKey ourKey = createKey(VCS_NAME); public static final Topic<Runnable> WC_CONVERTED = new Topic<Runnable>("WC_CONVERTED", Runnable.class); - private final Map<String, Map<String, Pair<SVNPropertyValue, Trinity<Long, Long, Long>>>> myPropertyCache = - new SoftHashMap<String, Map<String, Pair<SVNPropertyValue, Trinity<Long, Long, Long>>>>(); + private final Map<String, Map<String, Pair<PropertyValue, Trinity<Long, Long, Long>>>> myPropertyCache = + new SoftHashMap<String, Map<String, Pair<PropertyValue, Trinity<Long, Long, Long>>>>(); private final SvnConfiguration myConfiguration; private final SvnEntriesFileListener myEntriesFileListener; @@ -567,9 +568,9 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> { } @Nullable - public SVNPropertyValue getPropertyWithCaching(final VirtualFile file, final String propName) throws VcsException { - Map<String, Pair<SVNPropertyValue, Trinity<Long, Long, Long>>> cachedMap = myPropertyCache.get(keyForVf(file)); - final Pair<SVNPropertyValue, Trinity<Long, Long, Long>> cachedValue = cachedMap == null ? null : cachedMap.get(propName); + public PropertyValue getPropertyWithCaching(final VirtualFile file, final String propName) throws VcsException { + Map<String, Pair<PropertyValue, Trinity<Long, Long, Long>>> cachedMap = myPropertyCache.get(keyForVf(file)); + final Pair<PropertyValue, Trinity<Long, Long, Long>> cachedValue = cachedMap == null ? null : cachedMap.get(propName); final File ioFile = new File(file.getPath()); final Trinity<Long, Long, Long> tsTrinity = getTimestampForPropertiesChange(ioFile, file.isDirectory()); @@ -582,17 +583,16 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> { } PropertyClient client = getFactory(ioFile).createPropertyClient(); - final SVNPropertyData value = client.getProperty(SvnTarget.fromFile(ioFile, SVNRevision.WORKING), propName, false, SVNRevision.WORKING); - final SVNPropertyValue propValue = value == null ? null : value.getValue(); + final PropertyValue value = client.getProperty(SvnTarget.fromFile(ioFile, SVNRevision.WORKING), propName, false, SVNRevision.WORKING); if (cachedMap == null) { - cachedMap = new HashMap<String, Pair<SVNPropertyValue, Trinity<Long, Long, Long>>>(); + cachedMap = new HashMap<String, Pair<PropertyValue, Trinity<Long, Long, Long>>>(); myPropertyCache.put(keyForVf(file), cachedMap); } - cachedMap.put(propName, Pair.create(propValue, tsTrinity)); + cachedMap.put(propName, Pair.create(value, tsTrinity)); - return propValue; + return value; } @Override diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/AbstractShowPropertiesDiffAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/AbstractShowPropertiesDiffAction.java index 97e6a618ba7c..395dc36b7371 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/AbstractShowPropertiesDiffAction.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/AbstractShowPropertiesDiffAction.java @@ -19,12 +19,15 @@ import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.diff.DiffManager; import com.intellij.openapi.diff.SimpleContent; import com.intellij.openapi.diff.SimpleDiffRequest; +import com.intellij.openapi.progress.PerformInBackgroundOption; 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.Condition; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.AbstractVcs; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.VcsDataKeys; @@ -34,17 +37,20 @@ import com.intellij.openapi.vcs.changes.ChangesUtil; import com.intellij.openapi.vcs.changes.ContentRevision; import com.intellij.openapi.vcs.changes.MarkerVcsContentRevision; import com.intellij.openapi.vfs.VirtualFile; -import org.jetbrains.annotations.NonNls; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnBundle; -import org.jetbrains.idea.svn.SvnRevisionNumber; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.api.Depth; import org.jetbrains.idea.svn.history.SvnRepositoryContentRevision; -import org.tmatesoft.svn.core.*; -import org.tmatesoft.svn.core.wc.ISVNPropertyHandler; -import org.tmatesoft.svn.core.wc.SVNPropertyData; +import org.jetbrains.idea.svn.properties.PropertyConsumer; +import org.jetbrains.idea.svn.properties.PropertyData; +import org.jetbrains.idea.svn.properties.PropertyValue; +import org.tmatesoft.svn.core.SVNErrorCode; +import org.tmatesoft.svn.core.SVNErrorMessage; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; @@ -69,8 +75,6 @@ public abstract class AbstractShowPropertiesDiffAction extends AnAction implemen @Override public void update(final AnActionEvent e) { final DataContext dataContext = e.getDataContext(); - final Project project = CommonDataKeys.PROJECT.getData(dataContext); - final Presentation presentation = e.getPresentation(); final Change[] data = VcsDataKeys.CHANGES.getData(dataContext); boolean showAction = checkThatChangesAreUnderSvn(data); @@ -78,38 +82,23 @@ public abstract class AbstractShowPropertiesDiffAction extends AnAction implemen presentation.setEnabled(showAction); } - private boolean checkThatChangesAreUnderSvn(Change[] data) { - boolean showAction = false; - if (data != null) { - for (Change change : data) { - final ContentRevision before = change.getBeforeRevision(); - if (before != null) { - showAction = showAction || before instanceof MarkerVcsContentRevision && SvnVcs.getKey().equals(((MarkerVcsContentRevision)before).getVcsKey()); - } - final ContentRevision after = change.getAfterRevision(); - if (after != null) { - showAction = showAction || after instanceof MarkerVcsContentRevision && SvnVcs.getKey().equals(((MarkerVcsContentRevision)after).getVcsKey()); + private static boolean checkThatChangesAreUnderSvn(@Nullable Change[] changes) { + boolean result = false; + + if (changes != null) { + result = ContainerUtil.or(changes, new Condition<Change>() { + @Override + public boolean value(Change change) { + return isUnderSvn(change.getBeforeRevision()) || isUnderSvn(change.getAfterRevision()); } - if (showAction) break; - } + }); } - return showAction; - } - private boolean enabled(final Project project, final Change[] changes) { - final boolean noChange = (project == null) || (changes == null) || (changes.length != 1); - if (noChange) { - return false; - } else { - final Change change = changes[0]; - - final ContentRevision revision = (change.getBeforeRevision() != null) ? change.getBeforeRevision() : change.getAfterRevision(); - if ((revision == null) || (! (revision.getRevisionNumber() instanceof SvnRevisionNumber))) { - return false; - } + return result; + } - return checkVcs(project, change); - } + private static boolean isUnderSvn(@Nullable ContentRevision revision) { + return revision instanceof MarkerVcsContentRevision && SvnVcs.getKey().equals(((MarkerVcsContentRevision)revision).getVcsKey()); } protected boolean checkVcs(final Project project, final Change change) { @@ -146,7 +135,7 @@ public abstract class AbstractShowPropertiesDiffAction extends AnAction implemen private final String myErrorTitle; private CalculateAndShow(@Nullable final Project project, final Change change, final String errorTitle) { - super(project, SvnBundle.message("fetching.properties.contents.progress.title"), true, Backgroundable.DEAF); + super(project, SvnBundle.message("fetching.properties.contents.progress.title"), true, PerformInBackgroundOption.DEAF); myChange = change; myErrorTitle = errorTitle; } @@ -179,7 +168,7 @@ public abstract class AbstractShowPropertiesDiffAction extends AnAction implemen } if (myBeforeContent != null && myAfterContent != null && myBeforeRevisionValue != null && myAfterRevision != null) { final SimpleDiffRequest diffRequest = new SimpleDiffRequest(myProject, getDiffWindowTitle(myChange)); - if (compareRevisions(myBeforeRevisionValue, myAfterRevision) >= 0) { + if (compareRevisions(myBeforeRevisionValue, myAfterRevision) > 0) { // before ahead diffRequest.setContents(new SimpleContent(myAfterContent), new SimpleContent(myBeforeContent)); diffRequest.setContentTitles(revisionToString(myAfterRevision), revisionToString(myBeforeRevisionValue)); @@ -194,7 +183,8 @@ public abstract class AbstractShowPropertiesDiffAction extends AnAction implemen } } - private String getDiffWindowTitle(final Change change) { + @NotNull + private static String getDiffWindowTitle(@NotNull Change change) { if (change.isMoved() || change.isRenamed()) { final FilePath beforeFilePath = ChangesUtil.getBeforePath(change); final FilePath afterFilePath = ChangesUtil.getAfterPath(change); @@ -207,7 +197,7 @@ public abstract class AbstractShowPropertiesDiffAction extends AnAction implemen } } - private int compareRevisions(@NonNls final SVNRevision revision1, @NonNls final SVNRevision revision2) { + private static int compareRevisions(@NotNull SVNRevision revision1, @NotNull SVNRevision revision2) { if (revision1.equals(revision2)) { return 0; } @@ -227,11 +217,9 @@ public abstract class AbstractShowPropertiesDiffAction extends AnAction implemen return revision1.getNumber() > revision2.getNumber() ? 1 : -1; } - private String revisionToString(final SVNRevision revision) { - if (revision == null) { - return "not exists"; - } - return revision.toString(); + @NotNull + private static String revisionToString(@Nullable SVNRevision revision) { + return revision == null ? "not exists" : revision.toString(); } private final static String ourPropertiesDelimiter = "\n"; @@ -273,35 +261,35 @@ public abstract class AbstractShowPropertiesDiffAction extends AnAction implemen private static String getPropertyList(@NotNull SvnVcs vcs, @NotNull SvnTarget target, @Nullable SVNRevision revision) throws VcsException { - final List<SVNPropertyData> lines = new ArrayList<SVNPropertyData>(); - final ISVNPropertyHandler propertyHandler = createHandler(revision, lines); + final List<PropertyData> lines = new ArrayList<PropertyData>(); + final PropertyConsumer propertyHandler = createHandler(revision, lines); vcs.getFactory(target).createPropertyClient().list(target, revision, Depth.EMPTY, propertyHandler); return toSortedStringPresentation(lines); } - private static ISVNPropertyHandler createHandler(SVNRevision revision, final List<SVNPropertyData> lines) { + private static PropertyConsumer createHandler(SVNRevision revision, final List<PropertyData> lines) { final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); if (indicator != null) { indicator.checkCanceled(); indicator.setText(SvnBundle.message("show.properties.diff.progress.text.revision.information", revision.toString())); } - return new ISVNPropertyHandler() { - public void handleProperty(final File path, final SVNPropertyData property) throws SVNException { + return new PropertyConsumer() { + public void handleProperty(final File path, final PropertyData property) throws SVNException { registerProperty(property); } - public void handleProperty(final SVNURL url, final SVNPropertyData property) throws SVNException { + public void handleProperty(final SVNURL url, final PropertyData property) throws SVNException { registerProperty(property); } - public void handleProperty(final long revision, final SVNPropertyData property) throws SVNException { + public void handleProperty(final long revision, final PropertyData property) throws SVNException { // revision properties here } - private void registerProperty(@NotNull SVNPropertyData property) { + private void registerProperty(@NotNull PropertyData property) { if (indicator != null) { indicator.checkCanceled(); indicator.setText2(SvnBundle.message("show.properties.diff.progress.text2.property.information", property.getName())); @@ -311,26 +299,26 @@ public abstract class AbstractShowPropertiesDiffAction extends AnAction implemen }; } - private static String toSortedStringPresentation(List<SVNPropertyData> lines) { + private static String toSortedStringPresentation(List<PropertyData> lines) { StringBuilder sb = new StringBuilder(); - Collections.sort(lines, new Comparator<SVNPropertyData>() { - public int compare(final SVNPropertyData o1, final SVNPropertyData o2) { + Collections.sort(lines, new Comparator<PropertyData>() { + public int compare(final PropertyData o1, final PropertyData o2) { return o1.getName().compareTo(o2.getName()); } }); - for (SVNPropertyData line : lines) { + for (PropertyData line : lines) { addPropertyPresentation(line, sb); } return sb.toString(); } - private static void addPropertyPresentation(final SVNPropertyData property, final StringBuilder sb) { + private static void addPropertyPresentation(final PropertyData property, final StringBuilder sb) { if (sb.length() != 0) { sb.append(ourPropertiesDelimiter); } - sb.append(property.getName()).append("=").append((property.getValue() == null) ? "" : SVNPropertyValue.getPropertyAsString(property.getValue())); + sb.append(property.getName()).append("=").append(StringUtil.notNullize(PropertyValue.toString(property.getValue()))); } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateExternalAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateExternalAction.java index 31206eec045c..d6d9c3152dde 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateExternalAction.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateExternalAction.java @@ -24,7 +24,6 @@ import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; -import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.*; import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager; @@ -42,15 +41,16 @@ import org.jetbrains.idea.svn.api.ProgressEvent; import org.jetbrains.idea.svn.api.ProgressTracker; import org.jetbrains.idea.svn.commandLine.CommandUtil; import org.jetbrains.idea.svn.dialogs.SelectCreateExternalTargetDialog; +import org.jetbrains.idea.svn.properties.ExternalsDefinitionParser; +import org.jetbrains.idea.svn.properties.PropertyValue; import org.jetbrains.idea.svn.update.UpdateClient; import org.tmatesoft.svn.core.SVNCancelException; import org.tmatesoft.svn.core.SVNException; -import org.tmatesoft.svn.core.SVNPropertyValue; -import org.tmatesoft.svn.core.internal.wc.SVNExternal; -import org.tmatesoft.svn.core.wc.*; +import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; import java.io.File; +import java.util.Map; /** * Created with IntelliJ IDEA. @@ -132,25 +132,24 @@ public class CreateExternalAction extends DumbAwareAction { public static boolean addToExternalProperty(@NotNull SvnVcs vcs, @NotNull File ioFile, String target, String url) throws SVNException, VcsException { ClientFactory factory = vcs.getFactory(ioFile); - SVNPropertyData propertyData = factory.createPropertyClient().getProperty(SvnTarget.fromFile(ioFile), SvnPropertyKeys.SVN_EXTERNALS, + PropertyValue propertyValue = factory.createPropertyClient().getProperty(SvnTarget.fromFile(ioFile), SvnPropertyKeys.SVN_EXTERNALS, false, SVNRevision.UNDEFINED); String newValue; - if (propertyData != null && propertyData.getValue() != null && ! StringUtil.isEmptyOrSpaces(propertyData.getValue().getString())) { - final SVNExternal[] externals = SVNExternal.parseExternals("Create External", propertyData.getValue().getString()); - for (SVNExternal external : externals) { - if (Comparing.equal(external.getPath(), target)) { - AbstractVcsHelper - .getInstance(vcs.getProject()).showError(new VcsException("Selected destination conflicts with existing: " + external.toString()), "Create External"); - return true; - } + if (propertyValue != null && !StringUtil.isEmptyOrSpaces(propertyValue.toString())) { + Map<String, String> externalsMap = ExternalsDefinitionParser.parseExternalsProperty(propertyValue.toString()); + String externalsForTarget = externalsMap.get(target); + + if (externalsForTarget != null) { + AbstractVcsHelper.getInstance(vcs.getProject()).showError( + new VcsException("Selected destination conflicts with existing: " + externalsForTarget), "Create External"); + return true; } final String string = createExternalDefinitionString(url, target); - newValue = propertyData.getValue().getString().trim() + "\n" + string; + newValue = propertyValue.toString().trim() + "\n" + string; } else { newValue = createExternalDefinitionString(url, target); } - factory.createPropertyClient().setProperty(ioFile, SvnPropertyKeys.SVN_EXTERNALS, SVNPropertyValue.create(newValue), Depth.EMPTY, - false); + factory.createPropertyClient().setProperty(ioFile, SvnPropertyKeys.SVN_EXTERNALS, PropertyValue.create(newValue), Depth.EMPTY, false); return false; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SetPropertyAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SetPropertyAction.java index cdc738cf2d40..5e53cc956e92 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SetPropertyAction.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SetPropertyAction.java @@ -30,7 +30,7 @@ import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.api.Depth; import org.jetbrains.idea.svn.dialogs.SetPropertyDialog; import org.jetbrains.idea.svn.properties.PropertyClient; -import org.tmatesoft.svn.core.SVNPropertyValue; +import org.jetbrains.idea.svn.properties.PropertyValue; import java.io.File; @@ -79,7 +79,7 @@ public class SetPropertyAction extends BasicAction { // TODO: most likely SVNDepth.getInfinityOrEmptyDepth should be used instead of SVNDepth.fromRecursive - to have either "infinity" // TODO: or "empty" depth, and not "infinity" or "files" depth. But previous logic used SVNDepth.fromRecursive implicitly - client.setProperty(ioFile, name, SVNPropertyValue.create(value), Depth.allOrFiles(recursive), false); + client.setProperty(ioFile, name, PropertyValue.create(value), Depth.allOrFiles(recursive), false); } for(int i = 0; i < file.length; i++) { if (recursive && file[i].isDirectory()) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnExcludingIgnoredOperation.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnExcludingIgnoredOperation.java index c206cd3451d8..94fc2e11c96e 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnExcludingIgnoredOperation.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnExcludingIgnoredOperation.java @@ -15,11 +15,10 @@ */ package org.jetbrains.idea.svn.actions; -import com.intellij.lifecycle.PeriodicalTasksCloser; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; -import com.intellij.openapi.roots.FileIndexFacade; import com.intellij.openapi.util.Computable; +import com.intellij.openapi.vcs.ProjectLevelVcsManager; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.changes.ChangeListManager; import com.intellij.openapi.vfs.VfsUtilCore; @@ -42,39 +41,36 @@ public class SvnExcludingIgnoredOperation { public static class Filter { private final Project myProject; - private final FileIndexFacade myIndex; + private final ProjectLevelVcsManager myVcsManager; private final ChangeListManager myClManager; public Filter(final Project project) { myProject = project; if (!project.isDefault()) { - myIndex = PeriodicalTasksCloser.getInstance().safeGetService(project, FileIndexFacade.class); + myVcsManager = ProjectLevelVcsManager.getInstance(project); myClManager = ChangeListManager.getInstance(project); } else { - myIndex = null; + myVcsManager = null; myClManager = null; } } public boolean accept(final VirtualFile file) { if (!myProject.isDefault()) { - if (isExcluded(file)) { - return false; - } - if (myClManager.isIgnoredFile(file)) { + if (isIgnoredByVcs(file) || myClManager.isIgnoredFile(file)) { return false; } } return true; } - private boolean isExcluded(final VirtualFile file) { + private boolean isIgnoredByVcs(final VirtualFile file) { return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() { @Override public Boolean compute() { - return myIndex.isExcludedFile(file); + return myVcsManager.isIgnored(file); } }); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnMergeProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnMergeProvider.java index 912bd970f7b0..ddd9bd572f0e 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnMergeProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnMergeProvider.java @@ -32,9 +32,9 @@ import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.api.Depth; import org.jetbrains.idea.svn.info.Info; import org.jetbrains.idea.svn.properties.PropertyClient; +import org.jetbrains.idea.svn.properties.PropertyValue; import org.tmatesoft.svn.core.SVNProperty; -import org.tmatesoft.svn.core.SVNPropertyValue; -import org.tmatesoft.svn.core.wc.*; +import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; import java.io.ByteArrayOutputStream; @@ -162,8 +162,8 @@ public class SvnMergeProvider implements MergeProvider { File ioFile = new File(file.getPath()); PropertyClient client = vcs.getFactory(ioFile).createPropertyClient(); - SVNPropertyData svnPropertyData = client.getProperty(SvnTarget.fromFile(ioFile), SVNProperty.MIME_TYPE, false, SVNRevision.WORKING); - if (svnPropertyData != null && SVNProperty.isBinaryMimeType(SVNPropertyValue.getPropertyAsString(svnPropertyData.getValue()))) { + PropertyValue value = client.getProperty(SvnTarget.fromFile(ioFile), SVNProperty.MIME_TYPE, false, SVNRevision.WORKING); + if (value != null && SVNProperty.isBinaryMimeType(value.toString())) { return true; } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandExecutor.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandExecutor.java index 33e06739ad0b..0b484e41d1c5 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandExecutor.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandExecutor.java @@ -23,6 +23,7 @@ import com.intellij.openapi.application.PathManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.util.EventDispatcher; @@ -36,6 +37,7 @@ import java.io.File; import java.io.IOException; import java.io.OutputStreamWriter; import java.util.List; +import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; @@ -152,9 +154,20 @@ public class CommandExecutor { protected void beforeCreateProcess() throws SvnBindException { EncodingEnvironmentUtil.fixDefaultEncodingIfMac(myCommandLine, null); + setupLocale(); ensureMessageFile(); } + private void setupLocale() { + String locale = Registry.stringValue("svn.executable.locale"); + Map<String, String> environment = myCommandLine.getEnvironment(); + + // TODO: check if we need to set LC_ALL to configured locale or just clear it + environment.put("LC_ALL", ""); + environment.put("LC_MESSAGES", locale); + environment.put("LANG", locale); + } + private void ensureMessageFile() throws SvnBindException { if (myMessage != null) { myMessageFile = createTempFile("commit-message", ".txt"); 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 eee798737846..eb2e6cf976cb 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java @@ -58,8 +58,7 @@ public class CommandUtil { boolean hasPegRevision = pegRevision != null && !SVNRevision.UNDEFINED.equals(pegRevision) && !SVNRevision.WORKING.equals(pegRevision) && - pegRevision.isValid() && - pegRevision.getNumber() != 0; + pegRevision.isValid(); if (hasPegRevision || hasAtSymbol) { // add '@' to correctly handle paths that contain '@' symbol diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/config/SvnConfigureProxiesDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/config/SvnConfigureProxiesDialog.java index a70a4f28d0fd..40e3c80d1fc6 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/config/SvnConfigureProxiesDialog.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/config/SvnConfigureProxiesDialog.java @@ -63,16 +63,10 @@ public class SvnConfigureProxiesDialog extends DialogWrapper implements Validati public void onError(final String text, final JComponent component, final boolean forbidSave) { myTabbedPane.setSelectedComponent(component); - String prefixString = ""; - for (int i = 0; i < myTabbedPane.getComponentCount(); i++) { - final Component currentComponent = myTabbedPane.getComponentAt(i); - // compare referencies - same objects - if (currentComponent == component) { - prefixString = myTabbedPane.getTitleAt(i) + ": "; - } - } + String errorPrefix = myTabbedPane.getTitleAt(myTabbedPane.indexOfComponent(component)) + ": "; + setOKActionEnabled(! forbidSave); - setInvalid(prefixString + text); + setInvalid(errorPrefix + text); } public void onSuccess() { 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 6bd08c1089cb..50ddd9615d41 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java @@ -22,10 +22,12 @@ import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.MultiLineLabelUI; import com.intellij.openapi.ui.TextFieldWithBrowseButton; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.*; import com.intellij.ui.components.JBList; +import com.intellij.util.ObjectUtils; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -100,16 +102,23 @@ public class BranchConfigurationDialog extends DialogWrapper { myListPanel.add( ToolbarDecorator.createDecorator(myLocationList) .setAddAction(new AnActionButtonRunnable() { + + @Nullable private SVNURL usedRootUrl; + @Override public void run(AnActionButton button) { - final String selectedUrl = SelectLocationDialog.selectLocation(project, rootUrl.toDecodedString()); - if (selectedUrl != null) { - if (!configuration.getBranchUrls().contains(selectedUrl)) { - configuration - .addBranches(selectedUrl, new InfoStorage<List<SvnBranchItem>>(new ArrayList<SvnBranchItem>(), InfoReliability.empty)); - mySvnBranchConfigManager.reloadBranches(myRoot, selectedUrl, null); - listModel.fireItemAdded(); - myLocationList.setSelectedIndex(listModel.getSize() - 1); + Pair<String, SVNURL> result = SelectLocationDialog.selectLocation(project, ObjectUtils.notNull(usedRootUrl, rootUrl)); + if (result != null) { + String selectedUrl = result.getFirst(); + usedRootUrl = result.getSecond(); + if (selectedUrl != null) { + if (!configuration.getBranchUrls().contains(selectedUrl)) { + configuration + .addBranches(selectedUrl, new InfoStorage<List<SvnBranchItem>>(new ArrayList<SvnBranchItem>(), InfoReliability.empty)); + mySvnBranchConfigManager.reloadBranches(myRoot, selectedUrl, null); + listModel.fireItemAdded(); + myLocationList.setSelectedIndex(listModel.getSize() - 1); + } } } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/PropertiesComponent.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/PropertiesComponent.java index 860c524ed591..cd504be56077 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/PropertiesComponent.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/PropertiesComponent.java @@ -37,9 +37,12 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnPropertyKeys; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.api.Depth; -import org.tmatesoft.svn.core.*; -import org.tmatesoft.svn.core.wc.ISVNPropertyHandler; -import org.tmatesoft.svn.core.wc.SVNPropertyData; +import org.jetbrains.idea.svn.properties.PropertyConsumer; +import org.jetbrains.idea.svn.properties.PropertyData; +import org.jetbrains.idea.svn.properties.PropertyValue; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNProperty; +import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; @@ -151,20 +154,20 @@ public class PropertiesComponent extends JPanel { } } - private void collectProperties(@NotNull SvnVcs vcs, @NotNull File file, @NotNull final Map<String, String> props) { + private static void collectProperties(@NotNull SvnVcs vcs, @NotNull File file, @NotNull final Map<String, String> props) { try { - ISVNPropertyHandler handler = new ISVNPropertyHandler() { - public void handleProperty(File path, SVNPropertyData property) throws SVNException { - final SVNPropertyValue value = property.getValue(); + PropertyConsumer handler = new PropertyConsumer() { + public void handleProperty(File path, PropertyData property) throws SVNException { + final PropertyValue value = property.getValue(); if (value != null) { - props.put(property.getName(), SVNPropertyValue.getPropertyAsString(property.getValue())); + props.put(property.getName(), PropertyValue.toString(property.getValue())); } } - public void handleProperty(SVNURL url, SVNPropertyData property) throws SVNException { + public void handleProperty(SVNURL url, PropertyData property) throws SVNException { } - public void handleProperty(long revision, SVNPropertyData property) throws SVNException { + public void handleProperty(long revision, PropertyData property) throws SVNException { } }; vcs.getFactory(file).createPropertyClient().list(SvnTarget.fromFile(file, SVNRevision.UNDEFINED), SVNRevision.WORKING, Depth.EMPTY, @@ -229,10 +232,12 @@ public class PropertiesComponent extends JPanel { String url = "file://" + myFile.getPath().replace(File.separatorChar, '/'); VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(url); if (file != null) { + VcsDirtyScopeManager dirtyScopeManager = VcsDirtyScopeManager.getInstance(myVcs.getProject()); + if (recursive && file.isDirectory()) { - VcsDirtyScopeManager.getInstance(myVcs.getProject()).dirDirtyRecursively(file, true); + dirtyScopeManager.dirDirtyRecursively(file); } else { - VcsDirtyScopeManager.getInstance(myVcs.getProject()).fileDirty(file); + dirtyScopeManager.fileDirty(file); } } } @@ -272,8 +277,7 @@ public class PropertiesComponent extends JPanel { if (!StringUtil.isEmpty(property)) { try { myVcs.getFactory(myFile).createPropertyClient() - .setProperty(myFile, property, value != null ? SVNPropertyValue.create(value) : null, - Depth.allOrEmpty(recursive), force); + .setProperty(myFile, property, PropertyValue.create(value), Depth.allOrEmpty(recursive), force); } catch (VcsException error) { VcsBalloonProblemNotifier @@ -302,7 +306,7 @@ public class PropertiesComponent extends JPanel { public void actionPerformed(AnActionEvent e) { Project project = CommonDataKeys.PROJECT.getData(e.getDataContext()); - SVNPropertyData propValue = null; + PropertyValue propValue = null; try { propValue = myVcs.getFactory(myFile).createPropertyClient() .getProperty(SvnTarget.fromFile(myFile), SVNProperty.KEYWORDS, false, SVNRevision.WORKING); @@ -311,8 +315,7 @@ public class PropertiesComponent extends JPanel { // show erorr message } - SetKeywordsDialog dialog = new SetKeywordsDialog(project, - propValue != null ? SVNPropertyValue.getPropertyAsString(propValue.getValue()) : null); + SetKeywordsDialog dialog = new SetKeywordsDialog(project, PropertyValue.toString(propValue)); dialog.show(); if (dialog.isOK()) { setProperty(SvnPropertyKeys.SVN_KEYWORDS, dialog.getKeywords(), false, false); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserComponent.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserComponent.java index 0fd1f06bf7cb..163be4922224 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserComponent.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserComponent.java @@ -76,10 +76,26 @@ public class RepositoryBrowserComponent extends JPanel implements Disposable, Da } public void setRepositoryURLs(SVNURL[] urls, final boolean showFiles) { + setRepositoryURLs(urls, showFiles, null, false); + } + + public void setRepositoryURLs(SVNURL[] urls, + final boolean showFiles, + @Nullable NotNullFunction<RepositoryBrowserComponent, Expander> defaultExpanderFactory, + boolean expandFirst) { RepositoryTreeModel model = new RepositoryTreeModel(myVCS, showFiles, this); + + if (defaultExpanderFactory != null) { + model.setDefaultExpanderFactory(defaultExpanderFactory); + } + model.setRoots(urls); Disposer.register(this, model); myRepositoryTree.setModel(model); + + if (expandFirst) { + myRepositoryTree.expandRow(0); + } } public void setRepositoryURL(SVNURL url, boolean showFiles, final NotNullFunction<RepositoryBrowserComponent, Expander> defaultExpanderFactory) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java index 191acf387b86..83d895b93ffc 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java @@ -93,7 +93,7 @@ public class RepositoryBrowserDialog extends DialogWrapper { private final boolean myShowFiles; - @NonNls private static final String PLACE_TOOLBAR = "RepositoryBrowser.Toolbar"; + @NonNls public static final String PLACE_TOOLBAR = "RepositoryBrowser.Toolbar"; @NonNls private static final String PLACE_MENU = "RepositoryBrowser.Menu"; private final String myRepositoriesLabelText; protected JLabel myRepositoriesLabel; @@ -138,7 +138,7 @@ public class RepositoryBrowserDialog extends DialogWrapper { DefaultActionGroup group = new DefaultActionGroup(); final RepositoryBrowserComponent browser = getRepositoryBrowser(); group.add(new AddLocationAction(browser)); - group.add(new EditLocationAction()); + group.add(new EditLocationAction(browser)); group.add(new DiscardLocationAction(browser)); group.add(new DetailsAction()); group.addSeparator(); @@ -216,7 +216,7 @@ public class RepositoryBrowserDialog extends DialogWrapper { group.add(copyUrlAction); group.addSeparator(); group.add(new RefreshAction(browser)); - group.add(new EditLocationAction()); + group.add(new EditLocationAction(browser)); group.add(new DiscardLocationAction(browser)); ActionPopupMenu menu = ActionManager.getInstance().createActionPopupMenu(PLACE_MENU, group); return menu.getComponent(); @@ -413,13 +413,17 @@ public class RepositoryBrowserDialog extends DialogWrapper { } } - protected class EditLocationAction extends AnAction { - public EditLocationAction() { + protected static class EditLocationAction extends AnAction { + + @NotNull private final RepositoryBrowserComponent myBrowserComponent; + + public EditLocationAction(@NotNull RepositoryBrowserComponent browserComponent) { super(SvnBundle.message("repository.browser.edit.location.menu.item")); + myBrowserComponent = browserComponent; } public void update(AnActionEvent e) { - RepositoryTreeNode node = getRepositoryBrowser().getSelectedNode(); + RepositoryTreeNode node = myBrowserComponent.getSelectedNode(); if (e.getPlace().equals(PLACE_TOOLBAR)) { e.getPresentation().setDescription(SvnBundle.message("repository.browser.edit.location.menu.item")); e.getPresentation().setText(SvnBundle.message("repository.browser.edit.location.menu.item")); @@ -429,13 +433,14 @@ public class RepositoryBrowserDialog extends DialogWrapper { } public void actionPerformed(AnActionEvent e) { - RepositoryTreeNode node = getRepositoryBrowser().getSelectedNode(); + RepositoryTreeNode node = myBrowserComponent.getSelectedNode(); if (node == null || (! (node.getParent() instanceof RepositoryTreeRootNode))) { return; } final String oldUrl = node.getURL().toString(); final SvnApplicationSettings settings = SvnApplicationSettings.getInstance(); - final AddRepositoryLocationDialog dialog = new AddRepositoryLocationDialog(myProject, settings.getTypedUrlsListCopy()) { + final AddRepositoryLocationDialog dialog = + new AddRepositoryLocationDialog(myBrowserComponent.getProject(), settings.getTypedUrlsListCopy()) { @Override protected String initText() { return oldUrl; @@ -453,9 +458,9 @@ public class RepositoryBrowserDialog extends DialogWrapper { settings.addTypedUrl(url); settings.removeCheckoutURL(oldUrl); settings.addCheckoutURL(url); - final RepositoryBrowserComponent browser = getRepositoryBrowser(); - browser.removeURL(oldUrl); - browser.addURL(url); + + myBrowserComponent.removeURL(oldUrl); + myBrowserComponent.addURL(url); } } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SelectLocationDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SelectLocationDialog.java index a6ca6ad54f11..bcbbe79c1b45 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SelectLocationDialog.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SelectLocationDialog.java @@ -15,12 +15,15 @@ */ package org.jetbrains.idea.svn.dialogs; +import com.intellij.openapi.actionSystem.ActionManager; +import com.intellij.openapi.actionSystem.DefaultActionGroup; import com.intellij.openapi.help.HelpManager; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -52,21 +55,30 @@ public class SelectLocationDialog extends DialogWrapper { private final String myDstLabel; private JTextField myDstText; private final boolean myIsShowFiles; + private final boolean myAllowActions; @NonNls private static final String HELP_ID = "vcs.subversion.common"; // todo check that works when authenticated @Nullable public static String selectLocation(Project project, String url) { - SelectLocationDialog dialog = openDialog(project, url, null, null, true, null); + SelectLocationDialog dialog = openDialog(project, url, null, null, true, false, null); return dialog == null || !dialog.isOK() ? null : dialog.getSelectedURL(); } @Nullable + public static Pair<String, SVNURL> selectLocation(Project project, @NotNull SVNURL url) { + SelectLocationDialog dialog = new SelectLocationDialog(project, url, null, null, true, true); + dialog.show(); + + return dialog.isOK() ? Pair.create(dialog.getSelectedURL(), dialog.getRootUrl()) : null; + } + + @Nullable public static String selectCopyDestination(Project project, String url, String dstLabel, String dstName, boolean showFiles) { SelectLocationDialog dialog = - openDialog(project, url, dstLabel, dstName, showFiles, SvnBundle.message("select.location.invalid.url.message", url)); + openDialog(project, url, dstLabel, dstName, showFiles, false, SvnBundle.message("select.location.invalid.url.message", url)); return dialog == null || !dialog.isOK() ? null : SVNPathUtil.append(dialog.getSelectedURL(), dialog.getDestinationName()); } @@ -77,6 +89,7 @@ public class SelectLocationDialog extends DialogWrapper { String dstLabel, String dstName, boolean showFiles, + boolean allowActions, String errorMessage) { try { SVNURL svnUrl = SvnUtil.createUrl(url); @@ -86,8 +99,7 @@ public class SelectLocationDialog extends DialogWrapper { SvnBundle.message("dialog.title.select.repository.location")); return null; } - - SelectLocationDialog dialog = new SelectLocationDialog(project, repositoryUrl, dstLabel, dstName, showFiles); + SelectLocationDialog dialog = new SelectLocationDialog(project, repositoryUrl, dstLabel, dstName, showFiles, allowActions); dialog.show(); return dialog; } @@ -98,13 +110,14 @@ public class SelectLocationDialog extends DialogWrapper { } } - private SelectLocationDialog(Project project, SVNURL url, String dstLabel, String dstName, boolean showFiles) { + private SelectLocationDialog(Project project, SVNURL url, String dstLabel, String dstName, boolean showFiles, boolean allowActions) { super(project, true); myProject = project; myDstLabel = dstLabel; myDstName = dstName; myURL = url; myIsShowFiles = showFiles; + myAllowActions = allowActions; setTitle(SvnBundle.message("dialog.title.select.repository.location")); getHelpAction().setEnabled(true); init(); @@ -146,7 +159,13 @@ public class SelectLocationDialog extends DialogWrapper { protected void init() { super.init(); final String urlString = myURL.toString(); - myRepositoryBrowser.setRepositoryURL(myURL, myIsShowFiles, new UrlOpeningExpander.Factory(urlString, urlString)); + if (myAllowActions) { + // initialize repo browser this way - to make actions work correctly + myRepositoryBrowser.setRepositoryURLs(new SVNURL[]{myURL}, myIsShowFiles, new UrlOpeningExpander.Factory(urlString, urlString), true); + } + else { + myRepositoryBrowser.setRepositoryURL(myURL, myIsShowFiles, new UrlOpeningExpander.Factory(urlString, urlString)); + } myRepositoryBrowser.addChangeListener(new TreeSelectionListener() { public void valueChanged(TreeSelectionEvent e) { getOKAction().setEnabled(isOKActionEnabled()); @@ -162,7 +181,10 @@ public class SelectLocationDialog extends DialogWrapper { protected JComponent createCenterPanel() { JPanel panel = new JPanel(); - panel.setLayout(new GridBagLayout()); + panel.setLayout(new BorderLayout()); + + JPanel browserPanel = new JPanel(); + browserPanel.setLayout(new GridBagLayout()); GridBagConstraints gc = new GridBagConstraints(); gc.insets = new Insets(2, 2, 2, 2); @@ -177,7 +199,7 @@ public class SelectLocationDialog extends DialogWrapper { myRepositoryBrowser = new RepositoryBrowserComponent(SvnVcs.getInstance(myProject)); - panel.add(myRepositoryBrowser, gc); + browserPanel.add(myRepositoryBrowser, gc); if (myDstName != null) { gc.gridy += 1; gc.gridwidth = 1; @@ -187,7 +209,7 @@ public class SelectLocationDialog extends DialogWrapper { gc.weighty = 0; JLabel dstLabel = new JLabel(myDstLabel); - panel.add(dstLabel, gc); + browserPanel.add(dstLabel, gc); gc.gridx += 1; gc.weightx = 1; @@ -196,7 +218,7 @@ public class SelectLocationDialog extends DialogWrapper { myDstText = new JTextField(); myDstText.setText(myDstName); myDstText.selectAll(); - panel.add(myDstText, gc); + browserPanel.add(myDstText, gc); myDstText.getDocument().addDocumentListener(new DocumentListener() { public void insertUpdate(DocumentEvent e) { @@ -217,12 +239,25 @@ public class SelectLocationDialog extends DialogWrapper { gc.gridy += 1; gc.gridwidth = 2; - panel.add(new JSeparator(), gc); + browserPanel.add(new JSeparator(), gc); + } + + if (myAllowActions) { + panel.add(createToolbar(), BorderLayout.NORTH); } + panel.add(browserPanel, BorderLayout.CENTER); return panel; } + @NotNull + private JComponent createToolbar() { + DefaultActionGroup group = new DefaultActionGroup(); + group.add(new RepositoryBrowserDialog.EditLocationAction(myRepositoryBrowser)); + + return ActionManager.getInstance().createActionToolbar(RepositoryBrowserDialog.PLACE_TOOLBAR, group, true).getComponent(); + } + public JComponent getPreferredFocusedComponent() { return (JComponent)myRepositoryBrowser.getPreferredFocusedComponent(); } @@ -246,4 +281,16 @@ public class SelectLocationDialog extends DialogWrapper { public String getSelectedURL() { return myRepositoryBrowser.getSelectedURL(); } + + @Nullable + public SVNURL getRootUrl() { + RepositoryTreeNode node = myRepositoryBrowser.getSelectedNode(); + + // find the most top parent of type RepositoryTreeNode + while (node != null && node.getParent() instanceof RepositoryTreeNode) { + node = (RepositoryTreeNode)node.getParent(); + } + + return node != null ? node.getURL() : null; + } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SetPropertyDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SetPropertyDialog.java index 28375d28b7ba..f2a58a0bd2da 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SetPropertyDialog.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SetPropertyDialog.java @@ -24,15 +24,16 @@ import com.intellij.openapi.vcs.VcsException; import com.intellij.ui.DocumentAdapter; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnBundle; import org.jetbrains.idea.svn.SvnPropertyKeys; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.api.Depth; import org.jetbrains.idea.svn.properties.PropertyClient; -import org.tmatesoft.svn.core.SVNPropertyValue; +import org.jetbrains.idea.svn.properties.PropertyConsumer; +import org.jetbrains.idea.svn.properties.PropertyData; +import org.jetbrains.idea.svn.properties.PropertyValue; import org.tmatesoft.svn.core.SVNURL; -import org.tmatesoft.svn.core.wc.ISVNPropertyHandler; -import org.tmatesoft.svn.core.wc.SVNPropertyData; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; @@ -154,10 +155,10 @@ public class SetPropertyDialog extends DialogWrapper { return; } File file = myFiles[0]; - SVNPropertyData property = !StringUtil.isEmpty(name) ? getProperty(file, name) : null; + PropertyValue property = !StringUtil.isEmpty(name) ? getProperty(file, name) : null; if (property != null) { - myValueText.setText(SVNPropertyValue.getPropertyAsString(property.getValue())); + myValueText.setText(property.toString()); myValueText.selectAll(); } else { @@ -165,19 +166,20 @@ public class SetPropertyDialog extends DialogWrapper { } } - private SVNPropertyData getProperty(@NotNull File file, @NotNull String name) { - SVNPropertyData property; + @Nullable + private PropertyValue getProperty(@NotNull File file, @NotNull String name) { + PropertyValue result; try { PropertyClient client = myVCS.getFactory(file).createPropertyClient(); - property = client.getProperty(SvnTarget.fromFile(file, SVNRevision.WORKING), name, false, SVNRevision.WORKING); + result = client.getProperty(SvnTarget.fromFile(file, SVNRevision.WORKING), name, false, SVNRevision.WORKING); } catch (VcsException e) { LOG.info(e); - property = null; + result = null; } - return property; + return result; } protected JComponent createCenterPanel() { @@ -205,18 +207,18 @@ public class SetPropertyDialog extends DialogWrapper { if (files.length == 1) { File file = files[0]; try { - ISVNPropertyHandler handler = new ISVNPropertyHandler() { - public void handleProperty(File path, SVNPropertyData property) { + PropertyConsumer handler = new PropertyConsumer() { + public void handleProperty(File path, PropertyData property) { String name = property.getName(); if (name != null) { names.add(name); } } - public void handleProperty(SVNURL url, SVNPropertyData property) { + public void handleProperty(SVNURL url, PropertyData property) { } - public void handleProperty(long revision, SVNPropertyData property) { + public void handleProperty(long revision, PropertyData property) { } }; 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 497134727ee4..be084b0986d0 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CmdDiffClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CmdDiffClient.java @@ -52,13 +52,14 @@ import java.util.List; */ public class CmdDiffClient extends BaseSvnClient implements DiffClient { + @NotNull @Override public List<Change> compare(@NotNull SvnTarget target1, @NotNull SvnTarget target2) throws VcsException { - assertUrl(target2); - if (target1.isFile()) { + assertUrl(target1); + if (target2.isFile()) { // Such combination (file and url) with "--summarize" option is supported only in svn 1.8. // For svn 1.7 "--summarize" is only supported when both targets are repository urls. - assertDirectory(target1); + assertDirectory(target2); WorkingCopyFormat format = WorkingCopyFormat.from(myFactory.createVersionClient().getVersion()); if (format.less(WorkingCopyFormat.ONE_DOT_EIGHT)) { @@ -95,6 +96,7 @@ public class CmdDiffClient extends BaseSvnClient implements DiffClient { } } + @NotNull private List<Change> parseOutput(@NotNull SvnTarget target1, @NotNull SvnTarget target2, @NotNull CommandExecutor executor) throws SvnBindException { try { @@ -114,16 +116,30 @@ public class CmdDiffClient extends BaseSvnClient implements DiffClient { } } - private ContentRevision createRemoteRevision(@NotNull FilePath remotePath, @NotNull FilePath localPath, @NotNull FileStatus status) { + @NotNull + private ContentRevision createRevision(@NotNull FilePath path, + @NotNull FilePath localPath, + @NotNull SVNRevision revision, + @NotNull FileStatus status) { + ContentRevision result; + + if (path.isNonLocal()) { // 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()); + result = SvnRepositoryContentRevision.create(myVcs, path, status == FileStatus.DELETED ? localPath : null, revision.getNumber()); + } + else { + result = CurrentContentRevision.create(path); } - private static ContentRevision createLocalRevision(@NotNull FilePath path) { - return CurrentContentRevision.create(path); + return result; + } + + private static FilePath createFilePath(@NotNull SvnTarget target, boolean isDirectory) { + return target.isFile() + ? VcsUtil.getFilePath(target.getFile(), isDirectory) + : VcsUtil.getFilePathOnNonLocal(SvnUtil.toDecodedString(target), isDirectory); } @NotNull @@ -134,9 +150,7 @@ public class CmdDiffClient extends BaseSvnClient implements DiffClient { // TODO: 3) Properties change is currently not added as part of result change like in SvnChangeProviderContext.patchWithPropertyChange SvnTarget subTarget1 = SvnUtil.append(target1, diffPath.path, true); - String relativePath = target1.isFile() - ? FileUtil.getRelativePath(target1.getFile(), subTarget1.getFile()) - : SvnUtil.getRelativeUrl(SvnUtil.toDecodedString(target1), SvnUtil.toDecodedString(subTarget1)); + String relativePath = SvnUtil.getRelativeUrl(SvnUtil.toDecodedString(target1), SvnUtil.toDecodedString(subTarget1)); if (relativePath == null) { throw new SvnBindException("Could not get relative path for " + target1 + " and " + subTarget1); @@ -144,27 +158,19 @@ public class CmdDiffClient extends BaseSvnClient implements DiffClient { SvnTarget subTarget2 = SvnUtil.append(target2, FileUtil.toSystemIndependentName(relativePath)); - FilePath target1Path = target1.isFile() - ? VcsUtil.getFilePath(subTarget1.getFile(), diffPath.isDirectory()) - : VcsUtil.getFilePathOnNonLocal(SvnUtil.toDecodedString(subTarget1), diffPath.isDirectory()); - FilePath target2Path = VcsUtil.getFilePathOnNonLocal(SvnUtil.toDecodedString(subTarget2), diffPath.isDirectory()); + FilePath target1Path = createFilePath(subTarget1, diffPath.isDirectory()); + FilePath target2Path = createFilePath(subTarget2, diffPath.isDirectory()); FileStatus status = SvnStatusConvertor .convertStatus(SvnStatusHandler.getStatus(diffPath.itemStatus), SvnStatusHandler.getStatus(diffPath.propertiesStatus)); - // for "file + url" pair - statuses determine changes needs to be done to "url" to get "file" state - // for "url1 + url2" pair - statuses determine changes needs to be done to "url1" to get "url2" state + // statuses determine changes needs to be done to "target1" to get "target2" state ContentRevision beforeRevision = status == FileStatus.ADDED ? null - : target1.isFile() - ? createRemoteRevision(target2Path, target1Path, status) - : createRemoteRevision(target1Path, target2Path, status); + : createRevision(target1Path, target2Path, target1.getPegRevision(), status); ContentRevision afterRevision = status == FileStatus.DELETED ? null - : target1.isFile() - ? createLocalRevision(target1Path) - : createRemoteRevision(target2Path, target1Path, status); - + : createRevision(target2Path, target1Path, target2.getPegRevision(), status); return createChange(status, beforeRevision, afterRevision); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DiffClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DiffClient.java index 35c35e9313f1..dfa43ddcb4bd 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DiffClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DiffClient.java @@ -29,6 +29,11 @@ import java.util.List; */ public interface DiffClient extends SvnClient { + /** + * @param target1 Should always be url. + * @param target2 Could be either url or file. And should be directory if file. + */ + @NotNull List<Change> compare(@NotNull SvnTarget target1, @NotNull SvnTarget target2) throws VcsException; void unifiedDiff(@NotNull SvnTarget target1, @NotNull SvnTarget target2, @NotNull OutputStream output) throws VcsException; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DirectoryWithBranchComparer.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DirectoryWithBranchComparer.java index 0f0e6a714037..784548d9e661 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DirectoryWithBranchComparer.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DirectoryWithBranchComparer.java @@ -24,6 +24,7 @@ import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.svn.SvnBundle; +import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.WorkingCopyFormat; import org.jetbrains.idea.svn.api.ClientFactory; import org.tmatesoft.svn.core.SVNException; @@ -53,19 +54,24 @@ public class DirectoryWithBranchComparer extends ElementWithBranchComparer { titleBuilder.append(SvnBundle.message("repository.browser.compare.title", myElementUrl, FileUtil.toSystemDependentName(myVirtualFile.getPresentableUrl()))); - SvnTarget target1 = SvnTarget.fromFile(new File(myVirtualFile.getPath())); - SvnTarget target2 = SvnTarget.fromURL(myElementUrl); + SvnTarget target1 = SvnTarget.fromURL(myElementUrl); + SvnTarget target2 = SvnTarget.fromFile(new File(myVirtualFile.getPath())); changes.addAll(getClientFactory().createDiffClient().compare(target1, target2)); } @NotNull private ClientFactory getClientFactory() { - WorkingCopyFormat format = myVcs.getWorkingCopyFormat(VfsUtilCore.virtualToIoFile(myVirtualFile)); + return getClientFactory(myVcs, VfsUtilCore.virtualToIoFile(myVirtualFile)); + } + + @NotNull + public static ClientFactory getClientFactory(@NotNull SvnVcs vcs, @NotNull File file) { + WorkingCopyFormat format = vcs.getWorkingCopyFormat(file); // 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 - return format.isOrGreater(WorkingCopyFormat.ONE_DOT_EIGHT) ? myVcs.getCommandLineFactory() : myVcs.getSvnKitFactory(); + return format.isOrGreater(WorkingCopyFormat.ONE_DOT_EIGHT) ? vcs.getCommandLineFactory() : vcs.getSvnKitFactory(); } @Override diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/SvnKitDiffClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/SvnKitDiffClient.java index 0a1b14837b7e..ec4c51288cc2 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/SvnKitDiffClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/SvnKitDiffClient.java @@ -54,6 +54,7 @@ import java.util.List; */ public class SvnKitDiffClient extends BaseSvnClient implements DiffClient { + @NotNull @Override public List<Change> compare(@NotNull SvnTarget target1, @NotNull SvnTarget target2) throws VcsException { DiffExecutor executor = new DiffExecutor(target1, target2); @@ -99,12 +100,12 @@ public class SvnKitDiffClient extends BaseSvnClient implements DiffClient { } public void run() throws SVNException { - assertUrl(myTarget2); + assertUrl(myTarget1); - if (myTarget1.isFile()) { - assertDirectory(myTarget1); + if (myTarget2.isFile()) { + assertDirectory(myTarget2); - WorkingCopyFormat format = myVcs.getWorkingCopyFormat(myTarget1.getFile()); + WorkingCopyFormat format = myVcs.getWorkingCopyFormat(myTarget2.getFile()); myChanges.addAll(WorkingCopyFormat.ONE_DOT_SIX.equals(format) ? run16Diff() : run17Diff()); } else { @@ -142,20 +143,20 @@ public class SvnKitDiffClient extends BaseSvnClient implements DiffClient { } private Collection<Change> run17Diff() throws SVNException { - final Info info1 = myVcs.getInfo(myTarget1.getFile(), SVNRevision.HEAD); + final Info info1 = myVcs.getInfo(myTarget2.getFile(), SVNRevision.HEAD); if (info1 == null) { SVNErrorMessage err = - SVNErrorMessage.create(SVNErrorCode.ENTRY_NOT_FOUND, "''{0}'' is not under version control", myTarget1); + SVNErrorMessage.create(SVNErrorCode.ENTRY_NOT_FOUND, "''{0}'' is not under version control", myTarget2); SVNErrorManager.error(err, SVNLogType.WC); } else if (info1.getURL() == null) { - SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_MISSING_URL, "''{0}'' has no URL", myTarget1); + SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_MISSING_URL, "''{0}'' has no URL", myTarget2); SVNErrorManager.error(err, SVNLogType.WC); } final SVNReporter17 reporter17 = - new SVNReporter17(myTarget1.getFile(), new SVNWCContext(myVcs.getSvnKitManager().getSvnOptions(), new ISVNEventHandler() { + new SVNReporter17(myTarget2.getFile(), new SVNWCContext(myVcs.getSvnKitManager().getSvnOptions(), new ISVNEventHandler() { @Override public void handleEvent(SVNEvent event, double progress) throws SVNException { } @@ -169,9 +170,9 @@ public class SvnKitDiffClient extends BaseSvnClient implements DiffClient { try { repository = myVcs.getSvnKitManager().createRepository(info1.getURL()); long rev = repository.getLatestRevision(); - repository2 = myVcs.getSvnKitManager().createRepository(myTarget2.getURL()); - SvnDiffEditor diffEditor = new SvnDiffEditor(myTarget1.getFile(), repository2, rev, true); - repository.diff(myTarget2.getURL(), rev, rev, null, true, SVNDepth.INFINITY, false, reporter17, + repository2 = myVcs.getSvnKitManager().createRepository(myTarget1.getURL()); + SvnDiffEditor diffEditor = new SvnDiffEditor(myTarget2.getFile(), repository2, rev, true); + repository.diff(myTarget1.getURL(), rev, rev, null, true, SVNDepth.INFINITY, false, reporter17, SVNCancellableEditor.newInstance(diffEditor, new SvnKitProgressCanceller(), null)); return diffEditor.getChangesMap().values(); @@ -193,7 +194,7 @@ public class SvnKitDiffClient extends BaseSvnClient implements DiffClient { SVNRepository repository = null; SVNRepository repository2 = null; try { - SVNAdminAreaInfo info = wcAccess.openAnchor(myTarget1.getFile(), false, SVNWCAccess.INFINITE_DEPTH); + SVNAdminAreaInfo info = wcAccess.openAnchor(myTarget2.getFile(), false, SVNWCAccess.INFINITE_DEPTH); File anchorPath = info.getAnchor().getRoot(); String target = "".equals(info.getTargetName()) ? null : info.getTargetName(); @@ -215,10 +216,10 @@ public class SvnKitDiffClient extends BaseSvnClient implements DiffClient { repository = myVcs.getSvnKitManager().createRepository(anchorURL.toString()); long rev = repository.getLatestRevision(); repository2 = - myVcs.getSvnKitManager().createRepository((target == null) ? myTarget2.getURL() : myTarget2.getURL().removePathTail()); + myVcs.getSvnKitManager().createRepository((target == null) ? myTarget1.getURL() : myTarget1.getURL().removePathTail()); SvnDiffEditor diffEditor = - new SvnDiffEditor(target == null ? myTarget1.getFile() : myTarget1.getFile().getParentFile(), repository2, rev, true); - repository.diff(myTarget2.getURL(), rev, rev, target, true, true, false, reporter, + new SvnDiffEditor(target == null ? myTarget2.getFile() : myTarget2.getFile().getParentFile(), repository2, rev, true); + repository.diff(myTarget1.getURL(), rev, rev, target, true, true, false, reporter, SVNCancellableEditor.newInstance(diffEditor, new SvnKitProgressCanceller(), null)); return diffEditor.getChangesMap().values(); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnDiffFromHistoryHandler.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnDiffFromHistoryHandler.java new file mode 100644 index 000000000000..be112127ecc9 --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnDiffFromHistoryHandler.java @@ -0,0 +1,80 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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.history; + +import com.intellij.openapi.vcs.FilePath; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vcs.changes.Change; +import com.intellij.openapi.vcs.history.BaseDiffFromHistoryHandler; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.svn.SvnUtil; +import org.jetbrains.idea.svn.SvnVcs; +import org.jetbrains.idea.svn.api.ClientFactory; +import org.jetbrains.idea.svn.diff.DirectoryWithBranchComparer; +import org.tmatesoft.svn.core.wc.SVNRevision; +import org.tmatesoft.svn.core.wc2.SvnTarget; + +import java.io.File; +import java.util.List; + +/** + * @author Konstantin Kolosovsky. + */ +public class SvnDiffFromHistoryHandler extends BaseDiffFromHistoryHandler<SvnFileRevision> { + + @NotNull private final SvnVcs myVcs; + + public SvnDiffFromHistoryHandler(@NotNull SvnVcs vcs) { + super(vcs.getProject()); + myVcs = vcs; + } + + @NotNull + @Override + protected List<Change> getChangesBetweenRevisions(@NotNull FilePath path, @NotNull SvnFileRevision rev1, @Nullable SvnFileRevision rev2) + throws VcsException { + File file = path.getIOFile(); + SvnTarget target1 = SvnTarget.fromURL(SvnUtil.createUrl(rev1.getURL()), rev1.getRevision()); + SvnTarget target2 = rev2 != null ? SvnTarget.fromURL(SvnUtil.createUrl(rev2.getURL()), rev2.getRevision()) : SvnTarget.fromFile(file); + + return executeDiff(path, target1, target2); + } + + @NotNull + @Override + protected List<Change> getAffectedChanges(@NotNull FilePath path, @NotNull SvnFileRevision rev) throws VcsException { + // Diff with zero revision is used here to get just affected changes under the path, and not all affected changes of the revision. + SvnTarget target1 = SvnTarget.fromURL(SvnUtil.createUrl(rev.getURL()), SVNRevision.create(0)); + SvnTarget target2 = SvnTarget.fromURL(SvnUtil.createUrl(rev.getURL()), rev.getRevision()); + + return executeDiff(path, target1, target2); + } + + @NotNull + @Override + protected String getPresentableName(@NotNull SvnFileRevision revision) { + return revision.getRevisionNumber().asString(); + } + + @NotNull + private List<Change> executeDiff(@NotNull FilePath path, @NotNull SvnTarget target1, @NotNull SvnTarget target2) throws VcsException { + File file = path.getIOFile(); + ClientFactory factory = target2.isURL() ? myVcs.getFactory(file) : DirectoryWithBranchComparer.getClientFactory(myVcs, file); + + return factory.createDiffClient().compare(target1, target2); + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnEditCommitMessageAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnEditCommitMessageAction.java index d2b820607ff4..8d1830763fc6 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnEditCommitMessageAction.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnEditCommitMessageAction.java @@ -40,8 +40,8 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnPropertyKeys; import org.jetbrains.idea.svn.SvnUtil; import org.jetbrains.idea.svn.SvnVcs; +import org.jetbrains.idea.svn.properties.PropertyValue; import org.tmatesoft.svn.core.SVNException; -import org.tmatesoft.svn.core.SVNPropertyValue; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; @@ -145,7 +145,7 @@ public class SvnEditCommitMessageAction extends AnAction { } SvnTarget target = SvnTarget.fromURL(root); myVcs.getFactory(target).createPropertyClient() - .setRevisionProperty(target, SvnPropertyKeys.LOG, SVNRevision.create(myNumber), SVNPropertyValue.create(myNewMessage), false); + .setRevisionProperty(target, SvnPropertyKeys.LOG, SVNRevision.create(myNumber), PropertyValue.create(myNewMessage), false); } catch (SVNException e) { myException = new VcsException(e); 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 9e9dd7e1befc..b23b57772535 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java @@ -73,7 +73,7 @@ public class SvnHistoryProvider @Override public DiffFromHistoryHandler getHistoryDiffHandler() { - return null; + return new SvnDiffFromHistoryHandler(myVcs); } @Override diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistorySession.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistorySession.java index f2f91bceec14..8ae2da7cf8b3 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistorySession.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistorySession.java @@ -77,11 +77,6 @@ public class SvnHistorySession extends VcsAbstractHistorySession { return myCommittedPath; } - @Override - public boolean isContentAvailable(final VcsFileRevision revision) { - return !myCommittedPath.isDirectory(); - } - public boolean isHaveMergeSources() { return myHaveMergeSources; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/ignore/SvnPropertyService.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/ignore/SvnPropertyService.java index 8a9dbf760922..e0bdc15f78b1 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/ignore/SvnPropertyService.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/ignore/SvnPropertyService.java @@ -24,8 +24,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.svn.SvnPropertyKeys; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.api.Depth; -import org.tmatesoft.svn.core.SVNPropertyValue; -import org.tmatesoft.svn.core.wc.SVNPropertyData; +import org.jetbrains.idea.svn.properties.PropertyValue; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; @@ -68,7 +67,7 @@ public class SvnPropertyService { protected final boolean myCanUseCachedProperty; protected abstract void processFolder(final VirtualFile folder, final File folderDir, final Set<String> data, - final SVNPropertyValue propertyValue) throws VcsException; + final PropertyValue propertyValue) throws VcsException; protected abstract void onAfterProcessing(final VirtualFile[] file) throws VcsException; @@ -92,14 +91,12 @@ public class SvnPropertyService { } final File dir = new File(entry.getKey().getPath()); try { - final SVNPropertyValue value; + final PropertyValue value; if (myCanUseCachedProperty) { value = myVcs.getPropertyWithCaching(entry.getKey(), SvnPropertyKeys.SVN_IGNORE); } else { - final SVNPropertyData data = - myVcs.getFactory(dir).createPropertyClient() - .getProperty(SvnTarget.fromFile(dir), SvnPropertyKeys.SVN_IGNORE, false, SVNRevision.WORKING); - value = data == null ? null : data.getValue(); + value = myVcs.getFactory(dir).createPropertyClient() + .getProperty(SvnTarget.fromFile(dir), SvnPropertyKeys.SVN_IGNORE, false, SVNRevision.WORKING); } processFolder(entry.getKey(), dir, entry.getValue(), value); } @@ -127,7 +124,7 @@ public class SvnPropertyService { return (! myFilesOk) && (! myExtensionOk); } - protected void processFolder(final VirtualFile folder, final File folderDir, final Set<String> data, final SVNPropertyValue propertyValue) + protected void processFolder(final VirtualFile folder, final File folderDir, final Set<String> data, final PropertyValue propertyValue) throws VcsException { if (propertyValue == null) { myFilesOk = false; @@ -135,7 +132,7 @@ public class SvnPropertyService { return; } final Set<String> ignorePatterns = new HashSet<String>(); - final StringTokenizer st = new StringTokenizer(SVNPropertyValue.getPropertyAsString(propertyValue), "\r\n "); + final StringTokenizer st = new StringTokenizer(PropertyValue.toString(propertyValue), "\r\n "); while (st.hasMoreElements()) { final String ignorePattern = (String)st.nextElement(); ignorePatterns.add(ignorePattern); @@ -180,14 +177,14 @@ public class SvnPropertyService { return false; } - protected abstract String getNewPropertyValue(final Set<String> data, final SVNPropertyValue propertyValue); + protected abstract String getNewPropertyValue(final Set<String> data, final PropertyValue propertyValue); - protected void processFolder(final VirtualFile folder, final File folderDir, final Set<String> data, final SVNPropertyValue propertyValue) + protected void processFolder(final VirtualFile folder, final File folderDir, final Set<String> data, final PropertyValue propertyValue) throws VcsException { String newValue = getNewPropertyValue(data, propertyValue); newValue = (newValue.trim().isEmpty()) ? null : newValue; myVcs.getFactory(folderDir).createPropertyClient() - .setProperty(folderDir, SvnPropertyKeys.SVN_IGNORE, SVNPropertyValue.create(newValue), Depth.EMPTY, false); + .setProperty(folderDir, SvnPropertyKeys.SVN_IGNORE, PropertyValue.create(newValue), Depth.EMPTY, false); if (myUseCommonExtension) { dirtyScopeManager.dirDirtyRecursively(folder); @@ -216,9 +213,9 @@ public class SvnPropertyService { super(activeVcs, project, useCommonExtension); } - protected String getNewPropertyValue(final Set<String> data, final SVNPropertyValue propertyValue) { + protected String getNewPropertyValue(final Set<String> data, final PropertyValue propertyValue) { if (propertyValue != null) { - return getNewPropertyValueForRemove(data, SVNPropertyValue.getPropertyAsString(propertyValue)); + return getNewPropertyValueForRemove(data, PropertyValue.toString(propertyValue)); } return ""; } @@ -241,7 +238,7 @@ public class SvnPropertyService { super(activeVcs, project, useCommonExtension); } - protected String getNewPropertyValue(final Set<String> data, final SVNPropertyValue propertyValue) { + protected String getNewPropertyValue(final Set<String> data, final PropertyValue propertyValue) { final String ignoreString; if (data.size() == 1) { ignoreString = data.iterator().next(); @@ -252,7 +249,7 @@ public class SvnPropertyService { } ignoreString = sb.toString(); } - return (propertyValue == null) ? ignoreString : (SVNPropertyValue.getPropertyAsString(propertyValue) + '\n' + ignoreString); + return (propertyValue == null) ? ignoreString : (PropertyValue.toString(propertyValue) + '\n' + ignoreString); } } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/GatheringChangelistBuilder.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/GatheringChangelistBuilder.java index b6228fca921d..1e031e20d408 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/GatheringChangelistBuilder.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/GatheringChangelistBuilder.java @@ -20,7 +20,10 @@ import com.intellij.openapi.util.Comparing; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.VcsKey; -import com.intellij.openapi.vcs.changes.*; +import com.intellij.openapi.vcs.changes.Change; +import com.intellij.openapi.vcs.changes.ChangeList; +import com.intellij.openapi.vcs.changes.ChangesUtil; +import com.intellij.openapi.vcs.changes.EmptyChangelistBuilder; import com.intellij.openapi.vcs.update.UpdatedFilesReverseSide; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.containers.ContainerUtil; @@ -28,12 +31,14 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnPropertyKeys; import org.jetbrains.idea.svn.SvnVcs; -import org.tmatesoft.svn.core.wc.SVNPropertyData; +import org.jetbrains.idea.svn.properties.PropertyValue; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; import java.io.File; -import java.util.*; +import java.util.Iterator; +import java.util.List; +import java.util.Set; public class GatheringChangelistBuilder extends EmptyChangelistBuilder { @@ -92,13 +97,13 @@ public class GatheringChangelistBuilder extends EmptyChangelistBuilder { SvnTarget target = SvnTarget.fromFile(file); try { - SVNPropertyData current = + PropertyValue current = myVcs.getFactory(target).createPropertyClient().getProperty(target, SvnPropertyKeys.MERGE_INFO, false, SVNRevision.WORKING); - SVNPropertyData base = + PropertyValue base = myVcs.getFactory(target).createPropertyClient().getProperty(target, SvnPropertyKeys.MERGE_INFO, false, SVNRevision.BASE); if (current != null) { - return base == null || !Comparing.equal(current.getValue(), base.getValue()); + return base == null || !Comparing.equal(current, base); } } catch (VcsException e) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/BranchInfo.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/BranchInfo.java index 62638291b485..701bb2575001 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/BranchInfo.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/BranchInfo.java @@ -22,10 +22,10 @@ import com.intellij.util.containers.MultiMap; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.history.SvnChangeList; import org.jetbrains.idea.svn.info.Info; +import org.jetbrains.idea.svn.properties.PropertyValue; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.internal.util.SVNMergeInfoUtil; import org.tmatesoft.svn.core.internal.util.SVNPathUtil; -import org.tmatesoft.svn.core.wc.SVNPropertyData; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; @@ -205,7 +205,7 @@ public class BranchInfo { return SvnMergeInfoCache.MergeCheckResult.getInstance(mergeInfo.contains(revisionAsked)); } - final SVNPropertyData mergeinfoProperty; + final PropertyValue mergeinfoProperty; SvnTarget target = SvnTarget.fromURL(branchUrl); try { @@ -235,7 +235,7 @@ public class BranchInfo { return goUpInRepo(revisionAsked, targetRevision, newBranchUrl, newTrunkUrl); } // process - return processMergeinfoProperty(keyString, revisionAsked, mergeinfoProperty.getValue(), trunkUrl, false); + return processMergeinfoProperty(keyString, revisionAsked, mergeinfoProperty, trunkUrl, false); } private Info getInfo(final File pathFile) { @@ -277,7 +277,7 @@ public class BranchInfo { return SvnMergeInfoCache.MergeCheckResult.getInstance(merged); } - final SVNPropertyData mergeinfoProperty; + final PropertyValue mergeinfoProperty; try { if (actualRevision == targetRevisionCorrected) { // look in WC @@ -302,11 +302,11 @@ public class BranchInfo { return goUp(revisionAsked, targetRevisionCorrected, branchRootPath, path, trunkUrl); } // process - return processMergeinfoProperty(keyString, revisionAsked, mergeinfoProperty.getValue(), trunkUrl, self); + return processMergeinfoProperty(keyString, revisionAsked, mergeinfoProperty, trunkUrl, self); } private SvnMergeInfoCache.MergeCheckResult processMergeinfoProperty(final String pathWithRevisionNumber, final long revisionAsked, - final SVNPropertyValue value, final String trunkRelativeUrl, + final PropertyValue value, final String trunkRelativeUrl, final boolean self) { final String valueAsString = value.toString().trim(); @@ -318,7 +318,7 @@ public class BranchInfo { final Map<String, SVNMergeRangeList> map; try { - map = SVNMergeInfoUtil.parseMergeInfo(new StringBuffer(replaceSeparators(value.getString())), null); + map = SVNMergeInfoUtil.parseMergeInfo(new StringBuffer(replaceSeparators(value.toString())), null); } catch (SVNException e) { LOG.info(e); 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 0ea95c99c4d4..225bc6ad0396 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java @@ -23,11 +23,12 @@ import com.intellij.util.PairProcessor; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.svn.api.Depth; import org.jetbrains.idea.svn.dialogs.MergeContext; +import org.jetbrains.idea.svn.properties.PropertyConsumer; +import org.jetbrains.idea.svn.properties.PropertyData; +import org.jetbrains.idea.svn.properties.PropertyValue; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.internal.util.SVNMergeInfoUtil; import org.tmatesoft.svn.core.internal.util.SVNPathUtil; -import org.tmatesoft.svn.core.wc.ISVNPropertyHandler; -import org.tmatesoft.svn.core.wc.SVNPropertyData; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; @@ -63,19 +64,19 @@ public class OneRecursiveShotMergeInfoWorker implements MergeInfoWorker { public void prepare() throws VcsException { final Depth depth = Depth.allOrEmpty(myMergeContext.getVcs().getSvnConfiguration().isCheckNestedForQuickMerge()); - ISVNPropertyHandler handler = new ISVNPropertyHandler() { - public void handleProperty(File path, SVNPropertyData property) throws SVNException { + PropertyConsumer handler = new PropertyConsumer() { + public void handleProperty(File path, PropertyData property) throws SVNException { final String key = keyFromFile(path); synchronized (myLock) { myDataMap.put(key, SVNMergeInfoUtil - .parseMergeInfo(new StringBuffer(replaceSeparators(SVNPropertyValue.getPropertyAsString(property.getValue()))), null)); + .parseMergeInfo(new StringBuffer(replaceSeparators(PropertyValue.toString(property.getValue()))), null)); } } - public void handleProperty(SVNURL url, SVNPropertyData property) throws SVNException { + public void handleProperty(SVNURL url, PropertyData property) throws SVNException { } - public void handleProperty(long revision, SVNPropertyData property) throws SVNException { + public void handleProperty(long revision, PropertyData property) throws SVNException { } }; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/CmdPropertyClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/CmdPropertyClient.java index e855abe1ec2e..e053776d14ce 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/CmdPropertyClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/CmdPropertyClient.java @@ -10,9 +10,8 @@ import org.jetbrains.idea.svn.commandLine.CommandExecutor; import org.jetbrains.idea.svn.commandLine.CommandUtil; import org.jetbrains.idea.svn.commandLine.SvnCommandName; import org.jetbrains.idea.svn.info.Info; -import org.tmatesoft.svn.core.*; -import org.tmatesoft.svn.core.wc.ISVNPropertyHandler; -import org.tmatesoft.svn.core.wc.SVNPropertyData; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; @@ -24,6 +23,7 @@ import javax.xml.bind.annotation.XmlValue; import java.io.File; import java.util.ArrayList; import java.util.List; +import java.util.Map; /** * @author Konstantin Kolosovsky. @@ -32,10 +32,10 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient { @Nullable @Override - public SVNPropertyData getProperty(@NotNull SvnTarget target, - @NotNull String property, - boolean revisionProperty, - @Nullable SVNRevision revision) + public PropertyValue getProperty(@NotNull SvnTarget target, + @NotNull String property, + boolean revisionProperty, + @Nullable SVNRevision revision) throws VcsException { List<String> parameters = new ArrayList<String>(); @@ -57,7 +57,9 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient { parameters.add("--xml"); CommandExecutor command = execute(myVcs, target, SvnCommandName.propget, parameters, null); - return parseSingleProperty(target, command.getOutput()); + PropertyData data = parseSingleProperty(target, command.getOutput()); + + return data != null ? data.getValue() : null; } @Override @@ -65,7 +67,7 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient { @NotNull String property, @Nullable SVNRevision revision, @Nullable Depth depth, - @Nullable ISVNPropertyHandler handler) throws VcsException { + @Nullable PropertyConsumer handler) throws VcsException { List<String> parameters = new ArrayList<String>(); parameters.add(property); @@ -79,7 +81,7 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient { public void list(@NotNull SvnTarget target, @Nullable SVNRevision revision, @Nullable Depth depth, - @Nullable ISVNPropertyHandler handler) throws VcsException { + @Nullable PropertyConsumer handler) throws VcsException { List<String> parameters = new ArrayList<String>(); fillListParameters(target, revision, depth, parameters, true); @@ -90,39 +92,39 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient { @Override public void setProperty(@NotNull File file, @NotNull String property, - @Nullable SVNPropertyValue value, + @Nullable PropertyValue value, @Nullable Depth depth, boolean force) throws VcsException { runSetProperty(SvnTarget.fromFile(file), property, null, depth, value, force); } @Override - public void setProperties(@NotNull File file, @NotNull SVNProperties properties) throws VcsException { - SVNProperties currentProperties = collectPropertiesToDelete(file); + public void setProperties(@NotNull File file, @NotNull PropertiesMap properties) throws VcsException { + PropertiesMap currentProperties = collectPropertiesToDelete(file); currentProperties.putAll(properties); - for (String propertyName : currentProperties.nameSet()) { - setProperty(file, propertyName, currentProperties.getSVNPropertyValue(propertyName), Depth.EMPTY, true); + for (Map.Entry<String, PropertyValue> entry : currentProperties.entrySet()) { + setProperty(file, entry.getKey(), entry.getValue(), Depth.EMPTY, true); } } @NotNull - private SVNProperties collectPropertiesToDelete(@NotNull File file) throws VcsException { - final SVNProperties result = new SVNProperties(); + private PropertiesMap collectPropertiesToDelete(@NotNull File file) throws VcsException { + final PropertiesMap result = new PropertiesMap(); - list(SvnTarget.fromFile(file), null, Depth.EMPTY, new ISVNPropertyHandler() { + list(SvnTarget.fromFile(file), null, Depth.EMPTY, new PropertyConsumer() { @Override - public void handleProperty(File path, SVNPropertyData property) throws SVNException { + public void handleProperty(File path, PropertyData property) throws SVNException { // null indicates property will be deleted - result.put(property.getName(), (SVNPropertyValue)null); + result.put(property.getName(), null); } @Override - public void handleProperty(SVNURL url, SVNPropertyData property) throws SVNException { + public void handleProperty(SVNURL url, PropertyData property) throws SVNException { } @Override - public void handleProperty(long revision, SVNPropertyData property) throws SVNException { + public void handleProperty(long revision, PropertyData property) throws SVNException { } }); @@ -133,7 +135,7 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient { public void setRevisionProperty(@NotNull SvnTarget target, @NotNull String property, @NotNull SVNRevision revision, - @Nullable SVNPropertyValue value, + @Nullable PropertyValue value, boolean force) throws VcsException { runSetProperty(target, property, revision, null, value, force); } @@ -142,7 +144,7 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient { @NotNull String property, @Nullable SVNRevision revision, @Nullable Depth depth, - @Nullable SVNPropertyValue value, + @Nullable PropertyValue value, boolean force) throws VcsException { List<String> parameters = new ArrayList<String>(); boolean isDelete = value == null; @@ -153,7 +155,7 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient { CommandUtil.put(parameters, revision); } if (!isDelete) { - parameters.add(SVNPropertyValue.getPropertyAsString(value)); + parameters.add(PropertyValue.toString(value)); // --force could only be used in "propset" command, but not in "propdel" command CommandUtil.put(parameters, force, "--force"); } @@ -180,21 +182,22 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient { CommandUtil.put(parameters, verbose, "--verbose"); } - private SVNPropertyData parseSingleProperty(SvnTarget target, String output) throws VcsException { - final SVNPropertyData[] data = new SVNPropertyData[1]; - ISVNPropertyHandler handler = new ISVNPropertyHandler() { + @Nullable + private PropertyData parseSingleProperty(SvnTarget target, String output) throws VcsException { + final PropertyData[] data = new PropertyData[1]; + PropertyConsumer handler = new PropertyConsumer() { @Override - public void handleProperty(File path, SVNPropertyData property) throws SVNException { + public void handleProperty(File path, PropertyData property) throws SVNException { data[0] = property; } @Override - public void handleProperty(SVNURL url, SVNPropertyData property) throws SVNException { + public void handleProperty(SVNURL url, PropertyData property) throws SVNException { data[0] = property; } @Override - public void handleProperty(long revision, SVNPropertyData property) throws SVNException { + public void handleProperty(long revision, PropertyData property) throws SVNException { data[0] = property; } }; @@ -204,7 +207,7 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient { return data[0]; } - private static void parseOutput(SvnTarget target, String output, ISVNPropertyHandler handler) throws VcsException { + private static void parseOutput(SvnTarget target, String output, PropertyConsumer handler) throws VcsException { try { Properties properties = CommandUtil.parse(output, Properties.class); @@ -231,7 +234,7 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient { } } - private static void invokeHandler(@NotNull SvnTarget target, @Nullable SVNPropertyData data, @Nullable ISVNPropertyHandler handler) + private static void invokeHandler(@NotNull SvnTarget target, @Nullable PropertyData data, @Nullable PropertyConsumer handler) throws SVNException { if (handler != null && data != null) { if (target.isFile()) { @@ -242,7 +245,7 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient { } } - private static void invokeHandler(long revision, @Nullable SVNPropertyData data, @Nullable ISVNPropertyHandler handler) + private static void invokeHandler(long revision, @Nullable PropertyData data, @Nullable PropertyConsumer handler) throws SVNException { if (handler != null && data != null) { handler.handleProperty(revision, data); @@ -250,13 +253,13 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient { } @Nullable - private static SVNPropertyData create(@NotNull String property, @Nullable String value) { - SVNPropertyData result = null; + private static PropertyData create(@NotNull String property, @Nullable String value) { + PropertyData result = null; // such behavior is required to compatibility with SVNKit as some logic in merge depends on // whether null property data or property data with empty string value is returned if (value != null) { - result = new SVNPropertyData(property, SVNPropertyValue.create(value.trim()), LF_SEPARATOR_OPTIONS); + result = new PropertyData(property, PropertyValue.create(value.trim())); } return result; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/ExternalsDefinitionParser.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/ExternalsDefinitionParser.java new file mode 100644 index 000000000000..b3ec74e397cb --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/ExternalsDefinitionParser.java @@ -0,0 +1,106 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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.properties; + +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.commandLine.SvnBindException; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author Konstantin Kolosovsky. + */ +public class ExternalsDefinitionParser { + + /** + * Parses "svn:externals" property in format starting from svn 1.5. + * + * @return map of externals definitions: key - relative directory, value - corresponding complete externals definition. + */ + @NotNull + public static Map<String, String> parseExternalsProperty(@NotNull String externals) throws SvnBindException { + HashMap<String, String> map = ContainerUtil.newHashMap(); + + for (String external : StringUtil.splitByLines(externals, true)) { + map.put(parseRelativeDirectory(external), external); + } + + return map; + } + + /** + * Parses relative directory from externals definition (in format starting from svn 1.5). Restrictions for relative directory: + * - is at the end of externals definition separated from other parameters by ' ' char + * - could be quoted with '"' char + * - certain chars could be escaped with '\' char + */ + @NotNull + public static String parseRelativeDirectory(@NotNull String s) throws SvnBindException { + s = s.trim(); + + int length = s.length(); + String result; + + if (isUnescapedQuote(s, length - 1)) { + int index = lastUnescapedIndexOf(s, length - 1, '"'); + assertIndex(s, index, "Could not find start quote"); + result = s.substring(index + 1, length - 1); + } + else { + int index = lastUnescapedIndexOf(s, length, ' '); + assertIndex(s, index, "Could not find separating space"); + result = s.substring(index + 1); + } + + return unescape(result); + } + + private static void assertIndex(@NotNull String s, int index, @NotNull String message) throws SvnBindException { + if (index < 0) { + throw new SvnBindException(message + " - " + s); + } + } + + @NotNull + private static String unescape(@NotNull String s) { + return s.replace("\\", ""); + } + + /** + * "from" index is excluded. + */ + private static int lastUnescapedIndexOf(@NotNull String s, int from, char c) { + int result = from; + + do { + result = s.lastIndexOf(c, result - 1); + } + while (result != -1 && !isUnescaped(s, result, c)); + + return result; + } + + private static boolean isUnescapedQuote(@NotNull String s, int index) { + return isUnescaped(s, index, '"'); + } + + private static boolean isUnescaped(@NotNull String s, int index, char c) { + return StringUtil.isChar(s, index, c) && !StringUtil.isChar(s, index - 1, '\\'); + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertiesMap.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertiesMap.java new file mode 100644 index 000000000000..c5857aa4b345 --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertiesMap.java @@ -0,0 +1,24 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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.properties; + +import com.intellij.util.containers.HashMap; + +/** + * @author Konstantin Kolosovsky. + */ +public class PropertiesMap extends HashMap<String, PropertyValue> { +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyClient.java index 1b61d59c0e20..42acfc8109d7 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyClient.java @@ -1,18 +1,10 @@ package org.jetbrains.idea.svn.properties; import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vfs.CharsetToolkit; -import com.intellij.util.LineSeparator; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.api.Depth; import org.jetbrains.idea.svn.api.SvnClient; -import org.tmatesoft.svn.core.SVNProperties; -import org.tmatesoft.svn.core.SVNPropertyValue; -import org.tmatesoft.svn.core.internal.wc.DefaultSVNOptions; -import org.tmatesoft.svn.core.wc.ISVNOptions; -import org.tmatesoft.svn.core.wc.ISVNPropertyHandler; -import org.tmatesoft.svn.core.wc.SVNPropertyData; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; @@ -23,40 +15,33 @@ import java.io.File; */ public interface PropertyClient extends SvnClient { - ISVNOptions LF_SEPARATOR_OPTIONS = new DefaultSVNOptions() { - @Override - public byte[] getNativeEOL() { - return CharsetToolkit.getUtf8Bytes(LineSeparator.LF.getSeparatorString()); - } - }; - @Nullable - SVNPropertyData getProperty(@NotNull final SvnTarget target, - @NotNull final String property, - boolean revisionProperty, - @Nullable SVNRevision revision) throws VcsException; + PropertyValue getProperty(@NotNull final SvnTarget target, + @NotNull final String property, + boolean revisionProperty, + @Nullable SVNRevision revision) throws VcsException; void getProperty(@NotNull SvnTarget target, @NotNull String property, @Nullable SVNRevision revision, @Nullable Depth depth, - @Nullable ISVNPropertyHandler handler) throws VcsException; + @Nullable PropertyConsumer handler) throws VcsException; void list(@NotNull SvnTarget target, @Nullable SVNRevision revision, @Nullable Depth depth, - @Nullable ISVNPropertyHandler handler) throws VcsException; + @Nullable PropertyConsumer handler) throws VcsException; void setProperty(@NotNull File file, @NotNull String property, - @Nullable SVNPropertyValue value, + @Nullable PropertyValue value, @Nullable Depth depth, boolean force) throws VcsException; - void setProperties(@NotNull File file, @NotNull SVNProperties properties) throws VcsException; + void setProperties(@NotNull File file, @NotNull PropertiesMap properties) throws VcsException; void setRevisionProperty(@NotNull SvnTarget target, @NotNull String property, @NotNull SVNRevision revision, - @Nullable SVNPropertyValue value, + @Nullable PropertyValue value, boolean force) throws VcsException; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyConsumer.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyConsumer.java new file mode 100644 index 000000000000..f45e09df39d5 --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyConsumer.java @@ -0,0 +1,33 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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.properties; + +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNURL; + +import java.io.File; + +/** + * @author Konstantin Kolosovsky. + */ +public interface PropertyConsumer { + + void handleProperty(File path, PropertyData property) throws SVNException; + + void handleProperty(SVNURL url, PropertyData property) throws SVNException; + + void handleProperty(long revision, PropertyData property) throws SVNException; +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyData.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyData.java new file mode 100644 index 000000000000..3953636d870c --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyData.java @@ -0,0 +1,53 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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.properties; + +import org.jetbrains.annotations.Nullable; +import org.tmatesoft.svn.core.wc.SVNPropertyData; + +/** + * @author Konstantin Kolosovsky. + */ +public class PropertyData { + + private final PropertyValue myValue; + + private final String myName; + + public PropertyData(String name, PropertyValue value) { + myName = name; + myValue = value; + } + + public String getName() { + return myName; + } + + public PropertyValue getValue() { + return myValue; + } + + @Nullable + public static PropertyData create(@Nullable SVNPropertyData data) { + PropertyData result = null; + + if (data != null) { + result = new PropertyData(data.getName(), PropertyValue.create(data.getValue())); + } + + return result; + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyValue.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyValue.java new file mode 100644 index 000000000000..62cb7cbd0340 --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyValue.java @@ -0,0 +1,53 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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.properties; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.tmatesoft.svn.core.SVNPropertyValue; + +/** + * TODO: Add correct support of binary properties - support in api, diff, etc. + * + * @author Konstantin Kolosovsky. + */ +public class PropertyValue { + + @NotNull private final String myValue; + + @Nullable + public static PropertyValue create(@Nullable SVNPropertyValue value) { + return create(SVNPropertyValue.getPropertyAsString(value)); + } + + private PropertyValue(@NotNull String propertyValue) { + myValue = propertyValue; + } + + @Nullable + public static PropertyValue create(@Nullable String propertyValue) { + return propertyValue == null ? null : new PropertyValue(propertyValue); + } + + @Nullable + public static String toString(@Nullable PropertyValue value) { + return value == null ? null : value.myValue; + } + + public String toString() { + return myValue; + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/SvnKitPropertyClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/SvnKitPropertyClient.java index 4ad3f10afccc..23fedd3c7ac8 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/SvnKitPropertyClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/SvnKitPropertyClient.java @@ -1,42 +1,57 @@ package org.jetbrains.idea.svn.properties; import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vfs.CharsetToolkit; +import com.intellij.util.LineSeparator; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.api.BaseSvnClient; import org.jetbrains.idea.svn.api.Depth; import org.jetbrains.idea.svn.commandLine.SvnBindException; import org.tmatesoft.svn.core.*; +import org.tmatesoft.svn.core.internal.wc.DefaultSVNOptions; import org.tmatesoft.svn.core.wc.*; import org.tmatesoft.svn.core.wc2.SvnTarget; import java.io.File; +import java.util.Map; /** * @author Konstantin Kolosovsky. */ public class SvnKitPropertyClient extends BaseSvnClient implements PropertyClient { + public static final ISVNOptions LF_SEPARATOR_OPTIONS = new DefaultSVNOptions() { + @Override + public byte[] getNativeEOL() { + return CharsetToolkit.getUtf8Bytes(LineSeparator.LF.getSeparatorString()); + } + }; + @Nullable @Override - public SVNPropertyData getProperty(@NotNull SvnTarget target, - @NotNull String property, - boolean revisionProperty, - @Nullable SVNRevision revision) throws VcsException { + public PropertyValue getProperty(@NotNull SvnTarget target, + @NotNull String property, + boolean revisionProperty, + @Nullable SVNRevision revision) throws VcsException { + PropertyData resultData; + try { if (!revisionProperty) { if (target.isFile()) { - return createClient().doGetProperty(target.getFile(), property, target.getPegRevision(), revision); + resultData = PropertyData.create(createClient().doGetProperty(target.getFile(), property, target.getPegRevision(), revision)); } else { - return createClient().doGetProperty(target.getURL(), property, target.getPegRevision(), revision); + resultData = PropertyData.create(createClient().doGetProperty(target.getURL(), property, target.getPegRevision(), revision)); } } else { - return getRevisionProperty(target, property, revision); + resultData = getRevisionProperty(target, property, revision); } } catch (SVNException e) { throw new VcsException(e); } + + return resultData != null ? resultData.getValue() : null; } @NotNull @@ -52,7 +67,7 @@ public class SvnKitPropertyClient extends BaseSvnClient implements PropertyClien @NotNull String property, @Nullable SVNRevision revision, @Nullable Depth depth, - @Nullable ISVNPropertyHandler handler) throws VcsException { + @Nullable PropertyConsumer handler) throws VcsException { runGetProperty(target, property, revision, depth, handler); } @@ -60,18 +75,18 @@ public class SvnKitPropertyClient extends BaseSvnClient implements PropertyClien public void list(@NotNull SvnTarget target, @Nullable SVNRevision revision, @Nullable Depth depth, - @Nullable ISVNPropertyHandler handler) throws VcsException { + @Nullable PropertyConsumer handler) throws VcsException { runGetProperty(target, null, revision, depth, handler); } @Override public void setProperty(@NotNull File file, @NotNull String property, - @Nullable SVNPropertyValue value, + @Nullable PropertyValue value, @Nullable Depth depth, boolean force) throws VcsException { try { - createClient().doSetProperty(file, property, value, force, toDepth(depth), null, null); + createClient().doSetProperty(file, property, toPropertyValue(value), force, toDepth(depth), null, null); } catch (SVNException e) { throw new SvnBindException(e); @@ -79,12 +94,13 @@ public class SvnKitPropertyClient extends BaseSvnClient implements PropertyClien } @Override - public void setProperties(@NotNull File file, @NotNull SVNProperties properties) throws VcsException { + public void setProperties(@NotNull File file, @NotNull PropertiesMap properties) throws VcsException { + final SVNProperties propertiesToSet = toSvnProperties(properties); try { createClient().doSetProperty(file, new ISVNPropertyValueProvider() { @Override public SVNProperties providePropertyValues(File path, SVNProperties properties) throws SVNException { - return properties; + return propertiesToSet; } }, true, SVNDepth.EMPTY, null, null); } @@ -97,14 +113,14 @@ public class SvnKitPropertyClient extends BaseSvnClient implements PropertyClien public void setRevisionProperty(@NotNull SvnTarget target, @NotNull String property, @NotNull SVNRevision revision, - @Nullable SVNPropertyValue value, + @Nullable PropertyValue value, boolean force) throws VcsException { try { if (target.isFile()) { - createClient().doSetRevisionProperty(target.getFile(), revision, property, value, force, null); + createClient().doSetRevisionProperty(target.getFile(), revision, property, toPropertyValue(value), force, null); } else { - createClient().doSetRevisionProperty(target.getURL(), revision, property, value, force, null); + createClient().doSetRevisionProperty(target.getURL(), revision, property, toPropertyValue(value), force, null); } } catch (SVNException e) { @@ -112,27 +128,39 @@ public class SvnKitPropertyClient extends BaseSvnClient implements PropertyClien } } + @NotNull + private static SVNProperties toSvnProperties(@NotNull PropertiesMap properties) { + SVNProperties result = new SVNProperties(); + + for (Map.Entry<String, PropertyValue> entry : properties.entrySet()) { + result.put(entry.getKey(), toPropertyValue(entry.getValue())); + } + + return result; + } + private void runGetProperty(@NotNull SvnTarget target, @Nullable String property, @Nullable SVNRevision revision, @Nullable Depth depth, - @Nullable ISVNPropertyHandler handler) throws VcsException { + @Nullable PropertyConsumer handler) throws VcsException { SVNWCClient client = createClient(); try { if (target.isURL()) { - client.doGetProperty(target.getURL(), property, target.getPegRevision(), revision, toDepth(depth), handler); + client.doGetProperty(target.getURL(), property, target.getPegRevision(), revision, toDepth(depth), toHandler(handler)); } else { - client.doGetProperty(target.getFile(), property, target.getPegRevision(), revision, toDepth(depth), handler, null); + client.doGetProperty(target.getFile(), property, target.getPegRevision(), revision, toDepth(depth), toHandler(handler), null); } } catch (SVNException e) { throw new VcsException(e); } } - private SVNPropertyData getRevisionProperty(@NotNull SvnTarget target, @NotNull final String property, @Nullable SVNRevision revision) throws SVNException{ + private PropertyData getRevisionProperty(@NotNull SvnTarget target, @NotNull final String property, @Nullable SVNRevision revision) + throws SVNException { final SVNWCClient client = createClient(); - final SVNPropertyData[] result = new SVNPropertyData[1]; + final PropertyData[] result = new PropertyData[1]; ISVNPropertyHandler handler = new ISVNPropertyHandler() { @Override public void handleProperty(File path, SVNPropertyData property) throws SVNException { @@ -151,7 +179,7 @@ public class SvnKitPropertyClient extends BaseSvnClient implements PropertyClien private void handle(@NotNull SVNPropertyData data) { if (property.equals(data.getName())) { - result[0] = data; + result[0] = PropertyData.create(data); } } }; @@ -164,4 +192,41 @@ public class SvnKitPropertyClient extends BaseSvnClient implements PropertyClien return result[0]; } + + @Nullable + private static ISVNPropertyHandler toHandler(@Nullable final PropertyConsumer consumer) { + ISVNPropertyHandler result = null; + + if (consumer != null) { + result = new ISVNPropertyHandler() { + @Override + public void handleProperty(File path, SVNPropertyData property) throws SVNException { + consumer.handleProperty(path, PropertyData.create(property)); + } + + @Override + public void handleProperty(SVNURL url, SVNPropertyData property) throws SVNException { + consumer.handleProperty(url, PropertyData.create(property)); + } + + @Override + public void handleProperty(long revision, SVNPropertyData property) throws SVNException { + consumer.handleProperty(revision, PropertyData.create(property)); + } + }; + } + + return result; + } + + @Nullable + private static SVNPropertyValue toPropertyValue(@Nullable PropertyValue value) { + SVNPropertyValue result = null; + + if (value != null) { + result = SVNPropertyValue.create(value.toString()); + } + + return result; + } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java index 237d05bd5f7a..7b09461b3766 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java @@ -34,6 +34,9 @@ import org.jetbrains.idea.svn.api.ProgressEvent; import org.jetbrains.idea.svn.api.ProgressTracker; import org.jetbrains.idea.svn.commandLine.SvnBindException; import org.jetbrains.idea.svn.info.Info; +import org.jetbrains.idea.svn.properties.PropertiesMap; +import org.jetbrains.idea.svn.properties.PropertyConsumer; +import org.jetbrains.idea.svn.properties.PropertyData; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.wc.*; import org.tmatesoft.svn.core.wc2.SvnTarget; @@ -100,7 +103,7 @@ public class SvnRollbackEnvironment extends DefaultRollbackEnvironment { }; final List<CopiedAsideInfo> fromToModified = new ArrayList<CopiedAsideInfo>(); - final Map<File, SVNProperties> properties = ContainerUtil.newHashMap(); + final Map<File, PropertiesMap> properties = ContainerUtil.newHashMap(); moveRenamesToTmp(exceptions, fromToModified, properties, collector); // adds (deletes) // deletes (adds) @@ -123,29 +126,29 @@ public class SvnRollbackEnvironment extends DefaultRollbackEnvironment { private void moveRenamesToTmp(List<VcsException> exceptions, List<CopiedAsideInfo> fromToModified, - final Map<File, SVNProperties> properties, + final Map<File, PropertiesMap> properties, final UnversionedAndNotTouchedFilesGroupCollector collector) { final Map<File, ThroughRenameInfo> fromTo = collector.getFromTo(); try { final File tmp = FileUtil.createTempDirectory("forRename", ""); - final ISVNPropertyHandler handler = new ISVNPropertyHandler() { + final PropertyConsumer handler = new PropertyConsumer() { @Override - public void handleProperty(File path, SVNPropertyData property) throws SVNException { + public void handleProperty(File path, PropertyData property) throws SVNException { final ThroughRenameInfo info = collector.findToFile(new FilePathImpl(path, path.isDirectory()), null); if (info != null) { if (!properties.containsKey(info.getTo())) { - properties.put(info.getTo(), new SVNProperties()); + properties.put(info.getTo(), new PropertiesMap()); } properties.get(info.getTo()).put(property.getName(), property.getValue()); } } @Override - public void handleProperty(SVNURL url, SVNPropertyData property) throws SVNException { + public void handleProperty(SVNURL url, PropertyData property) throws SVNException { } @Override - public void handleProperty(long revision, SVNPropertyData property) throws SVNException { + public void handleProperty(long revision, PropertyData property) throws SVNException { } }; @@ -181,7 +184,7 @@ public class SvnRollbackEnvironment extends DefaultRollbackEnvironment { private void moveGroup(final List<VcsException> exceptions, List<CopiedAsideInfo> fromTo, - Map<File, SVNProperties> properties) { + Map<File, PropertiesMap> properties) { Collections.sort(fromTo, new Comparator<CopiedAsideInfo>() { @Override public int compare(CopiedAsideInfo o1, CopiedAsideInfo o2) { @@ -240,8 +243,8 @@ public class SvnRollbackEnvironment extends DefaultRollbackEnvironment { applyProperties(properties, exceptions); } - private void applyProperties(Map<File, SVNProperties> propertiesMap, final List<VcsException> exceptions) { - for (Map.Entry<File, SVNProperties> entry : propertiesMap.entrySet()) { + private void applyProperties(Map<File, PropertiesMap> propertiesMap, final List<VcsException> exceptions) { + for (Map.Entry<File, PropertiesMap> entry : propertiesMap.entrySet()) { File file = entry.getKey(); try { mySvnVcs.getFactory(file).createPropertyClient().setProperties(file, entry.getValue()); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/svnkit/SvnKitAdminAreaFactorySelector.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/svnkit/SvnKitAdminAreaFactorySelector.java new file mode 100644 index 000000000000..0d1a4c0106e0 --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/svnkit/SvnKitAdminAreaFactorySelector.java @@ -0,0 +1,137 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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.svnkit; + +import com.intellij.openapi.application.ApplicationManager; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.svn.SvnFormatSelector; +import org.jetbrains.idea.svn.SvnWorkingCopyFormatHolder; +import org.jetbrains.idea.svn.WorkingCopyFormat; +import org.tmatesoft.svn.core.SVNErrorCode; +import org.tmatesoft.svn.core.SVNErrorMessage; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.internal.wc.admin.ISVNAdminAreaFactorySelector; +import org.tmatesoft.svn.core.internal.wc.admin.SVNAdminAreaFactory; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; + +/** + * @author Konstantin Kolosovsky. + */ +public class SvnKitAdminAreaFactorySelector implements ISVNAdminAreaFactorySelector { + + public Collection getEnabledFactories(File path, Collection factories, boolean writeAccess) throws SVNException { + if (ApplicationManager.getApplication().isUnitTestMode()) { + return factories; + } + + if (!writeAccess) { + return factories; + } + + Collection result = null; + final WorkingCopyFormat presetFormat = SvnWorkingCopyFormatHolder.getPresetFormat(); + if (presetFormat != null) { + result = format2Factories(presetFormat, factories); + } + + if (result == null) { + final WorkingCopyFormat format = SvnFormatSelector.getWorkingCopyFormat(path); + result = format2Factories(format, factories); + } + + if (result == null) { + throw new SVNException(SVNErrorMessage.create(SVNErrorCode.WC_NOT_DIRECTORY)); + } + return result; + } + + @Nullable + static Collection format2Factories(final WorkingCopyFormat format, final Collection factories) { + if (WorkingCopyFormat.ONE_DOT_SEVEN.equals(format)) { + return factories; + } + else if (WorkingCopyFormat.ONE_DOT_SIX.equals(format)) { + return factoriesFor16(factories); + } + else if (WorkingCopyFormat.ONE_DOT_FIVE.equals(format)) { + return factoriesFor15(factories); + } + else if (WorkingCopyFormat.ONE_DOT_FOUR.equals(format)) { + return factoriesFor14(factories); + } + else if (WorkingCopyFormat.ONE_DOT_THREE.equals(format)) { + return factoriesFor13(factories); + } + return null; + } + + private static Collection<SVNAdminAreaFactory> factoriesFor13(final Collection factories) { + for (Object item : factories) { + final SVNAdminAreaFactory factory = (SVNAdminAreaFactory)item; + final int supportedVersion = factory.getSupportedVersion(); + if (WorkingCopyFormat.ONE_DOT_THREE.getFormat() == supportedVersion) { + return Collections.singletonList(factory); + } + } + return Collections.emptyList(); + } + + private static Collection<SVNAdminAreaFactory> factoriesFor14(final Collection factories) { + final Collection<SVNAdminAreaFactory> result = new ArrayList<SVNAdminAreaFactory>(2); + for (Object item : factories) { + final SVNAdminAreaFactory factory = (SVNAdminAreaFactory)item; + final int supportedVersion = factory.getSupportedVersion(); + if ((WorkingCopyFormat.ONE_DOT_FOUR.getFormat() == supportedVersion) || + (WorkingCopyFormat.ONE_DOT_THREE.getFormat() == supportedVersion)) { + result.add(factory); + } + } + return result; + } + + private static Collection<SVNAdminAreaFactory> factoriesFor15(final Collection factories) { + final Collection<SVNAdminAreaFactory> result = new ArrayList<SVNAdminAreaFactory>(2); + for (Object item : factories) { + final SVNAdminAreaFactory factory = (SVNAdminAreaFactory)item; + final int supportedVersion = factory.getSupportedVersion(); + if ((WorkingCopyFormat.ONE_DOT_FOUR.getFormat() == supportedVersion) || + (WorkingCopyFormat.ONE_DOT_THREE.getFormat() == supportedVersion) || + (WorkingCopyFormat.ONE_DOT_FIVE.getFormat() == supportedVersion)) { + result.add(factory); + } + } + return result; + } + + private static Collection<SVNAdminAreaFactory> factoriesFor16(final Collection factories) { + final Collection<SVNAdminAreaFactory> result = new ArrayList<SVNAdminAreaFactory>(2); + for (Object item : factories) { + final SVNAdminAreaFactory factory = (SVNAdminAreaFactory)item; + final int supportedVersion = factory.getSupportedVersion(); + if ((WorkingCopyFormat.ONE_DOT_FOUR.getFormat() == supportedVersion) || + (WorkingCopyFormat.ONE_DOT_THREE.getFormat() == supportedVersion) || + (WorkingCopyFormat.ONE_DOT_FIVE.getFormat() == supportedVersion) || + (WorkingCopyFormat.ONE_DOT_SIX.getFormat() == supportedVersion)) { + result.add(factory); + } + } + return result; + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/svnkit/SvnKitManager.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/svnkit/SvnKitManager.java index a446b58bb1cb..757100026797 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/svnkit/SvnKitManager.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/svnkit/SvnKitManager.java @@ -26,7 +26,6 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnConfiguration; -import org.jetbrains.idea.svn.SvnFormatSelector; import org.jetbrains.idea.svn.SvnHttpAuthMethodsDefaultChecker; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.auth.SvnAuthenticationManager; @@ -72,7 +71,7 @@ public class SvnKitManager { SVNJNAUtil.setJNAEnabled(true); SvnHttpAuthMethodsDefaultChecker.check(); - SVNAdminAreaFactory.setSelector(new SvnFormatSelector()); + SVNAdminAreaFactory.setSelector(new SvnKitAdminAreaFactorySelector()); DAVRepositoryFactory.setup(); SVNRepositoryFactoryImpl.setup(); |