(** Read active build/doc/tool locks from day10's cache directory. *) type stage = Build | Doc | Tool type active_lock = { stage : stage; package : string; version : string; universe : string option; (* For Build/Doc: dependency hash. For Tool: OCaml version if applicable *) pid : int; start_time : float; duration : float; (* seconds since start *) layer_name : string option; (* Final layer directory name *) temp_log_path : string option; (* Temp log path for live viewing *) } (** Convert library lock record to web-friendly format *) let of_lib_lock (lock : Day10_lib.Build_lock.lock_info) = let now = Unix.time () in let stage = match lock.stage with | Day10_lib.Build_lock.Build -> Build | Day10_lib.Build_lock.Doc -> Doc | Day10_lib.Build_lock.Tool -> Tool in { stage; package = lock.package; version = lock.version; universe = lock.universe; pid = lock.pid; start_time = lock.start_time; duration = now -. lock.start_time; layer_name = lock.layer_name; temp_log_path = lock.temp_log_path; } let list_active_locks ~cache_dir = Day10_lib.Build_lock.list_active ~cache_dir |> List.map of_lib_lock let has_active_locks ~cache_dir = match Day10_lib.Build_lock.list_active ~cache_dir with | [] -> false | _ -> true let format_duration seconds = let seconds = int_of_float seconds in if seconds < 60 then Printf.sprintf "%ds" seconds else if seconds < 3600 then Printf.sprintf "%dm%ds" (seconds / 60) (seconds mod 60) else Printf.sprintf "%dh%dm" (seconds / 3600) ((seconds mod 3600) / 60)