Skip to content

Commit e10e176

Browse files
authored
Merge pull request #586 from SGrondin/process-exit-success
Add `Process.run ?is_success` to control definition of success
2 parents 3fe5755 + 7bb7c2b commit e10e176

File tree

3 files changed

+39
-8
lines changed

3 files changed

+39
-8
lines changed

lib_eio/process.ml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ end
3939
let pid proc = proc#pid
4040
let await proc = proc#await
4141

42-
let await_exn proc =
42+
let await_exn ?(is_success = Int.equal 0) proc =
4343
match proc#await with
44-
| `Exited 0 -> ()
44+
| `Exited code when is_success code -> ()
4545
| status -> raise (err (Child_error status))
4646

4747
let signal proc = proc#signal
@@ -84,26 +84,26 @@ let spawn ~sw (t:#mgr) ?cwd ?stdin ?stdout ?stderr ?env ?executable args =
8484
?stdout:(stdout :> Flow.sink option)
8585
?stderr:(stderr :> Flow.sink option)
8686

87-
let run (t:#mgr) ?cwd ?stdin ?stdout ?stderr ?env ?executable args =
87+
let run (t:#mgr) ?cwd ?stdin ?stdout ?stderr ?(is_success = Int.equal 0) ?env ?executable args =
8888
Switch.run @@ fun sw ->
8989
let child = spawn ~sw t ?cwd ?stdin ?stdout ?stderr ?env ?executable args in
9090
match await child with
91-
| `Exited 0 -> ()
91+
| `Exited code when is_success code -> ()
9292
| status ->
9393
let ex = err (Child_error status) in
9494
raise (Exn.add_context ex "running command: %a" pp_args args)
9595

9696
let pipe ~sw (t:#mgr) = t#pipe ~sw
9797

98-
let parse_out (t:#mgr) parse ?cwd ?stdin ?stderr ?env ?executable args =
98+
let parse_out (t:#mgr) parse ?cwd ?stdin ?stderr ?is_success ?env ?executable args =
9999
Switch.run @@ fun sw ->
100100
let r, w = pipe t ~sw in
101101
try
102102
let child = spawn ~sw t ?cwd ?stdin ~stdout:w ?stderr ?env ?executable args in
103103
Flow.close w;
104104
let output = Buf_read.parse_exn parse r ~max_size:max_int in
105105
Flow.close r;
106-
await_exn child;
106+
await_exn ?is_success child;
107107
output
108108
with Exn.Io _ as ex ->
109109
let bt = Printexc.get_raw_backtrace () in

lib_eio/process.mli

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,12 @@ val pid : #t -> int
4949
val await : #t -> exit_status
5050
(** [await t] waits for process [t] to exit and then reports the status. *)
5151

52-
val await_exn : #t -> unit
53-
(** Like {! await} except an exception is raised if the status is not [`Exited 0]. *)
52+
val await_exn : ?is_success:(int -> bool) -> #t -> unit
53+
(** Like {! await} except an exception is raised if does not return a successful
54+
exit status.
55+
56+
@param is_success Used to determine if an exit code is successful.
57+
Default is [Int.equal 0]. *)
5458

5559
val signal : #t -> int -> unit
5660
(** [signal t i] sends the signal [i] to process [t].
@@ -113,12 +117,16 @@ val run :
113117
?stdin:#Flow.source ->
114118
?stdout:#Flow.sink ->
115119
?stderr:#Flow.sink ->
120+
?is_success:(int -> bool) ->
116121
?env:string array ->
117122
?executable:string ->
118123
string list -> unit
119124
(** [run] does {!spawn} followed by {!await_exn}, with the advantage that if the process fails then
120125
the error message includes the command that failed.
121126
127+
When [is_success] is provided, it is called with the exit code to determine whether it indicates success or failure.
128+
Without [is_success], success requires the process to return an exit code of 0.
129+
122130
Note: If [spawn] needed to create extra fibers to copy [stdin], etc, then it also waits for those to finish. *)
123131

124132
val parse_out :
@@ -127,6 +135,7 @@ val parse_out :
127135
?cwd:#Fs.dir Path.t ->
128136
?stdin:#Flow.source ->
129137
?stderr:#Flow.sink ->
138+
?is_success:(int -> bool) ->
130139
?env:string array ->
131140
?executable:string ->
132141
string list -> 'a

tests/process.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,28 @@ Eio.Io Process Child_error Exited (code 3),
148148
running command: bash -c "exit 3" "" foo
149149
```
150150

151+
Exit code success can be determined by is_success (Process.run):
152+
153+
```ocaml
154+
# run @@ fun mgr env ->
155+
Process.run ~is_success:(Int.equal 3) mgr ["bash"; "-c"; "exit 3"];;
156+
- : unit = ()
157+
158+
# run @@ fun mgr env ->
159+
Process.run ~is_success:(Int.equal 3) mgr ["bash"; "-c"; "exit 0"];;
160+
Exception:
161+
Eio.Io Process Child_error Exited (code 0),
162+
running command: bash -c "exit 0"
163+
```
164+
165+
Exit code success can be determined by is_success (Process.parse_out):
166+
167+
```ocaml
168+
# run @@ fun mgr env ->
169+
Process.parse_out ~is_success:(Int.equal 5) mgr Eio.Buf_read.line ["sh"; "-c"; "echo 123; exit 5"];;
170+
- : string = "123"
171+
```
172+
151173
The default environment:
152174

153175
```ocaml

0 commit comments

Comments
 (0)