diff --git a/infer/src/base/ResultsDir.ml b/infer/src/base/ResultsDir.ml index 64c8ddab2..e555b0a63 100644 --- a/infer/src/base/ResultsDir.ml +++ b/infer/src/base/ResultsDir.ml @@ -8,6 +8,77 @@ open! IStd open PolyVariantEqual module L = Logging +module RunState = struct + let run_time_string = Time.now () |> Time.to_string + + let state0 = + let open Runstate_t in + { run_sequence= [] + ; results_dir_format= + Printf.sprintf "db_filename: %s\ndb_schema: %s" ResultsDatabase.database_filename + ResultsDatabase.schema_hum + ; should_merge_capture= false } + + + let state : Runstate_t.t ref = ref state0 + + let state_filename = ".infer_runstate.json" + + let state_file_path = Config.results_dir ^/ state_filename + + let store () = + Utils.with_file_out state_file_path ~f:(fun oc -> + Runstate_j.string_of_t !state |> Out_channel.output_string oc ) + + + let load_and_validate () = + let error msg = + Printf.ksprintf + (fun err_msg -> + Error + (Printf.sprintf + "'%s' already exists but it is not an empty directory and it does not look like an \ + infer results directory:\n\ + \ %s\n\ + Was it created using an older version of infer?" Config.results_dir err_msg) ) + msg + in + if PolyVariantEqual.(Sys.file_exists state_file_path <> `Yes) then + error "save state not found: '%s' does not exist" state_file_path + else + match Atdgen_runtime.Util.Json.from_file Runstate_j.read_t state_file_path with + | {Runstate_t.results_dir_format} as loaded_state + when String.equal !state.Runstate_t.results_dir_format results_dir_format -> + state := loaded_state ; + Ok () + | {Runstate_t.results_dir_format} -> + error "Incompatible formats: found\n %s\n\nbut expected this format:\n %s\n\n" + results_dir_format !state.Runstate_t.results_dir_format + | exception e -> + error "could not read the save state '%s': %s" state_file_path (Exn.to_string e) + + + let reset () = state := state0 + + let set_merge_capture onoff = + state := {!state with Runstate_t.should_merge_capture= onoff} ; + (* store change to the runstate *) + store () + + + let get_merge_capture () = !state.Runstate_t.should_merge_capture + + let add_run_to_sequence () = + let run = + { Runstate_t.infer_version= Version.{Runstate_t.major; minor; patch; commit} + ; date= run_time_string + ; command= Config.command } + in + state := {!state with Runstate_t.run_sequence= run :: !state.run_sequence} ; + (* store change to the runstate *) + store () +end + let results_dir_dir_markers = [Config.results_dir ^/ Config.specs_dir_name] let is_results_dir ~check_correct_version () = diff --git a/infer/src/base/ResultsDir.mli b/infer/src/base/ResultsDir.mli index 58f3a5db4..b8f66826e 100644 --- a/infer/src/base/ResultsDir.mli +++ b/infer/src/base/ResultsDir.mli @@ -7,6 +7,17 @@ open! IStd +module RunState : sig + val add_run_to_sequence : unit -> unit + (** add an entry with the current run date *) + + val set_merge_capture : bool -> unit + (** update the 'merge after capture' smart option *) + + val get_merge_capture : unit -> bool + (** fetch the value of the 'merge after capture' smart option *) +end + val assert_results_dir : string -> unit (** Check that the results dir exists and sets up logging, the database, etc. *) diff --git a/infer/src/base/RunState.ml b/infer/src/base/RunState.ml deleted file mode 100644 index 57b7ea735..000000000 --- a/infer/src/base/RunState.ml +++ /dev/null @@ -1,72 +0,0 @@ -(* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - *) - -open! IStd - -let run_time_string = Time.now () |> Time.to_string - -let state0 = - let open Runstate_t in - { run_sequence= [] - ; results_dir_format= - Printf.sprintf "db_filename: %s\ndb_schema: %s" ResultsDatabase.database_filename - ResultsDatabase.schema_hum - ; should_merge_capture= false } - - -let state : Runstate_t.t ref = ref state0 - -let add_run_to_sequence () = - let run = - { Runstate_t.infer_version= Version.{Runstate_t.major; minor; patch; commit} - ; date= run_time_string - ; command= Config.command } - in - Runstate_t.(state := {!state with run_sequence= run :: !state.run_sequence}) - - -let state_filename = ".infer_runstate.json" - -let state_file_path = Config.results_dir ^/ state_filename - -let store () = - Utils.with_file_out state_file_path ~f:(fun oc -> - Runstate_j.string_of_t !state |> Out_channel.output_string oc ) - - -let load_and_validate () = - let error msg = - Printf.ksprintf - (fun err_msg -> - Error - (Printf.sprintf - "'%s' already exists but it is not an empty directory and it does not look like an \ - infer results directory:\n\ - \ %s\n\ - Was it created using an older version of infer?" Config.results_dir err_msg) ) - msg - in - if PolyVariantEqual.(Sys.file_exists state_file_path <> `Yes) then - error "save state not found: '%s' does not exist" state_file_path - else - match Atdgen_runtime.Util.Json.from_file Runstate_j.read_t state_file_path with - | {Runstate_t.results_dir_format} as loaded_state - when String.equal !state.Runstate_t.results_dir_format results_dir_format -> - state := loaded_state ; - Ok () - | {Runstate_t.results_dir_format} -> - error "Incompatible formats: found\n %s\n\nbut expected this format:\n %s\n\n" - results_dir_format !state.Runstate_t.results_dir_format - | exception e -> - error "could not read the save state '%s': %s" state_file_path (Exn.to_string e) - - -let reset () = state := state0 - -let set_merge_capture onoff = Runstate_t.(state := {!state with should_merge_capture= onoff}) - -let get_merge_capture () = !state.Runstate_t.should_merge_capture diff --git a/infer/src/base/RunState.mli b/infer/src/base/RunState.mli deleted file mode 100644 index 3e486ad8f..000000000 --- a/infer/src/base/RunState.mli +++ /dev/null @@ -1,26 +0,0 @@ -(* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - *) - -open! IStd - -val add_run_to_sequence : unit -> unit -(** add an entry with the current run date *) - -val set_merge_capture : bool -> unit -(** update the 'merge after capture' smart option *) - -val get_merge_capture : unit -> bool -(** fetch the value of the 'merge after capture' smart option *) - -val store : unit -> unit -(** save the current state to disk *) - -val load_and_validate : unit -> (unit, string) Result.t -(** attempt to load state from disk *) - -val reset : unit -> unit -(** reset the in-memory state to what it would be if this were a fresh run of infer *) diff --git a/infer/src/infer.ml b/infer/src/infer.ml index c083c1e6d..2c5850c07 100644 --- a/infer/src/infer.ml +++ b/infer/src/infer.ml @@ -61,7 +61,7 @@ let setup () = ResultsDir.assert_results_dir "please run an infer analysis first" ) ; db_start () ; NullsafeInit.init () ; - if CLOpt.is_originator then (RunState.add_run_to_sequence () ; RunState.store ()) ; + if CLOpt.is_originator then ResultsDir.RunState.add_run_to_sequence () ; () diff --git a/infer/src/integration/BuckGenrule.ml b/infer/src/integration/BuckGenrule.ml index 43d2922a3..51943414d 100644 --- a/infer/src/integration/BuckGenrule.ml +++ b/infer/src/integration/BuckGenrule.ml @@ -147,5 +147,5 @@ let capture build_cmd = run_buck_capture updated_buck_cmd ; infer_deps_of_build_report build_report_file ; L.progress "Genrule capture took %a.@." Mtime.Span.pp (Mtime_clock.count time0) ; - RunState.set_merge_capture true ; - RunState.store () + ResultsDir.RunState.set_merge_capture true ; + () diff --git a/infer/src/integration/Driver.ml b/infer/src/integration/Driver.ml index 247705032..8e58fe2d5 100644 --- a/infer/src/integration/Driver.ml +++ b/infer/src/integration/Driver.ml @@ -141,8 +141,8 @@ let buck_capture build_cmd = in Option.iter prog_build_cmd_opt ~f:(fun (prog, buck_build_cmd) -> L.progress "Capturing in buck mode...@." ; - if Option.exists ~f:BuckMode.is_clang_flavors Config.buck_mode then ( - RunState.set_merge_capture true ; RunState.store () ) ; + if Option.exists ~f:BuckMode.is_clang_flavors Config.buck_mode then + ResultsDir.RunState.set_merge_capture true ; Buck.clang_flavor_capture ~prog ~buck_build_cmd ) @@ -283,15 +283,14 @@ let analyze_and_report ?suppress_console_report ~changed_files mode = (* if doing capture + analysis of buck with flavors, we always need to merge targets before the analysis phase *) true | Analyze | BuckGenruleMaster _ -> - RunState.get_merge_capture () + ResultsDir.RunState.get_merge_capture () | _ -> false in if should_merge then ( if Config.export_changed_functions then MergeCapture.merge_changed_functions () ; MergeCapture.merge_captured_targets () ; - RunState.set_merge_capture false ; - RunState.store () ) ; + ResultsDir.RunState.set_merge_capture false ) ; if should_analyze then if SourceFiles.is_empty () && Config.capture then error_nothing_to_analyze mode else (