[vfs] more accurate Windows short name detection (IDEA-144285)

This commit is contained in:
Roman Shevchenko
2015-08-25 18:37:16 +03:00
parent ed817985c5
commit 530cb96829
3 changed files with 56 additions and 12 deletions
@@ -74,8 +74,8 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
@Override
public VirtualFile findFileByIoFile(@NotNull File file) {
String path = file.getAbsolutePath();
return findFileByPath(path.replace(File.separatorChar, '/'));
String path = FileUtil.toSystemIndependentName(file.getAbsolutePath());
return findFileByPath(path);
}
@NotNull
@@ -197,13 +197,11 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
path = path.substring(1); // hack over new File(path).toURI().toURL().getFile()
}
if (path.contains("~")) {
try {
path = new File(FileUtil.toSystemDependentName(path)).getCanonicalPath();
}
catch (IOException e) {
return null;
}
try {
path = FileUtil.resolveShortWindowsName(path);
}
catch (IOException e) {
return null;
}
}
@@ -227,8 +225,8 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
@Override
public VirtualFile refreshAndFindFileByIoFile(@NotNull File file) {
String path = file.getAbsolutePath();
return refreshAndFindFileByPath(path.replace(File.separatorChar, '/'));
String path = FileUtil.toSystemIndependentName(file.getAbsolutePath());
return refreshAndFindFileByPath(path);
}
@Override
@@ -1016,6 +1016,7 @@ public class FileUtil extends FileUtilRt {
* Use {@link FileUtilRt#getExtension(String)} instead to get the unchanged extension.
* If you need to check whether a file has a specified extension use {@link FileUtilRt#extensionEquals(String, String)}
*/
@SuppressWarnings("StringToUpperCaseOrToLowerCaseWithoutLocale")
@NotNull
public static String getExtension(@NotNull String fileName) {
return FileUtilRt.getExtension(fileName).toLowerCase();
@@ -1023,7 +1024,31 @@ public class FileUtil extends FileUtilRt {
@NotNull
public static String resolveShortWindowsName(@NotNull String path) throws IOException {
return SystemInfo.isWindows && StringUtil.containsChar(path, '~') ? new File(path).getCanonicalPath() : path;
return SystemInfo.isWindows && containsWindowsShortName(path) ? new File(path).getCanonicalPath() : path;
}
public static boolean containsWindowsShortName(@NotNull String path) {
if (StringUtil.containsChar(path, '~')) {
path = toSystemIndependentName(path);
int start = 0;
while (start < path.length()) {
int end = path.indexOf('/', start);
if (end < 0) end = path.length();
// "How Windows Generates 8.3 File Names from Long File Names", https://support.microsoft.com/en-us/kb/142982
int dot = path.lastIndexOf('.', end);
if (dot < start) dot = end;
if (dot - start > 2 && dot - start <= 8 && end - dot - 1 <= 3 &&
path.charAt(dot - 2) == '~' && Character.isDigit(path.charAt(dot - 1))) {
return true;
}
start = end + 1;
}
}
return false;
}
public static void collectMatchedFiles(@NotNull File root, @NotNull Pattern pattern, @NotNull List<File> outFiles) {
@@ -1672,4 +1697,8 @@ public class FileUtil extends FileUtilRt {
FileAttributes lower = FileSystemUtil.getAttributes(path.toLowerCase(Locale.ENGLISH));
return !(attributes.equals(upper) && attributes.equals(lower));
}
public static boolean isWindowsShortName(@NotNull String fileName) {
return false;
}
}
@@ -214,4 +214,21 @@ public class FileUtilLightTest {
assertThat(FileUtil.sanitizeFileName("a+b+c")).isEqualTo("a_b_c");
}
@Test
public void windowsShortName() {
assertTrue(FileUtil.containsWindowsShortName("C:\\dir~1"));
assertTrue(FileUtil.containsWindowsShortName("C:\\dir~1\\"));
assertTrue(FileUtil.containsWindowsShortName("C:\\dir~1\\file.txt"));
assertTrue(FileUtil.containsWindowsShortName("C:/dir/file~1"));
assertTrue(FileUtil.containsWindowsShortName("C:/dir/file~1.txt"));
assertTrue(FileUtil.containsWindowsShortName("C:/dir/file~1.1"));
assertFalse(FileUtil.containsWindowsShortName("~"));
assertFalse(FileUtil.containsWindowsShortName("C:\\some~dir"));
assertFalse(FileUtil.containsWindowsShortName("C:\\some-dir~1"));
assertFalse(FileUtil.containsWindowsShortName("C:/dir/file~1.extension"));
assertFalse(FileUtil.containsWindowsShortName("C:/dir/file.~1"));
assertFalse(FileUtil.containsWindowsShortName("C:/dir/file.ext~1"));
}
}