summaryrefslogtreecommitdiff
path: root/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigurationManager.java
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigurationManager.java')
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigurationManager.java224
1 files changed, 224 insertions, 0 deletions
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigurationManager.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigurationManager.java
new file mode 100644
index 000000000000..772e5edd2755
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigurationManager.java
@@ -0,0 +1,224 @@
+/*
+ * 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.branchConfig;
+
+import com.intellij.lifecycle.PeriodicalTasksCloser;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.components.PersistentStateComponent;
+import com.intellij.openapi.components.State;
+import com.intellij.openapi.components.Storage;
+import com.intellij.openapi.components.StoragePathMacros;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.openapi.progress.ProgressManagerQueue;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.vcs.ProjectLevelVcsManager;
+import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vcs.changes.committed.VcsConfigurationChangeListener;
+import com.intellij.openapi.vcs.impl.ProjectLevelVcsManagerImpl;
+import com.intellij.openapi.vcs.impl.VcsInitObject;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.messages.MessageBus;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.svn.SvnVcs;
+
+import java.io.File;
+import java.util.*;
+
+/**
+ * @author yole
+ */
+@State(
+ name = "SvnBranchConfigurationManager",
+ storages = {
+ @Storage(
+ file = StoragePathMacros.PROJECT_FILE
+ )}
+)
+public class SvnBranchConfigurationManager implements PersistentStateComponent<SvnBranchConfigurationManager.ConfigurationBean> {
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationManager");
+ private final Project myProject;
+ private final ProjectLevelVcsManager myVcsManager;
+ private final SvnLoadedBranchesStorage myStorage;
+ private final ProgressManagerQueue myBranchesLoader;
+ private boolean myIsInitialized;
+
+ public SvnBranchConfigurationManager(final Project project,
+ final ProjectLevelVcsManager vcsManager,
+ final SvnLoadedBranchesStorage storage) {
+ myProject = project;
+ myVcsManager = vcsManager;
+ myStorage = storage;
+ myBranchesLoader = new ProgressManagerQueue(myProject, "Subversion Branches Preloader");
+ // TODO: Seems that ProgressManagerQueue is not suitable here at least for some branches loading tasks. For instance,
+ // TODO: for DefaultConfigLoader it would be better to run modal cancellable task - so branches structure could be detected and
+ // TODO: shown in dialog. Currently when "Configure Branches" is invoked for the first time - no branches are shown.
+ // TODO: If "Cancel" is pressed and "Configure Branches" invoked once again - already detected (in background) branches are shown.
+ ((ProjectLevelVcsManagerImpl) vcsManager).addInitializationRequest(VcsInitObject.BRANCHES, new Runnable() {
+ @Override
+ public void run() {
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ if (myProject.isDisposed()) return;
+ myBranchesLoader.start();
+ }
+ });
+ }
+ });
+ myBunch = new NewRootBunch(project, myBranchesLoader);
+ }
+
+ public static SvnBranchConfigurationManager getInstance(final Project project) {
+ SvnBranchConfigurationManager result = PeriodicalTasksCloser.getInstance().safeGetService(project, SvnBranchConfigurationManager.class);
+
+ if (result != null) {
+ result.initialize();
+ }
+
+ return result;
+ }
+
+ public static class ConfigurationBean {
+ public Map<String, SvnBranchConfiguration> myConfigurationMap = new TreeMap<String, SvnBranchConfiguration>();
+ /**
+ * version of "support SVN in IDEA". for features tracking. should grow
+ */
+ public Long myVersion;
+ public boolean mySupportsUserInfoFilter;
+ }
+
+ public Long getSupportValue() {
+ return myConfigurationBean.myVersion;
+ }
+
+ private ConfigurationBean myConfigurationBean = new ConfigurationBean();
+ private final NewRootBunch myBunch;
+
+ public SvnBranchConfigurationNew get(@NotNull final VirtualFile vcsRoot) throws VcsException {
+ return myBunch.getConfig(vcsRoot);
+ }
+
+ public NewRootBunch getSvnBranchConfigManager() {
+ return myBunch;
+ }
+
+ public void setConfiguration(final VirtualFile vcsRoot, final SvnBranchConfigurationNew configuration) {
+ myBunch.updateForRoot(vcsRoot, new InfoStorage<SvnBranchConfigurationNew>(configuration, InfoReliability.setByUser), true);
+
+ SvnBranchMapperManager.getInstance().notifyBranchesChanged(myProject, vcsRoot, configuration);
+
+ final MessageBus messageBus = myProject.getMessageBus();
+ messageBus.syncPublisher(VcsConfigurationChangeListener.BRANCHES_CHANGED).execute(myProject, vcsRoot);
+ }
+
+ public ConfigurationBean getState() {
+ final ConfigurationBean result = new ConfigurationBean();
+ result.myVersion = myConfigurationBean.myVersion;
+ final UrlSerializationHelper helper = new UrlSerializationHelper(SvnVcs.getInstance(myProject));
+
+ for (VirtualFile root : myBunch.getMapCopy().keySet()) {
+ final String key = root.getPath();
+ final SvnBranchConfigurationNew configOrig = myBunch.getConfig(root);
+ final SvnBranchConfiguration configuration =
+ new SvnBranchConfiguration(configOrig.getTrunkUrl(), configOrig.getBranchUrls(), configOrig.isUserinfoInUrl());
+
+ result.myConfigurationMap.put(key, helper.prepareForSerialization(configuration));
+ }
+ result.mySupportsUserInfoFilter = true;
+ return result;
+ }
+
+ public void loadState(ConfigurationBean object) {
+ myConfigurationBean = object;
+ }
+
+ private synchronized void initialize() {
+ if (!myIsInitialized) {
+ myIsInitialized = true;
+
+ preloadBranches(resolveAllBranchPoints());
+ }
+ }
+
+ @NotNull
+ private Set<Pair<VirtualFile, SvnBranchConfigurationNew>> resolveAllBranchPoints() {
+ final LocalFileSystem lfs = LocalFileSystem.getInstance();
+ final UrlSerializationHelper helper = new UrlSerializationHelper(SvnVcs.getInstance(myProject));
+ final Set<Pair<VirtualFile, SvnBranchConfigurationNew>> branchPointsToLoad = ContainerUtil.newHashSet();
+ for (Map.Entry<String, SvnBranchConfiguration> entry : myConfigurationBean.myConfigurationMap.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()) {
+ configToConvert = helper.afterDeserialization(entry.getKey(), configuration);
+ } else {
+ configToConvert = configuration;
+ }
+ final SvnBranchConfigurationNew newConfig = new SvnBranchConfigurationNew();
+ newConfig.setTrunkUrl(configToConvert.getTrunkUrl());
+ newConfig.setUserinfoInUrl(configToConvert.isUserinfoInUrl());
+ for (String branchUrl : configToConvert.getBranchUrls()) {
+ List<SvnBranchItem> stored = getStored(branchUrl);
+ if (stored != null && ! stored.isEmpty()) {
+ newConfig.addBranches(branchUrl, new InfoStorage<List<SvnBranchItem>>(stored, InfoReliability.setByUser));
+ } else {
+ branchPointsToLoad.add(Pair.create(root, newConfig));
+ newConfig.addBranches(branchUrl, new InfoStorage<List<SvnBranchItem>>(new ArrayList<SvnBranchItem>(), InfoReliability.empty));
+ }
+ }
+
+ myBunch.updateForRoot(root, new InfoStorage<SvnBranchConfigurationNew>(newConfig, InfoReliability.setByUser), false);
+ }
+ return branchPointsToLoad;
+ }
+
+ private void preloadBranches(@NotNull final Collection<Pair<VirtualFile, SvnBranchConfigurationNew>> branchPoints) {
+ ((ProjectLevelVcsManagerImpl) myVcsManager).addInitializationRequest(VcsInitObject.BRANCHES, new Runnable() {
+ public void run() {
+ ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
+ public void run() {
+ try {
+ for (Pair<VirtualFile, SvnBranchConfigurationNew> pair : branchPoints) {
+ myBunch.reloadBranches(pair.getFirst(), null, pair.getSecond());
+ }
+ }
+ catch (ProcessCanceledException e) {
+ //
+ }
+ }
+ });
+ }
+ });
+ }
+
+ private List<SvnBranchItem> getStored(String branchUrl) {
+ Collection<SvnBranchItem> collection = myStorage.get(branchUrl);
+ if (collection == null) return null;
+ final List<SvnBranchItem> items = new ArrayList<SvnBranchItem>(collection);
+ Collections.sort(items);
+ return items;
+ }
+}