VCS: allow Git to report changed on server files comparing the whole tree. !! require...
[fedora-idea.git] / platform / vcs-impl / src / com / intellij / openapi / vcs / changes / RemoteRevisionsStateCache.java
blob3625ea5266a506f7e78ab0d043ec9e813bb7cb0d
1 package com.intellij.openapi.vcs.changes;
3 import com.intellij.openapi.project.Project;
4 import com.intellij.openapi.util.Pair;
5 import com.intellij.openapi.vcs.*;
6 import com.intellij.openapi.vfs.VirtualFile;
7 import com.intellij.util.containers.MultiMap;
8 import org.jetbrains.annotations.Nullable;
10 import java.io.File;
11 import java.util.*;
13 public class RemoteRevisionsStateCache implements ChangesOnServerTracker {
14 private final static long DISCRETE = 600000;
15 // true -> changed
16 private final Map<String, Pair<Boolean, VcsRoot>> myChanged;
18 private final MultiMap<VcsRoot, String> myQueries;
19 private final Map<VcsRoot, Long> myTs;
20 private final Object myLock;
21 private ProjectLevelVcsManager myVcsManager;
23 RemoteRevisionsStateCache(final Project project) {
24 myVcsManager = ProjectLevelVcsManager.getInstance(project);
25 myChanged = new HashMap<String, Pair<Boolean, VcsRoot>>();
26 myQueries = new MultiMap<VcsRoot, String>();
27 myTs = new HashMap<VcsRoot, Long>();
28 myLock = new Object();
31 public void invalidate(final Collection<String> paths) {
32 synchronized (myLock) {
33 for (String path : paths) {
34 myChanged.remove(path);
39 @Nullable
40 private VirtualFile getRootForPath(final String s) {
41 return myVcsManager.getVcsRootFor(new FilePathImpl(new File(s), false));
44 public boolean isUpToDate(final Change change) {
45 final List<File> files = ChangesUtil.getIoFilesFromChanges(Collections.singletonList(change));
46 synchronized (myLock) {
47 for (File file : files) {
48 final String path = file.getAbsolutePath();
49 final Pair<Boolean, VcsRoot> data = myChanged.get(path);
50 if (data != null && Boolean.TRUE.equals(data.getFirst())) return false;
53 return true;
56 public void plus(final Pair<String, AbstractVcs> pair) {
57 final VirtualFile root = getRootForPath(pair.getFirst());
58 if (root == null) return;
59 synchronized (myLock) {
60 myQueries.putValue(new VcsRoot(pair.getSecond(), root), pair.getFirst());
64 public void minus(Pair<String, AbstractVcs> pair) {
65 final VirtualFile root = getRootForPath(pair.getFirst());
66 if (root == null) return;
67 synchronized (myLock) {
68 myQueries.removeValue(new VcsRoot(pair.getSecond(), root), pair.getFirst());
69 myChanged.remove(pair.getFirst());
73 public void directoryMappingChanged() {
74 // todo will work?
75 synchronized (myLock) {
76 myChanged.clear();
77 myTs.clear();
81 public boolean updateStep() {
82 final MultiMap<VcsRoot, String> dirty = new MultiMap<VcsRoot, String>();
83 final long oldPoint = System.currentTimeMillis() - DISCRETE;
85 synchronized (myLock) {
86 for (VcsRoot root : myQueries.keySet()) {
87 final Collection<String> collection = myQueries.get(root);
88 for (String s : collection) {
89 dirty.putValue(root, s);
92 myQueries.clear();
94 final Set<VcsRoot> roots = new HashSet<VcsRoot>();
95 for (Map.Entry<VcsRoot, Long> entry : myTs.entrySet()) {
96 if (! dirty.get(entry.getKey()).isEmpty()) continue;
98 final Long ts = entry.getValue();
99 if ((ts == null) || (oldPoint > ts)) {
100 roots.add(entry.getKey());
103 for (Map.Entry<String, Pair<Boolean, VcsRoot>> entry : myChanged.entrySet()) {
104 final VcsRoot vcsRoot = entry.getValue().getSecond();
105 if ((! dirty.get(vcsRoot).isEmpty()) || roots.contains(vcsRoot)) {
106 dirty.putValue(vcsRoot, entry.getKey());
111 if (dirty.isEmpty()) return false;
113 final Map<String, Pair<Boolean, VcsRoot>> results = new HashMap<String, Pair<Boolean, VcsRoot>>();
114 for (VcsRoot vcsRoot : dirty.keySet()) {
115 final TreeDiffProvider provider = vcsRoot.vcs.getTreeDiffProvider();
116 if (provider == null) continue;
118 final Collection<String> paths = dirty.get(vcsRoot);
119 final Collection<String> remotelyChanged = provider.getRemotelyChanged(vcsRoot.path, paths);
120 for (String path : paths) {
121 results.put(path, new Pair<Boolean, VcsRoot>(remotelyChanged.contains(path), vcsRoot));
125 final long curTime = System.currentTimeMillis();
126 synchronized (myLock) {
127 myChanged.putAll(results);
128 for (VcsRoot vcsRoot : dirty.keySet()) {
129 myTs.put(vcsRoot, curTime);
133 return true;