Source file packages.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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
open ExtLib
open Dose_common
open Dose_extra
include Util.Logging (struct
let label = "dose_opam.packages"
end)
type options =
Dose_pef.Packages_types.architecture
* Dose_pef.Packages_types.architecture list
* Dose_pef.Packages_types.buildprofile list
type request =
{ install : Dose_pef.Packages_types.vpkg list;
remove : Dose_pef.Packages_types.vpkg list;
upgrade : Dose_pef.Packages_types.vpkg list;
dist_upgrade : bool;
switch : string;
switches : string list;
profiles : string list;
preferences : string
}
let default_request =
{ install = [];
remove = [];
upgrade = [];
dist_upgrade = false;
switch = "";
switches = [];
profiles = [];
preferences = ""
}
let matchswitch switches = function
| [] -> true
| (true, _) :: _ as al -> List.exists (fun (_, a) -> List.mem a switches) al
| (false, _) :: _ as al ->
List.for_all (fun (_, a) -> not (List.mem a switches)) al
let matchos profiles = function
| [] -> true
| ll -> List.exists (List.for_all (fun (c, p) -> c = List.mem p profiles)) ll
let select (switch, switches, profiles) (v, al, pl) =
if matchswitch (switch :: switches) al && matchos profiles pl then [v] else []
let vpkglist_filter options l = List.flatten (List.map (select options) l)
let vpkgformula_filter options ll =
List.filter_map
(fun l -> match vpkglist_filter options l with [] -> None | l -> Some l)
ll
let parse_req =
Dose_pef.Packages.lexbuf_wrapper Dose_pef.Packages_parser.vpkglist_top
let parse_request_stanza par =
try
{ install = Dose_pef.Packages.parse_s ~default:[] parse_req "install" par;
remove = Dose_pef.Packages.parse_s ~default:[] parse_req "remove" par;
upgrade = Dose_pef.Packages.parse_s ~default:[] parse_req "upgrade" par;
dist_upgrade =
Dose_pef.Packages.parse_s
~default:false
Dose_pef.Packages.parse_bool
"dist_upgrade"
par;
switch =
Dose_pef.Packages.parse_s
~required:true
Dose_pef.Packages.parse_string
"switch"
par;
switches =
Dose_pef.Packages.parse_s
~default:[]
Dose_pef.Packages.parse_string_list
"switches"
par;
profiles =
Dose_pef.Packages.parse_s
~default:[]
Dose_pef.Packages.parse_string_list
"profiles"
par;
preferences =
Dose_pef.Packages.parse_s
~default:""
Dose_pef.Packages.parse_string
"preferences"
par
}
with Format822.ParseError (cl, f, err) ->
let c = "Parser Error in Preamble" in
raise (Format822.ParseError (c :: cl, f, err))
class package ?(name = ("package", None)) ?(version = ("version", None))
?(depends = ("depends", None)) ?(conflicts = ("conflicts", None))
?(provides = ("provides", None)) ?(depopts = ("depopts", None))
?(switch = ("switches", None)) ?(installedlist = ("installed", None))
?(pinnedlist = ("pinned", None)) ?(baselist = ("base", None))
?( = ([], None)) par =
object
inherit
Dose_pef.Packages.package
~name
~version
~depends
~conflicts
~provides
~recommends:depopts
~extras
par
val switch : string * string list =
let p =
Dose_pef.Packages.parse_string_list ~rex:Dose_pef.Packages.comma_regexp
in
let parse = Dose_pef.Packages.parse_s ~default:["all"] p in
Dose_pef.Packages.get_field_value ~parse ~par ~field:switch
val installedlist : string * string list =
let p =
Dose_pef.Packages.parse_string_list ~rex:Dose_pef.Packages.comma_regexp
in
let parse = Dose_pef.Packages.parse_s ~default:[] p in
Dose_pef.Packages.get_field_value ~parse ~par ~field:installedlist
val baselist : string * string list =
let p =
Dose_pef.Packages.parse_string_list ~rex:Dose_pef.Packages.comma_regexp
in
let parse = Dose_pef.Packages.parse_s ~default:[] p in
Dose_pef.Packages.get_field_value ~parse ~par ~field:baselist
val pinnedlist : string * string list =
let p =
Dose_pef.Packages.parse_string_list ~rex:Dose_pef.Packages.comma_regexp
in
let parse = Dose_pef.Packages.parse_s ~default:[] p in
Dose_pef.Packages.get_field_value ~parse ~par ~field:pinnedlist
method switch = snd switch
method installedlist = snd installedlist
method baselist = snd baselist
method pinnedlist = snd pinnedlist
method depopts = snd recommends
method! pp oc =
Dose_pef.Printer.pp_string_wl oc name ;
Dose_pef.Printer.pp_string_wl oc version ;
Dose_pef.Printer.pp_string_list_wl oc switch ;
Dose_pef.Printer.pp_string_list_wl oc installedlist ;
Dose_pef.Printer.pp_string_list_wl oc pinnedlist ;
Dose_pef.Printer.pp_string_list_wl oc baselist ;
Dose_pef.Printer.pp_vpkglist_wl oc provides ;
Dose_pef.Printer.pp_vpkgformula_wl oc depends ;
Dose_pef.Printer.pp_vpkgformula_wl oc recommends ;
Dose_pef.Printer.pp_vpkglist_wl oc conflicts ;
Printf.fprintf oc "\n"
end
let parse_package_stanza ((switch, switches, _profiles) as options)
?( = []) par =
try
let pkg_switch =
let p =
Dose_pef.Packages.parse_string_list ~rex:Dose_pef.Packages.comma_regexp
in
let f = Dose_pef.Packages.parse_s ~default:["all"] p in
f "switches" par
in
if
not
(List.mem "all" pkg_switch
|| List.exists (fun s -> List.mem s pkg_switch) (switch :: switches))
then
raise
(Dose_pef.Packages.IgnorePackage
(Printf.sprintf
"None of the active switches [%s] are available [%s]"
(ExtString.String.join "," (switch :: switches))
(ExtString.String.join "," pkg_switch)))
else
let pkg =
let depends =
let f =
Dose_pef.Packages.parse_s
~default:[]
Dose_pef.Packages.parse_builddepsformula
in
("depends", Some (vpkgformula_filter options (f "depends" par)))
in
let depopts =
let f =
Dose_pef.Packages.parse_s
~default:[]
Dose_pef.Packages.parse_builddepsformula
in
("depopts", Some (vpkgformula_filter options (f "depopts" par)))
in
let conflicts =
let f =
Dose_pef.Packages.parse_s
~default:[]
Dose_pef.Packages.parse_builddepslist
in
("conflicts", Some (vpkglist_filter options (f "conflicts" par)))
in
let provides =
let f =
Dose_pef.Packages.parse_s
~default:[]
Dose_pef.Packages.parse_builddepslist
in
("provides", Some (vpkglist_filter options (f "provides" par)))
in
new package
~depends
~conflicts
~provides
~depopts
~extras:(extras, None)
par
in
Some pkg
with
| Dose_pef.Packages.IgnorePackage s ->
let n =
Dose_pef.Packages.parse_s
~default:"?"
Dose_pef.Packages.parse_name
"package"
par
in
let v =
Dose_pef.Packages.parse_s
~default:"?"
Dose_pef.Packages.parse_version
"version"
par
in
warning "Ignoring Package (%s,%s) : %s" n v s ;
None
| Format822.ParseError (cl, f, err) ->
let n =
Dose_pef.Packages.parse_s
~default:"?"
Dose_pef.Packages.parse_name
"package"
par
in
let v =
Dose_pef.Packages.parse_s
~default:"?"
Dose_pef.Packages.parse_version
"version"
par
in
let c = Printf.sprintf "Parser Error in Package (%s,%s)" n v in
raise (Format822.ParseError (c :: cl, f, err))
let rec packages_parser ?(request = false) (req, acc) p =
let options = (req.switch, req.switches, req.profiles) in
match
Format822_parser.stanza_822 Format822_lexer.token_822 p.Format822.lexbuf
with
| None -> (req, acc)
| Some stanza when request = true ->
let req = parse_request_stanza stanza in
packages_parser (req, acc) p
| Some stanza -> (
match parse_package_stanza options stanza with
| None -> packages_parser (req, acc) p
| Some st -> packages_parser (req, st :: acc) p)
let input_raw_in ic =
Format822.parse_from_ch
(packages_parser ~request:true (default_request, []))
ic
let input_raw file =
try
let ch =
match file with
| "-" -> IO.input_channel stdin
| _ -> Input.open_file file
in
let l = input_raw_in ch in
let _ = Input.close_ch ch in
l
with
| Input.File_empty -> (default_request, [])
| Format822.ParseError (cl, field, errmsg) ->
fatal
"Filename %s\n %s\n %s : %s"
file
(String.concat "\n " cl)
field
errmsg