Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for dune #3

Merged
merged 8 commits into from
Feb 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## Unreleased

- Add support of dune formatter. (#3)

## 0.1 (2019-02-19)

- Initial release.
- Initial release.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ code formatters.
`merge-fmt` currently only knows about the following formatters:
- [ocamlformat](https://github.com/ocaml-ppx/ocamlformat) for OCaml.
- [refmt](https://github.com/facebook/reason) for reason.
- [dune](https://github.com/ocaml/dune) for dune.

Note that supporting new code formatters is trivial.

Expand Down Expand Up @@ -47,4 +48,4 @@ Install
-------
```sh
$ opam pin add merge-fmt git@github.com:hhugo/merge-fmt.git
```
```
3 changes: 3 additions & 0 deletions merge-fmt-help.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ COMMANDS
Register the [merge-fmt] mergetool in git

OPTIONS
--dune=VAL
dune path

--echo
Echo all commands.

Expand Down
3 changes: 3 additions & 0 deletions merge-fmt-mergetool-help.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ OPTIONS

--current=<current-file>

--dune=VAL
dune path

--echo
Echo all commands.

Expand Down
64 changes: 52 additions & 12 deletions src/fmters.ml
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,62 @@ open Common
type config =
{ ocamlformat_path : string option
; refmt_path : string option
; dune_path : string option
}

type t = string
type t =
| Inplace of string
| Stdout of string

let transfer ic oc =
let b = Bytes.create 4096 in
let rec loop () =
match Stdlib.input ic b 0 (Bytes.length b) with
| 0 -> ()
| l ->
Stdlib.output oc b 0 l;
loop ()
in
loop ()

let ocamlformat ~bin ~name =
sprintf "%s -i %s"
(Option.value ~default:"ocamlformat" bin)
(Option.value_map ~default:"" ~f:(fun name -> " --name=" ^ name) name)
Inplace
(sprintf "%s -i %s"
(Option.value ~default:"ocamlformat" bin)
(Option.value_map ~default:"" ~f:(fun name -> " --name=" ^ name) name))

let refmt ~bin =
Inplace (sprintf "%s --inplace" (Option.value ~default:"refmt" bin))

let refmt ~bin = sprintf "%s --inplace" (Option.value ~default:"refmt" bin)
let dune ~bin =
Stdout (sprintf "%s format-dune-file --" (Option.value ~default:"dune" bin))

let find ~config ~filename ~name =
let filename = Option.value ~default:filename name in
match (Caml.Filename.extension filename, config) with
| (".ml" | ".mli"), { ocamlformat_path; _ } ->
match (filename, Caml.Filename.extension filename, config) with
| _, (".ml" | ".mli"), { ocamlformat_path; _ } ->
Some (ocamlformat ~bin:ocamlformat_path ~name)
| (".re" | ".rei"), { refmt_path; _ } -> Some (refmt ~bin:refmt_path)
| _, (".re" | ".rei"), { refmt_path; _ } -> Some (refmt ~bin:refmt_path)
| ("dune" | "dune-project" | "dune-workspace"), "", { dune_path; _ } ->
Some (dune ~bin:dune_path)
| _ -> None

let run t ~echo ~filename = system ~echo "%s %s" t filename
let run t ~echo ~filename =
match t with
| Inplace t -> system ~echo "%s %s" t filename
| Stdout t -> (
let ic = open_process_in ~echo "%s %s" t filename in
let tmp_file, oc = Stdlib.Filename.open_temp_file "merge-fmt" "stdout" in
transfer ic oc;
Stdlib.close_out oc;
match Unix.close_process_in ic with
| WEXITED 0 ->
Stdlib.Sys.rename tmp_file filename;
Ok ()
| WEXITED n ->
Stdlib.Printf.eprintf ">>> Exit with %d\n" n;
Error ()
| WSIGNALED _ | WSTOPPED _ -> Error ())

module Flags = struct
open Cmdliner
Expand All @@ -36,9 +72,13 @@ module Flags = struct
let doc = "refmt path" in
Arg.(value & opt (some string) None & info [ "refmt" ] ~doc)

let dune_path =
let doc = "dune path" in
Arg.(value & opt (some string) None & info [ "dune" ] ~doc)

let t =
Term.(
const (fun ocamlformat_path refmt_path ->
{ ocamlformat_path; refmt_path })
$ ocamlformat_path $ refmt_path)
const (fun ocamlformat_path refmt_path dune_path ->
{ ocamlformat_path; refmt_path; dune_path })
$ ocamlformat_path $ refmt_path $ dune_path)
end
10 changes: 7 additions & 3 deletions src/resolve_cmd.ml
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,10 @@ let show ~echo version versions =

let create_tmp ~echo fn version versions =
let content = show ~echo version versions in
let ext = Caml.Filename.extension fn
and base = Caml.Filename.chop_extension fn in
let ext = Caml.Filename.extension fn in
let base =
if String.equal ext "" then fn else Caml.Filename.chop_extension fn
in
let fn' = sprintf "%s.%s%s" base (string_of_version version) ext in
let oc = Out_channel.create fn' in
Out_channel.output_string oc content;
Expand Down Expand Up @@ -123,7 +125,9 @@ let resolve config echo () =
~f:(fun () -> git_add ~echo ~filename)
|> (ignore : (unit, unit) Result.t -> unit);
let n2 = conflict ~filename in
eprintf "Resolved %d/%d %s\n%!" (n1 - n2) n1 filename
if n2 > n1
then eprintf "Resolved ?? %s\n%!" filename
else eprintf "Resolved %d/%d %s\n%!" (n1 - n2) n1 filename
| None -> eprintf "Ignore %s (no formatter register)\n%!" filename)
| Error reason -> eprintf "Ignore %s (%s)\n%!" filename reason);
let all = ls ~echo () in
Expand Down
177 changes: 177 additions & 0 deletions test/merge_dune.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
open! Base
open! Stdio
open! Common

let%expect_test "default merge tool" =
within_temp_dir (fun () ->
git_init ();

write "dune" {|
(executable
(name aaaa)
(libraries unix))
|};
git_commit "first commit";
git_branch "branch1";

(* add public name *)
if false
then (
write "dune"
{|
(executable
(name aaaa)
(libraries unix)
(public_name pppp))
|};
git_commit "second commit");

(* add library *)
write "dune"
{|
(executable
(name aaaa)
(libraries unix))

(library
(name liblib))
|};
git_commit "third commit";
git_branch "branch2";

git_checkout "branch1";
[%expect {| Switched to branch 'branch1' |}];
(* change name to b, reformat *)
write "dune" {|
(executable
(name bbbb)
(libraries unix))
|};
git_commit "second commit (fork)";

write "dune"
{|
(alias
(name runtest)
(action
(diff rebase.diff rebase.diff.gen)))

(executable
(name bbbb)
(libraries unix))
|};

git_commit "third commit (fork)";
git_branch "old_branch1";
system "git rebase branch2 -q";
[%expect
{|
Auto-merging dune
CONFLICT (content): Merge conflict in dune
error: could not apply 2e00bc1... second commit (fork)
hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
hint: You can instead skip this commit: run "git rebase --skip".
hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply 2e00bc1... second commit (fork)
Exit with 1 |}];
print_file "dune";
[%expect
{|
File dune

(executable
<<<<<<< HEAD
(name aaaa)
(libraries unix))

(library
(name liblib))
=======
(name bbbb)
(libraries unix))
>>>>>>> 2e00bc1 (second commit (fork)) |}])

let%expect_test "custom merge tool" =
within_temp_dir (fun () ->
git_init ();
system "%s setup-merge --merge-fmt-path %s --update" merge_fmt merge_fmt;
[%expect {||}];

write "dune" {|
(executable
(name aaaa)
(libraries unix))
|};
git_commit "first commit";
git_branch "branch1";

(* add public name *)
if false
then (
write "dune"
{|
(executable
(name aaaa)
(libraries unix)
(public_name pppp))
|};
git_commit "second commit");

(* add library *)
write "dune"
{|
(executable
(name aaaa)
(libraries unix))

(library
(name liblib))
|};
git_commit "third commit";
git_branch "branch2";

git_checkout "branch1";
[%expect {| Switched to branch 'branch1' |}];
(* change name to b, reformat *)
write "dune" {|
(executable
(name bbbb)
(libraries unix))
|};
git_commit "second commit (fork)";

write "dune"
{|
(alias
(name runtest)
(action
(diff rebase.diff rebase.diff.gen)))

(executable
(name bbbb)
(libraries unix))
|};
git_commit "third commit (fork)";
git_branch "old_branch1";

system "git rebase branch2 -q";
[%expect {| |}];
system "%s" merge_fmt;
print_file "dune";
[%expect
{|
Nothing to resolve
Exit with 1
File dune
(alias
(name runtest)
(action
(diff rebase.diff rebase.diff.gen)))

(executable
(name bbbb)
(libraries unix))

(library
(name liblib)) |}])
11 changes: 6 additions & 5 deletions test/rebase.diff
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,20 @@
---
> }
> >>>>>>> 6070a8f (second commit (fork)) |}];
59,62c69
59,62c69,70
< [%expect
< {|
< Ignore a.ml (not a 3-way merge)
< Exit with 1 |}];
---
> [%expect {| Resolved 1/1 b.ml |}];
66,67c73
> [%expect {|
> Resolved 1/1 b.ml |}];
66,67c74
< DU File a.ml
<
---
> M File b.ml
69,71c75,78
69,71c76,79
< { a : int option;
< b : string;
< c : float;
Expand All @@ -49,7 +50,7 @@
> ; b : string
> ; c : float
> ; d : unit option
76,79c83,84
76,79c84,85
< a.ml: needs merge
< You must edit all merge conflicts and then
< mark them as resolved using git add
Expand Down
3 changes: 2 additions & 1 deletion test/rebase_b.ml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ type t =
}
>>>>>>> 6070a8f (second commit (fork)) |}];
resolve ();
[%expect {| Resolved 1/1 b.ml |}];
[%expect {|
Resolved 1/1 b.ml |}];
print_status ();
[%expect
{|
Expand Down
3 changes: 2 additions & 1 deletion test/resolve1.ml
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,8 @@ type t =
| A
| B of int |}];
resolve ();
[%expect {| Resolved 1/1 b.ml |}];
[%expect {|
Resolved 1/1 b.ml |}];
print_status ();
[%expect
{|
Expand Down
3 changes: 2 additions & 1 deletion test/resolve2.ml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ type t =
}
>>>>>>> ead71ee (second commit (fork)):a.ml |}];
resolve ();
[%expect {| Resolved 1/1 b.ml |}];
[%expect {|
Resolved 1/1 b.ml |}];
print_status ();
[%expect
{|
Expand Down