type part =
| Comparator of Semver_comparator.t
| Caret of Semver_version.t
type t = part list
let expand_caret version =
Semver_version.(
let upper =
match version with
| { major = 0; minor = 0; _ } -> incr_patch version
| { major = 0; _ } -> incr_minor version
| _ -> incr_major version
in
[
Semver_comparator.{ op = Some GreaterOrEqual; version };
Semver_comparator.{ op = Some Less; version = upper };
])
let fold_comparators_of_range f acc t =
List.fold_left
(fun acc part ->
match part with
| Comparator c -> f acc c
| Caret v -> List.fold_left f acc (expand_caret v))
acc
t
let comparators_of_range t : Semver_comparator.t list =
let comparators = fold_comparators_of_range (fun acc comp -> comp :: acc) [] t in
List.rev comparators
let satisfies ?(include_prereleases = false) range version =
Semver_version.(
Semver_comparator.(
let satisfied =
fold_comparators_of_range
(fun acc comp ->
if not acc then
acc
else
Semver_comparator.satisfies version comp)
true
range
in
if not satisfied then
false
else
let { major; minor; patch; prerelease; build = _ } = version in
if prerelease = [] || include_prereleases then
true
else
fold_comparators_of_range
(fun acc { version = allowed; op = _ } ->
if acc then
acc
else
match allowed with
| { major = major'; minor = minor'; patch = patch'; prerelease = _ :: _; build = _ }
->
major = major' && minor = minor' && patch = patch'
| _ -> false)
false
range))
let string_of_part = function
| Comparator c -> Semver_comparator.to_string c
| Caret ver -> "^" ^ Semver_version.to_string ver
let to_string t = t |> List.map string_of_part |> String.concat " "