mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
VCS: allow Git to report changed on server files comparing the whole tree. !! requires fetch now. to be continued.
This commit is contained in:
@@ -19,6 +19,7 @@ import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.vcs.AbstractVcs;
|
||||
import com.intellij.openapi.vcs.FileStatus;
|
||||
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
|
||||
import com.intellij.openapi.vcs.VcsKey;
|
||||
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.vcsUtil.VcsUtil;
|
||||
@@ -91,10 +92,6 @@ public class FileGroup implements JDOMExternalizable {
|
||||
return mySupportsDeletion;
|
||||
}
|
||||
|
||||
public void add(@NotNull final String path) {
|
||||
myFiles.add(new UpdatedFile(path));
|
||||
}
|
||||
|
||||
public void addError(@NotNull final String path, @NotNull final String error) {
|
||||
myErrorsMap.put(path, error);
|
||||
}
|
||||
@@ -103,8 +100,12 @@ public class FileGroup implements JDOMExternalizable {
|
||||
return myErrorsMap;
|
||||
}
|
||||
|
||||
public void add(@NotNull String path, @NotNull AbstractVcs vcs, @NotNull VcsRevisionNumber revision) {
|
||||
myFiles.add(new UpdatedFile(path, vcs.getName(), revision.asString()));
|
||||
public void add(@NotNull String path, @NotNull String vcsName, @Nullable VcsRevisionNumber revision) {
|
||||
myFiles.add(new UpdatedFile(path, vcsName, revision == null ? "" : revision.asString()));
|
||||
}
|
||||
|
||||
public void add(@NotNull String path, @NotNull VcsKey vcsKey, @Nullable VcsRevisionNumber revision) {
|
||||
myFiles.add(new UpdatedFile(path, vcsKey, revision == null ? "" : revision.asString()));
|
||||
}
|
||||
|
||||
public void remove(String path) {
|
||||
@@ -128,6 +129,10 @@ public class FileGroup implements JDOMExternalizable {
|
||||
return files;
|
||||
}
|
||||
|
||||
public Collection<UpdatedFile> getUpdatedFiles() {
|
||||
return new ArrayList<UpdatedFile>(myFiles);
|
||||
}
|
||||
|
||||
public List<Pair<String, VcsRevisionNumber>> getFilesAndRevisions(ProjectLevelVcsManager vcsManager) {
|
||||
ArrayList<Pair<String, VcsRevisionNumber>> files = new ArrayList<Pair<String, VcsRevisionNumber>>();
|
||||
for (UpdatedFile file : myFiles) {
|
||||
@@ -248,7 +253,7 @@ public class FileGroup implements JDOMExternalizable {
|
||||
public void setRevisions(final String path, final AbstractVcs vcs, final VcsRevisionNumber revision) {
|
||||
for (UpdatedFile file : myFiles) {
|
||||
if (file.getPath().startsWith(path)) {
|
||||
file.setVcsName(vcs.getName());
|
||||
file.setVcsKey(vcs.getKeyInstanceMethod());
|
||||
file.setRevision(revision.asString());
|
||||
}
|
||||
}
|
||||
@@ -257,7 +262,7 @@ public class FileGroup implements JDOMExternalizable {
|
||||
}
|
||||
}
|
||||
|
||||
private static class UpdatedFile {
|
||||
static class UpdatedFile {
|
||||
private final String myPath;
|
||||
private String myVcsName;
|
||||
private String myRevision;
|
||||
@@ -266,7 +271,13 @@ public class FileGroup implements JDOMExternalizable {
|
||||
myPath = path;
|
||||
}
|
||||
|
||||
public UpdatedFile(final String path, final String vcsName, final String revision) {
|
||||
public UpdatedFile(final String path, @NotNull final VcsKey vcsKey, final String revision) {
|
||||
myPath = path;
|
||||
myVcsName = vcsKey.getName();
|
||||
myRevision = revision;
|
||||
}
|
||||
|
||||
private UpdatedFile(final String path, @NotNull String vcsName, final String revision) {
|
||||
myPath = path;
|
||||
myVcsName = vcsName;
|
||||
myRevision = revision;
|
||||
@@ -280,8 +291,8 @@ public class FileGroup implements JDOMExternalizable {
|
||||
return myVcsName;
|
||||
}
|
||||
|
||||
public void setVcsName(final String vcsName) {
|
||||
myVcsName = vcsName;
|
||||
public void setVcsKey(final VcsKey vcsKey) {
|
||||
myVcsName = vcsKey.getName();
|
||||
}
|
||||
|
||||
public String getRevision() {
|
||||
|
||||
@@ -26,13 +26,6 @@ public class UpdatedFilesReverseSide {
|
||||
myFileIdx = new HashMap<String, FileGroup>();
|
||||
}
|
||||
|
||||
/**
|
||||
* removes file from group that previously contained it
|
||||
*/
|
||||
public void addFileToGroup(final String groupId, final VirtualFile file, final DuplicateLevel duplicateLevel) {
|
||||
addFileToGroup(groupId, file.getPresentableUrl(), duplicateLevel);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return myFileIdx.isEmpty();
|
||||
}
|
||||
@@ -41,12 +34,12 @@ public class UpdatedFilesReverseSide {
|
||||
return myGroupHolder.get(id);
|
||||
}
|
||||
|
||||
public void addFileToGroup(final String groupId, final String file, final DuplicateLevel duplicateLevel) {
|
||||
public void addFileToGroup(final String groupId, final String file, final DuplicateLevel duplicateLevel, final String vcsName) {
|
||||
final FileGroup newGroup = myGroupHolder.get(groupId);
|
||||
addFileToGroup(newGroup, file, duplicateLevel);
|
||||
addFileToGroup(newGroup, file, duplicateLevel, vcsName);
|
||||
}
|
||||
|
||||
public void addFileToGroup(final FileGroup group, final String file, final DuplicateLevel duplicateLevel) {
|
||||
public void addFileToGroup(final FileGroup group, final String file, final DuplicateLevel duplicateLevel, final String vcsName) {
|
||||
if (duplicateLevel.searchPreviousContainment(group.getId())) {
|
||||
final FileGroup oldGroup = myFileIdx.get(file);
|
||||
if (oldGroup != null) {
|
||||
@@ -57,7 +50,7 @@ public class UpdatedFilesReverseSide {
|
||||
}
|
||||
}
|
||||
|
||||
group.add(file);
|
||||
group.add(file, vcsName, null);
|
||||
myFileIdx.put(file, group);
|
||||
}
|
||||
|
||||
@@ -89,8 +82,8 @@ public class UpdatedFilesReverseSide {
|
||||
private void copyGroup(final Parent parent, final FileGroup from, final DuplicateLevel duplicateLevel) {
|
||||
final FileGroup to = createOrGet(parent, from);
|
||||
|
||||
for (String file : from.getFiles()) {
|
||||
addFileToGroup(to, file, duplicateLevel);
|
||||
for (FileGroup.UpdatedFile updatedFile : from.getUpdatedFiles()) {
|
||||
addFileToGroup(to, updatedFile.getPath(), duplicateLevel, updatedFile.getVcsName());
|
||||
}
|
||||
for (FileGroup fromChild : from.getChildren()) {
|
||||
copyGroup(new GroupParent(to), fromChild, duplicateLevel);
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.intellij.openapi.vcs.changes;
|
||||
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.vcs.AbstractVcs;
|
||||
import com.intellij.openapi.vcs.VcsListener;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public interface ChangesOnServerTracker extends PlusMinus<Pair<String, AbstractVcs>>, VcsListener {
|
||||
// todo add vcs parameter???
|
||||
void invalidate(final Collection<String> paths);
|
||||
boolean isUpToDate(final Change change);
|
||||
boolean updateStep();
|
||||
}
|
||||
@@ -7,97 +7,85 @@ import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.vcs.*;
|
||||
import com.intellij.openapi.vcs.changes.ui.RemoteStatusChangeNodeDecorator;
|
||||
import com.intellij.openapi.vcs.diff.ItemLatestState;
|
||||
import com.intellij.openapi.vcs.diff.DiffProvider;
|
||||
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
|
||||
import com.intellij.openapi.vcs.update.UpdateFilesHelper;
|
||||
import com.intellij.openapi.vcs.update.UpdatedFiles;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.messages.Topic;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
|
||||
public class RemoteRevisionsCache implements PlusMinus<Pair<String, AbstractVcs>>, VcsListener {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.changes.RemoteRevisionsCache");
|
||||
|
||||
public static Topic<Runnable> REMOTE_VERSION_CHANGED = new Topic<Runnable>("REMOTE_VERSION_CHANGED", Runnable.class);
|
||||
|
||||
// every 5 minutes.. (time unit to check for server commits)
|
||||
private static final long ourRottenPeriod = 300 * 1000;
|
||||
private final Map<String, Pair<VcsRoot, VcsRevisionNumber>> myData;
|
||||
private final Map<VcsRoot, LazyRefreshingSelfQueue<String>> myRefreshingQueues;
|
||||
private final Map<String, VcsRevisionNumber> myLatestRevisionsMap;
|
||||
private final RemoteRevisionsNumbersCache myRemoteRevisionsNumbersCache;
|
||||
private final RemoteRevisionsStateCache myRemoteRevisionsStateCache;
|
||||
|
||||
private final ProjectLevelVcsManager myVcsManager;
|
||||
private final LocalFileSystem myLfs;
|
||||
|
||||
private final Object myLock;
|
||||
|
||||
private final RemoteStatusChangeNodeDecorator myChangeDecorator;
|
||||
|
||||
public static final VcsRevisionNumber NOT_LOADED = new VcsRevisionNumber() {
|
||||
public String asString() {
|
||||
return "NOT_LOADED";
|
||||
}
|
||||
|
||||
public int compareTo(VcsRevisionNumber o) {
|
||||
if (o == this) return 0;
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
public static final VcsRevisionNumber UNKNOWN = new VcsRevisionNumber() {
|
||||
public String asString() {
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
public int compareTo(VcsRevisionNumber o) {
|
||||
if (o == this) return 0;
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
private final Project myProject;
|
||||
private final Object myLock;
|
||||
private final Map<String, RemoteDifferenceStrategy> myKinds;
|
||||
|
||||
public static RemoteRevisionsCache getInstance(final Project project) {
|
||||
return ServiceManager.getService(project, RemoteRevisionsCache.class);
|
||||
}
|
||||
|
||||
private RemoteRevisionsCache(final Project project) {
|
||||
myLock = new Object();
|
||||
myData = new HashMap<String, Pair<VcsRoot, VcsRevisionNumber>>();
|
||||
myRefreshingQueues = Collections.synchronizedMap(new HashMap<VcsRoot, LazyRefreshingSelfQueue<String>>());
|
||||
myLatestRevisionsMap = new HashMap<String, VcsRevisionNumber>();
|
||||
myProject = project;
|
||||
myLfs = LocalFileSystem.getInstance();
|
||||
myLock = new Object();
|
||||
|
||||
myRemoteRevisionsNumbersCache = new RemoteRevisionsNumbersCache(myProject);
|
||||
myRemoteRevisionsStateCache = new RemoteRevisionsStateCache(myProject);
|
||||
|
||||
myChangeDecorator = new RemoteStatusChangeNodeDecorator(this);
|
||||
|
||||
myVcsManager = ProjectLevelVcsManager.getInstance(project);
|
||||
myVcsManager.addVcsListener(this);
|
||||
myKinds = new HashMap<String, RemoteDifferenceStrategy>();
|
||||
Disposer.register(project, new Disposable() {
|
||||
public void dispose() {
|
||||
myVcsManager.removeVcsListener(RemoteRevisionsCache.this);
|
||||
}
|
||||
});
|
||||
updateKinds();
|
||||
final MyRecursiveUpdateRequest request = new MyRecursiveUpdateRequest(project, new Runnable() {
|
||||
public void run() {
|
||||
final List<LazyRefreshingSelfQueue<String>> list = new ArrayList<LazyRefreshingSelfQueue<String>>();
|
||||
synchronized (myLock) {
|
||||
list.addAll(myRefreshingQueues.values());
|
||||
}
|
||||
LOG.debug("queues refresh started, queues: " + list.size());
|
||||
for (LazyRefreshingSelfQueue<String> queue : list) {
|
||||
queue.updateStep();
|
||||
boolean somethingChanged = myRemoteRevisionsNumbersCache.updateStep();
|
||||
somethingChanged |= myRemoteRevisionsStateCache.updateStep();
|
||||
if (somethingChanged) {
|
||||
myProject.getMessageBus().syncPublisher(REMOTE_VERSION_CHANGED).run();
|
||||
}
|
||||
}
|
||||
});
|
||||
request.start();
|
||||
}
|
||||
|
||||
private void updateKinds() {
|
||||
final VcsRoot[] roots = myVcsManager.getAllVcsRoots();
|
||||
synchronized (myLock) {
|
||||
for (VcsRoot root : roots) {
|
||||
final AbstractVcs vcs = root.vcs;
|
||||
if (! myKinds.containsKey(vcs.getName())) {
|
||||
myKinds.put(vcs.getName(), vcs.getRemoteDifferenceStrategy());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyRecursiveUpdateRequest implements Runnable {
|
||||
private final Alarm mySimpleAlarm;
|
||||
private final SlowlyClosingAlarm myControlledAlarm;
|
||||
@@ -137,198 +125,68 @@ public class RemoteRevisionsCache implements PlusMinus<Pair<String, AbstractVcs>
|
||||
}
|
||||
|
||||
public void directoryMappingChanged() {
|
||||
synchronized (myLock) {
|
||||
final HashSet<String> keys = new HashSet<String>(myData.keySet());
|
||||
for (String key : keys) {
|
||||
final Pair<VcsRoot, VcsRevisionNumber> value = myData.get(key);
|
||||
final VcsRoot storedVcsRoot = value.getFirst();
|
||||
final VirtualFile vf = myLfs.refreshAndFindFileByIoFile(new File(key));
|
||||
final AbstractVcs newVcs = (vf == null) ? null : myVcsManager.getVcsFor(vf);
|
||||
|
||||
if (newVcs == null) {
|
||||
myData.remove(key);
|
||||
getQueue(storedVcsRoot).forceRemove(key);
|
||||
} else {
|
||||
final VirtualFile newRoot = myVcsManager.getVcsRootFor(vf);
|
||||
final VcsRoot newVcsRoot = new VcsRoot(newVcs, newRoot);
|
||||
if (! storedVcsRoot.equals(newVcsRoot)) {
|
||||
switchVcs(storedVcsRoot, newVcsRoot, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void switchVcs(final VcsRoot oldVcsRoot, final VcsRoot newVcsRoot, final String key) {
|
||||
synchronized (myLock) {
|
||||
final LazyRefreshingSelfQueue<String> oldQueue = getQueue(oldVcsRoot);
|
||||
final LazyRefreshingSelfQueue<String> newQueue = getQueue(newVcsRoot);
|
||||
myData.put(key, new Pair<VcsRoot, VcsRevisionNumber>(newVcsRoot, NOT_LOADED));
|
||||
oldQueue.forceRemove(key);
|
||||
newQueue.addRequest(key);
|
||||
}
|
||||
updateKinds();
|
||||
myRemoteRevisionsNumbersCache.directoryMappingChanged();
|
||||
myRemoteRevisionsStateCache.directoryMappingChanged();
|
||||
}
|
||||
|
||||
public void plus(final Pair<String, AbstractVcs> pair) {
|
||||
LOG.debug("add " + pair.getFirst());
|
||||
// does not support
|
||||
if (pair.getSecond().getDiffProvider() == null) return;
|
||||
|
||||
final String key = pair.getFirst();
|
||||
final AbstractVcs newVcs = pair.getSecond();
|
||||
|
||||
final VirtualFile root = getRootForPath(key);
|
||||
if (root == null) return;
|
||||
|
||||
final VcsRoot vcsRoot = new VcsRoot(newVcs, root);
|
||||
|
||||
synchronized (myLock) {
|
||||
final Pair<VcsRoot, VcsRevisionNumber> value = myData.get(key);
|
||||
if (value == null) {
|
||||
LOG.debug("adding new " + key);
|
||||
final LazyRefreshingSelfQueue<String> queue = getQueue(vcsRoot);
|
||||
myData.put(key, new Pair<VcsRoot, VcsRevisionNumber>(vcsRoot, NOT_LOADED));
|
||||
queue.addRequest(key);
|
||||
} else if (! value.getFirst().equals(vcsRoot)) {
|
||||
LOG.debug("switch vcs " + key);
|
||||
switchVcs(value.getFirst(), vcsRoot, key);
|
||||
}
|
||||
final AbstractVcs vcs = pair.getSecond();
|
||||
if (RemoteDifferenceStrategy.ASK_TREE_PROVIDER.equals(vcs.getRemoteDifferenceStrategy())) {
|
||||
myRemoteRevisionsStateCache.plus(pair);
|
||||
} else {
|
||||
myRemoteRevisionsNumbersCache.plus(pair);
|
||||
}
|
||||
}
|
||||
|
||||
public void invalidate(final String path) {
|
||||
public void invalidate(final UpdatedFiles updatedFiles) {
|
||||
final Map<String, RemoteDifferenceStrategy> strategyMap;
|
||||
synchronized (myLock) {
|
||||
final Pair<VcsRoot, VcsRevisionNumber> pair = myData.remove(path);
|
||||
if (pair != null) {
|
||||
// vcs [root] seems to not change
|
||||
final VcsRoot vcsRoot = pair.getFirst();
|
||||
final LazyRefreshingSelfQueue<String> queue = getQueue(vcsRoot);
|
||||
queue.forceRemove(path);
|
||||
queue.addRequest(path);
|
||||
myData.put(path, new Pair<VcsRoot, VcsRevisionNumber>(vcsRoot, NOT_LOADED));
|
||||
}
|
||||
strategyMap = new HashMap<String, RemoteDifferenceStrategy>(myKinds);
|
||||
}
|
||||
}
|
||||
final Collection<String> newForTree = new LinkedList<String>();
|
||||
final Collection<String> newForUsual = new LinkedList<String>();
|
||||
UpdateFilesHelper.iterateAffectedFiles(updatedFiles, new Consumer<Pair<String, String>>() {
|
||||
public void consume(final Pair<String, String> pair) {
|
||||
final String vcsName = pair.getSecond();
|
||||
RemoteDifferenceStrategy strategy = strategyMap.get(vcsName);
|
||||
if (strategy == null) {
|
||||
final AbstractVcs vcs = myVcsManager.findVcsByName(vcsName);
|
||||
if (vcs == null) return;
|
||||
strategy = vcs.getRemoteDifferenceStrategy();
|
||||
}
|
||||
if (RemoteDifferenceStrategy.ASK_TREE_PROVIDER.equals(strategy)) {
|
||||
newForTree.add(pair.getFirst());
|
||||
} else {
|
||||
newForUsual.add(pair.getFirst());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@Nullable
|
||||
private VirtualFile getRootForPath(final String s) {
|
||||
return myVcsManager.getVcsRootFor(new FilePathImpl(new File(s), false));
|
||||
myRemoteRevisionsStateCache.invalidate(newForTree);
|
||||
myRemoteRevisionsNumbersCache.invalidate(newForUsual);
|
||||
}
|
||||
|
||||
public void minus(Pair<String, AbstractVcs> pair) {
|
||||
LOG.debug("minus " + pair.getFirst());
|
||||
// does not support
|
||||
if (pair.getSecond().getDiffProvider() == null) return;
|
||||
final VirtualFile root = getRootForPath(pair.getFirst());
|
||||
if (root == null) return;
|
||||
|
||||
final LazyRefreshingSelfQueue<String> queue;
|
||||
final String key = pair.getFirst();
|
||||
synchronized (myLock) {
|
||||
LOG.debug("removing " + key);
|
||||
queue = getQueue(new VcsRoot(pair.getSecond(), root));
|
||||
myData.remove(key);
|
||||
}
|
||||
queue.forceRemove(key);
|
||||
}
|
||||
|
||||
// +-
|
||||
@NotNull
|
||||
private LazyRefreshingSelfQueue<String> getQueue(final VcsRoot vcsRoot) {
|
||||
synchronized (myLock) {
|
||||
LazyRefreshingSelfQueue<String> queue = myRefreshingQueues.get(vcsRoot);
|
||||
if (queue != null) return queue;
|
||||
|
||||
queue = new LazyRefreshingSelfQueue<String>(ourRottenPeriod, new MyShouldUpdateChecker(vcsRoot), new MyUpdater(vcsRoot));
|
||||
myRefreshingQueues.put(vcsRoot, queue);
|
||||
return queue;
|
||||
final AbstractVcs vcs = pair.getSecond();
|
||||
if (RemoteDifferenceStrategy.ASK_TREE_PROVIDER.equals(vcs.getRemoteDifferenceStrategy())) {
|
||||
myRemoteRevisionsStateCache.minus(pair);
|
||||
} else {
|
||||
myRemoteRevisionsNumbersCache.minus(pair);
|
||||
}
|
||||
}
|
||||
|
||||
private class MyUpdater implements Consumer<String> {
|
||||
private final VcsRoot myVcsRoot;
|
||||
|
||||
public MyUpdater(final VcsRoot vcsRoot) {
|
||||
myVcsRoot = vcsRoot;
|
||||
/**
|
||||
* @return false if not up to date
|
||||
*/
|
||||
public boolean isUpToDate(final Change change) {
|
||||
final AbstractVcs vcs = ChangesUtil.getVcsForChange(change, myProject);
|
||||
final RemoteDifferenceStrategy strategy = vcs.getRemoteDifferenceStrategy();
|
||||
if (RemoteDifferenceStrategy.ASK_TREE_PROVIDER.equals(strategy)) {
|
||||
return myRemoteRevisionsStateCache.isUpToDate(change);
|
||||
} else {
|
||||
return myRemoteRevisionsNumbersCache.isUpToDate(change);
|
||||
}
|
||||
|
||||
public void consume(String s) {
|
||||
LOG.debug("update for: " + s);
|
||||
final VirtualFile vf = myLfs.refreshAndFindFileByIoFile(new File(s));
|
||||
final ItemLatestState state;
|
||||
final DiffProvider diffProvider = myVcsRoot.vcs.getDiffProvider();
|
||||
if (vf == null) {
|
||||
// doesnt matter if directory or not
|
||||
state = diffProvider.getLastRevision(FilePathImpl.createForDeletedFile(new File(s), false));
|
||||
} else {
|
||||
state = diffProvider.getLastRevision(vf);
|
||||
}
|
||||
final VcsRevisionNumber newNumber = state == null ? UNKNOWN : state.getNumber();
|
||||
|
||||
final Pair<VcsRoot, VcsRevisionNumber> oldPair;
|
||||
synchronized (myLock) {
|
||||
oldPair = myData.get(s);
|
||||
myData.put(s, new Pair<VcsRoot, VcsRevisionNumber>(myVcsRoot, newNumber));
|
||||
}
|
||||
|
||||
if ((oldPair == null) || (oldPair != null) && (oldPair.getSecond().compareTo(newNumber) != 0)) {
|
||||
LOG.debug("refresh triggered by " + s);
|
||||
myVcsRoot.vcs.getProject().getMessageBus().syncPublisher(REMOTE_VERSION_CHANGED).run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MyShouldUpdateChecker implements Computable<Boolean> {
|
||||
private final VcsRoot myVcsRoot;
|
||||
|
||||
public MyShouldUpdateChecker(final VcsRoot vcsRoot) {
|
||||
myVcsRoot = vcsRoot;
|
||||
}
|
||||
|
||||
public Boolean compute() {
|
||||
final AbstractVcs vcs = myVcsRoot.vcs;
|
||||
// won't be called in parallel for same vcs -> just synchronized map is ok
|
||||
final String vcsName = vcs.getName();
|
||||
LOG.debug("should update for: " + vcsName + " root: " + myVcsRoot.path.getPath());
|
||||
final VcsRevisionNumber latestNew = vcs.getDiffProvider().getLatestCommittedRevision(myVcsRoot.path);
|
||||
|
||||
final VcsRevisionNumber latestKnown = myLatestRevisionsMap.get(vcsName);
|
||||
// not known
|
||||
if (latestNew == null) return true;
|
||||
if ((latestKnown == null) || (latestNew.compareTo(latestKnown) != 0)) {
|
||||
myLatestRevisionsMap.put(vcsName, latestNew);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public VcsRevisionNumber getNumber(final String path) {
|
||||
synchronized (myLock) {
|
||||
final Pair<VcsRoot, VcsRevisionNumber> pair = myData.get(path);
|
||||
return pair == null ? NOT_LOADED : pair.getSecond();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getState(final Change change) {
|
||||
if (change.getBeforeRevision() != null && change.getAfterRevision() != null && (! change.isMoved()) && (! change.isRenamed())) {
|
||||
// just edit
|
||||
return getRevisionState(change.getBeforeRevision());
|
||||
}
|
||||
return getRevisionState(change.getBeforeRevision()) & getRevisionState(change.getAfterRevision());
|
||||
}
|
||||
|
||||
private boolean getRevisionState(final ContentRevision revision) {
|
||||
if (revision != null) {
|
||||
final VcsRevisionNumber local = revision.getRevisionNumber();
|
||||
final String path = revision.getFile().getIOFile().getAbsolutePath();
|
||||
final VcsRevisionNumber remote = getNumber(path);
|
||||
if ((NOT_LOADED == remote) || (UNKNOWN == remote)) {
|
||||
return true;
|
||||
}
|
||||
return local.compareTo(remote) == 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public RemoteStatusChangeNodeDecorator getChangesNodeDecorator() {
|
||||
|
||||
+273
@@ -0,0 +1,273 @@
|
||||
package com.intellij.openapi.vcs.changes;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.vcs.AbstractVcs;
|
||||
import com.intellij.openapi.vcs.FilePathImpl;
|
||||
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
|
||||
import com.intellij.openapi.vcs.VcsRoot;
|
||||
import com.intellij.openapi.vcs.diff.DiffProvider;
|
||||
import com.intellij.openapi.vcs.diff.ItemLatestState;
|
||||
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.Consumer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* for vcses where it is reasonable to ask revision of each item separately
|
||||
*/
|
||||
public class RemoteRevisionsNumbersCache implements ChangesOnServerTracker {
|
||||
public static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.changes.RemoteRevisionsNumbersCache");
|
||||
|
||||
// every 5 minutes.. (time unit to check for server commits)
|
||||
private static final long ourRottenPeriod = 300 * 1000;
|
||||
private final Map<String, Pair<VcsRoot, VcsRevisionNumber>> myData;
|
||||
private final Map<VcsRoot, LazyRefreshingSelfQueue<String>> myRefreshingQueues;
|
||||
private final Map<String, VcsRevisionNumber> myLatestRevisionsMap;
|
||||
private final ProjectLevelVcsManager myVcsManager;
|
||||
private final LocalFileSystem myLfs;
|
||||
private boolean mySomethingChanged;
|
||||
|
||||
private final Object myLock;
|
||||
|
||||
public static final VcsRevisionNumber NOT_LOADED = new VcsRevisionNumber() {
|
||||
public String asString() {
|
||||
return "NOT_LOADED";
|
||||
}
|
||||
|
||||
public int compareTo(VcsRevisionNumber o) {
|
||||
if (o == this) return 0;
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
public static final VcsRevisionNumber UNKNOWN = new VcsRevisionNumber() {
|
||||
public String asString() {
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
public int compareTo(VcsRevisionNumber o) {
|
||||
if (o == this) return 0;
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
RemoteRevisionsNumbersCache(final Project project) {
|
||||
myLock = new Object();
|
||||
myData = new HashMap<String, Pair<VcsRoot, VcsRevisionNumber>>();
|
||||
myRefreshingQueues = Collections.synchronizedMap(new HashMap<VcsRoot, LazyRefreshingSelfQueue<String>>());
|
||||
myLatestRevisionsMap = new HashMap<String, VcsRevisionNumber>();
|
||||
myLfs = LocalFileSystem.getInstance();
|
||||
myVcsManager = ProjectLevelVcsManager.getInstance(project);
|
||||
}
|
||||
|
||||
public boolean updateStep() {
|
||||
final List<LazyRefreshingSelfQueue<String>> list = new ArrayList<LazyRefreshingSelfQueue<String>>();
|
||||
mySomethingChanged = false;
|
||||
synchronized (myLock) {
|
||||
list.addAll(myRefreshingQueues.values());
|
||||
}
|
||||
LOG.debug("queues refresh started, queues: " + list.size());
|
||||
for (LazyRefreshingSelfQueue<String> queue : list) {
|
||||
queue.updateStep();
|
||||
}
|
||||
return mySomethingChanged;
|
||||
}
|
||||
|
||||
public void directoryMappingChanged() {
|
||||
synchronized (myLock) {
|
||||
final HashSet<String> keys = new HashSet<String>(myData.keySet());
|
||||
for (String key : keys) {
|
||||
final Pair<VcsRoot, VcsRevisionNumber> value = myData.get(key);
|
||||
final VcsRoot storedVcsRoot = value.getFirst();
|
||||
final VirtualFile vf = myLfs.refreshAndFindFileByIoFile(new File(key));
|
||||
final AbstractVcs newVcs = (vf == null) ? null : myVcsManager.getVcsFor(vf);
|
||||
|
||||
if (newVcs == null) {
|
||||
myData.remove(key);
|
||||
getQueue(storedVcsRoot).forceRemove(key);
|
||||
} else {
|
||||
final VirtualFile newRoot = myVcsManager.getVcsRootFor(vf);
|
||||
final VcsRoot newVcsRoot = new VcsRoot(newVcs, newRoot);
|
||||
if (! storedVcsRoot.equals(newVcsRoot)) {
|
||||
switchVcs(storedVcsRoot, newVcsRoot, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void switchVcs(final VcsRoot oldVcsRoot, final VcsRoot newVcsRoot, final String key) {
|
||||
synchronized (myLock) {
|
||||
final LazyRefreshingSelfQueue<String> oldQueue = getQueue(oldVcsRoot);
|
||||
final LazyRefreshingSelfQueue<String> newQueue = getQueue(newVcsRoot);
|
||||
myData.put(key, new Pair<VcsRoot, VcsRevisionNumber>(newVcsRoot, NOT_LOADED));
|
||||
oldQueue.forceRemove(key);
|
||||
newQueue.addRequest(key);
|
||||
}
|
||||
}
|
||||
|
||||
public void plus(final Pair<String, AbstractVcs> pair) {
|
||||
// does not support
|
||||
if (pair.getSecond().getDiffProvider() == null) return;
|
||||
|
||||
final String key = pair.getFirst();
|
||||
final AbstractVcs newVcs = pair.getSecond();
|
||||
|
||||
final VirtualFile root = getRootForPath(key);
|
||||
if (root == null) return;
|
||||
|
||||
final VcsRoot vcsRoot = new VcsRoot(newVcs, root);
|
||||
|
||||
synchronized (myLock) {
|
||||
final Pair<VcsRoot, VcsRevisionNumber> value = myData.get(key);
|
||||
if (value == null) {
|
||||
final LazyRefreshingSelfQueue<String> queue = getQueue(vcsRoot);
|
||||
myData.put(key, new Pair<VcsRoot, VcsRevisionNumber>(vcsRoot, NOT_LOADED));
|
||||
queue.addRequest(key);
|
||||
} else if (! value.getFirst().equals(vcsRoot)) {
|
||||
switchVcs(value.getFirst(), vcsRoot, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void invalidate(final Collection<String> paths) {
|
||||
synchronized (myLock) {
|
||||
for (String path : paths) {
|
||||
final Pair<VcsRoot, VcsRevisionNumber> pair = myData.remove(path);
|
||||
if (pair != null) {
|
||||
// vcs [root] seems to not change
|
||||
final VcsRoot vcsRoot = pair.getFirst();
|
||||
final LazyRefreshingSelfQueue<String> queue = getQueue(vcsRoot);
|
||||
queue.forceRemove(path);
|
||||
queue.addRequest(path);
|
||||
myData.put(path, new Pair<VcsRoot, VcsRevisionNumber>(vcsRoot, NOT_LOADED));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private VirtualFile getRootForPath(final String s) {
|
||||
return myVcsManager.getVcsRootFor(new FilePathImpl(new File(s), false));
|
||||
}
|
||||
|
||||
public void minus(Pair<String, AbstractVcs> pair) {
|
||||
// does not support
|
||||
if (pair.getSecond().getDiffProvider() == null) return;
|
||||
final VirtualFile root = getRootForPath(pair.getFirst());
|
||||
if (root == null) return;
|
||||
|
||||
final LazyRefreshingSelfQueue<String> queue;
|
||||
final String key = pair.getFirst();
|
||||
synchronized (myLock) {
|
||||
queue = getQueue(new VcsRoot(pair.getSecond(), root));
|
||||
myData.remove(key);
|
||||
}
|
||||
queue.forceRemove(key);
|
||||
}
|
||||
|
||||
// +-
|
||||
@NotNull
|
||||
private LazyRefreshingSelfQueue<String> getQueue(final VcsRoot vcsRoot) {
|
||||
synchronized (myLock) {
|
||||
LazyRefreshingSelfQueue<String> queue = myRefreshingQueues.get(vcsRoot);
|
||||
if (queue != null) return queue;
|
||||
|
||||
queue = new LazyRefreshingSelfQueue<String>(ourRottenPeriod, new MyShouldUpdateChecker(vcsRoot), new MyUpdater(vcsRoot));
|
||||
myRefreshingQueues.put(vcsRoot, queue);
|
||||
return queue;
|
||||
}
|
||||
}
|
||||
|
||||
private class MyUpdater implements Consumer<String> {
|
||||
private final VcsRoot myVcsRoot;
|
||||
|
||||
public MyUpdater(final VcsRoot vcsRoot) {
|
||||
myVcsRoot = vcsRoot;
|
||||
}
|
||||
|
||||
public void consume(String s) {
|
||||
LOG.debug("update for: " + s);
|
||||
final VirtualFile vf = myLfs.refreshAndFindFileByIoFile(new File(s));
|
||||
final ItemLatestState state;
|
||||
final DiffProvider diffProvider = myVcsRoot.vcs.getDiffProvider();
|
||||
if (vf == null) {
|
||||
// doesnt matter if directory or not
|
||||
state = diffProvider.getLastRevision(FilePathImpl.createForDeletedFile(new File(s), false));
|
||||
} else {
|
||||
state = diffProvider.getLastRevision(vf);
|
||||
}
|
||||
final VcsRevisionNumber newNumber = state == null ? UNKNOWN : state.getNumber();
|
||||
|
||||
final Pair<VcsRoot, VcsRevisionNumber> oldPair;
|
||||
synchronized (myLock) {
|
||||
oldPair = myData.get(s);
|
||||
myData.put(s, new Pair<VcsRoot, VcsRevisionNumber>(myVcsRoot, newNumber));
|
||||
}
|
||||
|
||||
if ((oldPair == null) || (oldPair != null) && (oldPair.getSecond().compareTo(newNumber) != 0)) {
|
||||
LOG.debug("refresh triggered by " + s);
|
||||
mySomethingChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MyShouldUpdateChecker implements Computable<Boolean> {
|
||||
private final VcsRoot myVcsRoot;
|
||||
|
||||
public MyShouldUpdateChecker(final VcsRoot vcsRoot) {
|
||||
myVcsRoot = vcsRoot;
|
||||
}
|
||||
|
||||
public Boolean compute() {
|
||||
final AbstractVcs vcs = myVcsRoot.vcs;
|
||||
// won't be called in parallel for same vcs -> just synchronized map is ok
|
||||
final String vcsName = vcs.getName();
|
||||
LOG.debug("should update for: " + vcsName + " root: " + myVcsRoot.path.getPath());
|
||||
final VcsRevisionNumber latestNew = vcs.getDiffProvider().getLatestCommittedRevision(myVcsRoot.path);
|
||||
|
||||
final VcsRevisionNumber latestKnown = myLatestRevisionsMap.get(vcsName);
|
||||
// not known
|
||||
if (latestNew == null) return true;
|
||||
if ((latestKnown == null) || (latestNew.compareTo(latestKnown) != 0)) {
|
||||
myLatestRevisionsMap.put(vcsName, latestNew);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private VcsRevisionNumber getNumber(final String path) {
|
||||
synchronized (myLock) {
|
||||
final Pair<VcsRoot, VcsRevisionNumber> pair = myData.get(path);
|
||||
return pair == null ? NOT_LOADED : pair.getSecond();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isUpToDate(final Change change) {
|
||||
if (change.getBeforeRevision() != null && change.getAfterRevision() != null && (! change.isMoved()) && (! change.isRenamed())) {
|
||||
return getRevisionState(change.getBeforeRevision());
|
||||
}
|
||||
return getRevisionState(change.getBeforeRevision()) && getRevisionState(change.getAfterRevision());
|
||||
}
|
||||
|
||||
private boolean getRevisionState(final ContentRevision revision) {
|
||||
if (revision != null) {
|
||||
final VcsRevisionNumber local = revision.getRevisionNumber();
|
||||
final String path = revision.getFile().getIOFile().getAbsolutePath();
|
||||
final VcsRevisionNumber remote = getNumber(path);
|
||||
if ((NOT_LOADED == remote) || (UNKNOWN == remote)) {
|
||||
return true;
|
||||
}
|
||||
return local.compareTo(remote) == 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
package com.intellij.openapi.vcs.changes;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.vcs.*;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
public class RemoteRevisionsStateCache implements ChangesOnServerTracker {
|
||||
private final static long DISCRETE = 600000;
|
||||
// true -> changed
|
||||
private final Map<String, Pair<Boolean, VcsRoot>> myChanged;
|
||||
|
||||
private final MultiMap<VcsRoot, String> myQueries;
|
||||
private final Map<VcsRoot, Long> myTs;
|
||||
private final Object myLock;
|
||||
private ProjectLevelVcsManager myVcsManager;
|
||||
|
||||
RemoteRevisionsStateCache(final Project project) {
|
||||
myVcsManager = ProjectLevelVcsManager.getInstance(project);
|
||||
myChanged = new HashMap<String, Pair<Boolean, VcsRoot>>();
|
||||
myQueries = new MultiMap<VcsRoot, String>();
|
||||
myTs = new HashMap<VcsRoot, Long>();
|
||||
myLock = new Object();
|
||||
}
|
||||
|
||||
public void invalidate(final Collection<String> paths) {
|
||||
synchronized (myLock) {
|
||||
for (String path : paths) {
|
||||
myChanged.remove(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private VirtualFile getRootForPath(final String s) {
|
||||
return myVcsManager.getVcsRootFor(new FilePathImpl(new File(s), false));
|
||||
}
|
||||
|
||||
public boolean isUpToDate(final Change change) {
|
||||
final List<File> files = ChangesUtil.getIoFilesFromChanges(Collections.singletonList(change));
|
||||
synchronized (myLock) {
|
||||
for (File file : files) {
|
||||
final String path = file.getAbsolutePath();
|
||||
final Pair<Boolean, VcsRoot> data = myChanged.get(path);
|
||||
if (data != null && Boolean.TRUE.equals(data.getFirst())) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void plus(final Pair<String, AbstractVcs> pair) {
|
||||
final VirtualFile root = getRootForPath(pair.getFirst());
|
||||
if (root == null) return;
|
||||
synchronized (myLock) {
|
||||
myQueries.putValue(new VcsRoot(pair.getSecond(), root), pair.getFirst());
|
||||
}
|
||||
}
|
||||
|
||||
public void minus(Pair<String, AbstractVcs> pair) {
|
||||
final VirtualFile root = getRootForPath(pair.getFirst());
|
||||
if (root == null) return;
|
||||
synchronized (myLock) {
|
||||
myQueries.removeValue(new VcsRoot(pair.getSecond(), root), pair.getFirst());
|
||||
myChanged.remove(pair.getFirst());
|
||||
}
|
||||
}
|
||||
|
||||
public void directoryMappingChanged() {
|
||||
// todo will work?
|
||||
synchronized (myLock) {
|
||||
myChanged.clear();
|
||||
myTs.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean updateStep() {
|
||||
final MultiMap<VcsRoot, String> dirty = new MultiMap<VcsRoot, String>();
|
||||
final long oldPoint = System.currentTimeMillis() - DISCRETE;
|
||||
|
||||
synchronized (myLock) {
|
||||
for (VcsRoot root : myQueries.keySet()) {
|
||||
final Collection<String> collection = myQueries.get(root);
|
||||
for (String s : collection) {
|
||||
dirty.putValue(root, s);
|
||||
}
|
||||
}
|
||||
myQueries.clear();
|
||||
|
||||
final Set<VcsRoot> roots = new HashSet<VcsRoot>();
|
||||
for (Map.Entry<VcsRoot, Long> entry : myTs.entrySet()) {
|
||||
if (! dirty.get(entry.getKey()).isEmpty()) continue;
|
||||
|
||||
final Long ts = entry.getValue();
|
||||
if ((ts == null) || (oldPoint > ts)) {
|
||||
roots.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
for (Map.Entry<String, Pair<Boolean, VcsRoot>> entry : myChanged.entrySet()) {
|
||||
final VcsRoot vcsRoot = entry.getValue().getSecond();
|
||||
if ((! dirty.get(vcsRoot).isEmpty()) || roots.contains(vcsRoot)) {
|
||||
dirty.putValue(vcsRoot, entry.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dirty.isEmpty()) return false;
|
||||
|
||||
final Map<String, Pair<Boolean, VcsRoot>> results = new HashMap<String, Pair<Boolean, VcsRoot>>();
|
||||
for (VcsRoot vcsRoot : dirty.keySet()) {
|
||||
final TreeDiffProvider provider = vcsRoot.vcs.getTreeDiffProvider();
|
||||
if (provider == null) continue;
|
||||
|
||||
final Collection<String> paths = dirty.get(vcsRoot);
|
||||
final Collection<String> remotelyChanged = provider.getRemotelyChanged(vcsRoot.path, paths);
|
||||
for (String path : paths) {
|
||||
results.put(path, new Pair<Boolean, VcsRoot>(remotelyChanged.contains(path), vcsRoot));
|
||||
}
|
||||
}
|
||||
|
||||
final long curTime = System.currentTimeMillis();
|
||||
synchronized (myLock) {
|
||||
myChanged.putAll(results);
|
||||
for (VcsRoot vcsRoot : dirty.keySet()) {
|
||||
myTs.put(vcsRoot, curTime);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -17,7 +17,7 @@ public class RemoteStatusChangeNodeDecorator implements ChangeNodeDecorator {
|
||||
}
|
||||
|
||||
public void decorate(final Change change, final SimpleColoredComponent component) {
|
||||
final boolean state = myRemoteRevisionsCache.getState(change);
|
||||
final boolean state = myRemoteRevisionsCache.isUpToDate(change);
|
||||
reportState(state);
|
||||
if (! state) {
|
||||
component.append(" ");
|
||||
|
||||
+1
-1
@@ -501,9 +501,9 @@ public abstract class AbstractCommonUpdateAction extends AbstractVcsAction {
|
||||
if (myActionInfo.canChangeFileStatus()) {
|
||||
final List<VirtualFile> files = new ArrayList<VirtualFile>();
|
||||
final RemoteRevisionsCache revisionsCache = RemoteRevisionsCache.getInstance(myProject);
|
||||
revisionsCache.invalidate(myUpdatedFiles);
|
||||
UpdateFilesHelper.iterateFileGroupFiles(myUpdatedFiles, new UpdateFilesHelper.Callback() {
|
||||
public void onFile(final String filePath, final String groupId) {
|
||||
revisionsCache.invalidate(filePath);
|
||||
@NonNls final String path = VfsUtil.pathToUrl(filePath.replace(File.separatorChar, '/'));
|
||||
final VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(path);
|
||||
if (file != null) {
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package com.intellij.openapi.vcs.update;
|
||||
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.util.Consumer;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class UpdateFilesHelper {
|
||||
@@ -47,6 +50,24 @@ public class UpdateFilesHelper {
|
||||
}
|
||||
}
|
||||
|
||||
private static void iterateGroup(final FileGroup group, final Consumer<Pair<String, String>> callback) {
|
||||
for (FileGroup.UpdatedFile updatedFile : group.getUpdatedFiles()) {
|
||||
callback.consume(new Pair<String, String>(updatedFile.getPath(), updatedFile.getVcsName()));
|
||||
}
|
||||
}
|
||||
|
||||
public static void iterateAffectedFiles(final UpdatedFiles updatedFiles, final Consumer<Pair<String, String>> callback) {
|
||||
final List<FileGroup> groups = updatedFiles.getTopLevelGroups();
|
||||
for (FileGroup group : groups) {
|
||||
iterateGroup(group, callback);
|
||||
|
||||
// for changed on server
|
||||
for (FileGroup childGroup : group.getChildren()) {
|
||||
iterateGroup(childGroup, callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface Callback {
|
||||
void onFile(final String filePath, final String groupId);
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vcs.AbstractVcsHelper;
|
||||
import com.intellij.openapi.vcs.FilePath;
|
||||
import com.intellij.openapi.vcs.VcsKey;
|
||||
import com.intellij.openapi.vcs.update.*;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -165,11 +166,12 @@ public class CvsUpdateEnvironment implements UpdateEnvironment {
|
||||
|
||||
final List<VirtualFile> list = invokeManualMerging(paths, myProject);
|
||||
FileGroup mergedGroup = updatedFiles.getGroupById(FileGroup.MERGED_ID);
|
||||
final VcsKey vcsKey = CvsVcs2.getKey();
|
||||
for(VirtualFile mergedFile: list) {
|
||||
String path = FileUtil.toSystemDependentName(mergedFile.getPresentableUrl());
|
||||
mergedWithConflictsGroup.remove(path);
|
||||
binaryMergedGroup.remove(path);
|
||||
mergedGroup.add(path);
|
||||
mergedGroup.add(path, vcsKey, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.intellij.cvsSupport2.cvshandlers;
|
||||
|
||||
import com.intellij.CvsBundle;
|
||||
import com.intellij.cvsSupport2.CvsVcs2;
|
||||
import com.intellij.cvsSupport2.actions.update.UpdateSettings;
|
||||
import com.intellij.cvsSupport2.config.CvsConfiguration;
|
||||
import com.intellij.cvsSupport2.connections.CvsRootProvider;
|
||||
@@ -16,6 +17,7 @@ import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vcs.FilePath;
|
||||
import com.intellij.openapi.vcs.VcsKey;
|
||||
import com.intellij.openapi.vcs.update.FileGroup;
|
||||
import com.intellij.openapi.vcs.update.UpdatedFiles;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
@@ -126,12 +128,13 @@ public class UpdateHandler extends CommandCvsHandler implements PostCvsActivity
|
||||
|
||||
}
|
||||
|
||||
final VcsKey vcsKey = CvsVcs2.getKey();
|
||||
for (final MergedWithConflictProjectOrModuleFile myCorruptedFile : myCorruptedFiles) {
|
||||
if (myCorruptedFile.shouldBeCheckedOut()) {
|
||||
addFileToCheckout(myCorruptedFile.getOriginal());
|
||||
}
|
||||
else {
|
||||
myUpdatedFiles.getGroupById(FileGroup.MODIFIED_ID).add(myCorruptedFile.getOriginal().getPath());
|
||||
myUpdatedFiles.getGroupById(FileGroup.MODIFIED_ID).add(myCorruptedFile.getOriginal().getPath(), vcsKey, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-6
@@ -65,12 +65,7 @@ public class UpdatedFilesProcessor extends CvsMessagesAdapter {
|
||||
FileGroup collection = getCollectionFor(message.getType(), virtualFile);
|
||||
LOG.assertTrue(collection != null, String.valueOf(message.getType()));
|
||||
final CvsRevisionNumber revision = message.getRevision();
|
||||
if (revision != null) {
|
||||
collection.add(path, CvsVcs2.getInstance(myProject), revision);
|
||||
}
|
||||
else {
|
||||
collection.add(path);
|
||||
}
|
||||
collection.add(path, CvsVcs2.getKey(), revision);
|
||||
}
|
||||
|
||||
private FileGroup getCollectionFor(int messageType, @Nullable VirtualFile vFile) {
|
||||
|
||||
Reference in New Issue
Block a user