(*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *)

(* This saved state fetcher is intended to be used mainly by tests. It assumes that there are 2
 * files next to /path/to/root/.flowconfig:
 *
 * /path/to/root/.flow.saved_state - the saved state file
 * /path/to/root/.flow.saved_state_file_changes - newline separated list of files which have changed
 *
 * if either file doesn't exist then we assume there's no saved state
 *)
let fetch ~options =
  Profiling_js.with_profiling_lwt ~label:"FetchSavedState" ~should_print_summary:false @@ fun _ ->
  let root_str = Options.root options |> File_path.to_string in
  let saved_state_file = Filename.concat root_str ".flow.saved_state" in
  let changed_files_input_file = Filename.concat root_str ".flow.saved_state_file_changes" in
  let%lwt saved_state_exists = Lwt_unix.file_exists saved_state_file
  and input_file_exists = Lwt_unix.file_exists changed_files_input_file in
  let errs =
    if saved_state_exists then
      []
    else
      [Utils_js.spf "File %S does not exist" saved_state_file]
  in
  let errs =
    if input_file_exists then
      errs
    else
      [Utils_js.spf "File %S does not exist" changed_files_input_file]
  in
  match errs with
  | _ :: _ -> Lwt.return (Saved_state_fetcher.Saved_state_error (String.concat "; " errs))
  | [] ->
    let saved_state_filename = File_path.make saved_state_file in
    let changed_files =
      Sys_utils.lines_of_file changed_files_input_file
      |> Files.canonicalize_filenames ~handle_imaginary:Files.imaginary_realpath ~cwd:root_str
      |> SSet.of_list
    in
    Lwt.return (Saved_state_fetcher.Saved_state { saved_state_filename; changed_files })
