From 8a33bd39e1378291e03804c871c04ca0f4dfc5b4 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Fri, 25 May 2018 17:51:45 +0200 Subject: [PATCH] fix for iterating content of directories that were changed outside IDE Reverting part of fa409e4 to ensure iterInDbChildren to load all children when IDE loaded all children in previous sessions. The change allows VFS event listeners to process all directory's children when handling directory deletion event. --- .../vfs/newvfs/impl/VirtualDirectoryImpl.java | 15 +++--- .../newvfs/persistent/PersistentFsTest.java | 54 +++++++++++++++++++ 2 files changed, 63 insertions(+), 6 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java index 3fd44e3ebef9..819d56f3f56c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java @@ -299,13 +299,16 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry { return Collections.emptyList(); } - if (!ourPersistence.areChildrenLoaded(this)) { - final String[] names = ourPersistence.listPersisted(this); - final NewVirtualFileSystem delegate = PersistentFS.replaceWithNativeFS(getFileSystem()); - for (String name : names) { - findChild(name, false, false, delegate); - } + if (ourPersistence.areChildrenLoaded(this)) { + return Arrays.asList(getChildren()); } + + final String[] names = ourPersistence.listPersisted(this); + final NewVirtualFileSystem delegate = PersistentFS.replaceWithNativeFS(getFileSystem()); + for (String name : names) { + findChild(name, false, false, delegate); + } + return getCachedChildren(); } diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/newvfs/persistent/PersistentFsTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/newvfs/persistent/PersistentFsTest.java index 1d4b76e993a4..59568a5f7d35 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/newvfs/persistent/PersistentFsTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/newvfs/persistent/PersistentFsTest.java @@ -187,6 +187,60 @@ public class PersistentFsTest extends PlatformTestCase { assertEquals(1, logCount[0]); } + public void testIterInDbChildrenWorksForRemovedDirsAfterRestart() throws IOException { + // test (re)creates /subDir/subSubDir/Foo.txt outside tested/watched project and checks removal events on subDir / subSubDir / Foo.txt + // test starts real testing ("after restart") after launching second time using same VFS + // hours spent writing this test: 4 + VirtualFile projectStructure = createTestProjectStructure(); + String testName = getTestName(false); + + // wrt persistence subDir becomes partially loaded and subsubDir becomes fully loaded + File nestedDirOutsideTheProject = new File(projectStructure.getPath() + "../../../"+testName + "/subDir", "subSubDir"); + Disposable disposable = null; + + try { + boolean atleastSecondRun = nestedDirOutsideTheProject.getParentFile().getParentFile().exists(); + StringBuilder eventLog = new StringBuilder(); + + if (atleastSecondRun) { + disposable = Disposer.newDisposable(); + getProject().getMessageBus().connect(disposable).subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener() { + @Override + public void before(@NotNull List events) { + for(VFileEvent event:events) { + if (event instanceof VFileDeleteEvent) process(((VFileDeleteEvent)event).getFile()); + } + } + private void process(VirtualFile file) { + String path = file.getPath(); + eventLog.append(path.substring(path.indexOf(testName) + testName.length() + 1)).append("\n"); + Iterable files = ((NewVirtualFile)file).iterInDbChildren(); + for(VirtualFile nested:files) process(nested); + } + }); + } + + // recreating structure will fire vfs removal events + VirtualFile nestedDirOutsideTheProjectFile = VfsUtil.createDirectories(nestedDirOutsideTheProject.getPath()); + WriteAction.run(() -> nestedDirOutsideTheProjectFile.createChildData(null, "Foo.txt")); + + // subsubDir becomes fully loaded wrt persistence + nestedDirOutsideTheProjectFile.getChildren(); + + if (atleastSecondRun) { + assertEquals("subDir\n" + + "subDir/subSubDir\n" + + "subDir/subSubDir/Foo.txt\n", + eventLog.toString() + ); + } + } finally { + if (disposable != null) Disposer.dispose(disposable); + // remove /subDir via java.io to have vfs events on next test launch + FileUtil.delete(nestedDirOutsideTheProject.getParentFile()); + } + } + public void testModCountIncreases() throws IOException { VirtualFile vFile = setupFile(); ManagingFS managingFS = ManagingFS.getInstance();