IDEA-27603 (Indicate which branch is being worked on)
[fedora-idea.git] / platform / vcs-impl / src / com / intellij / openapi / vcs / changes / RemoteRevisionsCache.java
blobc2fb1b20c04a93f6b0bdfb2de9aae1fc7e24dbd3
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.openapi.vcs.changes;
18 import com.intellij.lifecycle.AtomicSectionsAware;
19 import com.intellij.openapi.Disposable;
20 import com.intellij.openapi.components.ServiceManager;
21 import com.intellij.openapi.diagnostic.Logger;
22 import com.intellij.openapi.project.Project;
23 import com.intellij.openapi.util.Disposer;
24 import com.intellij.openapi.util.Pair;
25 import com.intellij.openapi.vcs.*;
26 import com.intellij.openapi.vcs.changes.ui.RemoteStatusChangeNodeDecorator;
27 import com.intellij.openapi.vcs.impl.ProjectLevelVcsManagerImpl;
28 import com.intellij.openapi.vcs.impl.VcsInitObject;
29 import com.intellij.openapi.vcs.update.UpdateFilesHelper;
30 import com.intellij.openapi.vcs.update.UpdatedFiles;
31 import com.intellij.util.Consumer;
32 import com.intellij.util.messages.Topic;
34 import java.util.Collection;
35 import java.util.HashMap;
36 import java.util.LinkedList;
37 import java.util.Map;
39 public class RemoteRevisionsCache implements PlusMinus<Pair<String, AbstractVcs>>, VcsListener {
40 private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.changes.RemoteRevisionsCache");
42 public static Topic<Runnable> REMOTE_VERSION_CHANGED = new Topic<Runnable>("REMOTE_VERSION_CHANGED", Runnable.class);
44 private final RemoteRevisionsNumbersCache myRemoteRevisionsNumbersCache;
45 private final RemoteRevisionsStateCache myRemoteRevisionsStateCache;
47 private final ProjectLevelVcsManager myVcsManager;
49 private final RemoteStatusChangeNodeDecorator myChangeDecorator;
50 private final Project myProject;
51 private final Object myLock;
52 private final Map<String, RemoteDifferenceStrategy> myKinds;
53 private ControlledCycle myControlledCycle;
55 public static RemoteRevisionsCache getInstance(final Project project) {
56 return ServiceManager.getService(project, RemoteRevisionsCache.class);
59 private RemoteRevisionsCache(final Project project) {
60 myProject = project;
61 myLock = new Object();
63 myRemoteRevisionsNumbersCache = new RemoteRevisionsNumbersCache(myProject);
64 myRemoteRevisionsStateCache = new RemoteRevisionsStateCache(myProject);
66 myChangeDecorator = new RemoteStatusChangeNodeDecorator(this);
68 myVcsManager = ProjectLevelVcsManager.getInstance(project);
69 myVcsManager.addVcsListener(this);
70 myKinds = new HashMap<String, RemoteDifferenceStrategy>();
71 Disposer.register(project, new Disposable() {
72 public void dispose() {
73 myVcsManager.removeVcsListener(RemoteRevisionsCache.this);
75 });
76 updateKinds();
77 myControlledCycle = new ControlledCycle(project, new ControlledCycle.MyCallback() {
78 public boolean call(final AtomicSectionsAware atomicSectionsAware) {
79 atomicSectionsAware.checkShouldExit();
80 final boolean shouldBeDone = VcsConfiguration.getInstance(myProject).CHECK_LOCALLY_CHANGED_CONFLICTS_IN_BACKGROUND;
81 if (shouldBeDone) {
82 boolean somethingChanged = myRemoteRevisionsNumbersCache.updateStep(atomicSectionsAware);
83 atomicSectionsAware.checkShouldExit();
84 somethingChanged |= myRemoteRevisionsStateCache.updateStep(atomicSectionsAware);
85 if (somethingChanged) {
86 myProject.getMessageBus().syncPublisher(REMOTE_VERSION_CHANGED).run();
89 return shouldBeDone;
91 }, "Finishing \"changed on server\" update", 3 * 60 * 1000);
92 if ((! myProject.isDefault()) && VcsConfiguration.getInstance(myProject).CHECK_LOCALLY_CHANGED_CONFLICTS_IN_BACKGROUND) {
93 ((ProjectLevelVcsManagerImpl) myVcsManager).addInitializationRequest(VcsInitObject.REMOTE_REVISIONS_CACHE,
94 new Runnable() {
95 public void run() {
96 myControlledCycle.start();
98 });
102 public void startRefreshInBackground() {
103 if (myProject.isDefault()) return;
104 myControlledCycle.start();
107 private void updateKinds() {
108 final VcsRoot[] roots = myVcsManager.getAllVcsRoots();
109 synchronized (myLock) {
110 for (VcsRoot root : roots) {
111 final AbstractVcs vcs = root.vcs;
112 if (! myKinds.containsKey(vcs.getName())) {
113 myKinds.put(vcs.getName(), vcs.getRemoteDifferenceStrategy());
119 public void directoryMappingChanged() {
120 updateKinds();
121 myRemoteRevisionsNumbersCache.directoryMappingChanged();
122 myRemoteRevisionsStateCache.directoryMappingChanged();
125 public void plus(final Pair<String, AbstractVcs> pair) {
126 final AbstractVcs vcs = pair.getSecond();
127 if (RemoteDifferenceStrategy.ASK_TREE_PROVIDER.equals(vcs.getRemoteDifferenceStrategy())) {
128 myRemoteRevisionsStateCache.plus(pair);
129 } else {
130 myRemoteRevisionsNumbersCache.plus(pair);
134 public void invalidate(final UpdatedFiles updatedFiles) {
135 final Map<String, RemoteDifferenceStrategy> strategyMap;
136 synchronized (myLock) {
137 strategyMap = new HashMap<String, RemoteDifferenceStrategy>(myKinds);
139 final Collection<String> newForTree = new LinkedList<String>();
140 final Collection<String> newForUsual = new LinkedList<String>();
141 UpdateFilesHelper.iterateAffectedFiles(updatedFiles, new Consumer<Pair<String, String>>() {
142 public void consume(final Pair<String, String> pair) {
143 final String vcsName = pair.getSecond();
144 RemoteDifferenceStrategy strategy = strategyMap.get(vcsName);
145 if (strategy == null) {
146 final AbstractVcs vcs = myVcsManager.findVcsByName(vcsName);
147 if (vcs == null) return;
148 strategy = vcs.getRemoteDifferenceStrategy();
150 if (RemoteDifferenceStrategy.ASK_TREE_PROVIDER.equals(strategy)) {
151 newForTree.add(pair.getFirst());
152 } else {
153 newForUsual.add(pair.getFirst());
158 myRemoteRevisionsStateCache.invalidate(newForTree);
159 myRemoteRevisionsNumbersCache.invalidate(newForUsual);
162 public void minus(Pair<String, AbstractVcs> pair) {
163 final AbstractVcs vcs = pair.getSecond();
164 if (RemoteDifferenceStrategy.ASK_TREE_PROVIDER.equals(vcs.getRemoteDifferenceStrategy())) {
165 myRemoteRevisionsStateCache.minus(pair);
166 } else {
167 myRemoteRevisionsNumbersCache.minus(pair);
172 * @return false if not up to date
174 public boolean isUpToDate(final Change change) {
175 final AbstractVcs vcs = ChangesUtil.getVcsForChange(change, myProject);
176 if (vcs == null) return true;
177 final RemoteDifferenceStrategy strategy = vcs.getRemoteDifferenceStrategy();
178 if (RemoteDifferenceStrategy.ASK_TREE_PROVIDER.equals(strategy)) {
179 return myRemoteRevisionsStateCache.isUpToDate(change);
180 } else {
181 return myRemoteRevisionsNumbersCache.isUpToDate(change);
185 public RemoteStatusChangeNodeDecorator getChangesNodeDecorator() {
186 return myChangeDecorator;