Summary: Record the db schema, infer version, and run dates into infer-out/.infer_runstate.json. This allows us to check on startup whether the results directory was generated using a compatible version of infer or not, and give a better error message in the latter case than some SQLite error about mismatching tables. This will be used in a follow-up diff to record capture phases too, and avoid relying on filesystem timestamps of the infer-out/capture/foo/ directories for reactive analysis. Had to change some tests Makefiles to make sure they do not attempt to re-use stale infer-out directories, which would now fail the run. The stale infer-out directory gets deleted if `--force-delete-results-dir` is passed (but a warning still gets printed). Reviewed By: mbouaziz Differential Revision: D6760787 fbshipit-source-id: f36f7dfmaster
parent
0c9b025857
commit
66ad5c3018
@ -0,0 +1,23 @@
|
|||||||
|
type infer_version = {
|
||||||
|
major: int;
|
||||||
|
minor: int;
|
||||||
|
patch: int;
|
||||||
|
commit: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
type command = string wrap <ocaml
|
||||||
|
t="InferCommand.t"
|
||||||
|
wrap="InferCommand.of_string"
|
||||||
|
unwrap="InferCommand.to_string"
|
||||||
|
>
|
||||||
|
|
||||||
|
type run_info = {
|
||||||
|
date: string;
|
||||||
|
command: command;
|
||||||
|
infer_version: infer_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
type t = {
|
||||||
|
run_sequence: run_info list; (** successive runs that re-used the same results directory *)
|
||||||
|
results_dir_format: string; (** to check if the versions of the results dir are compatible *)
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
(*
|
||||||
|
* Copyright (c) 2018 - present Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*)
|
||||||
|
|
||||||
|
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 }
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
"Incompatible results directory '%s':\n%s\nWas '%s' created using an older version of infer?"
|
||||||
|
Config.results_dir err_msg Config.results_dir) )
|
||||||
|
msg
|
||||||
|
in
|
||||||
|
if Sys.file_exists state_file_path <> `Yes then error "save state not found"
|
||||||
|
else
|
||||||
|
try
|
||||||
|
let loaded_state = Ag_util.Json.from_file Runstate_j.read_t state_file_path in
|
||||||
|
if not
|
||||||
|
(String.equal !state.Runstate_t.results_dir_format
|
||||||
|
loaded_state.Runstate_t.results_dir_format)
|
||||||
|
then
|
||||||
|
error "Incompatible formats: found\n %s\n\nbut expected this format:\n %s\n\n"
|
||||||
|
loaded_state.results_dir_format !state.Runstate_t.results_dir_format
|
||||||
|
else (
|
||||||
|
state := loaded_state ;
|
||||||
|
Ok () )
|
||||||
|
with _ -> Error "error reading the save state"
|
||||||
|
|
||||||
|
|
||||||
|
let reset () = state := state0
|
@ -0,0 +1,22 @@
|
|||||||
|
(*
|
||||||
|
* Copyright (c) 2018 - present Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*)
|
||||||
|
|
||||||
|
open! IStd
|
||||||
|
|
||||||
|
val add_run_to_sequence : unit -> unit
|
||||||
|
(** add an entry with the current run date *)
|
||||||
|
|
||||||
|
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 *)
|
Loading…
Reference in new issue