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
;
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
) {
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);
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
;
67 boolean somethingChanged
= myRemoteRevisionsNumbersCache
.updateStep();
68 somethingChanged
|= myRemoteRevisionsStateCache
.updateStep();
69 if (somethingChanged
) {
70 myProject
.getMessageBus().syncPublisher(REMOTE_VERSION_CHANGED
).run();
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() {
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
);
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());
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
);
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
);
159 return myRemoteRevisionsNumbersCache
.isUpToDate(change
);
163 public RemoteStatusChangeNodeDecorator
getChangesNodeDecorator() {
164 return myChangeDecorator
;