Unified · Split
| @@ -76,7 +76,7 @@ impl Watcher for FsWatcher { · 75 unmodified lines | |||
| 76 | paths.get(ancestor).is_some_and(|entry| match entry { | 76 | paths.get(ancestor).is_some_and(|entry| match entry { |
| 77 | FsWatcherRegistration::Pending { .. } => false, | 77 | FsWatcherRegistration::Pending { .. } => false, |
| 78 | FsWatcherRegistration::Registered { mode, .. } => { | 78 | FsWatcherRegistration::Registered { mode, .. } => { |
| 79 | recursive_mode(*mode) == notify::RecursiveMode::Recursive | 79 | platform_recursive_mode(*mode) == notify::RecursiveMode::Recursive |
| 80 | } | 80 | } |
| 81 | }) | 81 | }) |
| 82 | }); | 82 | }); |
| @@ -551,7 +551,7 @@ impl<T: notify::Watcher + Send> WatchBackend for T { · 468 unmodified lines | |||
| 551 | } | 551 | } |
| 552 | } | 552 | } |
| 553 | 553 | ||
| 554 | /// `GlobalWatcher` is the low-level manager of filesystem watching. There is one per `RealFs`. | 554 | /// `GlobalWatcher` is the low-level platform-agnostic manager of filesystem watching. There is one per `RealFs`. |
| 555 | /// | 555 | /// |
| 556 | /// `GlobalWatcher` talks to a `WatchBackend`, which handles the OS-specific details of filesystem watching. | 556 | /// `GlobalWatcher` talks to a `WatchBackend`, which handles the OS-specific details of filesystem watching. |
| 557 | /// In production, we use the `notify` crate for this. The job of `GlobalWatcher` is to convey watch and unwatch | 557 | /// In production, we use the `notify` crate for this. The job of `GlobalWatcher` is to convey watch and unwatch |
| @@ -648,13 +648,17 @@ impl GlobalWatcher { · 90 unmodified lines | |||
| 648 | } | 648 | } |
| 649 | 649 | ||
| 650 | pub(crate) fn new(executor: &BackgroundExecutor) -> Self { | 650 | pub(crate) fn new(executor: &BackgroundExecutor) -> Self { |
| 651 | Self::with_backends(executor, None, None) | 651 | Self::with_backends( |
| 652 | executor, | ||
| 653 | (None, platform_recursive_mode(WatcherMode::Native)), | ||
| 654 | (None, platform_recursive_mode(WatcherMode::Poll)), | ||
| 655 | ) | ||
| 652 | } | 656 | } |
| 653 | 657 | ||
| 654 | fn with_backends( | 658 | fn with_backends( |
| 655 | executor: &BackgroundExecutor, | 659 | executor: &BackgroundExecutor, |
| 656 | native_backend: Option<Box<dyn WatchBackend>>, | 660 | native: (Option<Box<dyn WatchBackend>>, notify::RecursiveMode), |
| 657 | poll_backend: Option<Box<dyn WatchBackend>>, | 661 | poll: (Option<Box<dyn WatchBackend>>, notify::RecursiveMode), |
| 658 | ) -> Self { | 662 | ) -> Self { |
| 659 | let state = Arc::new(Mutex::new(WatcherState { | 663 | let state = Arc::new(Mutex::new(WatcherState { |
| 660 | watchers: HashMap::new(), | 664 | watchers: HashMap::new(), |
| @@ -672,10 +676,11 @@ impl GlobalWatcher { · 11 unmodified lines | |||
| 672 | executor: executor.clone(), | 676 | executor: executor.clone(), |
| 673 | native: BackendState::new( | 677 | native: BackendState::new( |
| 674 | WatcherMode::Native, | 678 | WatcherMode::Native, |
| 679 | native.1, | ||
| 675 | executor.clone(), | 680 | executor.clone(), |
| 676 | native_backend, | 681 | native.0, |
| 677 | ), | 682 | ), |
| 678 | poll: BackendState::new(WatcherMode::Poll, executor.clone(), poll_backend), | 683 | poll: BackendState::new(WatcherMode::Poll, poll.1, executor.clone(), poll.0), |
| 679 | } | 684 | } |
| 680 | .run(wake_rx), | 685 | .run(wake_rx), |
| 681 | ) | 686 | ) |
| @@ -690,6 +695,10 @@ impl GlobalWatcher { · 8 unmodified lines | |||
| 690 | 695 | ||
| 691 | struct BackendState { | 696 | struct BackendState { |
| 692 | mode: WatcherMode, | 697 | mode: WatcherMode, |
| 698 | // Whether this backend watches recursively. Determined once at construction | ||
| 699 | // (from the platform for the real backend, or chosen explicitly in tests) so | ||
| 700 | // that coverage reasoning works even before the backend has been created. | ||
| 701 | recursive_mode: notify::RecursiveMode, | ||
| 693 | executor: BackgroundExecutor, | 702 | executor: BackgroundExecutor, |
| 694 | backend: Option<Box<dyn WatchBackend>>, | 703 | backend: Option<Box<dyn WatchBackend>>, |
| 695 | /// Paths that we have successfully asked the backend to watch. | 704 | /// Paths that we have successfully asked the backend to watch. |
| @@ -753,11 +762,11 @@ impl Reconciler { · 57 unmodified lines | |||
| 753 | health_checks = std::mem::take(&mut state.pending_health_checks); | 762 | health_checks = std::mem::take(&mut state.pending_health_checks); |
| 754 | let dirty = std::mem::take(&mut state.dirty_paths); | 763 | let dirty = std::mem::take(&mut state.dirty_paths); |
| 755 | for (mode, path) in dirty { | 764 | for (mode, path) in dirty { |
| 756 | let affected_paths = match mode { | 765 | let (affected_paths, is_recursive) = match mode { |
| 757 | WatcherMode::Native => &mut native_affected_paths, | 766 | WatcherMode::Native => (&mut native_affected_paths, self.native.is_recursive()), |
| 758 | WatcherMode::Poll => &mut poll_affected_paths, | 767 | WatcherMode::Poll => (&mut poll_affected_paths, self.poll.is_recursive()), |
| 759 | }; | 768 | }; |
| 760 | if recursive_mode(mode) == notify::RecursiveMode::Recursive { | 769 | if is_recursive { |
| 761 | for (descendant, _) in state.path_registrations(mode).range::<Path, _>(( | 770 | for (descendant, _) in state.path_registrations(mode).range::<Path, _>(( |
| 762 | std::ops::Bound::Excluded(path.as_ref()), | 771 | std::ops::Bound::Excluded(path.as_ref()), |
| 763 | std::ops::Bound::Unbounded, | 772 | std::ops::Bound::Unbounded, |
| @@ -797,11 +806,13 @@ impl Reconciler { · 33 unmodified lines | |||
| 797 | impl BackendState { | 806 | impl BackendState { |
| 798 | fn new( | 807 | fn new( |
| 799 | mode: WatcherMode, | 808 | mode: WatcherMode, |
| 809 | recursive_mode: notify::RecursiveMode, | ||
| 800 | executor: BackgroundExecutor, | 810 | executor: BackgroundExecutor, |
| 801 | backend: Option<Box<dyn WatchBackend>>, | 811 | backend: Option<Box<dyn WatchBackend>>, |
| 802 | ) -> Self { | 812 | ) -> Self { |
| 803 | Self { | 813 | Self { |
| 804 | mode, | 814 | mode, |
| 815 | recursive_mode, | ||
| 805 | executor, | 816 | executor, |
| 806 | backend, | 817 | backend, |
| 807 | applied_paths: HashSet::new(), | 818 | applied_paths: HashSet::new(), |
| @@ -811,6 +822,10 @@ impl BackendState { · 3 unmodified lines | |||
| 811 | } | 822 | } |
| 812 | } | 823 | } |
| 813 | 824 | ||
| 825 | fn is_recursive(&self) -> bool { | ||
| 826 | self.recursive_mode == notify::RecursiveMode::Recursive | ||
| 827 | } | ||
| 828 | |||
| 814 | fn reconcile( | 829 | fn reconcile( |
| 815 | &mut self, | 830 | &mut self, |
| 816 | affected_paths: HashSet<Arc<Path>>, | 831 | affected_paths: HashSet<Arc<Path>>, |
| @@ -829,7 +844,7 @@ impl BackendState { · 12 unmodified lines | |||
| 829 | let registrations = watcher_state.path_registrations(self.mode); | 844 | let registrations = watcher_state.path_registrations(self.mode); |
| 830 | for path in affected_paths { | 845 | for path in affected_paths { |
| 831 | let is_desired = registrations.contains_key(&path); | 846 | let is_desired = registrations.contains_key(&path); |
| 832 | let is_covered = recursive_mode(self.mode) == notify::RecursiveMode::Recursive | 847 | let is_covered = self.is_recursive() |
| 833 | && path | 848 | && path |
| 834 | .ancestors() | 849 | .ancestors() |
| 835 | .skip(1) | 850 | .skip(1) |
| @@ -938,7 +953,7 @@ impl BackendState { · 102 unmodified lines | |||
| 938 | 953 | ||
| 939 | // Check that no path in the applied set is a strict child of another, | 954 | // Check that no path in the applied set is a strict child of another, |
| 940 | // if the backend is recursive, since this would be redundant. | 955 | // if the backend is recursive, since this would be redundant. |
| 941 | if recursive_mode(self.mode) == notify::RecursiveMode::Recursive { | 956 | if self.is_recursive() { |
| 942 | let mut applied_paths = self | 957 | let mut applied_paths = self |
| 943 | .applied_paths | 958 | .applied_paths |
| 944 | .iter() | 959 | .iter() |
| @@ -1017,7 +1032,7 @@ impl BackendState { · 72 unmodified lines | |||
| 1017 | paths: Vec<Arc<Path>>, | 1032 | paths: Vec<Arc<Path>>, |
| 1018 | watcher_state: &Arc<Mutex<WatcherState>>, | 1033 | watcher_state: &Arc<Mutex<WatcherState>>, |
| 1019 | ) -> Option<Instant> { | 1034 | ) -> Option<Instant> { |
| 1020 | let recursive_mode = recursive_mode(self.mode); | 1035 | let recursive_mode = self.recursive_mode; |
| 1021 | let mut queue = paths; | 1036 | let mut queue = paths; |
| 1022 | let mut wake_at = None; | 1037 | let mut wake_at = None; |
| 1023 | while !queue.is_empty() { | 1038 | while !queue.is_empty() { |
| @@ -1195,7 +1210,7 @@ fn create_backend( · 171 unmodified lines | |||
| 1195 | } | 1210 | } |
| 1196 | } | 1211 | } |
| 1197 | 1212 | ||
| 1198 | fn recursive_mode(mode: WatcherMode) -> notify::RecursiveMode { | 1213 | fn platform_recursive_mode(mode: WatcherMode) -> notify::RecursiveMode { |
| 1199 | match mode { | 1214 | match mode { |
| 1200 | WatcherMode::Native => { | 1215 | WatcherMode::Native => { |
| 1201 | if cfg!(any(target_os = "windows", target_os = "macos")) { | 1216 | if cfg!(any(target_os = "windows", target_os = "macos")) { |
| @@ -1274,6 +1289,7 @@ fn handle_event(mode: WatcherMode, state: &Mutex<WatcherState>, event: notify::R · 72 unmodified lines | |||
| 1274 | #[cfg(test)] | 1289 | #[cfg(test)] |
| 1275 | mod tests { | 1290 | mod tests { |
| 1276 | use super::*; | 1291 | use super::*; |
| 1292 | use notify::RecursiveMode; | ||
| 1277 | use std::{collections::HashSet, path::PathBuf}; | 1293 | use std::{collections::HashSet, path::PathBuf}; |
| 1278 | 1294 | ||
| 1279 | fn rescan(path: &str) -> PathEvent { | 1295 | fn rescan(path: &str) -> PathEvent { |
| @@ -1461,17 +1477,30 @@ mod tests { · 181 unmodified lines | |||
| 1461 | } | 1477 | } |
| 1462 | } | 1478 | } |
| 1463 | 1479 | ||
| 1480 | type FakeBackend = Option<(Arc<Mutex<FakeWatchBackend>>, notify::RecursiveMode)>; | ||
| 1481 | |||
| 1482 | fn fake_backend( | ||
| 1483 | backend: FakeBackend, | ||
| 1484 | mode: WatcherMode, | ||
| 1485 | ) -> (Option<Box<dyn WatchBackend>>, notify::RecursiveMode) { | ||
| 1486 | match backend { | ||
| 1487 | Some((backend, recursive_mode)) => ( | ||
| 1488 | Some(Box::new(SharedFakeWatchBackend(backend)) as Box<dyn WatchBackend>), | ||
| 1489 | recursive_mode, | ||
| 1490 | ), | ||
| 1491 | None => (None, platform_recursive_mode(mode)), | ||
| 1492 | } | ||
| 1493 | } | ||
| 1494 | |||
| 1464 | fn test_global( | 1495 | fn test_global( |
| 1465 | executor: &BackgroundExecutor, | 1496 | executor: &BackgroundExecutor, |
| 1466 | native_backend: Option<Arc<Mutex<FakeWatchBackend>>>, | 1497 | native_backend: FakeBackend, |
| 1467 | poll_backend: Option<Arc<Mutex<FakeWatchBackend>>>, | 1498 | poll_backend: FakeBackend, |
| 1468 | ) -> GlobalWatcher { | 1499 | ) -> GlobalWatcher { |
| 1469 | GlobalWatcher::with_backends( | 1500 | GlobalWatcher::with_backends( |
| 1470 | executor, | 1501 | executor, |
| 1471 | native_backend | 1502 | fake_backend(native_backend, WatcherMode::Native), |
| 1472 | .map(|backend| Box::new(SharedFakeWatchBackend(backend)) as Box<dyn WatchBackend>), | 1503 | fake_backend(poll_backend, WatcherMode::Poll), |
| 1473 | poll_backend | ||
| 1474 | .map(|backend| Box::new(SharedFakeWatchBackend(backend)) as Box<dyn WatchBackend>), | ||
| 1475 | ) | 1504 | ) |
| 1476 | } | 1505 | } |
| 1477 | 1506 | ||
| @@ -1495,7 +1524,14 @@ mod tests { · 17 unmodified lines | |||
| 1495 | #[gpui::test] | 1524 | #[gpui::test] |
| 1496 | async fn watch_and_unwatch_call_the_backend_once_per_path(executor: BackgroundExecutor) { | 1525 | async fn watch_and_unwatch_call_the_backend_once_per_path(executor: BackgroundExecutor) { |
| 1497 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); | 1526 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); |
| 1498 | let global = test_global(&executor, Some(backend.clone()), None); | 1527 | let global = test_global( |
| 1528 | &executor, | ||
| 1529 | Some(( | ||
| 1530 | backend.clone(), | ||
| 1531 | platform_recursive_mode(WatcherMode::Native), | ||
| 1532 | )), | ||
| 1533 | None, | ||
| 1534 | ); | ||
| 1499 | let path = Arc::<Path>::from(Path::new("/repo")); | 1535 | let path = Arc::<Path>::from(Path::new("/repo")); |
| 1500 | 1536 | ||
| 1501 | let first = global.add(path.clone(), WatcherMode::Native, noop_callback()); | 1537 | let first = global.add(path.clone(), WatcherMode::Native, noop_callback()); |
| @@ -1516,7 +1552,11 @@ mod tests { · 14 unmodified lines | |||
| 1516 | #[gpui::test] | 1552 | #[gpui::test] |
| 1517 | async fn covered_child_is_promoted_when_parent_is_unregistered(executor: BackgroundExecutor) { | 1553 | async fn covered_child_is_promoted_when_parent_is_unregistered(executor: BackgroundExecutor) { |
| 1518 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); | 1554 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); |
| 1519 | let global = test_global(&executor, None, Some(backend.clone())); | 1555 | let global = test_global( |
| 1556 | &executor, | ||
| 1557 | None, | ||
| 1558 | Some((backend.clone(), RecursiveMode::Recursive)), | ||
| 1559 | ); | ||
| 1520 | let parent = Arc::<Path>::from(Path::new("/repo")); | 1560 | let parent = Arc::<Path>::from(Path::new("/repo")); |
| 1521 | let child = Arc::<Path>::from(Path::new("/repo/foo.csproj")); | 1561 | let child = Arc::<Path>::from(Path::new("/repo/foo.csproj")); |
| 1522 | 1562 | ||
| @@ -1543,7 +1583,11 @@ mod tests { · 20 unmodified lines | |||
| 1543 | #[gpui::test] | 1583 | #[gpui::test] |
| 1544 | async fn child_is_demoted_when_covering_parent_is_registered(executor: BackgroundExecutor) { | 1584 | async fn child_is_demoted_when_covering_parent_is_registered(executor: BackgroundExecutor) { |
| 1545 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); | 1585 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); |
| 1546 | let global = test_global(&executor, None, Some(backend.clone())); | 1586 | let global = test_global( |
| 1587 | &executor, | ||
| 1588 | None, | ||
| 1589 | Some((backend.clone(), RecursiveMode::Recursive)), | ||
| 1590 | ); | ||
| 1547 | let parent = Arc::<Path>::from(Path::new("/repo")); | 1591 | let parent = Arc::<Path>::from(Path::new("/repo")); |
| 1548 | let child = Arc::<Path>::from(Path::new("/repo/sub")); | 1592 | let child = Arc::<Path>::from(Path::new("/repo/sub")); |
| 1549 | 1593 | ||
| @@ -1568,10 +1612,83 @@ mod tests { · 18 unmodified lines | |||
| 1568 | assert!(!backend.watched_paths.contains(child.as_ref())); | 1612 | assert!(!backend.watched_paths.contains(child.as_ref())); |
| 1569 | } | 1613 | } |
| 1570 | 1614 | ||
| 1615 | #[gpui::test] | ||
| 1616 | async fn non_recursive_backend_does_not_cover_children(executor: BackgroundExecutor) { | ||
| 1617 | // A non-recursive backend (e.g. inotify) does not deliver events for a | ||
| 1618 | // child via an ancestor's watch, so coverage must not kick in: every | ||
| 1619 | // registered path keeps its own watch, nothing is demoted, and removing an | ||
| 1620 | // ancestor leaves the descendant's watch untouched. This is the mirror | ||
| 1621 | // image of `covered_child_is_promoted_when_parent_is_unregistered`, where | ||
| 1622 | // a recursive ancestor covers the child and its removal promotes it. The | ||
| 1623 | // polymorphic fake lets us pin this on any host, independent of what | ||
| 1624 | // `platform_recursive_mode` would pick. | ||
| 1625 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); | ||
| 1626 | let global = test_global( | ||
| 1627 | &executor, | ||
| 1628 | Some((backend.clone(), RecursiveMode::NonRecursive)), | ||
| 1629 | None, | ||
| 1630 | ); | ||
| 1631 | let parent = Arc::<Path>::from(Path::new("/repo")); | ||
| 1632 | let child = Arc::<Path>::from(Path::new("/repo/sub")); | ||
| 1633 | |||
| 1634 | let (child_events, child_callback) = collecting_callback(); | ||
| 1635 | global.add(child.clone(), WatcherMode::Native, child_callback); | ||
| 1636 | executor.run_until_parked(); | ||
| 1637 | assert_eq!(backend.lock().watch_calls, &[child.to_path_buf()]); | ||
| 1638 | |||
| 1639 | let parent_id = global.add(parent.clone(), WatcherMode::Native, noop_callback()); | ||
| 1640 | executor.run_until_parked(); | ||
| 1641 | { | ||
| 1642 | let backend = backend.lock(); | ||
| 1643 | assert_eq!( | ||
| 1644 | backend.watch_calls, | ||
| 1645 | &[child.to_path_buf(), parent.to_path_buf()], | ||
| 1646 | "the parent gets its own watch without covering the child" | ||
| 1647 | ); | ||
| 1648 | assert_eq!( | ||
| 1649 | backend.unwatch_calls, | ||
| 1650 | Vec::<PathBuf>::new(), | ||
| 1651 | "no demotion happens without recursive coverage" | ||
| 1652 | ); | ||
| 1653 | assert!(backend.watched_paths.contains(parent.as_ref())); | ||
| 1654 | assert!( | ||
| 1655 | backend.watched_paths.contains(child.as_ref()), | ||
| 1656 | "the child keeps its own watch under a non-recursive backend" | ||
| 1657 | ); | ||
| 1658 | } | ||
| 1659 | |||
| 1660 | // Removing the ancestor must not disturb the child: with no coverage there | ||
| 1661 | // is nothing to promote, so the child is neither re-watched nor rescanned. | ||
| 1662 | global.remove(parent_id); | ||
| 1663 | executor.run_until_parked(); | ||
| 1664 | { | ||
| 1665 | let backend = backend.lock(); | ||
| 1666 | assert_eq!( | ||
| 1667 | backend.unwatch_calls, | ||
| 1668 | &[parent.to_path_buf()], | ||
| 1669 | "only the ancestor is unwatched" | ||
| 1670 | ); | ||
| 1671 | assert_eq!( | ||
| 1672 | backend.watch_calls, | ||
| 1673 | &[child.to_path_buf(), parent.to_path_buf()], | ||
| 1674 | "the child is not re-watched when the ancestor goes away" | ||
| 1675 | ); | ||
| 1676 | assert!(backend.watched_paths.contains(child.as_ref())); | ||
| 1677 | } | ||
| 1678 | assert!( | ||
| 1679 | child_events.lock().is_empty(), | ||
| 1680 | "the child gets no rescan since its watch never lapsed" | ||
| 1681 | ); | ||
| 1682 | } | ||
| 1683 | |||
| 1571 | #[gpui::test] | 1684 | #[gpui::test] |
| 1572 | async fn removing_a_covered_child_issues_no_unwatch(executor: BackgroundExecutor) { | 1685 | async fn removing_a_covered_child_issues_no_unwatch(executor: BackgroundExecutor) { |
| 1573 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); | 1686 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); |
| 1574 | let global = test_global(&executor, None, Some(backend.clone())); | 1687 | let global = test_global( |
| 1688 | &executor, | ||
| 1689 | None, | ||
| 1690 | Some((backend.clone(), RecursiveMode::Recursive)), | ||
| 1691 | ); | ||
| 1575 | let parent = Arc::<Path>::from(Path::new("/repo")); | 1692 | let parent = Arc::<Path>::from(Path::new("/repo")); |
| 1576 | let child = Arc::<Path>::from(Path::new("/repo/foo.csproj")); | 1693 | let child = Arc::<Path>::from(Path::new("/repo/foo.csproj")); |
| 1577 | 1694 | ||
| @@ -1602,7 +1719,11 @@ mod tests { · 24 unmodified lines | |||
| 1602 | #[gpui::test] | 1719 | #[gpui::test] |
| 1603 | async fn nested_registrations_keep_applied_as_an_antichain(executor: BackgroundExecutor) { | 1720 | async fn nested_registrations_keep_applied_as_an_antichain(executor: BackgroundExecutor) { |
| 1604 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); | 1721 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); |
| 1605 | let global = test_global(&executor, None, Some(backend.clone())); | 1722 | let global = test_global( |
| 1723 | &executor, | ||
| 1724 | None, | ||
| 1725 | Some((backend.clone(), RecursiveMode::Recursive)), | ||
| 1726 | ); | ||
| 1606 | let parent = Arc::<Path>::from(Path::new("/repo")); | 1727 | let parent = Arc::<Path>::from(Path::new("/repo")); |
| 1607 | let child = Arc::<Path>::from(Path::new("/repo/a")); | 1728 | let child = Arc::<Path>::from(Path::new("/repo/a")); |
| 1608 | let grandchild = Arc::<Path>::from(Path::new("/repo/a/b")); | 1729 | let grandchild = Arc::<Path>::from(Path::new("/repo/a/b")); |
| @@ -1632,7 +1753,11 @@ mod tests { · 23 unmodified lines | |||
| 1632 | #[gpui::test] | 1753 | #[gpui::test] |
| 1633 | async fn deferred_child_is_not_retained_as_intent_once_covered(executor: BackgroundExecutor) { | 1754 | async fn deferred_child_is_not_retained_as_intent_once_covered(executor: BackgroundExecutor) { |
| 1634 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); | 1755 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); |
| 1635 | let global = test_global(&executor, None, Some(backend.clone())); | 1756 | let global = test_global( |
| 1757 | &executor, | ||
| 1758 | None, | ||
| 1759 | Some((backend.clone(), RecursiveMode::Recursive)), | ||
| 1760 | ); | ||
| 1636 | let parent = Arc::<Path>::from(Path::new("/repo")); | 1761 | let parent = Arc::<Path>::from(Path::new("/repo")); |
| 1637 | let child = Arc::<Path>::from(Path::new("/repo/sub")); | 1762 | let child = Arc::<Path>::from(Path::new("/repo/sub")); |
| 1638 | 1763 | ||
| @@ -1673,7 +1798,14 @@ mod tests { · 34 unmodified lines | |||
| 1673 | #[gpui::test] | 1798 | #[gpui::test] |
| 1674 | async fn unregister_then_register_same_path_coalesces(executor: BackgroundExecutor) { | 1799 | async fn unregister_then_register_same_path_coalesces(executor: BackgroundExecutor) { |
| 1675 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); | 1800 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); |
| 1676 | let global = test_global(&executor, Some(backend.clone()), None); | 1801 | let global = test_global( |
| 1802 | &executor, | ||
| 1803 | Some(( | ||
| 1804 | backend.clone(), | ||
| 1805 | platform_recursive_mode(WatcherMode::Native), | ||
| 1806 | )), | ||
| 1807 | None, | ||
| 1808 | ); | ||
| 1677 | let path = Arc::<Path>::from(Path::new("/repo")); | 1809 | let path = Arc::<Path>::from(Path::new("/repo")); |
| 1678 | 1810 | ||
| 1679 | let first = global.add(path.clone(), WatcherMode::Native, noop_callback()); | 1811 | let first = global.add(path.clone(), WatcherMode::Native, noop_callback()); |
| @@ -1703,7 +1835,14 @@ mod tests { · 23 unmodified lines | |||
| 1703 | #[gpui::test] | 1835 | #[gpui::test] |
| 1704 | async fn failed_watch_is_not_retried_until_reregistered(executor: BackgroundExecutor) { | 1836 | async fn failed_watch_is_not_retried_until_reregistered(executor: BackgroundExecutor) { |
| 1705 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); | 1837 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); |
| 1706 | let global = test_global(&executor, Some(backend.clone()), None); | 1838 | let global = test_global( |
| 1839 | &executor, | ||
| 1840 | Some(( | ||
| 1841 | backend.clone(), | ||
| 1842 | platform_recursive_mode(WatcherMode::Native), | ||
| 1843 | )), | ||
| 1844 | None, | ||
| 1845 | ); | ||
| 1707 | let path_a = Arc::<Path>::from(Path::new("/repo/a")); | 1846 | let path_a = Arc::<Path>::from(Path::new("/repo/a")); |
| 1708 | let path_b = Arc::<Path>::from(Path::new("/repo/b")); | 1847 | let path_b = Arc::<Path>::from(Path::new("/repo/b")); |
| 1709 | backend | 1848 | backend |
| @@ -1742,7 +1881,14 @@ mod tests { · 32 unmodified lines | |||
| 1742 | #[gpui::test] | 1881 | #[gpui::test] |
| 1743 | async fn batched_watch_skips_only_the_path_with_a_generic_error(executor: BackgroundExecutor) { | 1882 | async fn batched_watch_skips_only_the_path_with_a_generic_error(executor: BackgroundExecutor) { |
| 1744 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); | 1883 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); |
| 1745 | let global = test_global(&executor, Some(backend.clone()), None); | 1884 | let global = test_global( |
| 1885 | &executor, | ||
| 1886 | Some(( | ||
| 1887 | backend.clone(), | ||
| 1888 | platform_recursive_mode(WatcherMode::Native), | ||
| 1889 | )), | ||
| 1890 | None, | ||
| 1891 | ); | ||
| 1746 | let path_a = Arc::<Path>::from(Path::new("/repo/a")); | 1892 | let path_a = Arc::<Path>::from(Path::new("/repo/a")); |
| 1747 | let path_b = Arc::<Path>::from(Path::new("/repo/b")); | 1893 | let path_b = Arc::<Path>::from(Path::new("/repo/b")); |
| 1748 | let path_c = Arc::<Path>::from(Path::new("/repo/c")); | 1894 | let path_c = Arc::<Path>::from(Path::new("/repo/c")); |
| @@ -1806,7 +1952,14 @@ mod tests { · 57 unmodified lines | |||
| 1806 | executor: BackgroundExecutor, | 1952 | executor: BackgroundExecutor, |
| 1807 | ) { | 1953 | ) { |
| 1808 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); | 1954 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); |
| 1809 | let global = test_global(&executor, Some(backend.clone()), None); | 1955 | let global = test_global( |
| 1956 | &executor, | ||
| 1957 | Some(( | ||
| 1958 | backend.clone(), | ||
| 1959 | platform_recursive_mode(WatcherMode::Native), | ||
| 1960 | )), | ||
| 1961 | None, | ||
| 1962 | ); | ||
| 1810 | let path_a = Arc::<Path>::from(Path::new("/repo/a")); | 1963 | let path_a = Arc::<Path>::from(Path::new("/repo/a")); |
| 1811 | let path_b = Arc::<Path>::from(Path::new("/repo/b")); | 1964 | let path_b = Arc::<Path>::from(Path::new("/repo/b")); |
| 1812 | let path_c = Arc::<Path>::from(Path::new("/repo/c")); | 1965 | let path_c = Arc::<Path>::from(Path::new("/repo/c")); |
| @@ -1866,7 +2019,11 @@ mod tests { · 53 unmodified lines | |||
| 1866 | async fn events_are_dispatched_to_matching_mode_only(executor: BackgroundExecutor) { | 2019 | async fn events_are_dispatched_to_matching_mode_only(executor: BackgroundExecutor) { |
| 1867 | let native_backend = Arc::new(Mutex::new(FakeWatchBackend::default())); | 2020 | let native_backend = Arc::new(Mutex::new(FakeWatchBackend::default())); |
| 1868 | let poll_backend = Arc::new(Mutex::new(FakeWatchBackend::default())); | 2021 | let poll_backend = Arc::new(Mutex::new(FakeWatchBackend::default())); |
| 1869 | let global = test_global(&executor, Some(native_backend), Some(poll_backend)); | 2022 | let global = test_global( |
| 2023 | &executor, | ||
| 2024 | Some((native_backend, platform_recursive_mode(WatcherMode::Native))), | ||
| 2025 | Some((poll_backend, platform_recursive_mode(WatcherMode::Poll))), | ||
| 2026 | ); | ||
| 1870 | 2027 | ||
| 1871 | let (native_events, native_callback) = collecting_callback(); | 2028 | let (native_events, native_callback) = collecting_callback(); |
| 1872 | let (poll_events, poll_callback) = collecting_callback(); | 2029 | let (poll_events, poll_callback) = collecting_callback(); |
| @@ -1906,7 +2063,14 @@ mod tests { · 33 unmodified lines | |||
| 1906 | #[gpui::test] | 2063 | #[gpui::test] |
| 1907 | async fn cooldown_defers_watches_without_further_syscalls(executor: BackgroundExecutor) { | 2064 | async fn cooldown_defers_watches_without_further_syscalls(executor: BackgroundExecutor) { |
| 1908 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); | 2065 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); |
| 1909 | let global = test_global(&executor, Some(backend.clone()), None); | 2066 | let global = test_global( |
| 2067 | &executor, | ||
| 2068 | Some(( | ||
| 2069 | backend.clone(), | ||
| 2070 | platform_recursive_mode(WatcherMode::Native), | ||
| 2071 | )), | ||
| 2072 | None, | ||
| 2073 | ); | ||
| 1910 | let path_a = Arc::<Path>::from(Path::new("/repo/a")); | 2074 | let path_a = Arc::<Path>::from(Path::new("/repo/a")); |
| 1911 | let path_b = Arc::<Path>::from(Path::new("/repo/b")); | 2075 | let path_b = Arc::<Path>::from(Path::new("/repo/b")); |
| 1912 | backend | 2076 | backend |
| @@ -1928,7 +2092,14 @@ mod tests { · 15 unmodified lines | |||
| 1928 | #[gpui::test] | 2092 | #[gpui::test] |
| 1929 | async fn deferred_watches_recover_after_cooldown(executor: BackgroundExecutor) { | 2093 | async fn deferred_watches_recover_after_cooldown(executor: BackgroundExecutor) { |
| 1930 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); | 2094 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); |
| 1931 | let global = test_global(&executor, Some(backend.clone()), None); | 2095 | let global = test_global( |
| 2096 | &executor, | ||
| 2097 | Some(( | ||
| 2098 | backend.clone(), | ||
| 2099 | platform_recursive_mode(WatcherMode::Native), | ||
| 2100 | )), | ||
| 2101 | None, | ||
| 2102 | ); | ||
| 1932 | let path_a = Arc::<Path>::from(Path::new("/repo/a")); | 2103 | let path_a = Arc::<Path>::from(Path::new("/repo/a")); |
| 1933 | let path_b = Arc::<Path>::from(Path::new("/repo/b")); | 2104 | let path_b = Arc::<Path>::from(Path::new("/repo/b")); |
| 1934 | backend | 2105 | backend |
| @@ -1964,7 +2135,14 @@ mod tests { · 29 unmodified lines | |||
| 1964 | #[gpui::test] | 2135 | #[gpui::test] |
| 1965 | async fn unwatch_clears_the_cooldown(executor: BackgroundExecutor) { | 2136 | async fn unwatch_clears_the_cooldown(executor: BackgroundExecutor) { |
| 1966 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); | 2137 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); |
| 1967 | let global = test_global(&executor, Some(backend.clone()), None); | 2138 | let global = test_global( |
| 2139 | &executor, | ||
| 2140 | Some(( | ||
| 2141 | backend.clone(), | ||
| 2142 | platform_recursive_mode(WatcherMode::Native), | ||
| 2143 | )), | ||
| 2144 | None, | ||
| 2145 | ); | ||
| 1968 | let path_a = Arc::<Path>::from(Path::new("/repo/a")); | 2146 | let path_a = Arc::<Path>::from(Path::new("/repo/a")); |
| 1969 | let path_b = Arc::<Path>::from(Path::new("/repo/b")); | 2147 | let path_b = Arc::<Path>::from(Path::new("/repo/b")); |
| 1970 | 2148 | ||
| @@ -1995,7 +2173,14 @@ mod tests { · 24 unmodified lines | |||
| 1995 | #[gpui::test] | 2173 | #[gpui::test] |
| 1996 | async fn unregistering_a_deferred_path_clears_it(executor: BackgroundExecutor) { | 2174 | async fn unregistering_a_deferred_path_clears_it(executor: BackgroundExecutor) { |
| 1997 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); | 2175 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); |
| 1998 | let global = test_global(&executor, Some(backend.clone()), None); | 2176 | let global = test_global( |
| 2177 | &executor, | ||
| 2178 | Some(( | ||
| 2179 | backend.clone(), | ||
| 2180 | platform_recursive_mode(WatcherMode::Native), | ||
| 2181 | )), | ||
| 2182 | None, | ||
| 2183 | ); | ||
| 1999 | let path = Arc::<Path>::from(Path::new("/repo/a")); | 2184 | let path = Arc::<Path>::from(Path::new("/repo/a")); |
| 2000 | backend | 2185 | backend |
| 2001 | .lock() | 2186 | .lock() |
| @@ -2030,7 +2215,14 @@ mod tests { · 28 unmodified lines | |||
| 2030 | #[gpui::test] | 2215 | #[gpui::test] |
| 2031 | async fn stream_restart_failure_reestablishes_all_watches(executor: BackgroundExecutor) { | 2216 | async fn stream_restart_failure_reestablishes_all_watches(executor: BackgroundExecutor) { |
| 2032 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); | 2217 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); |
| 2033 | let global = test_global(&executor, Some(backend.clone()), None); | 2218 | let global = test_global( |
| 2219 | &executor, | ||
| 2220 | Some(( | ||
| 2221 | backend.clone(), | ||
| 2222 | platform_recursive_mode(WatcherMode::Native), | ||
| 2223 | )), | ||
| 2224 | None, | ||
| 2225 | ); | ||
| 2034 | let path_a = Arc::<Path>::from(Path::new("/repo/a")); | 2226 | let path_a = Arc::<Path>::from(Path::new("/repo/a")); |
| 2035 | let path_b = Arc::<Path>::from(Path::new("/repo/b")); | 2227 | let path_b = Arc::<Path>::from(Path::new("/repo/b")); |
| 2036 | 2228 | ||
| @@ -2068,7 +2260,14 @@ mod tests { · 31 unmodified lines | |||
| 2068 | #[gpui::test] | 2260 | #[gpui::test] |
| 2069 | async fn unwatch_skips_the_failed_path_and_unwatches_the_rest(executor: BackgroundExecutor) { | 2261 | async fn unwatch_skips_the_failed_path_and_unwatches_the_rest(executor: BackgroundExecutor) { |
| 2070 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); | 2262 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); |
| 2071 | let global = test_global(&executor, Some(backend.clone()), None); | 2263 | let global = test_global( |
| 2264 | &executor, | ||
| 2265 | Some(( | ||
| 2266 | backend.clone(), | ||
| 2267 | platform_recursive_mode(WatcherMode::Native), | ||
| 2268 | )), | ||
| 2269 | None, | ||
| 2270 | ); | ||
| 2072 | let path_a = Arc::<Path>::from(Path::new("/repo/a")); | 2271 | let path_a = Arc::<Path>::from(Path::new("/repo/a")); |
| 2073 | let path_b = Arc::<Path>::from(Path::new("/repo/b")); | 2272 | let path_b = Arc::<Path>::from(Path::new("/repo/b")); |
| 2074 | let path_c = Arc::<Path>::from(Path::new("/repo/c")); | 2273 | let path_c = Arc::<Path>::from(Path::new("/repo/c")); |
| @@ -2111,7 +2310,14 @@ mod tests { · 36 unmodified lines | |||
| 2111 | executor: BackgroundExecutor, | 2310 | executor: BackgroundExecutor, |
| 2112 | ) { | 2311 | ) { |
| 2113 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); | 2312 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); |
| 2114 | let global = test_global(&executor, Some(backend.clone()), None); | 2313 | let global = test_global( |
| 2314 | &executor, | ||
| 2315 | Some(( | ||
| 2316 | backend.clone(), | ||
| 2317 | platform_recursive_mode(WatcherMode::Native), | ||
| 2318 | )), | ||
| 2319 | None, | ||
| 2320 | ); | ||
| 2115 | let path_a = Arc::<Path>::from(Path::new("/repo/a")); | 2321 | let path_a = Arc::<Path>::from(Path::new("/repo/a")); |
| 2116 | let path_b = Arc::<Path>::from(Path::new("/repo/b")); | 2322 | let path_b = Arc::<Path>::from(Path::new("/repo/b")); |
| 2117 | 2323 | ||
| @@ -2147,7 +2353,14 @@ mod tests { · 29 unmodified lines | |||
| 2147 | executor: BackgroundExecutor, | 2353 | executor: BackgroundExecutor, |
| 2148 | ) { | 2354 | ) { |
| 2149 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); | 2355 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); |
| 2150 | let global = test_global(&executor, Some(backend.clone()), None); | 2356 | let global = test_global( |
| 2357 | &executor, | ||
| 2358 | Some(( | ||
| 2359 | backend.clone(), | ||
| 2360 | platform_recursive_mode(WatcherMode::Native), | ||
| 2361 | )), | ||
| 2362 | None, | ||
| 2363 | ); | ||
| 2151 | let path = Arc::<Path>::from(Path::new("/repo")); | 2364 | let path = Arc::<Path>::from(Path::new("/repo")); |
| 2152 | 2365 | ||
| 2153 | // The initial watch applies in the backend, but the stream fails to | 2366 | // The initial watch applies in the backend, but the stream fails to |
| @@ -2175,7 +2388,14 @@ mod tests { · 21 unmodified lines | |||
| 2175 | #[gpui::test] | 2388 | #[gpui::test] |
| 2176 | async fn flush_resolves_after_reconcile(executor: BackgroundExecutor) { | 2389 | async fn flush_resolves_after_reconcile(executor: BackgroundExecutor) { |
| 2177 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); | 2390 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); |
| 2178 | let global = test_global(&executor, Some(backend.clone()), None); | 2391 | let global = test_global( |
| 2392 | &executor, | ||
| 2393 | Some(( | ||
| 2394 | backend.clone(), | ||
| 2395 | platform_recursive_mode(WatcherMode::Native), | ||
| 2396 | )), | ||
| 2397 | None, | ||
| 2398 | ); | ||
| 2179 | let path = Arc::<Path>::from(Path::new("/repo")); | 2399 | let path = Arc::<Path>::from(Path::new("/repo")); |
| 2180 | 2400 | ||
| 2181 | global.add(path.clone(), WatcherMode::Native, noop_callback()); | 2401 | global.add(path.clone(), WatcherMode::Native, noop_callback()); |
| @@ -2191,7 +2411,11 @@ mod tests { · 9 unmodified lines | |||
| 2191 | executor: BackgroundExecutor, | 2411 | executor: BackgroundExecutor, |
| 2192 | ) { | 2412 | ) { |
| 2193 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); | 2413 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); |
| 2194 | let global = test_global(&executor, Some(backend), None); | 2414 | let global = test_global( |
| 2415 | &executor, | ||
| 2416 | Some((backend, platform_recursive_mode(WatcherMode::Native))), | ||
| 2417 | None, | ||
| 2418 | ); | ||
| 2195 | 2419 | ||
| 2196 | let mut health = global.check_health(); | 2420 | let mut health = global.check_health(); |
| 2197 | executor.run_until_parked(); | 2421 | executor.run_until_parked(); |
| @@ -2201,8 +2425,8 @@ mod tests { · 3 unmodified lines | |||
| 2201 | 2425 | ||
| 2202 | fn test_sink( | 2426 | fn test_sink( |
| 2203 | executor: &BackgroundExecutor, | 2427 | executor: &BackgroundExecutor, |
| 2204 | native_backend: Option<Arc<Mutex<FakeWatchBackend>>>, | 2428 | native_backend: FakeBackend, |
| 2205 | poll_backend: Option<Arc<Mutex<FakeWatchBackend>>>, | 2429 | poll_backend: FakeBackend, |
| 2206 | ) -> ( | 2430 | ) -> ( |
| 2207 | FsWatcher, | 2431 | FsWatcher, |
| 2208 | async_channel::Receiver<()>, | 2432 | async_channel::Receiver<()>, |
| @@ -2210,10 +2434,8 @@ mod tests { · 1 unmodified line | |||
| 2210 | ) { | 2434 | ) { |
| 2211 | let global = GlobalWatcher::with_backends( | 2435 | let global = GlobalWatcher::with_backends( |
| 2212 | executor, | 2436 | executor, |
| 2213 | native_backend | 2437 | fake_backend(native_backend, WatcherMode::Native), |
| 2214 | .map(|backend| Box::new(SharedFakeWatchBackend(backend)) as Box<dyn WatchBackend>), | 2438 | fake_backend(poll_backend, WatcherMode::Poll), |
| 2215 | poll_backend | ||
| 2216 | .map(|backend| Box::new(SharedFakeWatchBackend(backend)) as Box<dyn WatchBackend>), | ||
| 2217 | ); | 2439 | ); |
| 2218 | let (tx, rx) = async_channel::unbounded(); | 2440 | let (tx, rx) = async_channel::unbounded(); |
| 2219 | let pending_path_events: Arc<Mutex<Vec<PathEvent>>> = Default::default(); | 2441 | let pending_path_events: Arc<Mutex<Vec<PathEvent>>> = Default::default(); |
| @@ -2224,7 +2446,14 @@ mod tests { · 4 unmodified lines | |||
| 2224 | #[gpui::test] | 2446 | #[gpui::test] |
| 2225 | async fn sink_establishes_watch_for_existing_path(executor: BackgroundExecutor) { | 2447 | async fn sink_establishes_watch_for_existing_path(executor: BackgroundExecutor) { |
| 2226 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); | 2448 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); |
| 2227 | let (sink, _rx, _pending) = test_sink(&executor, Some(backend.clone()), None); | 2449 | let (sink, _rx, _pending) = test_sink( |
| 2450 | &executor, | ||
| 2451 | Some(( | ||
| 2452 | backend.clone(), | ||
| 2453 | platform_recursive_mode(WatcherMode::Native), | ||
| 2454 | )), | ||
| 2455 | None, | ||
| 2456 | ); | ||
| 2228 | let dir = tempfile::TempDir::new().expect("create temp dir"); | 2457 | let dir = tempfile::TempDir::new().expect("create temp dir"); |
| 2229 | 2458 | ||
| 2230 | sink.add(dir.path()).expect("add succeeds"); | 2459 | sink.add(dir.path()).expect("add succeeds"); |
| @@ -2242,7 +2471,14 @@ mod tests { · 11 unmodified lines | |||
| 2242 | #[gpui::test] | 2471 | #[gpui::test] |
| 2243 | async fn sink_waits_for_path_creation(executor: BackgroundExecutor) { | 2472 | async fn sink_waits_for_path_creation(executor: BackgroundExecutor) { |
| 2244 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); | 2473 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); |
| 2245 | let (sink, rx, pending_path_events) = test_sink(&executor, Some(backend.clone()), None); | 2474 | let (sink, rx, pending_path_events) = test_sink( |
| 2475 | &executor, | ||
| 2476 | Some(( | ||
| 2477 | backend.clone(), | ||
| 2478 | platform_recursive_mode(WatcherMode::Native), | ||
| 2479 | )), | ||
| 2480 | None, | ||
| 2481 | ); | ||
| 2246 | let dir = tempfile::TempDir::new().expect("create temp dir"); | 2482 | let dir = tempfile::TempDir::new().expect("create temp dir"); |
| 2247 | let file = dir.path().join("missing.txt"); | 2483 | let file = dir.path().join("missing.txt"); |
| 2248 | 2484 | ||
| @@ -2271,7 +2507,14 @@ mod tests { · 22 unmodified lines | |||
| 2271 | #[gpui::test] | 2507 | #[gpui::test] |
| 2272 | async fn sink_remove_cancels_pending_watch(executor: BackgroundExecutor) { | 2508 | async fn sink_remove_cancels_pending_watch(executor: BackgroundExecutor) { |
| 2273 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); | 2509 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); |
| 2274 | let (sink, _rx, _pending) = test_sink(&executor, Some(backend.clone()), None); | 2510 | let (sink, _rx, _pending) = test_sink( |
| 2511 | &executor, | ||
| 2512 | Some(( | ||
| 2513 | backend.clone(), | ||
| 2514 | platform_recursive_mode(WatcherMode::Native), | ||
| 2515 | )), | ||
| 2516 | None, | ||
| 2517 | ); | ||
| 2275 | let dir = tempfile::TempDir::new().expect("create temp dir"); | 2518 | let dir = tempfile::TempDir::new().expect("create temp dir"); |
| 2276 | let file = dir.path().join("missing.txt"); | 2519 | let file = dir.path().join("missing.txt"); |
| 2277 | 2520 | ||
| @@ -2291,7 +2534,14 @@ mod tests { · 13 unmodified lines | |||
| 2291 | #[gpui::test] | 2534 | #[gpui::test] |
| 2292 | async fn sink_recovers_deferred_watch_and_emits_rescan(executor: BackgroundExecutor) { | 2535 | async fn sink_recovers_deferred_watch_and_emits_rescan(executor: BackgroundExecutor) { |
| 2293 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); | 2536 | let backend = Arc::new(Mutex::new(FakeWatchBackend::default())); |
| 2294 | let (sink, _rx, pending_path_events) = test_sink(&executor, Some(backend.clone()), None); | 2537 | let (sink, _rx, pending_path_events) = test_sink( |
| 2538 | &executor, | ||
| 2539 | Some(( | ||
| 2540 | backend.clone(), | ||
| 2541 | platform_recursive_mode(WatcherMode::Native), | ||
| 2542 | )), | ||
| 2543 | None, | ||
| 2544 | ); | ||
| 2295 | let dir = tempfile::TempDir::new().expect("create temp dir"); | 2545 | let dir = tempfile::TempDir::new().expect("create temp dir"); |
| 2296 | backend | 2546 | backend |
| 2297 | .lock() | 2547 | .lock() |