Skip to content

Commit

Permalink
thread results through calls to Watchman.watch_project
Browse files Browse the repository at this point in the history
Summary: now that `watch_project` returns a `result`, this updates its caller to also return a `result`. eventually `re_init` itself will return a result, but for now it just converts to exceptions to maintain existing behavior.

Reviewed By: nmote

Differential Revision: D28224050

fbshipit-source-id: 3ec0b4538f82f8af0cea1dacc88a320a74730b1e
  • Loading branch information
mroch authored and facebook-github-bot committed May 6, 2021
1 parent 8534137 commit 0bdc705
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 11 deletions.
13 changes: 13 additions & 0 deletions src/common/lwt/lwtUtils.ml
Expand Up @@ -45,3 +45,16 @@ let output_graph out strip_root graph =
graph
in
Lwt_io.fprint out "}"

(** [fold_result_s ~f ~init l] calls [f init x] for each [x] in [l], where [f] returns an
['acc result Lwt.t], and the fold short circuits if an [Error] is returned. Each
promise returned by [f] is resolved sequentially (hence the [_s]), and if any
promise rejects, the entire fold rejects. This is like a combination of
[Base.List.fold_result] and [Lwt_list.fold_left_s]. *)
let rec fold_result_s ~f ~init l =
match l with
| [] -> Lwt.return (Ok init)
| x :: l ->
(match%lwt f init x with
| Ok acc -> (fold_result_s [@ocaml.tailcall]) f acc l
| Error _ as err -> Lwt.return err)
3 changes: 3 additions & 0 deletions src/common/lwt/lwtUtils.mli
Expand Up @@ -10,3 +10,6 @@ val iter_all : unit Lwt.t list -> unit Lwt.t
val all : 'a Lwt.t list -> 'a list Lwt.t

val output_graph : Lwt_io.output_channel -> ('a -> string) -> ('a * 'a list) list -> unit Lwt.t

val fold_result_s :
f:('acc -> 'b -> ('acc, 'c) result Lwt.t) -> init:'acc -> 'b list -> ('acc, 'c) result Lwt.t
32 changes: 21 additions & 11 deletions src/hack_forked/watchman/watchman.ml
Expand Up @@ -565,6 +565,24 @@ let watch_project ~debug_logging ~conn root =
in
Lwt.return result

(** Calls [watchman watch-project] on a list of paths to watch (e.g. all of the
include directories). The paths may be children of the actual watchman root,
in which case watch-project returns the watch root and relative path.
This function computes the set of terms that should be included in queries
against the root to filter it to only the relative paths we care about. *)
let watch_paths ~debug_logging ~conn paths =
LwtUtils.fold_result_s
~f:(fun (terms, watch_roots, failed_paths) path ->
match%lwt watch_project ~debug_logging ~conn path with
| Error _ as err -> Lwt.return err
| Ok None -> Lwt.return (Ok (terms, watch_roots, SSet.add (Path.to_string path) failed_paths))
| Ok (Some (watch_root, relative_path)) ->
let terms = prepend_relative_path_term ~relative_path ~terms in
let watch_roots = SSet.add watch_root watch_roots in
Lwt.return (Ok (terms, watch_roots, failed_paths)))
~init:(Some [], SSet.empty, SSet.empty)
paths

let re_init
?prior_clockspec
{
Expand All @@ -583,17 +601,9 @@ let re_init
| Error err -> raise_error err
in
let%lwt (watched_path_expression_terms, watch_roots, failed_paths) =
Lwt_list.fold_left_s
(fun (terms, watch_roots, failed_paths) path ->
match%lwt watch_project ~debug_logging ~conn path with
| Error err -> raise_error err
| Ok None -> Lwt.return (terms, watch_roots, SSet.add (Path.to_string path) failed_paths)
| Ok (Some (watch_root, relative_path)) ->
let terms = prepend_relative_path_term ~relative_path ~terms in
let watch_roots = SSet.add watch_root watch_roots in
Lwt.return (terms, watch_roots, failed_paths))
(Some [], SSet.empty, SSet.empty)
roots
match%lwt watch_paths ~debug_logging ~conn roots with
| Ok result -> Lwt.return result
| Error err -> raise_error err
in
(* The failed_paths are likely includes which don't exist on the filesystem, so watch_project
* returned an error. Let's do a best effort attempt to infer the watch root and relative
Expand Down

0 comments on commit 0bdc705

Please sign in to comment.