blob: df1cdba7f73631005f3ca20e06d7441da986d061 [file] [log] [blame]
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.openapi.vcs.changes;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vcs.BaseRevision;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.FileStatus;
import com.intellij.openapi.vcs.VcsKey;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.BeforeAfter;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.*;
public class ChangeListsIndexes {
private final TreeMap<String, FileStatus> myFileToStatus;
private final Map<String, Pair<VcsKey, VcsRevisionNumber>> myFileToVcs;
ChangeListsIndexes() {
myFileToStatus = new TreeMap<String, FileStatus>();
myFileToVcs = new HashMap<String, Pair<VcsKey, VcsRevisionNumber>>();
}
ChangeListsIndexes(final ChangeListsIndexes idx) {
myFileToStatus = new TreeMap<String, FileStatus>(idx.myFileToStatus);
myFileToVcs = new HashMap<String, Pair<VcsKey, VcsRevisionNumber>>(idx.myFileToVcs);
}
void add(final FilePath file, final FileStatus status, final VcsKey key, VcsRevisionNumber number) {
final String fileKey = file.getIOFile().getAbsolutePath();
myFileToStatus.put(fileKey, status);
myFileToVcs.put(fileKey, Pair.create(key, number));
}
void remove(final FilePath file) {
final String fileKey = file.getIOFile().getAbsolutePath();
myFileToStatus.remove(fileKey);
myFileToVcs.remove(fileKey);
}
public FileStatus getStatus(final VirtualFile file) {
return myFileToStatus.get(new File(file.getPath()).getAbsolutePath());
}
public FileStatus getStatus(final File file) {
return myFileToStatus.get(file.getAbsolutePath());
}
public void changeAdded(final Change change, final VcsKey key) {
addChangeToIdx(change, key);
}
public void changeRemoved(final Change change) {
final ContentRevision afterRevision = change.getAfterRevision();
final ContentRevision beforeRevision = change.getBeforeRevision();
if (afterRevision != null) {
remove(afterRevision.getFile());
}
if (beforeRevision != null) {
remove(beforeRevision.getFile());
}
}
public VcsKey getVcsFor(final Change change) {
VcsKey key = getVcsForRevision(change.getAfterRevision());
if (key != null) return key;
return getVcsForRevision(change.getBeforeRevision());
}
@Nullable
private VcsKey getVcsForRevision(final ContentRevision revision) {
if (revision != null) {
final String fileKey = revision.getFile().getIOFile().getAbsolutePath();
final Pair<VcsKey, VcsRevisionNumber> pair = myFileToVcs.get(fileKey);
return pair == null ? null : pair.getFirst();
}
return null;
}
private void addChangeToIdx(final Change change, final VcsKey key) {
final ContentRevision afterRevision = change.getAfterRevision();
final ContentRevision beforeRevision = change.getBeforeRevision();
if (afterRevision != null) {
add(afterRevision.getFile(), change.getFileStatus(), key, beforeRevision == null ? VcsRevisionNumber.NULL : beforeRevision.getRevisionNumber());
}
if (beforeRevision != null) {
if (afterRevision != null) {
if (! Comparing.equal(beforeRevision.getFile(), afterRevision.getFile())) {
add(beforeRevision.getFile(), FileStatus.DELETED, key, beforeRevision.getRevisionNumber());
}
} else {
add(beforeRevision.getFile(), change.getFileStatus(), key, beforeRevision.getRevisionNumber());
}
}
}
/**
* this method is called after each local changes refresh and collects all:
* - paths that are new in local changes
* - paths that are no more changed locally
* - paths that were and are changed, but base revision has changed (ex. external update)
* (for RemoteRevisionsCache and annotation listener)
*/
public void getDelta(final ChangeListsIndexes newIndexes,
final Set<BaseRevision> toRemove,
Set<BaseRevision> toAdd,
Set<BeforeAfter<BaseRevision>> toModify) {
// this is old
final Set<String> oldKeySet = new HashSet<String>(myFileToVcs.keySet());
final Set<String> toRemoveSet = new HashSet<String>(oldKeySet);
final Set<String> newKeySet = newIndexes.myFileToVcs.keySet();
final Set<String> toAddSet = new HashSet<String>(newKeySet);
toRemoveSet.removeAll(newKeySet);
toAddSet.removeAll(oldKeySet);
// those that modified
oldKeySet.removeAll(toRemoveSet);
for (String s : toRemoveSet) {
final Pair<VcsKey, VcsRevisionNumber> pair = myFileToVcs.get(s);
toRemove.add(fromPairAndPath(s, pair));
}
for (String s : toAddSet) {
final Pair<VcsKey, VcsRevisionNumber> pair = newIndexes.myFileToVcs.get(s);
toAdd.add(fromPairAndPath(s, pair));
}
for (String s : oldKeySet) {
final Pair<VcsKey, VcsRevisionNumber> old = myFileToVcs.get(s);
final Pair<VcsKey, VcsRevisionNumber> newOne = newIndexes.myFileToVcs.get(s);
assert old != null && newOne != null;
if (! old.equals(newOne)) {
toModify.add(new BeforeAfter<BaseRevision>(fromPairAndPath(s, old), fromPairAndPath(s, newOne)));
}
}
}
private BaseRevision fromPairAndPath(String s, Pair<VcsKey, VcsRevisionNumber> pair) {
return new BaseRevision(pair.getFirst(), pair.getSecond(), s);
}
public List<BaseRevision> getAffectedFilesUnderVcs() {
final List<BaseRevision> result = new ArrayList<BaseRevision>();
for (Map.Entry<String, Pair<VcsKey, VcsRevisionNumber>> entry : myFileToVcs.entrySet()) {
final Pair<VcsKey, VcsRevisionNumber> value = entry.getValue();
result.add(fromPairAndPath(entry.getKey(), value));
}
return result;
}
public SortedSet<String> getAffectedPaths() {
return Collections.unmodifiableSortedSet((SortedSet<String>)myFileToStatus.keySet());
}
}