diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java index fe9bfe3c7e8a..1ff08a049430 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java @@ -348,14 +348,14 @@ public class FileWatcher { public boolean isWatched(@NotNull final VirtualFile file) { if (isOperational()) { synchronized (myLock) { - return !checkWatchable(file.getPresentableUrl(), true, false).isEmpty(); + return !checkWatchable(file.getPresentableUrl(), true, true).isEmpty(); } } return false; } @NotNull - private Collection checkWatchable(String reportedPath, boolean isExact, boolean checkRootParents) { + private Collection checkWatchable(String reportedPath, boolean isExact, boolean fastPath) { if (reportedPath == null) return Collections.emptyList(); myAllPaths.clear(); @@ -372,26 +372,33 @@ public class FileWatcher { myWatchedPaths.clear(); ext: for (String path : myAllPaths) { + if (fastPath && !myWatchedPaths.isEmpty()) break; + + for (String root : myFlatWatchRoots) { + if (FileUtil.pathsEqual(path, root)) { + myWatchedPaths.add(path); + continue ext; + } + if (isExact) { + String parentPath = new File(path).getParent(); + if (parentPath != null && FileUtil.pathsEqual(parentPath, root)) { + myWatchedPaths.add(path); + continue ext; + } + } + } + for (String root : myRecursiveWatchRoots) { if (FileUtil.startsWith(path, root)) { myWatchedPaths.add(path); continue ext; } - if (checkRootParents && FileUtil.startsWith(root, path)) { - myWatchedPaths.add(root); - continue ext; - } - } - - String checkPath = isExact ? new File(path).getParent() : path; - for (String root : myFlatWatchRoots) { - if (FileUtil.pathsEqual(checkPath, root)) { - myWatchedPaths.add(path); - continue ext; - } - if (checkRootParents && FileUtil.startsWith(root, checkPath)) { - myWatchedPaths.add(root); - continue ext; + if (!isExact) { + String parentPath = new File(root).getParent(); + if (parentPath != null && FileUtil.pathsEqual(path, parentPath)) { + myWatchedPaths.add(root); + continue ext; + } } } } @@ -538,7 +545,7 @@ public class FileWatcher { synchronized (myLock) { boolean exactPath = op != WatcherOp.DIRTY && op != WatcherOp.RECDIRTY; - Collection paths = checkWatchable(path, exactPath, true); + Collection paths = checkWatchable(path, exactPath, false); if (paths.isEmpty()) { if (LOG.isDebugEnabled()) { diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemImpl.java index 41d1be296cb4..54a344365961 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemImpl.java @@ -17,6 +17,7 @@ package com.intellij.openapi.vfs.impl.local; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.PathManager; import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.util.io.FileUtil; @@ -59,7 +60,18 @@ public final class LocalFileSystemImpl extends LocalFileSystemBase implements Ap public WatchRequestImpl(String rootPath, boolean toWatchRecursively) throws FileNotFoundException { int index = rootPath.indexOf(JarFileSystem.JAR_SEPARATOR); if (index >= 0) rootPath = rootPath.substring(0, index); + File rootFile = new File(FileUtil.toSystemDependentName(rootPath)); + if (index > 0 || !rootFile.isDirectory()) { + File parentFile = rootFile.getParentFile(); + if (parentFile == null) { + throw new FileNotFoundException(rootPath); + } + if (!parentFile.getPath().equals(PathManager.getSystemPath()) || !rootFile.mkdir()) { + rootFile = parentFile; + } + } + myFSRootPath = rootFile.getAbsolutePath(); myRootPath = FileUtil.toSystemIndependentName(myFSRootPath); myToWatchRecursively = toWatchRecursively; @@ -266,28 +278,27 @@ public final class LocalFileSystemImpl extends LocalFileSystemBase implements Ap private void storeRefreshStatusToFiles() { if (myWatcher.isOperational()) { - // TODO: different ways to mark dirty for all these cases - final FileWatcher.DirtyPaths dirtyPaths = myWatcher.getDirtyPaths(); + FileWatcher.DirtyPaths dirtyPaths = myWatcher.getDirtyPaths(); markPathsDirty(dirtyPaths.dirtyPaths); markFlatDirsDirty(dirtyPaths.dirtyDirectories); markRecursiveDirsDirty(dirtyPaths.dirtyPathsRecursive); } } - private void markPathsDirty(final List dirtyFiles) { - for (String dirtyFile : dirtyFiles) { - VirtualFile file = findFileByPathIfCached(dirtyFile); + private void markPathsDirty(List dirtyPaths) { + for (String dirtyPath : dirtyPaths) { + VirtualFile file = findFileByPathIfCached(dirtyPath); if (file instanceof NewVirtualFile) { ((NewVirtualFile)file).markDirty(); } } } - private void markFlatDirsDirty(final List dirtyFiles) { - for (String dirtyFile : dirtyFiles) { - VirtualFile file = findFileByPathIfCached(dirtyFile); + private void markFlatDirsDirty(List dirtyPaths) { + for (String dirtyPath : dirtyPaths) { + VirtualFile file = findFileOrParentIfCached(dirtyPath); if (file instanceof NewVirtualFile) { - final NewVirtualFile nvf = (NewVirtualFile)file; + NewVirtualFile nvf = (NewVirtualFile)file; nvf.markDirty(); for (VirtualFile child : nvf.getCachedChildren()) { ((NewVirtualFile)child).markDirty(); @@ -296,15 +307,26 @@ public final class LocalFileSystemImpl extends LocalFileSystemBase implements Ap } } - private void markRecursiveDirsDirty(final List dirtyFiles) { - for (String dirtyFile : dirtyFiles) { - VirtualFile file = findFileByPathIfCached(dirtyFile); + private void markRecursiveDirsDirty(List dirtyPaths) { + for (String dirtyPath : dirtyPaths) { + VirtualFile file = findFileOrParentIfCached(dirtyPath); if (file instanceof NewVirtualFile) { ((NewVirtualFile)file).markDirtyRecursively(); } } } + private VirtualFile findFileOrParentIfCached(String path) { + VirtualFile file = findFileByPathIfCached(path); + if (file == null) { + String parentPath = new File(path).getParent(); + if (parentPath != null) { + file = findFileByPathIfCached(parentPath); + } + } + return file; + } + public void markSuspiciousFilesDirty(List files) { storeRefreshStatusToFiles(); diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/FileWatcherTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/FileWatcherTest.java index 3d2188a0afd5..f5e1ce6dac3c 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/FileWatcherTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/FileWatcherTest.java @@ -521,6 +521,14 @@ public class FileWatcherTest extends PlatformLangTestCase { assertTrue(rootDir2.renameTo(rootDir)); assertEvent(VFileEvent.class, rootDir.getPath(), rootDir2.getPath()); + myAccept = true; + assertTrue(FileUtil.delete(rootDir)); + assertEvent(VFileDeleteEvent.class, rootDir.getPath()); + + myAccept = true; + assertTrue(rootDir.mkdirs()); + assertEvent(VFileCreateEvent.class, rootDir.getPath()); + myAccept = true; assertTrue(FileUtil.delete(topDir)); assertEvent(VFileDeleteEvent.class, topDir.getPath());