From 38ed7a7ba34201e6862151103d089ef9e83a73a7 Mon Sep 17 00:00:00 2001 From: irengrig Date: Sun, 6 Dec 2009 18:23:38 +0300 Subject: [PATCH] IDEADEV-41714 ("Collecting Information on Changes" hangs entire GUI) r=yole --- .../jetbrains/idea/svn/SvnBranchConfiguration.java | 496 +++------------------ .../idea/svn/SvnBranchConfigurationManager.java | 218 ++++----- .../jetbrains/idea/svn/SvnBranchMapperManager.java | 3 +- .../src/org/jetbrains/idea/svn/SvnUtil.java | 5 +- .../idea/svn/actions/CompareWithBranchAction.java | 7 +- .../idea/svn/actions/SelectBranchPopup.java | 57 ++- .../idea/svn/branchConfig/BranchesLoader.java | 58 +++ .../idea/svn/branchConfig/DefaultConfigLoader.java | 104 +++++ .../idea/svn/branchConfig/InfoReliability.java | 43 ++ .../idea/svn/branchConfig/InfoStorage.java | 47 ++ .../idea/svn/branchConfig/NewRootBunch.java | 165 +++++++ .../svn/branchConfig/SvnBranchConfigManager.java | 42 ++ .../branchConfig/SvnBranchConfigurationNew.java | 278 ++++++++++++ .../svn/dialogs/BranchConfigurationDialog.java | 38 +- .../org/jetbrains/idea/svn/dialogs/CopyDialog.java | 3 +- .../svn/history/SvnMergeInfoRootPanelManual.java | 3 +- .../jetbrains/idea/svn/history/WcInfoLoader.java | 11 +- .../SvnIntegrateChangesActionPerformer.java | 3 +- .../idea/svn/update/SvnUpdateRootOptionsPanel.java | 3 +- 19 files changed, 983 insertions(+), 601 deletions(-) rewrite plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfiguration.java (86%) create mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchesLoader.java create mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/DefaultConfigLoader.java create mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/InfoReliability.java create mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/InfoStorage.java create mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/NewRootBunch.java create mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigManager.java create mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigurationNew.java diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfiguration.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfiguration.java dissimilarity index 86% index 826b7d0330..0deb0e4fdf 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfiguration.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfiguration.java @@ -1,427 +1,69 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.idea.svn; - -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.progress.ProgressManager; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.Ref; -import com.intellij.openapi.vcs.changes.committed.VcsConfigurationChangeListener; -import com.intellij.openapi.vfs.VirtualFile; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.svn.integrate.SvnBranchItem; -import org.tmatesoft.svn.core.ISVNDirEntryHandler; -import org.tmatesoft.svn.core.SVNDirEntry; -import org.tmatesoft.svn.core.SVNException; -import org.tmatesoft.svn.core.SVNURL; -import org.tmatesoft.svn.core.internal.util.SVNPathUtil; -import org.tmatesoft.svn.core.internal.util.SVNURLUtil; -import org.tmatesoft.svn.core.wc.SVNInfo; -import org.tmatesoft.svn.core.wc.SVNLogClient; -import org.tmatesoft.svn.core.wc.SVNRevision; -import org.tmatesoft.svn.core.wc.SVNWCClient; - -import java.io.File; -import java.util.*; - -/** - * @author yole - */ -public class SvnBranchConfiguration { - private String myTrunkUrl; - private List myBranchUrls; - private Map> myBranchMap; - private boolean myUserinfoInUrl; - - public SvnBranchConfiguration() { - myBranchUrls = new ArrayList(); - myBranchMap = new HashMap>(); - } - - public void setTrunkUrl(final String trunkUrl) { - myTrunkUrl = trunkUrl; - } - - public boolean isUserinfoInUrl() { - return myUserinfoInUrl; - } - - public void setUserinfoInUrl(final boolean userinfoInUrl) { - myUserinfoInUrl = userinfoInUrl; - } - - public void setBranchUrls(final List branchUrls) { - myBranchUrls = branchUrls; - - Collections.sort(myBranchUrls); - - checkMapConsistency(); - } - - private void checkMapConsistency() { - final Map> map = new HashMap>(); - for (String branchUrl : myBranchUrls) { - final List items = myBranchMap.get(branchUrl); - if (items != null) { - map.put(branchUrl, items); - } - } - myBranchMap = map; - } - - public String getTrunkUrl() { - return myTrunkUrl; - } - - public List getBranchUrls() { - return myBranchUrls; - } - - public Map> getBranchMap() { - return myBranchMap; - } - - public Map> getLoadedBranchMap(final Project project) { - loadBranches(project, false); - return myBranchMap; - } - - public void setBranchMap(final Map> branchMap) { - myBranchMap = branchMap; - - checkMapConsistency(); - } - - public SvnBranchConfiguration copy() { - SvnBranchConfiguration result = new SvnBranchConfiguration(); - result.myUserinfoInUrl = myUserinfoInUrl; - result.myTrunkUrl = myTrunkUrl; - result.myBranchUrls = new ArrayList(myBranchUrls); - result.myBranchMap = new HashMap>(); - for (Map.Entry> entry : myBranchMap.entrySet()) { - result.myBranchMap.put(entry.getKey(), new ArrayList(entry.getValue())); - } - return result; - } - - @Nullable - public String getBaseUrl(String url) { - if ((myTrunkUrl != null) && url.startsWith(myTrunkUrl)) { - return myTrunkUrl; - } - for(String branchUrl: myBranchUrls) { - if (url.startsWith(branchUrl)) { - int pos = url.indexOf('/', branchUrl.length()+1); - if (pos >= 0) { - return url.substring(0, pos); - } - return branchUrl; - } - } - return null; - } - - @Nullable - public String getBaseName(String url) { - String baseUrl = getBaseUrl(url); - if (baseUrl == null) { - return null; - } - if (myBranchUrls.size() == 0) { - return baseUrl; - } - int commonPrefixLength = getCommonPrefixLength(url, myTrunkUrl); - for(String branchUrl: myBranchUrls) { - commonPrefixLength = Math.min(commonPrefixLength, getCommonPrefixLength(url, branchUrl)); - if (commonPrefixLength <= 0) { - return baseUrl; - } - } - return baseUrl.substring(commonPrefixLength); - } - - private static int getCommonPrefixLength(final String s1, final String s2) { - final int minLength = Math.min(s1.length(), s2.length()); - for(int i=0; i< minLength; i++) { - if (s1.charAt(i) != s2.charAt(i)) { - return i; - } - } - return minLength; - } - - @Nullable - public String getRelativeUrl(String url) { - String baseUrl = getBaseUrl(url); - return baseUrl == null ? null : url.substring(baseUrl.length()); - } - - @Nullable - public String getBranchByName(final Project project, final String name) throws SVNException { - if (name == null) { - return null; - } - final UrlIterator iterator = new UrlIterator(project); - final MyBranchByNameSearcher listener = new MyBranchByNameSearcher(name); - iterator.iterateUrls(listener); - return listener.getUrl(); - } - - @Nullable - public SVNURL getWorkingBranch(final Project project, final SVNURL someUrl) throws SVNException { - final BranchSearcher branchSearcher = new BranchSearcher(someUrl); - final UrlIterator iterator = new UrlIterator(project); - iterator.iterateUrls(branchSearcher); - - return branchSearcher.getResult(); - } - - private class UrlIterator { - private final Project myProject; - - private UrlIterator(final Project project) { - myProject = project; - } - - public void iterateUrls(final UrlListener listener) throws SVNException { - if (listener.accept(myTrunkUrl)) { - return; - } - - for (String branchUrl : myBranchUrls) { - // use more exact comparison first (paths longer) - final List children = getBranches(branchUrl, myProject, false, true); - for (SvnBranchItem child : children) { - if (listener.accept(child.getUrl())) { - return; - } - } - - if (listener.accept(branchUrl)) { - return; - } - } - } - } - - @Nullable - public Map getUrl2FileMappings(final Project project, final VirtualFile root) { - try { - final BranchRootSearcher searcher = new BranchRootSearcher(SvnVcs.getInstance(project), root); - final UrlIterator iterator = new UrlIterator(project); - iterator.iterateUrls(searcher); - return searcher.getBranchesUnder(); - } catch (SVNException e) { - return null; - } - } - - private static class BranchRootSearcher implements UrlListener { - private final VirtualFile myRoot; - private final SVNURL myRootUrl; - // url path to file path - private final Map myBranchesUnder; - - private BranchRootSearcher(final SvnVcs vcs, final VirtualFile root) throws SVNException { - myRoot = root; - myBranchesUnder = new HashMap(); - final SVNWCClient client = vcs.createWCClient(); - final SVNInfo info = client.doInfo(new File(myRoot.getPath()), SVNRevision.WORKING); - myRootUrl = info.getURL(); - } - - public boolean accept(final String url) throws SVNException { - if (myRootUrl != null) { - final File baseDir = new File(myRoot.getPath()); - final String baseUrl = myRootUrl.getPath(); - - final SVNURL branchUrl = SVNURL.parseURIEncoded(url); - if (myRootUrl.equals(SVNURLUtil.getCommonURLAncestor(myRootUrl, branchUrl))) { - final File file = SvnUtil.fileFromUrl(baseDir, baseUrl, branchUrl.getPath()); - myBranchesUnder.put(url, file.getAbsolutePath()); - } - } - return false; // iterate everything - } - - public Map getBranchesUnder() { - return myBranchesUnder; - } - } - - private interface UrlListener { - boolean accept(final String url) throws SVNException; - } - - private static class BranchSearcher implements UrlListener { - private final SVNURL mySomeUrl; - private SVNURL myResult; - - private BranchSearcher(final SVNURL someUrl) { - mySomeUrl = someUrl; - } - - public boolean accept(final String url) throws SVNException { - myResult = urlIsParent(url, mySomeUrl); - return myResult != null; - } - - public SVNURL getResult() { - return myResult; - } - } - - @Nullable - private static SVNURL urlIsParent(final String parentCandidate, final SVNURL child) throws SVNException { - final SVNURL parentUrl = SVNURL.parseURIEncoded(parentCandidate); - if(parentUrl.equals(SVNURLUtil.getCommonURLAncestor(parentUrl, child))) { - return parentUrl; - } - return null; - } - - public void loadBranches(final Project project, final boolean underProgress) { - for (String branchUrl : myBranchUrls) { - try { - getBranches(branchUrl, project, underProgress, true); - } - catch (SVNException e) { - // clear current (may be incomplete; better to detect it and reload on demand) - myBranchMap.remove(branchUrl); - } - } - } - - public List reloadBranches(final String url, final Project project, final VirtualFile vcsRoot) throws SVNException { - final List result = getBranchesUnderProgress(url, project); - myBranchMap.put(url, result); - - ApplicationManager.getApplication().getMessageBus().asyncPublisher(VcsConfigurationChangeListener.BRANCHES_CHANGED).execute(project, vcsRoot); - - return result; - } - - public List getBranches(final String url, final Project project, final boolean underProgress, final boolean load) throws SVNException { - List result = myBranchMap.get(url); - if ((result != null) && (result.isEmpty() || (result.get(0).getCreationDateMillis() > 0))) { - return result; - } - if (! load) { - return Collections.emptyList(); - } - result = underProgress ? getBranchesUnderProgress(url, project) : getBranchesWithoutProgress(url, project); - myBranchMap.put(url, result); - - return result; - } - - private static List getBranchesUnderProgress(final String url, final Project project) throws SVNException { - final ArrayList result = new ArrayList(); - final Ref ex = new Ref(); - boolean rc = ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { - public void run() { - final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); - if (indicator != null) { - indicator.setIndeterminate(true); - } - try { - getBranchesImpl(project, url, result, true); - } - catch (SVNException e) { - ex.set(e); - } - } - }, SvnBundle.message("compare.with.branch.progress.loading.branches"), true, project); - if (!rc) { - return Collections.emptyList(); - } - if (!ex.isNull()) { - throw ex.get(); - } - return result; - } - - private static List getBranchesWithoutProgress(final String url, final Project project) throws SVNException { - final ArrayList result = new ArrayList(); - getBranchesImpl(project, url, result, false); - return result; - } - - private static void getBranchesImpl(final Project project, final String url, final ArrayList result, - final boolean underProgress) throws SVNException { - final SVNLogClient logClient; - logClient = SvnVcs.getInstance(project).createLogClient(); - final SVNURL branchesUrl = SVNURL.parseURIEncoded(url); - logClient.doList(branchesUrl, SVNRevision.UNDEFINED, SVNRevision.HEAD, false, new ISVNDirEntryHandler() { - public void handleDirEntry(final SVNDirEntry dirEntry) throws SVNException { - if (underProgress) { - ProgressManager.checkCanceled(); - } - final SVNURL currentUrl = dirEntry.getURL(); - if (! branchesUrl.equals(currentUrl)) { - final String url = currentUrl.toString(); - // if have permissions - if (dirEntry.getDate() != null) { - result.add(new SvnBranchItem(url, dirEntry.getDate(), dirEntry.getRevision())); - } - } - } - }); - Collections.sort(result); - } - - public boolean urlsMissing(final SvnBranchConfiguration branch) { - if (! Comparing.equal(myTrunkUrl, branch.getTrunkUrl())) { - return true; - } - - for (String url : branch.getBranchUrls()) { - if (! myBranchUrls.contains(url)) { - return true; - } - } - - return false; - } - - private class MyBranchByNameSearcher implements UrlListener { - private final String myName; - private String myUrl; - - public MyBranchByNameSearcher(final String name) { - myName = name; - } - - public boolean accept(final String url) throws SVNException { - if (myBranchUrls.contains(url)) { - // do not take into account urls of groups - return false; - } - if (myName.equals(SVNPathUtil.tail(url))) { - myUrl = url; - return true; - } - return false; - } - - public String getUrl() { - return myUrl; - } - } -} +/* + * Copyright 2000-2009 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.idea.svn; + +import org.jetbrains.idea.svn.integrate.SvnBranchItem; + +import java.util.*; + +/** + * @author yole + */ +public class SvnBranchConfiguration { + private String myTrunkUrl; + private List myBranchUrls; + private Map> myBranchMap; + private boolean myUserinfoInUrl; + + public SvnBranchConfiguration() { + myBranchUrls = new ArrayList(); + myBranchMap = new HashMap>(); + } + + public boolean isUserinfoInUrl() { + return myUserinfoInUrl; + } + + public void setUserinfoInUrl(final boolean userinfoInUrl) { + myUserinfoInUrl = userinfoInUrl; + } + + public void setBranchUrls(final List branchUrls) { + myBranchUrls = branchUrls; + Collections.sort(myBranchUrls); + } + + public void setTrunkUrl(final String trunkUrl) { + myTrunkUrl = trunkUrl; + } + + public String getTrunkUrl() { + return myTrunkUrl; + } + + public List getBranchUrls() { + return myBranchUrls; + } + + public Map> getBranchMap() { + return myBranchMap; + } + + public void setBranchMap(final Map> branchMap) { + myBranchMap = branchMap; + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfigurationManager.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfigurationManager.java index 225a2d7590..0e3b85226c 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfigurationManager.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfigurationManager.java @@ -16,36 +16,29 @@ package org.jetbrains.idea.svn; +import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.PersistentStateComponent; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; -import com.intellij.openapi.progress.ProcessCanceledException; -import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Ref; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.changes.committed.VcsConfigurationChangeListener; +import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.PairConsumer; import com.intellij.util.messages.MessageBus; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.svn.branchConfig.*; import org.jetbrains.idea.svn.integrate.SvnBranchItem; import org.tmatesoft.svn.core.*; -import org.tmatesoft.svn.core.internal.util.SVNPathUtil; -import org.tmatesoft.svn.core.internal.wc.admin.SVNEntry; -import org.tmatesoft.svn.core.internal.wc.admin.SVNWCAccess; -import org.tmatesoft.svn.core.wc.SVNLogClient; -import org.tmatesoft.svn.core.wc.SVNRevision; import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; /** * @author yole @@ -59,33 +52,18 @@ import java.util.Map; )} ) public class SvnBranchConfigurationManager implements PersistentStateComponent { + private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.SvnBranchConfigurationManager"); private final Project myProject; public SvnBranchConfigurationManager(final Project project) { myProject = project; + myBunch = new NewRootBunch(project); } public static SvnBranchConfigurationManager getInstance(Project project) { return ServiceManager.getService(project, SvnBranchConfigurationManager.class); } - /** - * Gets the instance of the component if the project wasn't disposed. If the project was - * disposed, throws ProcessCanceledException. Should only be used for calling from background - * threads (for example, committed changes refresh thread). - * - * @param project the project for which the component instance should be retrieved. - * @return component instance - */ - public static SvnBranchConfigurationManager getInstanceChecked(final Project project) { - return ApplicationManager.getApplication().runReadAction(new Computable() { - public SvnBranchConfigurationManager compute() { - if (project.isDisposed()) throw new ProcessCanceledException(); - return getInstance(project); - } - }); - } - public static class ConfigurationBean { public Map myConfigurationMap = new HashMap(); /** @@ -100,109 +78,20 @@ public class SvnBranchConfigurationManager implements PersistentStateComponent exceptionRef = new Ref(); - ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { - public void run() { - try { - ProgressManager.getInstance().getProgressIndicator().setText( - SvnBundle.message("loading.data.for.root.text", vcsRoot.getPresentableUrl())); - final SvnBranchConfiguration loadedConfiguration = load(vcsRoot); - setConfiguration(vcsRoot, loadedConfiguration, false); - } - catch (VcsException e) { - exceptionRef.set(e); - } - } - }, SvnBundle.message("loading.default.branches.configuration.text"), false, myProject); - if (! exceptionRef.isNull()) { - // set empty configuration... to do not repeat forever when invoked in cycle - setConfiguration(vcsRoot, new SvnBranchConfiguration(), true); - throw exceptionRef.get(); - } - configuration = myConfigurationBean.myConfigurationMap.get(vcsRoot.getPath()); - } else { - configuration = load(vcsRoot); - setConfiguration(vcsRoot, configuration, false); - } - } - return configuration; + public SvnBranchConfigurationNew get(@NotNull final VirtualFile vcsRoot) throws VcsException { + return myBunch.getConfig(vcsRoot); } - private SvnBranchConfiguration load(VirtualFile vcsRoot) throws VcsException { - try { - SVNURL baseUrl = null; - final SVNWCAccess wcAccess = SVNWCAccess.newInstance(null); - File rootFile = new File(vcsRoot.getPath()); - wcAccess.open(rootFile, false, 0); - try { - SVNEntry entry = wcAccess.getEntry(rootFile, false); - if (entry != null) { - baseUrl = entry.getSVNURL(); - } - else { - throw new VcsException("Directory is not a working copy: " + vcsRoot.getPresentableUrl()); - } - } - finally { - wcAccess.close(); - } - - final SvnBranchConfiguration result = new SvnBranchConfiguration(); - result.setTrunkUrl(baseUrl.toString()); - while(true) { - final String s = SVNPathUtil.tail(baseUrl.getPath()); - if (s.equalsIgnoreCase(DEFAULT_TRUNK_NAME) || s.equalsIgnoreCase(DEFAULT_BRANCHES_NAME) || s.equalsIgnoreCase(DEFAULT_TAGS_NAME)) { - final SVNURL rootPath = baseUrl.removePathTail(); - SVNLogClient client = SvnVcs.getInstance(myProject).createLogClient(); - client.doList(rootPath, SVNRevision.UNDEFINED, SVNRevision.HEAD, false, new ISVNDirEntryHandler() { - public void handleDirEntry(final SVNDirEntry dirEntry) throws SVNException { - if (("".equals(dirEntry.getRelativePath())) || (! SVNNodeKind.DIR.equals(dirEntry.getKind()))) { - // do not use itself or files - return; - } - - if (dirEntry.getName().toLowerCase().endsWith(DEFAULT_TRUNK_NAME)) { - result.setTrunkUrl(rootPath.appendPath(dirEntry.getName(), false).toString()); - } - else { - result.getBranchUrls().add(rootPath.appendPath(dirEntry.getName(), false).toString()); - } - } - }); - - break; - } - if (SVNPathUtil.removeTail(baseUrl.getPath()).length() == 0) { - break; - } - baseUrl = baseUrl.removePathTail(); - } - return result; - } - catch (SVNException e) { - throw new VcsException(e); - } + public SvnBranchConfigManager getSvnBranchConfigManager() { + return myBunch; } - public void setConfiguration(VirtualFile vcsRoot, SvnBranchConfiguration configuration, final boolean underProgress) { - final String key = vcsRoot.getPath(); - final SvnBranchConfiguration oldConfiguration = myConfigurationBean.myConfigurationMap.get(key); - if ((oldConfiguration == null) || (oldConfiguration.getBranchMap().isEmpty()) || (oldConfiguration.urlsMissing(configuration))) { - configuration.loadBranches(myProject, underProgress); - } else { - configuration.setBranchMap(oldConfiguration.getBranchMap()); - } + public void setConfiguration(final VirtualFile vcsRoot, final SvnBranchConfigurationNew configuration) { + myBunch.updateForRoot(vcsRoot, new InfoStorage(configuration, InfoReliability.setByUser), + new BranchesPreloader(myProject, myBunch, vcsRoot)); - myConfigurationBean.myConfigurationMap.put(key, configuration); SvnBranchMapperManager.getInstance().notifyBranchesChanged(myProject, vcsRoot, configuration); final MessageBus messageBus = myProject.getMessageBus(); @@ -213,29 +102,88 @@ public class SvnBranchConfigurationManager implements PersistentStateComponent entry : myConfigurationBean.myConfigurationMap.entrySet()) { - final SvnBranchConfiguration configuration = entry.getValue(); - if ((! myConfigurationBean.mySupportsUserInfoFilter) || configuration.isUserinfoInUrl()) { - result.myConfigurationMap.put(entry.getKey(), helper.prepareForSerialization(configuration)); - } else { - result.myConfigurationMap.put(entry.getKey(), entry.getValue()); + + for (VirtualFile root : myBunch.getMapCopy().keySet()) { + final String key = root.getPath(); + final SvnBranchConfigurationNew configOrig = myBunch.getConfig(root); + final SvnBranchConfiguration configuration = new SvnBranchConfiguration(); + configuration.setTrunkUrl(configOrig.getTrunkUrl()); + configuration.setUserinfoInUrl(configOrig.isUserinfoInUrl()); + configuration.setBranchUrls(configOrig.getBranchUrls()); + final HashMap> map = new HashMap>(); + final Map>> origMap = configOrig.getBranchMap(); + for (String origKey : origMap.keySet()) { + map.put(origKey, origMap.get(origKey).getValue()); } + configuration.setBranchMap(map); + result.myConfigurationMap.put(key, helper.prepareForSerialization(configuration)); } result.mySupportsUserInfoFilter = true; return result; } + private static class BranchesPreloader implements PairConsumer { + private final Project myProject; + private final VirtualFile myRoot; + private final SvnBranchConfigManager myBunch; + private boolean myAll; + + public BranchesPreloader(Project project, @NotNull final SvnBranchConfigManager bunch, VirtualFile root) { + myBunch = bunch; + myProject = project; + myRoot = root; + } + + public void consume(final SvnBranchConfigurationNew prev, final SvnBranchConfigurationNew next) { + final Set oldUrls = (prev == null) ? Collections.emptySet() : new HashSet(prev.getBranchUrls()); + final Application application = ApplicationManager.getApplication(); + for (String newBranchUrl : next.getBranchUrls()) { + if (myAll || (! oldUrls.contains(newBranchUrl))) { + application.executeOnPooledThread(new NewRootBunch.BranchesLoadRunnable(myProject, myBunch, newBranchUrl, + InfoReliability.defaultValues, myRoot, null)); + } + } + } + + public void setAll(boolean all) { + myAll = all; + } + } + public void loadState(final ConfigurationBean object) { final UrlSerializationHelper helper = new UrlSerializationHelper(SvnVcs.getInstance(myProject)); final Map map = object.myConfigurationMap; final Map newMap = new HashMap(map.size(), 1); + final LocalFileSystem lfs = LocalFileSystem.getInstance(); + for (Map.Entry entry : map.entrySet()) { final SvnBranchConfiguration configuration = entry.getValue(); + final VirtualFile root = lfs.refreshAndFindFileByIoFile(new File(entry.getKey())); + if (root == null) { + LOG.info("root not found: " + entry.getKey()); + continue; + } + + final SvnBranchConfiguration configToConvert; if ((! myConfigurationBean.mySupportsUserInfoFilter) || configuration.isUserinfoInUrl()) { - newMap.put(entry.getKey(), helper.afterDeserialization(entry.getKey(), configuration)); + configToConvert = helper.afterDeserialization(entry.getKey(), configuration); } else { - newMap.put(entry.getKey(), entry.getValue()); + configToConvert = configuration; } + final SvnBranchConfigurationNew newConfig = new SvnBranchConfigurationNew(); + newConfig.setTrunkUrl(configToConvert.getTrunkUrl()); + newConfig.setUserinfoInUrl(configToConvert.isUserinfoInUrl()); + final Map> oldMap = configToConvert.getBranchMap(); + for (String branchUrl : configToConvert.getBranchUrls()) { + List items = oldMap.get(branchUrl); + items = ((items == null) || (items.isEmpty())) ? new ArrayList() : items; + newConfig.addBranches(branchUrl, new InfoStorage>(items, + (items.isEmpty()) ? InfoReliability.defaultValues : InfoReliability.setByUser)); + } + + final BranchesPreloader branchesPreloader = new BranchesPreloader(myProject, myBunch, root); + branchesPreloader.setAll(true); + myBunch.updateForRoot(root, new InfoStorage(newConfig, InfoReliability.setByUser), branchesPreloader); } object.myConfigurationMap.clear(); object.myConfigurationMap.putAll(newMap); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchMapperManager.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchMapperManager.java index d438c6b7cc..03d950cd3c 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchMapperManager.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchMapperManager.java @@ -23,6 +23,7 @@ import com.intellij.openapi.components.Storage; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.messages.Topic; +import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew; import java.io.File; import java.util.*; @@ -71,7 +72,7 @@ public class SvnBranchMapperManager implements PersistentStateComponent map = configuration.getUrl2FileMappings(project, vcsRoot); if (map != null) { for (Map.Entry entry : map.entrySet()) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java index 0e18a44a0f..cb9142fab1 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java @@ -33,6 +33,7 @@ import com.intellij.util.ArrayUtil; import com.intellij.util.NotNullFunction; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew; import org.jetbrains.idea.svn.dialogs.LockDialog; import org.jetbrains.idea.svn.dialogs.WCInfo; import org.tmatesoft.svn.core.SVNException; @@ -443,11 +444,11 @@ public class SvnUtil { @Nullable public static SVNURL getBranchForUrl(final SvnVcs vcs, final VirtualFile vcsRoot, final String urlPath) { - final SvnBranchConfiguration configuration; + final SvnBranchConfigurationNew configuration; try { final SVNURL url = SVNURL.parseURIEncoded(urlPath); configuration = SvnBranchConfigurationManager.getInstance(vcs.getProject()).get(vcsRoot); - return (configuration == null) ? null : configuration.getWorkingBranch(vcs.getProject(), url); + return (configuration == null) ? null : configuration.getWorkingBranch(url); } catch (SVNException e) { return null; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CompareWithBranchAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CompareWithBranchAction.java index 5dc6abc1c9..f95e4eb46e 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CompareWithBranchAction.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CompareWithBranchAction.java @@ -39,6 +39,7 @@ import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.*; +import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew; import org.jetbrains.idea.svn.status.SvnDiffEditor; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.internal.util.SVNPathUtil; @@ -72,7 +73,7 @@ public class CompareWithBranchAction extends AnAction implements DumbAware { final VirtualFile virtualFile = e.getData(PlatformDataKeys.VIRTUAL_FILE); SelectBranchPopup.show(project, virtualFile, new SelectBranchPopup.BranchSelectedCallback() { - public void branchSelected(final Project project, final SvnBranchConfiguration configuration, final String url, final long revision) { + public void branchSelected(final Project project, final SvnBranchConfigurationNew configuration, final String url, final long revision) { new CompareWithBranchOperation(project, virtualFile, configuration).compareWithBranch(url, revision); } }, SvnBundle.message("compare.with.branch.popup.title")); @@ -100,9 +101,9 @@ public class CompareWithBranchAction extends AnAction implements DumbAware { private class CompareWithBranchOperation { private final Project myProject; private final VirtualFile myVirtualFile; - private final SvnBranchConfiguration myConfiguration; + private final SvnBranchConfigurationNew myConfiguration; - public CompareWithBranchOperation(final Project project, final VirtualFile virtualFile, final SvnBranchConfiguration config) { + public CompareWithBranchOperation(final Project project, final VirtualFile virtualFile, final SvnBranchConfigurationNew config) { myProject = project; myVirtualFile = virtualFile; myConfiguration = config; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SelectBranchPopup.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SelectBranchPopup.java index 053fdbdb14..aabd3d78d6 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SelectBranchPopup.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SelectBranchPopup.java @@ -16,21 +16,27 @@ package org.jetbrains.idea.svn.actions; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.ui.popup.ListSeparator; import com.intellij.openapi.ui.popup.PopupStep; import com.intellij.openapi.ui.popup.util.BaseListPopupStep; +import com.intellij.openapi.util.Ref; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.Consumer; +import com.intellij.util.concurrency.Semaphore; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.*; +import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigManager; +import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew; import org.jetbrains.idea.svn.dialogs.BranchConfigurationDialog; import org.jetbrains.idea.svn.integrate.SvnBranchItem; -import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.internal.util.SVNPathUtil; @@ -53,7 +59,7 @@ public class SelectBranchPopup { } public interface BranchSelectedCallback { - void branchSelected(Project project, SvnBranchConfiguration configuration, String url, long revision); + void branchSelected(Project project, SvnBranchConfigurationNew configuration, String url, long revision); } public static void show(Project project, VirtualFile file, BranchSelectedCallback callback, final String title) { @@ -72,7 +78,7 @@ public class SelectBranchPopup { } public static void showForBranchRoot(Project project, VirtualFile vcsRoot, BranchSelectedCallback callback, final String title) { - final SvnBranchConfiguration configuration; + final SvnBranchConfigurationNew configuration; try { configuration = SvnBranchConfigurationManager.getInstance(project).get(vcsRoot); } @@ -97,13 +103,13 @@ public class SelectBranchPopup { private static class BranchBasesPopupStep extends BaseListPopupStep { protected final Project myProject; private final VirtualFile myVcsRoot; - private final SvnBranchConfiguration myConfiguration; + private final SvnBranchConfigurationNew myConfiguration; private final boolean myTopLevel; private BranchSelectedCallback myCallback; private static final String REFRESH_MESSAGE = SvnBundle.message("refresh.branches.item"); - protected BranchBasesPopupStep(final Project project, final VirtualFile vcsRoot, final SvnBranchConfiguration configuration, boolean topLevel, + protected BranchBasesPopupStep(final Project project, final VirtualFile vcsRoot, final SvnBranchConfigurationNew configuration, boolean topLevel, final BranchSelectedCallback callback) { myProject = project; myVcsRoot = vcsRoot; @@ -113,7 +119,7 @@ public class SelectBranchPopup { } public BranchBasesPopupStep(final Project project, final VirtualFile vcsRoot, - final SvnBranchConfiguration configuration, final BranchSelectedCallback callback, final List items, + final SvnBranchConfigurationNew configuration, final BranchSelectedCallback callback, final List items, final String title) { this(project, vcsRoot, configuration, true, callback); init(title, items, null); @@ -167,13 +173,40 @@ public class SelectBranchPopup { @Nullable private List loadBranches(final String selectedBranchesHolder, final boolean cached) { - try { - return cached ? myConfiguration.getBranches(selectedBranchesHolder, myProject, true, true) : - myConfiguration.reloadBranches(selectedBranchesHolder, myProject, myVcsRoot); + if (cached) { + return myConfiguration.getBranches(selectedBranchesHolder); } - catch (SVNException e) { - Messages.showErrorDialog(myProject, e.getMessage(), SvnBundle.message("compare.with.branch.list.error")); - return null; + + final List result = new ArrayList(); + final ProgressManager pm = ProgressManager.getInstance(); + + final boolean wasCanceled = ! pm.runProcessWithProgressSynchronously(new Runnable() { + public void run() { + final ProgressIndicator pi = pm.getProgressIndicator(); + final Semaphore s = new Semaphore(); + s.down(); + final Ref completedRef = new Ref(); + final SvnBranchConfigManager manager = SvnBranchConfigurationManager.getInstance(myProject).getSvnBranchConfigManager(); + manager.reloadBranches(myVcsRoot, selectedBranchesHolder, new Consumer>() { + public void consume(final List svnBranchItems) { + result.addAll(svnBranchItems); + completedRef.set(true); + s.up(); + } + }); + while (true) { + s.waitFor(500); + if (Boolean.TRUE.equals(completedRef.get())) break; + pi.checkCanceled(); + } + } + }, SvnBundle.message("compare.with.branch.progress.loading.branches"), true, myProject); + + + if (wasCanceled) { + return myConfiguration.getBranches(selectedBranchesHolder); + } else { + return result; } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchesLoader.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchesLoader.java new file mode 100644 index 0000000000..58bd321f0b --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchesLoader.java @@ -0,0 +1,58 @@ +/* + * Copyright 2000-2009 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.svn.branchConfig; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import org.jetbrains.idea.svn.SvnVcs; +import org.jetbrains.idea.svn.integrate.SvnBranchItem; +import org.tmatesoft.svn.core.ISVNDirEntryHandler; +import org.tmatesoft.svn.core.SVNDirEntry; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNURL; +import org.tmatesoft.svn.core.wc.SVNLogClient; +import org.tmatesoft.svn.core.wc.SVNRevision; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +public class BranchesLoader { + private static Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.branchConfig.BranchesLoader"); + + private BranchesLoader() { + } + + public static List loadBranches(final Project project, final String url) throws SVNException { + final List result = new LinkedList(); + final SVNLogClient logClient = SvnVcs.getInstance(project).createLogClient(); + final SVNURL branchesUrl = SVNURL.parseURIEncoded(url); + logClient.doList(branchesUrl, SVNRevision.UNDEFINED, SVNRevision.HEAD, false, false, new ISVNDirEntryHandler() { + public void handleDirEntry(final SVNDirEntry dirEntry) throws SVNException { + final SVNURL currentUrl = dirEntry.getURL(); + if (! branchesUrl.equals(currentUrl)) { + final String url = currentUrl.toString(); + // if have permissions + if (dirEntry.getDate() != null) { + result.add(new SvnBranchItem(url, dirEntry.getDate(), dirEntry.getRevision())); + } + } + } + }); + Collections.sort(result); + return result; + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/DefaultConfigLoader.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/DefaultConfigLoader.java new file mode 100644 index 0000000000..12f122fc4a --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/DefaultConfigLoader.java @@ -0,0 +1,104 @@ +/* + * Copyright 2000-2009 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.svn.branchConfig; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.svn.SvnVcs; +import org.jetbrains.idea.svn.integrate.SvnBranchItem; +import org.tmatesoft.svn.core.*; +import org.tmatesoft.svn.core.internal.util.SVNPathUtil; +import org.tmatesoft.svn.core.internal.wc.admin.SVNEntry; +import org.tmatesoft.svn.core.internal.wc.admin.SVNWCAccess; +import org.tmatesoft.svn.core.wc.SVNLogClient; +import org.tmatesoft.svn.core.wc.SVNRevision; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +public class DefaultConfigLoader { + private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.branchConfig.DefaultConfigLoader"); + @NonNls private static final String DEFAULT_TRUNK_NAME = "trunk"; + @NonNls private static final String DEFAULT_BRANCHES_NAME = "branches"; + @NonNls private static final String DEFAULT_TAGS_NAME = "tags"; + + private DefaultConfigLoader() { + } + + @Nullable + public static SvnBranchConfigurationNew loadDefaultConfiguration(final Project project, final VirtualFile vcsRoot) { + try { + SVNURL baseUrl = null; + final SVNWCAccess wcAccess = SVNWCAccess.newInstance(null); + File rootFile = new File(vcsRoot.getPath()); + wcAccess.open(rootFile, false, 0); + try { + SVNEntry entry = wcAccess.getEntry(rootFile, false); + if (entry != null) { + baseUrl = entry.getSVNURL(); + } + else { + LOG.info("Directory is not a working copy: " + vcsRoot.getPresentableUrl()); + return null; + } + } + finally { + wcAccess.close(); + } + + final SvnBranchConfigurationNew result = new SvnBranchConfigurationNew(); + result.setTrunkUrl(baseUrl.toString()); + while(true) { + final String s = SVNPathUtil.tail(baseUrl.getPath()); + if (s.equalsIgnoreCase(DEFAULT_TRUNK_NAME) || s.equalsIgnoreCase(DEFAULT_BRANCHES_NAME) || s.equalsIgnoreCase(DEFAULT_TAGS_NAME)) { + final SVNURL rootPath = baseUrl.removePathTail(); + SVNLogClient client = SvnVcs.getInstance(project).createLogClient(); + client.doList(rootPath, SVNRevision.UNDEFINED, SVNRevision.HEAD, false, false, new ISVNDirEntryHandler() { + public void handleDirEntry(final SVNDirEntry dirEntry) throws SVNException { + if (("".equals(dirEntry.getRelativePath())) || (! SVNNodeKind.DIR.equals(dirEntry.getKind()))) { + // do not use itself or files + return; + } + + if (dirEntry.getName().toLowerCase().endsWith(DEFAULT_TRUNK_NAME)) { + result.setTrunkUrl(rootPath.appendPath(dirEntry.getName(), false).toString()); + } + else { + result.addBranches(rootPath.appendPath(dirEntry.getName(), false).toString(), + new InfoStorage>(new ArrayList(0), InfoReliability.defaultValues)); + } + } + }); + + break; + } + if (SVNPathUtil.removeTail(baseUrl.getPath()).length() == 0) { + break; + } + baseUrl = baseUrl.removePathTail(); + } + return result; + } + catch (SVNException e) { + LOG.info(e); + return null; + } + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/InfoReliability.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/InfoReliability.java new file mode 100644 index 0000000000..e8a69a06ff --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/InfoReliability.java @@ -0,0 +1,43 @@ +/* + * Copyright 2000-2009 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.svn.branchConfig; + +public enum InfoReliability { + empty() { + @Override + protected final InfoReliability[] getOverriddenBy() { + return new InfoReliability[] {defaultValues, setByUser}; + }}, + defaultValues() { + @Override + protected final InfoReliability[] getOverriddenBy() { + return new InfoReliability[] {setByUser}; + }}, + setByUser() { + @Override + protected final InfoReliability[] getOverriddenBy() { + return new InfoReliability[] {setByUser}; + }}; + + protected abstract InfoReliability[] getOverriddenBy(); + + public boolean shouldOverride(final InfoReliability other) { + for (InfoReliability info : other.getOverriddenBy()) { + if (info.equals(this)) return true; + } + return false; + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/InfoStorage.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/InfoStorage.java new file mode 100644 index 0000000000..493721e3a8 --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/InfoStorage.java @@ -0,0 +1,47 @@ +/* + * Copyright 2000-2009 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.svn.branchConfig; + +import com.intellij.util.PairConsumer; +import org.jetbrains.annotations.Nullable; + +public class InfoStorage { + public T myT; + public InfoReliability myInfoReliability; + + public InfoStorage(final T t, final InfoReliability infoReliability) { + myT = t; + myInfoReliability = infoReliability; + } + + public void accept(final InfoStorage infoStorage, @Nullable final PairConsumer callbackOnUpdate) { + if (infoStorage.myInfoReliability.shouldOverride(myInfoReliability)) { + if (callbackOnUpdate != null) { + callbackOnUpdate.consume(myT, infoStorage.myT); + } + myT = infoStorage.myT; + myInfoReliability = infoStorage.myInfoReliability; + } + } + + public T getValue() { + return myT; + } + + public InfoReliability getInfoReliability() { + return myInfoReliability; + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/NewRootBunch.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/NewRootBunch.java new file mode 100644 index 0000000000..779b4c09dd --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/NewRootBunch.java @@ -0,0 +1,165 @@ +/* + * Copyright 2000-2009 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.svn.branchConfig; + +import com.intellij.openapi.application.Application; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.MessageType; +import com.intellij.openapi.vcs.changes.ui.ChangesViewBalloonProblemNotifier; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.Consumer; +import com.intellij.util.PairConsumer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.svn.integrate.SvnBranchItem; +import org.tmatesoft.svn.core.SVNException; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +// synch is here +public class NewRootBunch implements SvnBranchConfigManager { + private final static Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.branchConfig.NewRootBunch"); + private final Object myLock = new Object(); + private final Project myProject; + private final Map> myMap; + + public NewRootBunch(final Project project) { + myProject = project; + myMap = new HashMap>(); + } + + public void updateForRoot(@NotNull final VirtualFile root, @NotNull final InfoStorage config, + @Nullable final PairConsumer callbackOnUpdate) { + synchronized (myLock) { + final InfoStorage existing = myMap.get(root); + if (existing == null) { + myMap.put(root, config); + if (callbackOnUpdate != null) { + callbackOnUpdate.consume(null, config.getValue()); + } + } else { + existing.accept(config, callbackOnUpdate); + } + } + } + + public void updateBranches(@NotNull final VirtualFile root, @NotNull final String branchesParent, + @NotNull final InfoStorage> items) { + synchronized (myLock) { + final InfoStorage existing = myMap.get(root); + if (existing == null) { + LOG.info("cannot update branches, branches parent not found: " + branchesParent); + } else { + existing.getValue().updateBranch(branchesParent, items); + } + } + } + + @NotNull + public SvnBranchConfigurationNew getConfig(@NotNull final VirtualFile root) { + synchronized (myLock) { + final InfoStorage value = myMap.get(root); + final SvnBranchConfigurationNew result; + if (value == null) { + result = new SvnBranchConfigurationNew(); + myMap.put(root, new InfoStorage(result, InfoReliability.empty)); + ApplicationManager.getApplication().executeOnPooledThread(new DefaultBranchConfigInitializer(myProject, this, root)); + } else { + result = value.getValue(); + } + return result; + } + } + + public void reloadBranches(@NotNull final VirtualFile root, @NotNull final String branchParentUrl, + final Consumer> callback) { + ApplicationManager.getApplication().executeOnPooledThread(new BranchesLoadRunnable(myProject, this, branchParentUrl, + InfoReliability.setByUser, root, callback)); + } + + public static class BranchesLoadRunnable implements Runnable { + private final Project myProject; + private final SvnBranchConfigManager myBunch; + private final VirtualFile myRoot; + @Nullable + private final Consumer> myCallback; + private final String myUrl; + private final InfoReliability myInfoReliability; + + public BranchesLoadRunnable(final Project project, final SvnBranchConfigManager bunch, final String url, final InfoReliability infoReliability, + final VirtualFile root, @Nullable final Consumer> callback) { + myProject = project; + myBunch = bunch; + myUrl = url; + myInfoReliability = infoReliability; + myRoot = root; + myCallback = callback; + } + + public void run() { + try { + final List items = BranchesLoader.loadBranches(myProject, myUrl); + myBunch.updateBranches(myRoot, myUrl, new InfoStorage>(items, myInfoReliability)); + if (myCallback != null) { + myCallback.consume(items); + } + } + catch (SVNException e) { + // already logged inside + if (InfoReliability.setByUser.equals(myInfoReliability)) { + ChangesViewBalloonProblemNotifier.showMe(myProject, "Branches load error: " + e.getMessage(), MessageType.ERROR); + } + } + } + } + + private static class DefaultBranchConfigInitializer implements Runnable { + private final Project myProject; + private final SvnBranchConfigManager myBunch; + private final VirtualFile myRoot; + + private DefaultBranchConfigInitializer(final Project project, final SvnBranchConfigManager bunch, final VirtualFile root) { + myProject = project; + myRoot = root; + myBunch = bunch; + } + + public void run() { + final SvnBranchConfigurationNew result = DefaultConfigLoader.loadDefaultConfiguration(myProject, myRoot); + if (result != null) { + final Application application = ApplicationManager.getApplication(); + for (String url : result.getBranchUrls()) { + application.executeOnPooledThread(new BranchesLoadRunnable(myProject, myBunch, url, InfoReliability.defaultValues, myRoot, null)); + } + myBunch.updateForRoot(myRoot, new InfoStorage(result, InfoReliability.defaultValues), null); + } + } + } + + public Map getMapCopy() { + synchronized (myLock) { + final Map result = new HashMap(); + for (VirtualFile vf : myMap.keySet()) { + result.put(vf, myMap.get(vf).getValue()); + } + return result; + } + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigManager.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigManager.java new file mode 100644 index 0000000000..5ee613d32a --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigManager.java @@ -0,0 +1,42 @@ +/* + * Copyright 2000-2009 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.svn.branchConfig; + +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.Consumer; +import com.intellij.util.PairConsumer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.svn.integrate.SvnBranchItem; + +import java.util.List; +import java.util.Map; + +public interface SvnBranchConfigManager { + void updateForRoot(@NotNull VirtualFile root, @NotNull InfoStorage config, + @Nullable final PairConsumer callbackOnUpdate); + + void updateBranches(@NotNull VirtualFile root, @NotNull String branchesParent, + @NotNull InfoStorage> items); + + @NotNull + SvnBranchConfigurationNew getConfig(@NotNull VirtualFile root); + + void reloadBranches(@NotNull VirtualFile root, @NotNull String branchParentUrl, + Consumer> callback); + + Map getMapCopy(); +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigurationNew.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigurationNew.java new file mode 100644 index 0000000000..1d8a3b8121 --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigurationNew.java @@ -0,0 +1,278 @@ +/* + * Copyright 2000-2009 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.svn.branchConfig; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.svn.SvnUtil; +import org.jetbrains.idea.svn.SvnVcs; +import org.jetbrains.idea.svn.integrate.SvnBranchItem; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNURL; +import org.tmatesoft.svn.core.internal.util.SVNURLUtil; +import org.tmatesoft.svn.core.wc.SVNInfo; +import org.tmatesoft.svn.core.wc.SVNRevision; +import org.tmatesoft.svn.core.wc.SVNWCClient; + +import java.io.File; +import java.util.*; + +public class SvnBranchConfigurationNew { + private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew"); + private String myTrunkUrl; + // need public for serialization + public Map>> myBranchMap; + private boolean myUserinfoInUrl; + + public SvnBranchConfigurationNew() { + myTrunkUrl = ""; + myBranchMap = new HashMap>>(); + } + + public boolean isUserinfoInUrl() { + return myUserinfoInUrl; + } + + public void setUserinfoInUrl(final boolean userinfoInUrl) { + myUserinfoInUrl = userinfoInUrl; + } + + public void setTrunkUrl(final String trunkUrl) { + myTrunkUrl = trunkUrl; + } + + public String getTrunkUrl() { + return myTrunkUrl; + } + + public List getBranchUrls() { + final ArrayList result = new ArrayList(myBranchMap.keySet()); + Collections.sort(result); + return result; + } + + public void addBranches(final String branchParentName, final InfoStorage> items) { + InfoStorage> current = myBranchMap.get(branchParentName); + if (current != null) { + LOG.info("Branches list not added for : '" + branchParentName + "; this branch parent URL is already present."); + return; + } + myBranchMap.put(branchParentName, items); + } + + public void updateBranch(final String branchParentName, final InfoStorage> items) { + final InfoStorage> current = myBranchMap.get(branchParentName); + if (current == null) { + LOG.info("Branches list not updated for : '" + branchParentName + "; since config has changed."); + return; + } + current.accept(items, null); + } + + public Map>> getBranchMap() { + return myBranchMap; + } + + public List getBranches(String url) { + return myBranchMap.get(url).getValue(); + } + + /*public SvnBranchConfiguration createFromVcsRootBranches() { + final SvnBranchConfiguration result = new SvnBranchConfiguration(); + result.setTrunkUrl(myTrunkUrl); + final Map> branchMap = result.getBranchMap(); + for (String key : myBranchMap.keySet()) { + result.setTrunkUrl(key); + final List list = myBranchMap.get(key).getT(); + branchMap.put(key, list); + } + return result; + }*/ + + public SvnBranchConfigurationNew copy() { + SvnBranchConfigurationNew result = new SvnBranchConfigurationNew(); + result.myUserinfoInUrl = myUserinfoInUrl; + result.myTrunkUrl = myTrunkUrl; + result.myBranchMap = new HashMap>>(); + for (Map.Entry>> entry : myBranchMap.entrySet()) { + final InfoStorage> infoStorage = entry.getValue(); + result.myBranchMap.put(entry.getKey(), new InfoStorage>( + new ArrayList(infoStorage.getValue()), infoStorage.getInfoReliability())); + } + return result; + } + + @Nullable + public String getBaseUrl(String url) { + if ((myTrunkUrl != null) && url.startsWith(myTrunkUrl)) { + return myTrunkUrl; + } + for(String branchUrl: myBranchMap.keySet()) { + if (url.startsWith(branchUrl)) { + int pos = url.indexOf('/', branchUrl.length()+1); + if (pos >= 0) { + return url.substring(0, pos); + } + return branchUrl; + } + } + return null; + } + + @Nullable + public String getBaseName(String url) { + String baseUrl = getBaseUrl(url); + if (baseUrl == null) { + return null; + } + if (myBranchMap.isEmpty()) { + return baseUrl; + } + int commonPrefixLength = getCommonPrefixLength(url, myTrunkUrl); + for (String branchUrl : myBranchMap.keySet()) { + commonPrefixLength = Math.min(commonPrefixLength, getCommonPrefixLength(url, branchUrl)); + if (commonPrefixLength <= 0) { + return baseUrl; + } + } + return baseUrl.substring(commonPrefixLength); + } + + private static int getCommonPrefixLength(final String s1, final String s2) { + final int minLength = Math.min(s1.length(), s2.length()); + for(int i=0; i< minLength; i++) { + if (s1.charAt(i) != s2.charAt(i)) { + return i; + } + } + return minLength; + } + + @Nullable + public String getRelativeUrl(String url) { + String baseUrl = getBaseUrl(url); + return baseUrl == null ? null : url.substring(baseUrl.length()); + } + + @Nullable + public SVNURL getWorkingBranch(final SVNURL someUrl) throws SVNException { + final BranchSearcher branchSearcher = new BranchSearcher(someUrl); + iterateUrls(branchSearcher); + + return branchSearcher.getResult(); + } + + private void iterateUrls(final UrlListener listener) throws SVNException { + if (listener.accept(myTrunkUrl)) { + return; + } + + for (String branchUrl : myBranchMap.keySet()) { + // use more exact comparison first (paths longer) + final List children = myBranchMap.get(branchUrl).getValue(); + for (SvnBranchItem child : children) { + if (listener.accept(child.getUrl())) { + return; + } + } + + if (listener.accept(branchUrl)) { + return; + } + } + } + + @Nullable + public Map getUrl2FileMappings(final Project project, final VirtualFile root) { + try { + final BranchRootSearcher searcher = new BranchRootSearcher(SvnVcs.getInstance(project), root); + iterateUrls(searcher); + return searcher.getBranchesUnder(); + } catch (SVNException e) { + return null; + } + } + + public void removeBranch(final String url) { + myBranchMap.remove(url); + } + + private static class BranchRootSearcher implements UrlListener { + private final VirtualFile myRoot; + private final SVNURL myRootUrl; + // url path to file path + private final Map myBranchesUnder; + + private BranchRootSearcher(final SvnVcs vcs, final VirtualFile root) throws SVNException { + myRoot = root; + myBranchesUnder = new HashMap(); + final SVNWCClient client = vcs.createWCClient(); + final SVNInfo info = client.doInfo(new File(myRoot.getPath()), SVNRevision.WORKING); + myRootUrl = info.getURL(); + } + + public boolean accept(final String url) throws SVNException { + if (myRootUrl != null) { + final File baseDir = new File(myRoot.getPath()); + final String baseUrl = myRootUrl.getPath(); + + final SVNURL branchUrl = SVNURL.parseURIEncoded(url); + if (myRootUrl.equals(SVNURLUtil.getCommonURLAncestor(myRootUrl, branchUrl))) { + final File file = SvnUtil.fileFromUrl(baseDir, baseUrl, branchUrl.getPath()); + myBranchesUnder.put(url, file.getAbsolutePath()); + } + } + return false; // iterate everything + } + + public Map getBranchesUnder() { + return myBranchesUnder; + } + } + + private interface UrlListener { + boolean accept(final String url) throws SVNException; + } + + private static class BranchSearcher implements UrlListener { + private final SVNURL mySomeUrl; + private SVNURL myResult; + + private BranchSearcher(final SVNURL someUrl) { + mySomeUrl = someUrl; + } + + public boolean accept(final String url) throws SVNException { + myResult = urlIsParent(url, mySomeUrl); + return myResult != null; + } + + public SVNURL getResult() { + return myResult; + } + } + + @Nullable + private static SVNURL urlIsParent(final String parentCandidate, final SVNURL child) throws SVNException { + final SVNURL parentUrl = SVNURL.parseURIEncoded(parentCandidate); + if(parentUrl.equals(SVNURLUtil.getCommonURLAncestor(parentUrl, child))) { + return parentUrl; + } + return null; + } +} 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 2a00d6fdff..e0128ad933 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java @@ -27,6 +27,11 @@ import com.intellij.ui.DocumentAdapter; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.*; +import org.jetbrains.idea.svn.branchConfig.InfoReliability; +import org.jetbrains.idea.svn.branchConfig.InfoStorage; +import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigManager; +import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew; +import org.jetbrains.idea.svn.integrate.SvnBranchItem; import org.tmatesoft.svn.core.SVNException; import javax.swing.*; @@ -34,6 +39,8 @@ import javax.swing.event.DocumentEvent; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; +import java.util.ArrayList; +import java.util.List; /** * @author yole @@ -44,9 +51,13 @@ public class BranchConfigurationDialog extends DialogWrapper { private JList myLocationList; private JButton myAddButton; private JButton myRemoveButton; + private final SvnBranchConfigManager mySvnBranchConfigManager; + private final VirtualFile myRoot; - public BranchConfigurationDialog(final Project project, final SvnBranchConfiguration configuration, final String rootUrl) { + public BranchConfigurationDialog(final Project project, final SvnBranchConfigurationNew configuration, final String rootUrl, + final VirtualFile root) { super(project, true); + myRoot = root; init(); setTitle(SvnBundle.message("configure.branches.title")); @@ -54,6 +65,8 @@ public class BranchConfigurationDialog extends DialogWrapper { configuration.setTrunkUrl(rootUrl); } + mySvnBranchConfigManager = SvnBranchConfigurationManager.getInstance(project).getSvnBranchConfigManager(); + myTrunkLocationTextField.setText(configuration.getTrunkUrl()); myTrunkLocationTextField.addActionListener(new ActionListener() { public void actionPerformed(final ActionEvent e) { @@ -83,7 +96,9 @@ public class BranchConfigurationDialog extends DialogWrapper { dlg.show(); if (dlg.isOK()) { if (!configuration.getBranchUrls().contains(dlg.getSelectedURL())) { - configuration.getBranchUrls().add(dlg.getSelectedURL()); + final String url = dlg.getSelectedURL(); + configuration.addBranches(url, new InfoStorage>(new ArrayList(), InfoReliability.empty)); + mySvnBranchConfigManager.reloadBranches(myRoot, url, null); listModel.fireItemAdded(); myLocationList.setSelectedIndex(listModel.getSize()-1); } @@ -102,8 +117,7 @@ public class BranchConfigurationDialog extends DialogWrapper { for(Object urlObj: selection) { String url = (String) urlObj; int index = configuration.getBranchUrls().indexOf(url); - configuration.getBranchUrls().remove(index); - configuration.getBranchMap().remove(url); + configuration.removeBranch(url); listModel.fireItemRemoved(index); } if (listModel.getSize() > 0) { @@ -118,9 +132,9 @@ public class BranchConfigurationDialog extends DialogWrapper { private class TrunkUrlValidator extends DocumentAdapter { private final String myRootUrl; private final String myRootUrlPrefix; - private final SvnBranchConfiguration myConfiguration; + private final SvnBranchConfigurationNew myConfiguration; - private TrunkUrlValidator(final String rootUrl, final SvnBranchConfiguration configuration) { + private TrunkUrlValidator(final String rootUrl, final SvnBranchConfigurationNew configuration) { myRootUrl = rootUrl; myRootUrlPrefix = rootUrl + "/"; myConfiguration = configuration; @@ -177,7 +191,7 @@ public class BranchConfigurationDialog extends DialogWrapper { return; } - SvnBranchConfiguration configuration; + SvnBranchConfigurationNew configuration; try { configuration = SvnBranchConfigurationManager.getInstance(project).get(vcsRoot); } @@ -187,18 +201,18 @@ public class BranchConfigurationDialog extends DialogWrapper { return; } - final SvnBranchConfiguration clonedConfiguration = configuration.copy(); - BranchConfigurationDialog dlg = new BranchConfigurationDialog(project, clonedConfiguration, rootUrl); + final SvnBranchConfigurationNew clonedConfiguration = configuration.copy(); + BranchConfigurationDialog dlg = new BranchConfigurationDialog(project, clonedConfiguration, rootUrl, vcsRoot); dlg.show(); if (dlg.isOK()) { - SvnBranchConfigurationManager.getInstance(project).setConfiguration(vcsRoot, clonedConfiguration, true); + SvnBranchConfigurationManager.getInstance(project).setConfiguration(vcsRoot, clonedConfiguration); } } private static class MyListModel extends AbstractListModel { - private final SvnBranchConfiguration myConfiguration; + private final SvnBranchConfigurationNew myConfiguration; - public MyListModel(final SvnBranchConfiguration configuration) { + public MyListModel(final SvnBranchConfigurationNew configuration) { myConfiguration = configuration; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopyDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopyDialog.java index 7c221b786d..030e0117b3 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopyDialog.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopyDialog.java @@ -36,6 +36,7 @@ import org.jetbrains.idea.svn.SvnBranchConfiguration; import org.jetbrains.idea.svn.SvnBranchConfigurationManager; import org.jetbrains.idea.svn.SvnBundle; import org.jetbrains.idea.svn.SvnVcs; +import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew; import org.jetbrains.idea.svn.update.SvnRevisionPanel; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.internal.util.SVNEncodingUtil; @@ -84,7 +85,7 @@ public class CopyDialog extends DialogWrapper { private JLabel myErrorLabel; @NonNls private static final String HELP_ID = "vcs.subversion.branch"; - private SvnBranchConfiguration myBranchConfiguration; + private SvnBranchConfigurationNew myBranchConfiguration; private final VirtualFile mySrcVirtualFile; public CopyDialog(final Project project, boolean canBeParent, File file) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnMergeInfoRootPanelManual.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnMergeInfoRootPanelManual.java index 1d87bc1503..088382e605 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnMergeInfoRootPanelManual.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnMergeInfoRootPanelManual.java @@ -29,6 +29,7 @@ import org.jetbrains.idea.svn.SvnBranchMapperManager; import org.jetbrains.idea.svn.SvnBundle; import org.jetbrains.idea.svn.SvnUtil; import org.jetbrains.idea.svn.actions.SelectBranchPopup; +import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew; import org.jetbrains.idea.svn.dialogs.WCInfoWithBranches; import org.jetbrains.idea.svn.integrate.IntegratedSelectedOptionsDialog; import org.jetbrains.idea.svn.integrate.WorkingCopyInfo; @@ -108,7 +109,7 @@ public class SvnMergeInfoRootPanelManual { final VirtualFile vf = SvnUtil.getVirtualFile(myInfo.getPath()); if (vf != null) { SelectBranchPopup.show(myProject, vf, new SelectBranchPopup.BranchSelectedCallback() { - public void branchSelected(final Project project, final SvnBranchConfiguration configuration, final String url, final long revision) { + public void branchSelected(final Project project, final SvnBranchConfigurationNew configuration, final String url, final long revision) { refreshSelectedBranch(url); calculateBranchPathByBranch(mySelectedBranch.getUrl(), null); myListener.run(); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/WcInfoLoader.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/WcInfoLoader.java index c02eec1a06..c2a27122e2 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/WcInfoLoader.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/WcInfoLoader.java @@ -23,6 +23,8 @@ import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.*; +import org.jetbrains.idea.svn.branchConfig.InfoStorage; +import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew; import org.jetbrains.idea.svn.dialogs.WCInfo; import org.jetbrains.idea.svn.dialogs.WCInfoWithBranches; import org.jetbrains.idea.svn.integrate.SvnBranchItem; @@ -104,7 +106,7 @@ public class WcInfoLoader { if (wcRoot == null) { return null; } - final SvnBranchConfiguration configuration; + final SvnBranchConfigurationNew configuration; try { configuration = SvnBranchConfigurationManager.getInstance(myProject).get(wcRoot); } @@ -123,7 +125,7 @@ public class WcInfoLoader { branchRoot); } - private String createBranchesList(final String url, final SvnBranchConfiguration configuration, + private static String createBranchesList(final String url, final SvnBranchConfigurationNew configuration, final List items) { String result = null; final String trunkUrl = configuration.getTrunkUrl(); @@ -132,9 +134,8 @@ public class WcInfoLoader { } else if (trunkUrl != null) { result = trunkUrl; } - final Map> branchMap = configuration.getLoadedBranchMap(myProject); - for (Map.Entry> entry : branchMap.entrySet()) { - for (SvnBranchItem branchItem : entry.getValue()) { + for(String branchUrl: configuration.getBranchUrls()) { + for (SvnBranchItem branchItem : configuration.getBranches(branchUrl)) { if (! SVNPathUtil.isAncestor(branchItem.getUrl(), url)) { items.add(new WCInfoWithBranches.Branch(branchItem.getUrl())); } else { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesActionPerformer.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesActionPerformer.java index d9d2366fe7..91eab8163f 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesActionPerformer.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesActionPerformer.java @@ -24,6 +24,7 @@ import org.jetbrains.idea.svn.SvnBranchConfiguration; import org.jetbrains.idea.svn.SvnBundle; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.actions.SelectBranchPopup; +import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; @@ -39,7 +40,7 @@ public class SvnIntegrateChangesActionPerformer implements SelectBranchPopup.Bra myMergerFactory = mergerFactory; } - public void branchSelected(final Project project, final SvnBranchConfiguration configuration, final String url, final long revision) { + public void branchSelected(final Project project, final SvnBranchConfigurationNew configuration, final String url, final long revision) { onBranchSelected(url, null, null); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateRootOptionsPanel.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateRootOptionsPanel.java index 8560805988..bffa3e3570 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateRootOptionsPanel.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateRootOptionsPanel.java @@ -23,6 +23,7 @@ import com.intellij.openapi.vcs.FilePath; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.*; import org.jetbrains.idea.svn.actions.SelectBranchPopup; +import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew; import org.jetbrains.idea.svn.dialogs.SelectLocationDialog; import org.jetbrains.idea.svn.history.SvnChangeList; import org.jetbrains.idea.svn.history.SvnRepositoryLocation; @@ -125,7 +126,7 @@ public class SvnUpdateRootOptionsPanel implements SvnPanel{ return; } SelectBranchPopup.show(myVcs.getProject(), myRoot.getVirtualFile(), new SelectBranchPopup.BranchSelectedCallback() { - public void branchSelected(final Project project, final SvnBranchConfiguration configuration, final String url, final long revision) { + public void branchSelected(final Project project, final SvnBranchConfigurationNew configuration, final String url, final long revision) { recalculateUrl(url); myBranchField.setText(SVNPathUtil.tail(url)); } -- 2.11.4.GIT