let summary t =
let rec count_start_attempts : starting history -> int = fun h ->
match h.previous_state with
| `Starting _ -> 1
| `Tried_to_start (hh, _) -> 1 + (count_start_attempts hh)
in
let rec count_kill_attempts : killing history -> int = fun h ->
match h.previous_state with
| `Killing _ -> 1
| `Tried_to_kill hh -> 1 + (count_kill_attempts hh)
in
let plural_of_int ?(y=false) n =
match y, n with
| true, 1 -> "y"
| true, _ -> "ies"
| _, 1 -> ""
| _, _ -> "s" in
let rec dive (t: t) =
let continue history = dive (history.previous_state :> t) in
match t with
| `Building history -> continue history
| `Tried_to_start (history, book) ->
let attempts = count_start_attempts history in
fmt " %d start-attempt%s" attempts (plural_of_int attempts)
:: continue history
| `Started_running (history, book) -> continue history
| `Starting history -> continue history
| `Still_building history -> continue history
| `Still_running (history, book) -> continue history
| `Still_running_despite_recoverable_error (error, history, book) ->
fmt "non-fatal error %S (check-running)" error :: continue history
| `Ran_successfully (history, book) -> continue history
| `Successfully_did_nothing history -> continue history
| `Active (history, _) -> continue history
| `Tried_to_eval_condition history -> continue history
| `Tried_to_reeval_condition (error, history) ->
fmt "non-fatal error %S (eval-condition)" error :: continue history
| `Verified_success history -> continue history
| `Already_done history ->
"already-done" :: continue history
| `Dependencies_failed (history, deps) ->
let nb_deps = (List.length deps) in
fmt "%d depependenc%s failed" nb_deps (plural_of_int ~y:true nb_deps)
:: continue history
| `Failed_running (history, reason, book) ->
fmt "Reason: %S" (match reason with | `Long_running_failure s -> s)
:: continue history
| `Failed_to_kill history -> continue history
| `Failed_to_eval_condition history -> continue history
| `Failed_to_start (history, book) ->
continue history
| `Killing history ->
fmt "killed from %s" (name (history.previous_state :> t))
:: continue history
| `Tried_to_kill history ->
fmt "%d killing-attempts" (count_kill_attempts history)
:: continue history
| `Did_not_ensure_condition history ->
"Did_not_ensure_condition" :: continue history
| `Killed history ->
"killed" :: continue history
| `Finished history -> continue history
| `Passive log -> []
in
let history_opt, bookkeeping_opt = contents t in
let time, message =
Option.map history_opt ~f:(fun history ->
let { log = {time; message}; previous_state } = history in
(time, message))
|> function
| None -> passive_time t, None
| Some (time, m) -> time, m in
(`Time time, `Log message, `Info (dive t))