Source file hg_lib_factory.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
open Core
module Unix = Core_unix
include Hg_lib_factory_intf
module With_global_args = struct
type 'a t =
?repository:string
-> ?cwd:string
-> ?config:(string * string) list
-> ?env:Async.Process.env
-> 'a
let map t ~f ?repository ?cwd ?config ?env = f (t ?repository ?cwd ?config ?env)
let prepend_to_args ~repository ~cwd ~config args =
List.concat
[ (match repository with
| None -> []
| Some repo -> [ "--repository"; repo ])
; (match cwd with
| None -> []
| Some cwd -> [ "--cwd"; cwd ])
; (match config with
| None -> []
| Some config ->
List.concat_map config ~f:(fun (key, data) -> [ "--config"; key ^ "=" ^ data ]))
; args
]
;;
end
module With_global_args_remote = struct
type 'a t =
server:Command_server.t
-> ?repository:string
-> ?cwd:string
-> ?config:(string * string) list
-> 'a
let map t ~f ~server ?repository ?cwd ?config = f (t ~server ?repository ?cwd ?config)
let prepend_to_args ~repository ~config args =
List.concat
[ (match repository with
| None -> []
| Some repo -> [ "--repository"; repo ])
; (match config with
| None -> []
| Some config ->
List.concat_map config ~f:(fun (key, data) -> [ "--config"; key ^ "=" ^ data ]))
; args
]
;;
end
let handle_output_with_args ~args handle_output (output : Async.Process.Output.t) =
Hg_private.Or_simple_error.tag
(handle_output output)
"hg error"
args
[%sexp_of: string list]
;;
let handle_output_exn ~args handle_output output =
Or_error.ok_exn (handle_output_with_args ~args handle_output output)
;;
module Simple = struct
module With_args = With_global_args
module Output = struct
type 'a t = 'a
let return = Fn.id
end
let run ?repository ?cwd ?config ?env ~args ~handle_output () =
let args = With_global_args.prepend_to_args ~repository ~cwd ~config args in
let { Unix.Process_info.stdin; stdout; stderr; pid } =
match env with
| None -> Unix.create_process ~prog:"hg" ~args
| Some env -> Unix.create_process_env ~prog:"hg" ~args ~env ()
in
let stdout_s = In_channel.input_all (Unix.in_channel_of_descr stdout) in
let stderr_s = In_channel.input_all (Unix.in_channel_of_descr stderr) in
let exit_status = Unix.waitpid pid in
Unix.close stdin;
Unix.close stdout;
Unix.close stderr;
handle_output_exn
~args
handle_output
{ exit_status; stdout = stdout_s; stderr = stderr_s }
;;
end
open Async
module Async = struct
module With_args = With_global_args
module Output = struct
type 'a t = 'a Or_error.t Deferred.t
let return x = return (Ok x)
end
let run ?repository ?cwd ?config ?env ~args ~handle_output () =
let args = With_global_args.prepend_to_args ~repository ~cwd ~config args in
Process.create ?env ~prog:"hg" ~args ()
>>=? fun process ->
Process.collect_output_and_wait process
>>| fun output -> handle_output_with_args ~args handle_output output
;;
end
module Fixed_hg_environment (E : Hg_env) = struct
module With_args = With_global_args
module Output = struct
type 'a t = 'a Or_error.t Deferred.t
let return x = return (Ok x)
end
let run ?repository ?cwd ?config ?env ~args ~handle_output () =
let config = Option.map config ~f:(fun config -> E.hg_config_options @ config) in
let args = With_global_args.prepend_to_args ~repository ~cwd ~config args in
let env =
let tuples = [ "HGRCPATH", E.hgrc_path; "HG_USER", E.hg_user ] in
match env with
| None -> `Extend tuples
| Some (`Extend envs) -> `Extend (tuples @ envs)
| Some (`Override l) -> `Override (List.map tuples ~f:(fun (x, y) -> x, Some y) @ l)
| Some (`Replace envs) -> `Replace (tuples @ envs)
| Some (`Replace_raw envs) ->
let env_strings = List.map tuples ~f:(fun (key, value) -> key ^ "=" ^ value) in
`Replace_raw (env_strings @ envs)
in
if false
then
Log.Global.debug
!"[%{sexp:Process.env}] %s %{sexp:string list}"
env
E.hg_binary
args;
Process.create ~env ~prog:E.hg_binary ~args ()
>>=? fun process ->
Process.collect_output_and_wait process
>>| fun output -> handle_output_with_args ~args handle_output output
;;
end
module Remote = struct
module With_args = With_global_args_remote
module Output = Deferred.Or_error
let run ~server ?repository ?(cwd = ".") ?config ~args ~handle_output () =
let args = With_global_args_remote.prepend_to_args ~repository ~config args in
Command_server.run_command server ~cwd args
>>=? fun output -> return (handle_output_with_args ~args handle_output output)
;;
end
module Make_lib (M : Make_s) = struct
module type S = sig
module Make (A : Arg) : M(A).S
module Simple : M(Simple).S
module Async : M(Async).S
module Fixed_hg_environment (E : Hg_env) : M(Fixed_hg_environment(E)).S
module Remote : M(Remote).S
end
end