From 19dfe129e6b02769c37038a745de211a0ea44039 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sun, 29 May 2016 20:05:37 +0300 Subject: [PATCH] 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 --- .../vcs/changes/VcsDirtyScopeImpl.java | 34 +++++++++++++++---- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeImpl.java index c4a961fa1b59..30fd70256faf 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeImpl.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeImpl.java @@ -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 CASE_SENSITIVE_FILE_PATH_HASHING_STRATEGY = + new TObjectHashingStrategy() { + @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> myDirtyFiles = new HashMap>(); private final Map> myDirtyDirectoriesRecursively = new HashMap>(); private final Set myAffectedContentRoots = new THashSet(); @@ -140,7 +155,7 @@ public class VcsDirtyScopeImpl extends VcsModifiableDirtyScope { @Override public Set getDirtyFiles() { - final THashSet result = new THashSet(); + final THashSet result = newFilePathsSet(); for (THashSet paths : myDirtyFiles.values()) { result.addAll(paths); } @@ -159,7 +174,7 @@ public class VcsDirtyScopeImpl extends VcsModifiableDirtyScope { @Override public Set getDirtyFilesNoExpand() { - final THashSet paths = new THashSet(); + final THashSet paths = newFilePathsSet(); for (THashSet filePaths : myDirtyFiles.values()) { paths.addAll(filePaths); } @@ -168,7 +183,7 @@ public class VcsDirtyScopeImpl extends VcsModifiableDirtyScope { @Override public Set getRecursivelyDirtyDirectories() { - THashSet result = new THashSet(); + THashSet result = newFilePathsSet(); for(THashSet dirsByRoot: myDirtyDirectoriesRecursively.values()) { result.addAll(dirsByRoot); } @@ -252,8 +267,8 @@ public class VcsDirtyScopeImpl extends VcsModifiableDirtyScope { myAffectedContentRoots.addAll(perRoot.keySet()); for (Map.Entry> entry : perRoot.entrySet()) { final VirtualFile root = entry.getKey(); - final THashSet curFiles = new THashSet(); - final THashSet curDirs = new THashSet(); + final THashSet curFiles = newFilePathsSet(); + final THashSet curDirs = newFilePathsSet(); final Collection value = entry.getValue(); for (FileOrDir fileOrDir : value) { if (fileOrDir.myRecursive) { @@ -273,6 +288,11 @@ public class VcsDirtyScopeImpl extends VcsModifiableDirtyScope { } } + @NotNull + private THashSet newFilePathsSet() { + return new THashSet(CASE_SENSITIVE_FILE_PATH_HASHING_STRATEGY); + } + private void addFilePathToMap(MultiMap perRoot, final FilePath dir, final boolean recursively) { VirtualFile vcsRoot = ApplicationManager.getApplication().runReadAction(new Computable() { @Override @@ -315,7 +335,7 @@ public class VcsDirtyScopeImpl extends VcsModifiableDirtyScope { THashSet dirsByRoot = myDirtyDirectoriesRecursively.get(vcsRoot); if (dirsByRoot == null) { - dirsByRoot = new THashSet(); + dirsByRoot = newFilePathsSet(); myDirtyDirectoriesRecursively.put(vcsRoot, dirsByRoot); } else { @@ -356,7 +376,7 @@ public class VcsDirtyScopeImpl extends VcsModifiableDirtyScope { final THashSet dirtyFiles = myDirtyFiles.get(vcsRoot); if (dirtyFiles == null) { - final THashSet set = new THashSet(); + final THashSet set = newFilePathsSet(); set.add(newcomer); myDirtyFiles.put(vcsRoot, set); } else {