builder-web/opamdiff/opamdiff.ml
Hannes Mehnert f4da9ad666 In Opamdiff.compare, do not figure out unchanged packages.
In the View.compare_builds (/compare/..), do not display
"XX opam packages unchanged".

The reasoning is that the diff view concerns:
(a) opam packages
(b) environment variables
(c) system packages

And we're only interested in what changed in each category. The list of
unchanged opam packages is not really of interest, but adds quite some noise to
the page.
2022-08-05 11:16:21 +02:00

129 lines
4.2 KiB
OCaml

module Set = OpamPackage.Set
type package = OpamPackage.t
let packages (switch : OpamFile.SwitchExport.t) =
assert (Set.cardinal switch.selections.sel_pinned = 0);
assert (Set.cardinal switch.selections.sel_compiler = 0);
assert (Set.subset switch.selections.sel_roots switch.selections.sel_installed);
switch.selections.sel_installed
type version_diff = {
name : OpamPackage.Name.t;
version_left : OpamPackage.Version.t;
version_right : OpamPackage.Version.t;
}
let pp_opampackage ppf p =
Format.fprintf ppf "%s" (OpamPackage.to_string p)
let pp_version_diff ppf { name; version_left; version_right } =
Format.fprintf ppf "%s.%s->%s"
(OpamPackage.Name.to_string name)
(OpamPackage.Version.to_string version_left)
(OpamPackage.Version.to_string version_right)
type opam_diff = {
pkg : OpamPackage.t ;
build : (OpamTypes.command list * OpamTypes.command list) option ;
install : (OpamTypes.command list * OpamTypes.command list) option ;
url : (OpamFile.URL.t option * OpamFile.URL.t option) option ;
otherwise_equal : bool ;
}
let commands_to_strings (l, r) =
let v a =
OpamPrinter.FullPos.value (OpamPp.print OpamFormat.V.command a)
in
List.map v l, List.map v r
let opt_url_to_string (l, r) =
let url_to_s = function
| None -> "" | Some u -> OpamFile.URL.write_to_string u
in
url_to_s l, url_to_s r
let pp_opam_diff ppf { pkg ; otherwise_equal ; _ } =
Format.fprintf ppf "%a%s"
pp_opampackage pkg
(if otherwise_equal then "" else " (and additional changes)")
let rec strip_common_prefix a b =
match a, b with
| hd::tl, hd'::tl' ->
if hd = hd' then
strip_common_prefix tl tl'
else
a, b
| a, b -> a, b
let detailed_opam_diff pkg l r =
let no_build_install_url p =
OpamFile.OPAM.with_url_opt None
(OpamFile.OPAM.with_install []
(OpamFile.OPAM.with_build [] p))
in
let otherwise_equal =
OpamFile.OPAM.effectively_equal
(no_build_install_url l) (no_build_install_url r)
and build =
if OpamFile.OPAM.build l = OpamFile.OPAM.build r then
None
else
Some (strip_common_prefix (OpamFile.OPAM.build l) (OpamFile.OPAM.build r))
and install =
if OpamFile.OPAM.install l = OpamFile.OPAM.install r then
None
else
Some (strip_common_prefix (OpamFile.OPAM.install l) (OpamFile.OPAM.install r))
and url =
if OpamFile.OPAM.url l = OpamFile.OPAM.url r then
None
else
Some (OpamFile.OPAM.url l, OpamFile.OPAM.url r)
in
{ pkg ; build ; install ; url ; otherwise_equal }
let detailed_opam_diffs left right pkgs =
OpamPackage.Set.fold (fun p acc ->
let find = OpamPackage.Name.Map.find p.name in
let opam_left = find left.OpamFile.SwitchExport.overlays
and opam_right = find right.OpamFile.SwitchExport.overlays in
(detailed_opam_diff p opam_left opam_right) :: acc)
pkgs []
let compare left right =
let packages_left = packages left and packages_right = packages right in
let module Set = OpamPackage.Set in
let equal_name p1 p2 = OpamPackage.Name.equal p1.OpamPackage.name p2.OpamPackage.name in
let diff l r =
Set.filter (fun p1 ->
not (Set.exists (equal_name p1) r))
l
in
let same_version = Set.inter packages_left packages_right in
let opam_diff =
Set.filter
(fun p ->
let find = OpamPackage.Name.Map.find p.name in
let opam_left = find left.overlays and opam_right = find right.overlays in
not (OpamFile.OPAM.effectively_equal opam_left opam_right))
same_version
and version_diff =
List.filter_map (fun p1 ->
match Set.find_opt (equal_name p1) packages_right with
| Some p2 ->
if OpamPackage.Version.equal p1.version p2.version
then None
else
Some { name = p1.OpamPackage.name;
version_left = p1.OpamPackage.version;
version_right = p2.OpamPackage.version }
| None ->
None)
(Set.elements packages_left)
and left_pkgs = diff packages_left packages_right
and right_pkgs = diff packages_right packages_left
in
let opam_diff = detailed_opam_diffs left right opam_diff in
(opam_diff, version_diff, left_pkgs, right_pkgs)