VCS: option to turn off background checks for "changed on server"
[fedora-idea.git] / platform / vcs-impl / src / com / intellij / openapi / vcs / changes / RemoteRevisionsCache.java
blob3ceb5556102caa66594e8746d33b96f922fe1266
1 package com.intellij.openapi.vcs.changes;
3 import com.intellij.openapi.Disposable;
4 import com.intellij.openapi.components.ServiceManager;
5 import com.intellij.openapi.diagnostic.Logger;
6 import com.intellij.openapi.project.Project;
7 import com.intellij.openapi.util.Disposer;
8 import com.intellij.openapi.util.Pair;
9 import com.intellij.openapi.util.Getter;
10 import com.intellij.openapi.vcs.*;
11 import com.intellij.openapi.vcs.changes.ui.RemoteStatusChangeNodeDecorator;
12 import com.intellij.openapi.vcs.update.UpdateFilesHelper;
13 import com.intellij.openapi.vcs.update.UpdatedFiles;
14 import com.intellij.openapi.vfs.LocalFileSystem;
15 import com.intellij.util.Consumer;
16 import com.intellij.util.messages.Topic;
18 import java.util.Collection;
19 import java.util.HashMap;
20 import java.util.LinkedList;
21 import java.util.Map;
23 public class RemoteRevisionsCache implements PlusMinus<Pair<String, AbstractVcs>>, VcsListener {
24 private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.changes.RemoteRevisionsCache");
26 public static Topic<Runnable> REMOTE_VERSION_CHANGED = new Topic<Runnable>("REMOTE_VERSION_CHANGED", Runnable.class);
28 private final RemoteRevisionsNumbersCache myRemoteRevisionsNumbersCache;
29 private final RemoteRevisionsStateCache myRemoteRevisionsStateCache;
31 private final ProjectLevelVcsManager myVcsManager;
32 private final LocalFileSystem myLfs;
34 private final RemoteStatusChangeNodeDecorator myChangeDecorator;
35 private final Project myProject;
36 private final Object myLock;
37 private final Map<String, RemoteDifferenceStrategy> myKinds;
38 private ControlledCycle myControlledCycle;
40 public static RemoteRevisionsCache getInstance(final Project project) {
41 return ServiceManager.getService(project, RemoteRevisionsCache.class);
44 private RemoteRevisionsCache(final Project project) {
45 myProject = project;
46 myLfs = LocalFileSystem.getInstance();
47 myLock = new Object();
49 myRemoteRevisionsNumbersCache = new RemoteRevisionsNumbersCache(myProject);
50 myRemoteRevisionsStateCache = new RemoteRevisionsStateCache(myProject);
52 myChangeDecorator = new RemoteStatusChangeNodeDecorator(this);
54 myVcsManager = ProjectLevelVcsManager.getInstance(project);
55 myVcsManager.addVcsListener(this);
56 myKinds = new HashMap<String, RemoteDifferenceStrategy>();
57 Disposer.register(project, new Disposable() {
58 public void dispose() {
59 myVcsManager.removeVcsListener(RemoteRevisionsCache.this);
61 });
62 updateKinds();
63 myControlledCycle = new ControlledCycle(project, new Getter<Boolean>() {
64 public Boolean get() {
65 final boolean shouldBeDone = VcsConfiguration.getInstance(myProject).CHECK_LOCALLY_CHANGED_CONFLICTS_IN_BACKGROUND;
66 if (shouldBeDone) {
67 boolean somethingChanged = myRemoteRevisionsNumbersCache.updateStep();
68 somethingChanged |= myRemoteRevisionsStateCache.updateStep();
69 if (somethingChanged) {
70 myProject.getMessageBus().syncPublisher(REMOTE_VERSION_CHANGED).run();
73 return shouldBeDone;
75 });
76 if ((! myProject.isDefault()) && VcsConfiguration.getInstance(myProject).CHECK_LOCALLY_CHANGED_CONFLICTS_IN_BACKGROUND) {
77 myControlledCycle.start();
81 public void startRefreshInBackground() {
82 if (myProject.isDefault()) return;
83 myControlledCycle.start();
86 private void updateKinds() {
87 final VcsRoot[] roots = myVcsManager.getAllVcsRoots();
88 synchronized (myLock) {
89 for (VcsRoot root : roots) {
90 final AbstractVcs vcs = root.vcs;
91 if (! myKinds.containsKey(vcs.getName())) {
92 myKinds.put(vcs.getName(), vcs.getRemoteDifferenceStrategy());
98 public void directoryMappingChanged() {
99 updateKinds();
100 myRemoteRevisionsNumbersCache.directoryMappingChanged();
101 myRemoteRevisionsStateCache.directoryMappingChanged();
104 public void plus(final Pair<String, AbstractVcs> pair) {
105 final AbstractVcs vcs = pair.getSecond();
106 if (RemoteDifferenceStrategy.ASK_TREE_PROVIDER.equals(vcs.getRemoteDifferenceStrategy())) {
107 myRemoteRevisionsStateCache.plus(pair);
108 } else {
109 myRemoteRevisionsNumbersCache.plus(pair);
113 public void invalidate(final UpdatedFiles updatedFiles) {
114 final Map<String, RemoteDifferenceStrategy> strategyMap;
115 synchronized (myLock) {
116 strategyMap = new HashMap<String, RemoteDifferenceStrategy>(myKinds);
118 final Collection<String> newForTree = new LinkedList<String>();
119 final Collection<String> newForUsual = new LinkedList<String>();
120 UpdateFilesHelper.iterateAffectedFiles(updatedFiles, new Consumer<Pair<String, String>>() {
121 public void consume(final Pair<String, String> pair) {
122 final String vcsName = pair.getSecond();
123 RemoteDifferenceStrategy strategy = strategyMap.get(vcsName);
124 if (strategy == null) {
125 final AbstractVcs vcs = myVcsManager.findVcsByName(vcsName);
126 if (vcs == null) return;
127 strategy = vcs.getRemoteDifferenceStrategy();
129 if (RemoteDifferenceStrategy.ASK_TREE_PROVIDER.equals(strategy)) {
130 newForTree.add(pair.getFirst());
131 } else {
132 newForUsual.add(pair.getFirst());
137 myRemoteRevisionsStateCache.invalidate(newForTree);
138 myRemoteRevisionsNumbersCache.invalidate(newForUsual);
141 public void minus(Pair<String, AbstractVcs> pair) {
142 final AbstractVcs vcs = pair.getSecond();
143 if (RemoteDifferenceStrategy.ASK_TREE_PROVIDER.equals(vcs.getRemoteDifferenceStrategy())) {
144 myRemoteRevisionsStateCache.minus(pair);
145 } else {
146 myRemoteRevisionsNumbersCache.minus(pair);
151 * @return false if not up to date
153 public boolean isUpToDate(final Change change) {
154 final AbstractVcs vcs = ChangesUtil.getVcsForChange(change, myProject);
155 final RemoteDifferenceStrategy strategy = vcs.getRemoteDifferenceStrategy();
156 if (RemoteDifferenceStrategy.ASK_TREE_PROVIDER.equals(strategy)) {
157 return myRemoteRevisionsStateCache.isUpToDate(change);
158 } else {
159 return myRemoteRevisionsNumbersCache.isUpToDate(change);
163 public RemoteStatusChangeNodeDecorator getChangesNodeDecorator() {
164 return myChangeDecorator;