diff --git a/doc/changes/9643.md b/doc/changes/9643.md new file mode 100644 index 00000000000..730e4dee8f6 --- /dev/null +++ b/doc/changes/9643.md @@ -0,0 +1,2 @@ +- Use watch exclusions in watch mode on MacOS (#9643, fixes #9517, + @PoorlyDefinedBehaviour) diff --git a/src/dune_file_watcher/dune_file_watcher.ml b/src/dune_file_watcher/dune_file_watcher.ml index fce6efd9356..fab71da5d46 100644 --- a/src/dune_file_watcher/dune_file_watcher.ml +++ b/src/dune_file_watcher/dune_file_watcher.ml @@ -143,6 +143,7 @@ type kind = ; source : Fsevents.t ; sync : Fsevents.t ; latency : float + ; on_event : Fsevents.Event.t -> Path.t -> Event.t option } | Inotify of Inotify_lib.t | Fswatch_win of @@ -549,18 +550,21 @@ let fsevents ?exclusion_paths ~latency ~paths scheduler f = fsevents ;; -let fsevents_standard_event event path = - let kind = - match Fsevents.Event.action event with - | Rename | Unknown -> Fs_memo_event.Unknown - | Create -> Created - | Remove -> Deleted - | Modify -> if Fsevents.Event.kind event = File then File_changed else Unknown - in - Some (Event.Fs_memo_event { Fs_memo_event.kind; path }) +let fsevents_standard_event ~should_exclude event path = + if should_exclude (Path.to_string path) + then None + else ( + let kind = + match Fsevents.Event.action event with + | Rename | Unknown -> Fs_memo_event.Unknown + | Create -> Created + | Remove -> Deleted + | Modify -> if Fsevents.Event.kind event = File then File_changed else Unknown + in + Some (Event.Fs_memo_event { Fs_memo_event.kind; path })) ;; -let create_fsevents ?(latency = 0.2) ~(scheduler : Scheduler.t) () = +let create_fsevents ?(latency = 0.2) ~(scheduler : Scheduler.t) ~should_exclude () = prepare_sync (); let sync_table = Table.create (module String) 64 in let sync = @@ -581,6 +585,7 @@ let create_fsevents ?(latency = 0.2) ~(scheduler : Scheduler.t) () = Option.map (Fs_sync.consume_event sync_table path) ~f:(fun id -> Event.Sync id))) in + let on_event = fsevents_standard_event ~should_exclude in let source = let paths = [ Path.root ] in let exclusion_paths = @@ -588,7 +593,7 @@ let create_fsevents ?(latency = 0.2) ~(scheduler : Scheduler.t) () = :: ([ "_esy"; "_opam"; ".git"; ".hg" ] |> List.rev_map ~f:(Path.relative (Path.source Path.Source.root))) in - fsevents ~latency scheduler ~exclusion_paths ~paths fsevents_standard_event + fsevents ~latency scheduler ~exclusion_paths ~paths on_event in let cv = Condition.create () in let dispatch_queue_ref = ref None in @@ -613,7 +618,8 @@ let create_fsevents ?(latency = 0.2) ~(scheduler : Scheduler.t) () = Mutex.unlock mutex; Option.value_exn !dispatch_queue_ref in - { kind = Fsevents { latency; scheduler; sync; source; external_; dispatch_queue } + { kind = + Fsevents { latency; scheduler; sync; source; external_; dispatch_queue; on_event } ; sync_table } ;; @@ -684,7 +690,7 @@ let create_default ?fsevents_debounce ~watch_exclusions ~scheduler () = ~debounce_interval:(Some 0.5 (* seconds *)) ~backend ~watch_exclusions - | `Fsevents -> create_fsevents ?latency:fsevents_debounce ~scheduler () + | `Fsevents -> create_fsevents ?latency:fsevents_debounce ~scheduler ~should_exclude () | `Inotify_lib -> create_inotifylib ~scheduler ~should_exclude | `Fswatch_win -> create_fswatch_win @@ -729,12 +735,7 @@ let add_watch t path = | None -> Ok () | Some ext -> let watch = - lazy - (fsevents - ~latency:f.latency - f.scheduler - ~paths:[ path ] - fsevents_standard_event) + lazy (fsevents ~latency:f.latency f.scheduler ~paths:[ path ] f.on_event) in (match Watch_trie.add f.external_ ext watch with | Watch_trie.Under_existing_node -> Ok () diff --git a/test/expect-tests/dune_file_watcher/dune_file_watcher_tests_patterns.ml b/test/expect-tests/dune_file_watcher/dune_file_watcher_tests_patterns.ml index 726a584762e..4121d180101 100644 --- a/test/expect-tests/dune_file_watcher/dune_file_watcher_tests_patterns.ml +++ b/test/expect-tests/dune_file_watcher/dune_file_watcher_tests_patterns.ml @@ -23,6 +23,7 @@ let%expect_test _ = test "dir/#file#"; test "dir/#subdir#/file"; test ".#file"; + test ".#foobar.ml"; test "dir/.#file"; test "dir/.#subdir/file"; [%expect @@ -40,6 +41,7 @@ let%expect_test _ = should_exclude(dir/#file#) = true should_exclude(dir/#subdir#/file) = false should_exclude(.#file) = true + should_exclude(.#foobar.ml) = true should_exclude(dir/.#file) = true should_exclude(dir/.#subdir/file) = true |}]