Fix missing events for files with directory prefix (dart-lang/watcher#84)

Fixes dart-lang/watcher#83

If any event had the same leading characters as a directory that was
also changed it would get filtered out. For example if both `lib/b/` and
`lib/b.dart` have change events we'd lose the events for `lib/b.dart`
because it shared a prefix with a directory, even though it isn't
contained within that directory.
diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md
index 65ab5df..7456590 100644
--- a/pkgs/watcher/CHANGELOG.md
+++ b/pkgs/watcher/CHANGELOG.md
@@ -1,3 +1,8 @@
+# 0.9.7+15-dev
+
+* Fix a bug on Mac where modifying a directory with a path exactly matching a
+  prefix of a modified file would suppress change events for that file.
+
 # 0.9.7+14
 
 * Prepare for breaking change in SDK where modified times for not found files
diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart
index 73703cb..0aa0566 100644
--- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart
+++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart
@@ -5,6 +5,8 @@
 import 'dart:async';
 import 'dart:io';
 
+import 'package:path/path.dart' as p;
+
 import '../directory_watcher.dart';
 import '../constructable_file_system_event.dart';
 import '../path_set.dart';
@@ -196,7 +198,7 @@
     }));
 
     bool isInModifiedDirectory(String path) =>
-        directories.any((dir) => path != dir && path.startsWith(dir));
+        directories.any((dir) => path != dir && p.isWithin(dir, path));
 
     void addEvent(String path, FileSystemEvent event) {
       if (isInModifiedDirectory(path)) return;
diff --git a/pkgs/watcher/lib/src/directory_watcher/windows.dart b/pkgs/watcher/lib/src/directory_watcher/windows.dart
index 2a70edc..9a7de5f 100644
--- a/pkgs/watcher/lib/src/directory_watcher/windows.dart
+++ b/pkgs/watcher/lib/src/directory_watcher/windows.dart
@@ -237,7 +237,7 @@
     }));
 
     bool isInModifiedDirectory(String path) =>
-        directories.any((dir) => path != dir && path.startsWith(dir));
+        directories.any((dir) => path != dir && p.isWithin(dir, path));
 
     void addEvent(String path, FileSystemEvent event) {
       if (isInModifiedDirectory(path)) return;
diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml
index 3982775..230b00b 100644
--- a/pkgs/watcher/pubspec.yaml
+++ b/pkgs/watcher/pubspec.yaml
@@ -1,5 +1,5 @@
 name: watcher
-version: 0.9.7+14
+version: 0.9.7+15-dev
 
 description: >-
   A file system watcher. It monitors changes to contents of directories and
diff --git a/pkgs/watcher/test/directory_watcher/mac_os_test.dart b/pkgs/watcher/test/directory_watcher/mac_os_test.dart
index b100f59..58ba31a 100644
--- a/pkgs/watcher/test/directory_watcher/mac_os_test.dart
+++ b/pkgs/watcher/test/directory_watcher/mac_os_test.dart
@@ -54,4 +54,15 @@
           (i, j, k) => isModifyEvent('dir/sub/sub-$i/sub-$j/file-$k.txt')));
     });
   });
+  test('does not suppress files with the same prefix as a directory', () async {
+    // Regression test for https://github.com/dart-lang/watcher/issues/83
+    writeFile('some_name.txt');
+
+    await startWatcher();
+
+    writeFile('some_name/some_name.txt');
+    deleteFile('some_name.txt');
+
+    await expectRemoveEvent('some_name.txt');
+  });
 }