let execute ?timeout t argl =
let final_log = ref Log.empty in
let ret out err exited =
let kv k v = Log.(brakets (s k % s " → " % v) |> indent) in
final_log := Log.(
!final_log %n % s "Success: " % kv "status" (sf "exit:%d" exited)
% kv "stdout" (sf "%S" out) % kv "stderr" (sf "%S" err));
return (object
method stdout = out method stderr = err method exited = exited
end)
in
let run ~log () =
final_log := Log.( !final_log % s "Host.execute " % s (to_string_hum t)
% OCaml.list s argl % sp % log);
match connection t with
| `Localhost ->
begin Ketrew_unix_process.exec argl
>>< function
| `Ok (out, err, `Exited n) -> ret out err n
| `Ok (out, err, other) ->
fail_exec t ~out ~err (System.Shell.status_to_string other)
| `Error (`Process _ as process_error) ->
let msg = Ketrew_unix_process.error_to_string process_error in
Log.(s "Ssh-cmd " % OCaml.list (sf "%S") argl
% s " failed: " %s msg @ verbose);
fail_exec t msg
end
| `Ssh ssh ->
begin Ssh.generic_ssh_exec ssh argl
>>< function
| `Ok (out, err, exited) -> ret out err exited
| `Error e -> fail (`Host e)
end
in
begin run_with_timeout ?timeout t ~run
>>< fun result ->
Log.(!final_log @ very_verbose);
match result with
| `Ok o -> return o
| `Error (`Host e) -> fail (`Host e)
| `Error (`System _ as e)
| `Error (`Timeout _ as e) -> fail (`Host e)
end