Source file opam_0install_cudf.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
module Context = struct
type rejection = UserConstraint of Cudf_types.vpkg
type t = {
universe : Cudf.universe;
constraints : (Cudf_types.pkgname * (Cudf_types.relop * Cudf_types.version)) list;
prefer_oldest : bool;
}
let user_restrictions t name =
List.fold_left (fun acc (name', c) ->
if String.equal name name' then
c :: acc
else
acc
) [] t.constraints
let version_compare t pkg1 pkg2 =
if t.prefer_oldest then
compare (pkg1.Cudf.version : int) pkg2.Cudf.version
else
compare (pkg2.Cudf.version : int) pkg1.Cudf.version
let candidates t name =
let user_constraints = user_restrictions t name in
match Cudf.lookup_packages t.universe name with
| [] ->
[]
| versions ->
List.fast_sort (version_compare t) versions
|> List.map (fun pkg ->
let rec check_constr = function
| [] -> (pkg.Cudf.version, Ok pkg)
| ((op, v)::c) ->
if Model.fop op pkg.Cudf.version v then
check_constr c
else
(pkg.Cudf.version, Error (UserConstraint (name, Some (op, v))))
in
check_constr user_constraints
)
let print_constr = function
| None -> ""
| Some (`Eq, v) -> "="^string_of_int v
| Some (`Neq, v) -> "!="^string_of_int v
| Some (`Geq, v) -> ">="^string_of_int v
| Some (`Gt, v) -> ">"^string_of_int v
| Some (`Leq, v) -> "<="^string_of_int v
| Some (`Lt, v) -> "<"^string_of_int v
let pp_rejection f = function
| UserConstraint (name, c) -> Fmt.pf f "Rejected by user-specified constraint %s%s" name (print_constr c)
end
module Input = Model.Make(Context)
let requirements ~context pkgs =
let role =
let impl = Input.virtual_impl ~context ~depends:pkgs () in
Input.virtual_role [impl]
in
{ Input.role; command = None }
module Solver = Zeroinstall_solver.Make(Input)
module Diagnostics = Zeroinstall_solver.Diagnostics(Solver.Output)
type t = Context.t
type selections = Solver.Output.t
type diagnostics = Input.requirements
let create ?(prefer_oldest=false) ~constraints universe =
{ Context.universe; constraints; prefer_oldest }
let solve context pkgs =
let req = requirements ~context pkgs in
match Solver.do_solve ~closest_match:false req with
| Some sels -> Ok sels
| None -> Error req
let diagnostics ?verbose req =
Solver.do_solve req ~closest_match:true
|> Option.get
|> Diagnostics.get_failure_reason ?verbose
let packages_of_result sels =
sels
|> Solver.Output.to_map |> Solver.Output.RoleMap.to_seq |> List.of_seq
|> List.filter_map (fun (_role, sel) -> Input.version (Solver.Output.unwrap sel))