mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[platform] fixes missed notifications on flat file watch root changes on macOS (IDEA-159022)
This commit is contained in:
+9
-2
@@ -141,6 +141,13 @@ class CanonicalPathMap {
|
||||
continue ext;
|
||||
}
|
||||
}
|
||||
else {
|
||||
String rootParent = new File(root).getParent();
|
||||
if (rootParent != null && FileUtil.namesEqual(path, rootParent)) {
|
||||
changedPaths.add(root);
|
||||
continue ext;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (String root : myRecursiveWatchRoots) {
|
||||
@@ -149,8 +156,8 @@ class CanonicalPathMap {
|
||||
continue ext;
|
||||
}
|
||||
if (!isExact) {
|
||||
String parentPath = new File(root).getParent();
|
||||
if (parentPath != null && FileUtil.namesEqual(path, parentPath)) {
|
||||
String rootParent = new File(root).getParent();
|
||||
if (rootParent != null && FileUtil.namesEqual(path, rootParent)) {
|
||||
changedPaths.add(root);
|
||||
continue ext;
|
||||
}
|
||||
|
||||
+103
-4
@@ -17,31 +17,130 @@ package com.intellij.openapi.vfs.impl.local;
|
||||
|
||||
import com.intellij.openapi.util.io.IoTestUtil;
|
||||
import com.intellij.testFramework.rules.TempDirectory;
|
||||
import com.intellij.util.PathUtil;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import static com.intellij.openapi.util.Pair.pair;
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class CanonicalPathMapTest {
|
||||
@Rule public TempDirectory myTempDir = new TempDirectory();
|
||||
|
||||
@Test
|
||||
public void testRemappedSymLinkReportsOriginalWatchedPath() throws Exception {
|
||||
public void flatRootReportedExactlyViaParent() {
|
||||
String root = "/parent/root";
|
||||
CanonicalPathMap map = new CanonicalPathMap(emptyList(), singletonList(root));
|
||||
Collection<String> paths = map.getWatchedPaths(PathUtil.getParentPath(root), true);
|
||||
assertThat(paths).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void flatRootReportedExactlyViaItself() {
|
||||
String root = "/parent/root.txt";
|
||||
CanonicalPathMap map = new CanonicalPathMap(emptyList(), singletonList(root));
|
||||
Collection<String> paths = map.getWatchedPaths(root, true);
|
||||
assertThat(paths).containsExactly(root);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void flatRootReportedExactlyViaChild() {
|
||||
String root = "/parent/root", child = root + "/child.txt";
|
||||
CanonicalPathMap map = new CanonicalPathMap(emptyList(), singletonList(root));
|
||||
Collection<String> paths = map.getWatchedPaths(child, true);
|
||||
assertThat(paths).containsExactly(child);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void flatRootReportedInexactlyViaParent() {
|
||||
String root = "/parent/root.txt";
|
||||
CanonicalPathMap map = new CanonicalPathMap(emptyList(), singletonList(root));
|
||||
Collection<String> paths = map.getWatchedPaths(PathUtil.getParentPath(root), false);
|
||||
assertThat(paths).containsExactly(root);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void flatRootReportedInexactlyViaItself() {
|
||||
String root = "/parent/root";
|
||||
CanonicalPathMap map = new CanonicalPathMap(emptyList(), singletonList(root));
|
||||
Collection<String> paths = map.getWatchedPaths(root, false);
|
||||
assertThat(paths).containsExactly(root);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void flatRootReportedInexactlyViaChild() {
|
||||
String root = "/parent/root", child = root + "/child_dir";
|
||||
CanonicalPathMap map = new CanonicalPathMap(emptyList(), singletonList(root));
|
||||
Collection<String> paths = map.getWatchedPaths(child, false);
|
||||
assertThat(paths).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void recursiveRootReportedExactlyViaParent() {
|
||||
String root = "/parent/root";
|
||||
CanonicalPathMap map = new CanonicalPathMap(singletonList(root), emptyList());
|
||||
Collection<String> paths = map.getWatchedPaths(PathUtil.getParentPath(root), true);
|
||||
assertThat(paths).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void recursiveRootReportedExactlyViaItself() {
|
||||
String root = "/parent/root";
|
||||
CanonicalPathMap map = new CanonicalPathMap(singletonList(root), emptyList());
|
||||
Collection<String> paths = map.getWatchedPaths(root, true);
|
||||
assertThat(paths).containsExactly(root);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void recursiveRootReportedExactlyViaChild() {
|
||||
String root = "/parent/root", child = root + "/child.txt";
|
||||
CanonicalPathMap map = new CanonicalPathMap(singletonList(root), emptyList());
|
||||
Collection<String> paths = map.getWatchedPaths(child, true);
|
||||
assertThat(paths).containsExactly(child);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void recursiveRootReportedInexactlyViaParent() {
|
||||
String root = "/parent/root";
|
||||
CanonicalPathMap map = new CanonicalPathMap(singletonList(root), emptyList());
|
||||
Collection<String> paths = map.getWatchedPaths(PathUtil.getParentPath(root), false);
|
||||
assertThat(paths).containsExactly(root);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void recursiveRootReportedInexactlyViaItself() {
|
||||
String root = "/parent/root";
|
||||
CanonicalPathMap map = new CanonicalPathMap(singletonList(root), emptyList());
|
||||
Collection<String> paths = map.getWatchedPaths(root, false);
|
||||
assertThat(paths).containsExactly(root);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void recursiveRootReportedInexactlyViaChild() {
|
||||
String root = "/parent/root", child = root + "/child";
|
||||
CanonicalPathMap map = new CanonicalPathMap(singletonList(root), emptyList());
|
||||
Collection<String> paths = map.getWatchedPaths(child, false);
|
||||
assertThat(paths).containsExactly(child);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void remappedSymLinkReportsOriginalWatchedPath() throws IOException, InterruptedException {
|
||||
// Tests the situation where the watch root is a symlink AND REMAPPED by the native file watcher.
|
||||
File realDir = myTempDir.newFolder("real");
|
||||
File symLink = IoTestUtil.createSymLink(realDir.getPath(), myTempDir.getRoot() + "/link");
|
||||
File mappedDir = new File(myTempDir.getRoot(), "mapped");
|
||||
|
||||
// Initial symlink map: /?/root/link_dir -> /?/root/real
|
||||
CanonicalPathMap pathMap = new CanonicalPathMap(Collections.singletonList(symLink.getPath()), Collections.emptyList());
|
||||
CanonicalPathMap pathMap = new CanonicalPathMap(singletonList(symLink.getPath()), emptyList());
|
||||
|
||||
// REMAP from native file watcher: /?/root/mapped -> /?/root/real
|
||||
pathMap.addMapping(Collections.singletonList(pair(mappedDir.getPath(), realDir.getPath())));
|
||||
pathMap.addMapping(singletonList(pair(mappedDir.getPath(), realDir.getPath())));
|
||||
|
||||
Collection<String> watchedPaths = pathMap.getWatchedPaths(new File(mappedDir, "file.txt").getPath(), true);
|
||||
assertThat(watchedPaths).containsExactly(new File(symLink, "file.txt").getPath());
|
||||
|
||||
@@ -81,6 +81,8 @@ class FileWatcherTest : BareTestFixtureTestCase() {
|
||||
|
||||
runInEdtAndWait { VirtualFileManager.getInstance().syncRefresh() }
|
||||
|
||||
alarm = Alarm(Alarm.ThreadToUse.POOLED_THREAD, testRootDisposable)
|
||||
|
||||
watcher = (fs as LocalFileSystemImpl).fileWatcher
|
||||
assertFalse(watcher.isOperational)
|
||||
watcher.startup { reset ->
|
||||
@@ -90,8 +92,6 @@ class FileWatcherTest : BareTestFixtureTestCase() {
|
||||
}
|
||||
wait { !watcher.isOperational }
|
||||
|
||||
alarm = Alarm(Alarm.ThreadToUse.POOLED_THREAD, testRootDisposable)
|
||||
|
||||
LOG.debug("================== setting up " + getTestName(false) + " ==================")
|
||||
}
|
||||
|
||||
@@ -122,7 +122,17 @@ class FileWatcherTest : BareTestFixtureTestCase() {
|
||||
val file = tempDir.newFile("test.txt")
|
||||
refresh(file)
|
||||
|
||||
watch(file)
|
||||
watch(file, false)
|
||||
assertEvents({ file.writeText("new content") }, mapOf(file to 'U'))
|
||||
assertEvents({ file.delete() }, mapOf(file to 'D'))
|
||||
assertEvents({ file.writeText("re-creation") }, mapOf(file to 'C'))
|
||||
}
|
||||
|
||||
@Test fun testFileRootRecursive() {
|
||||
val file = tempDir.newFile("test.txt")
|
||||
refresh(file)
|
||||
|
||||
watch(file, true)
|
||||
assertEvents({ file.writeText("new content") }, mapOf(file to 'U'))
|
||||
assertEvents({ file.delete() }, mapOf(file to 'D'))
|
||||
assertEvents({ file.writeText("re-creation") }, mapOf(file to 'C'))
|
||||
|
||||
Reference in New Issue
Block a user