1module History = History
2module Engine = Engine
3module Script = Script
4
5let process_error e = Error (`Process e)
6let shell_error e = Error (`Shell e)
7
8module Make (H : History.S) (Engine : Engine.S with type entry = H.t) = struct
9 module Store = Irmin_git_unix.FS.KV (H)
10
11 let run config ~stdout fs clock proc store =
12 let store = History.Store ((module Store), store) in
13 let initial_ctx = Engine.init fs proc store in
14 let rec loop store ctx exit_code =
15 let prompt = Engine.prompt exit_code store in
16 match LNoise.linenoise prompt with
17 | None -> ()
18 | Some input -> (
19 let action = Engine.action_of_command input in
20 match Engine.run config ~stdout fs clock proc (store, ctx) action with
21 | Error (`Process (Eio.Process.Child_error exit_code)) ->
22 Fmt.epr "%a\n%!" Eio.Process.pp_status exit_code;
23 loop store ctx exit_code
24 | Error (`Process (Eio.Process.Executable_not_found m)) ->
25 Fmt.epr "shelter: excutable not found %s\n%!" m;
26 loop store ctx (`Exited 127)
27 | Error (`Shell e) ->
28 Fmt.epr "shelter: %a\n%!" Engine.pp_error e;
29 loop store ctx (`Exited 255)
30 | Ok (store, ctx) -> loop store ctx (`Exited 0))
31 in
32 loop store initial_ctx (`Exited 0)
33
34 let command_file_to_actions cf =
35 Eio.Path.load cf |> String.split_on_char '\n'
36 |> List.map Engine.action_of_command
37
38 let main config ~stdout fs clock proc directory command_file =
39 let conf = Irmin_git.config (Eio.Path.native_exn directory) in
40 let repo = Store.Repo.v conf in
41 let store = Store.main repo in
42 match command_file with
43 | Some file -> (
44 let actions = command_file_to_actions file in
45 let store = History.Store ((module Store), store) in
46 let initial_ctx = Engine.init fs proc store in
47 let folder (store, ctx, exit_code) action =
48 if exit_code <> `Exited 0 then (store, ctx, exit_code)
49 else
50 match
51 Engine.run config ~stdout fs clock proc (store, ctx) action
52 with
53 | Error (`Process (Eio.Process.Child_error exit_code)) ->
54 Fmt.epr "%a\n%!" Eio.Process.pp_status exit_code;
55 (store, ctx, exit_code)
56 | Error (`Process (Eio.Process.Executable_not_found m)) ->
57 Fmt.epr "shelter: excutable not found %s\n%!" m;
58 (store, ctx, `Exited 127)
59 | Error (`Shell e) ->
60 Fmt.epr "shelter: %a\n%!" Engine.pp_error e;
61 (store, ctx, `Exited 255)
62 | Ok (store, ctx) -> (store, ctx, `Exited 0)
63 in
64 let _store, _ctx, exit_code =
65 List.fold_left folder (store, initial_ctx, `Exited 0) actions
66 in
67 match exit_code with
68 | `Exited 0 -> ()
69 | `Exited n | `Signaled n ->
70 Fmt.epr "%a\n%!" Eio.Process.pp_status exit_code;
71 exit n)
72 | None -> run config ~stdout fs clock proc store
73end