Compute and present the opam file differences as a unified diff #7

Merged
reynir merged 3 commits from opam-diff-as-diff into main 2025-01-08 14:16:05 +00:00
Showing only changes of commit b9668365cd - Show all commits

View file

@ -178,9 +178,10 @@ let pp_opam_diff ppf { pkg ; effectively_equal ; _ } =
(if effectively_equal then "" else " (effectively equal)")
let detailed_opam_diff pkg l r =
let ( let* ) = Result.bind in
let opaml = OpamFile.OPAM.write_to_string l in
let opamr =
(* Let's minimize the difference between opaml and opamr by taking opaml
as template for opamr. *)
let o = OpamFile.make (OpamFilename.raw "opam") in
reynir marked this conversation as resolved
Review

So this dance here is to try to get the same formatting as for l/opaml? I think that makes sense. Maybe worth attaching a comment?

I am curious what the behavior is if the two packages differ too much. I guess since OpamFile.OPAM.write_to_string is likely to use a fixed formatting style the style will be consistent even with a larger difference in packages? (this doesn't have to be answered IMO)

So this dance here is to try to get the same formatting as for `l`/`opaml`? I think that makes sense. Maybe worth attaching a comment? I am curious what the behavior is if the two packages differ too much. I guess since `OpamFile.OPAM.write_to_string` is likely to use a fixed formatting style the style will be consistent even with a larger difference in packages? (this doesn't have to be answered IMO)
Review

in my experience, using the "with_preserved_format" is good -- apart from potentially dangling comments (in the last line). I also think a comment is worth it. Of course we can leave the opam files as is and do a direct diff, i.e. do not care about the "minimal" diff...

in my experience, using the "with_preserved_format" is good -- apart from potentially dangling comments (in the last line). I also think a comment is worth it. Of course we can leave the opam files as is and do a direct diff, i.e. do not care about the "minimal" diff...
OpamFile.OPAM.to_string_with_preserved_format ~format_from_string:opaml o r
in
@ -194,16 +195,30 @@ let detailed_opam_diff pkg l r =
(no_build_install_url l) (no_build_install_url r)
in
let diff =
reynir marked this conversation as resolved
Review

I think the files are only deleted at_exit. There are functions Bos.OS.File.with_tmp_output / Bos.OS.File.with_tmp_oc that ensure the file is deleted when the callback returns - maybe worth using one of them?

The files are usually quite small so I imagine it would usually take years before the dangling temporary files become a problem.

I think the files are only deleted `at_exit`. There are functions `Bos.OS.File.with_tmp_output` / `Bos.OS.File.with_tmp_oc` that ensure the file is deleted when the callback returns - maybe worth using one of them? The files are usually quite small so I imagine it would usually take years before the dangling temporary files become a problem.
Review

Yes, you're right. I'll adapt.

Yes, you're right. I'll adapt.
let* tmpl = Bos.OS.File.tmp "opaml_%s" in
let* () = Bos.OS.File.write tmpl opaml in
let* tmpr = Bos.OS.File.tmp "opamr_%s" in
let* () = Bos.OS.File.write tmpr opamr in
let cmd = Bos.Cmd.(v "diff" % "-u" % p tmpl % p tmpr) in
Bos.OS.Cmd.(run_out cmd |> out_string)
try
Bos.OS.File.with_tmp_oc "opaml_%s"
(fun pl oc () ->
Out_channel.output_string oc opaml;
Out_channel.close oc;
Bos.OS.File.with_tmp_oc "opamr_%s"
(fun pr oc () ->
Out_channel.output_string oc opamr;
Out_channel.close oc;
let cmd = Bos.Cmd.(v "diff" % "-u" % p pl % p pr) in
Bos.OS.Cmd.(run_out cmd |> out_string))
())
()
with e ->
Error (`Msg ("exception " ^ Printexc.to_string e))
in
let diff = match diff with
Review

I think we can write match Result.join (Result.join diff) with to avoid the nested matches, but this is fine, too.

I think we can write `match Result.join (Result.join diff) with` to avoid the nested matches, but this is fine, too.
| Ok (s, _) -> s
| Error `Msg m -> "error when comparing the opam files: " ^ m
| Ok (Ok (Ok (data, _))) -> data
| Ok (Ok (Error `Msg msg))
| Ok (Error `Msg msg)
| Error `Msg msg ->
Logs.err (fun m -> m "Error %s while running diff on opam files@.@.%s@.@.%s@.@."
msg opaml opamr);
"Error comparing opam files"
in
{ pkg ; effectively_equal ; diff }