diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index 30a19756e..d4c7bbce3 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,3 +1,12 @@ +## 2.0.0 + +- Changes the behavior of the `DirectoryWatcher` so that it no longer follows + symlinks. On Linux, but not on MacOS or Windows, it used to watch directories + to which there was a symlink within the directory being watched. It no longer + does that. Code that depends on that behavior will need to be updated so that + it independently traverses the root directory, locating and resolving + symlinks, and watching any directories being linked to. + ## 1.1.3 - Improve handling of diff --git a/pkgs/watcher/lib/src/directory_watcher/linux.dart b/pkgs/watcher/lib/src/directory_watcher/linux.dart index cb1d07781..2a6e1ebcd 100644 --- a/pkgs/watcher/lib/src/directory_watcher/linux.dart +++ b/pkgs/watcher/lib/src/directory_watcher/linux.dart @@ -92,7 +92,7 @@ class _LinuxDirectoryWatcher }); _listen( - Directory(path).list(recursive: true), + Directory(path).list(recursive: true, followLinks: false), (FileSystemEntity entity) { if (entity is Directory) { _watchSubdir(entity.path); @@ -228,7 +228,7 @@ class _LinuxDirectoryWatcher /// Emits [ChangeType.ADD] events for the recursive contents of [path]. void _addSubdir(String path) { - _listen(Directory(path).list(recursive: true), (FileSystemEntity entity) { + _listen(Directory(path).list(recursive: true, followLinks: false), (FileSystemEntity entity) { if (entity is Directory) { _watchSubdir(entity.path); } else { diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index b46138347..b57c6e106 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -148,7 +148,7 @@ class _MacOSDirectoryWatcher if (_files.containsDir(path)) continue; - var stream = Directory(path).list(recursive: true); + var stream = Directory(path).list(recursive: true, followLinks: false); var subscription = stream.listen((entity) { if (entity is Directory) return; if (_files.contains(path)) return; @@ -373,7 +373,7 @@ class _MacOSDirectoryWatcher _files.clear(); var completer = Completer(); - var stream = Directory(path).list(recursive: true); + var stream = Directory(path).list(recursive: true, followLinks: false); _initialListSubscription = stream.listen((entity) { if (entity is! Directory) _files.add(entity.path); }, onError: _emitError, onDone: completer.complete, cancelOnError: true); diff --git a/pkgs/watcher/lib/src/directory_watcher/polling.dart b/pkgs/watcher/lib/src/directory_watcher/polling.dart index 207679b1a..67b5ee6a0 100644 --- a/pkgs/watcher/lib/src/directory_watcher/polling.dart +++ b/pkgs/watcher/lib/src/directory_watcher/polling.dart @@ -112,7 +112,7 @@ class _PollingDirectoryWatcher _filesToProcess.add(null); } - var stream = Directory(path).list(recursive: true); + var stream = Directory(path).list(recursive: true, followLinks: false); _listSubscription = stream.listen((entity) { assert(!_events.isClosed); diff --git a/pkgs/watcher/lib/src/directory_watcher/windows.dart b/pkgs/watcher/lib/src/directory_watcher/windows.dart index 8f212684c..0f503205e 100644 --- a/pkgs/watcher/lib/src/directory_watcher/windows.dart +++ b/pkgs/watcher/lib/src/directory_watcher/windows.dart @@ -185,7 +185,7 @@ class _WindowsDirectoryWatcher if (_files.containsDir(path)) continue; - var stream = Directory(path).list(recursive: true); + var stream = Directory(path).list(recursive: true, followLinks: false); var subscription = stream.listen((entity) { if (entity is Directory) return; if (_files.contains(entity.path)) return; @@ -435,7 +435,7 @@ class _WindowsDirectoryWatcher _files.clear(); var completer = Completer(); - var stream = Directory(path).list(recursive: true); + var stream = Directory(path).list(recursive: true, followLinks: false); void handleEntity(FileSystemEntity entity) { if (entity is! Directory) _files.add(entity.path); } diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 16af27bc2..9ab46d275 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 1.1.3 +version: 2.0.0 description: >- A file system watcher. It monitors changes to contents of directories and sends notifications when files have been added, removed, or modified. diff --git a/pkgs/watcher/test/directory_watcher/shared.dart b/pkgs/watcher/test/directory_watcher/shared.dart index 1ebc78d4b..b35722121 100644 --- a/pkgs/watcher/test/directory_watcher/shared.dart +++ b/pkgs/watcher/test/directory_watcher/shared.dart @@ -341,4 +341,19 @@ void sharedTests() { await inAnyOrder(events); }); }); + group('symlinks', () { + test('are not watched when not enabled', () async { + writeFile('dir/sub/a.txt', contents: 'a'); + writeFile('sibling/sub/b.txt', contents: '1'); + writeSymlink('dir/linked', target: 'sibling'); + await startWatcher(path: 'dir'); + + writeFile('sibling/sub/b.txt', contents: '2'); + // Ensure that any events for the first modification arrive before the + // events for the second modification. + await pumpEventQueue(); + writeFile('dir/sub/a.txt', contents: 'a'); + await expectModifyEvent('dir/sub/a.txt'); + }); + }); } diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 7867b9fc2..88062ca4c 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -267,6 +267,19 @@ void renameDir(String from, String to) { void deleteDir(String path) { Directory(p.join(d.sandbox, path)).deleteSync(recursive: true); } + +/// Schedules writing a symlink in the sandbox at [path] that links to [target]. +void writeSymlink(String path, {required String target}) { + var fullPath = p.join(d.sandbox, path); + + // Create any needed subdirectories. + var dir = Directory(p.dirname(fullPath)); + if (!dir.existsSync()) { + dir.createSync(recursive: true); + } + + Link(fullPath).createSync(target); +} /// Runs [callback] with every permutation of non-negative numbers for each /// argument less than [limit].