case-only rename: store paths case-sensitively in dirty scope

Otherwise, if "A" and "a" are marked as dirty on a case-insensitive
system, they are compared by FilePath.equals which is case-insensitive,
and thus only one of these paths are stored in the VcsDirtyScopeImpl.

IDEA-53175, IDEA-94470
This commit is contained in:
Kirill Likhodedov
2016-05-30 17:46:19 +03:00
parent 845f69be36
commit 19dfe129e6
@@ -34,6 +34,7 @@ import com.intellij.util.containers.Convertor;
import com.intellij.util.containers.MultiMap;
import com.intellij.vcsUtil.VcsUtil;
import gnu.trove.THashSet;
import gnu.trove.TObjectHashingStrategy;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -45,6 +46,20 @@ import java.util.*;
* @author yole
*/
public class VcsDirtyScopeImpl extends VcsModifiableDirtyScope {
private static final TObjectHashingStrategy<FilePath> CASE_SENSITIVE_FILE_PATH_HASHING_STRATEGY =
new TObjectHashingStrategy<FilePath>() {
@Override
public int computeHashCode(@NotNull FilePath path) {
return Objects.hash(path.getPath(), path.isDirectory(), path.isNonLocal());
}
@Override
public boolean equals(@NotNull FilePath path1, @NotNull FilePath path2) {
return path1.isDirectory() == path2.isDirectory() &&
path1.isNonLocal() == path2.isNonLocal() &&
path1.getPath().equals(path2.getPath());
}
};
private final Map<VirtualFile, THashSet<FilePath>> myDirtyFiles = new HashMap<VirtualFile, THashSet<FilePath>>();
private final Map<VirtualFile, THashSet<FilePath>> myDirtyDirectoriesRecursively = new HashMap<VirtualFile, THashSet<FilePath>>();
private final Set<VirtualFile> myAffectedContentRoots = new THashSet<VirtualFile>();
@@ -140,7 +155,7 @@ public class VcsDirtyScopeImpl extends VcsModifiableDirtyScope {
@Override
public Set<FilePath> getDirtyFiles() {
final THashSet<FilePath> result = new THashSet<FilePath>();
final THashSet<FilePath> result = newFilePathsSet();
for (THashSet<FilePath> paths : myDirtyFiles.values()) {
result.addAll(paths);
}
@@ -159,7 +174,7 @@ public class VcsDirtyScopeImpl extends VcsModifiableDirtyScope {
@Override
public Set<FilePath> getDirtyFilesNoExpand() {
final THashSet<FilePath> paths = new THashSet<FilePath>();
final THashSet<FilePath> paths = newFilePathsSet();
for (THashSet<FilePath> filePaths : myDirtyFiles.values()) {
paths.addAll(filePaths);
}
@@ -168,7 +183,7 @@ public class VcsDirtyScopeImpl extends VcsModifiableDirtyScope {
@Override
public Set<FilePath> getRecursivelyDirtyDirectories() {
THashSet<FilePath> result = new THashSet<FilePath>();
THashSet<FilePath> result = newFilePathsSet();
for(THashSet<FilePath> dirsByRoot: myDirtyDirectoriesRecursively.values()) {
result.addAll(dirsByRoot);
}
@@ -252,8 +267,8 @@ public class VcsDirtyScopeImpl extends VcsModifiableDirtyScope {
myAffectedContentRoots.addAll(perRoot.keySet());
for (Map.Entry<VirtualFile, Collection<FileOrDir>> entry : perRoot.entrySet()) {
final VirtualFile root = entry.getKey();
final THashSet<FilePath> curFiles = new THashSet<FilePath>();
final THashSet<FilePath> curDirs = new THashSet<FilePath>();
final THashSet<FilePath> curFiles = newFilePathsSet();
final THashSet<FilePath> curDirs = newFilePathsSet();
final Collection<FileOrDir> value = entry.getValue();
for (FileOrDir fileOrDir : value) {
if (fileOrDir.myRecursive) {
@@ -273,6 +288,11 @@ public class VcsDirtyScopeImpl extends VcsModifiableDirtyScope {
}
}
@NotNull
private THashSet<FilePath> newFilePathsSet() {
return new THashSet<FilePath>(CASE_SENSITIVE_FILE_PATH_HASHING_STRATEGY);
}
private void addFilePathToMap(MultiMap<VirtualFile, FileOrDir> perRoot, final FilePath dir, final boolean recursively) {
VirtualFile vcsRoot = ApplicationManager.getApplication().runReadAction(new Computable<VirtualFile>() {
@Override
@@ -315,7 +335,7 @@ public class VcsDirtyScopeImpl extends VcsModifiableDirtyScope {
THashSet<FilePath> dirsByRoot = myDirtyDirectoriesRecursively.get(vcsRoot);
if (dirsByRoot == null) {
dirsByRoot = new THashSet<FilePath>();
dirsByRoot = newFilePathsSet();
myDirtyDirectoriesRecursively.put(vcsRoot, dirsByRoot);
}
else {
@@ -356,7 +376,7 @@ public class VcsDirtyScopeImpl extends VcsModifiableDirtyScope {
final THashSet<FilePath> dirtyFiles = myDirtyFiles.get(vcsRoot);
if (dirtyFiles == null) {
final THashSet<FilePath> set = new THashSet<FilePath>();
final THashSet<FilePath> set = newFilePathsSet();
set.add(newcomer);
myDirtyFiles.put(vcsRoot, set);
} else {