3-way merge with Myers diff
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

ocaml-linkedin: apply dune fmt

Pure formatting changes from `dune fmt`: doc comment placement moves
from above the binding to below it for `type`s, multi-line `match`
expressions collapse onto one line where they fit, and infix operator
applications pick up spaces (`Soup.($?)` -> `Soup.( $? )`). No
semantic changes.

+104 -1
+96
README.md
··· 1 + # merge3 2 + 3 + Myers diff and diff3 three-way merge for OCaml. 4 + 5 + `merge3` implements [Myers][myers]' O(ND) line-level diff and the 6 + [diff3][khanna] three-way merge with git-compatible conflict 7 + markers. It also exposes Irmin-style merge combinators (`pair`, 8 + `option`, `alist`) for composing merges on structured types. 9 + 10 + [myers]: https://www.cs.dartmouth.edu/~doug/diff.pdf 11 + [khanna]: https://www.cis.upenn.edu/~bcpierce/papers/diff3-short.pdf 12 + 13 + ## Installation 14 + 15 + Install with opam: 16 + 17 + <!-- $MDX skip --> 18 + ```sh 19 + $ opam install merge3 20 + ``` 21 + 22 + If opam cannot find the package, it may not yet be released in the 23 + public `opam-repository`. Add the overlay repository, then install 24 + it: 25 + 26 + <!-- $MDX skip --> 27 + ```sh 28 + $ opam repo add samoht https://tangled.org/gazagnaire.org/opam-overlay.git 29 + $ opam update 30 + $ opam install merge3 31 + ``` 32 + 33 + ## Usage 34 + 35 + ### Line-level diff 36 + 37 + `Merge3.diff` returns a shortest edit script that transforms one 38 + array of lines into another: 39 + 40 + ```ocaml 41 + # let a = [| "one"; "two"; "three" |] 42 + and b = [| "one"; "TWO"; "three" |] in 43 + Merge3.diff ~eq:String.equal a b 44 + - : string Merge3.edit list = 45 + [Merge3.Keep "one"; Merge3.Delete "two"; Merge3.Insert "TWO"; 46 + Merge3.Keep "three"] 47 + ``` 48 + 49 + ### Three-way merge 50 + 51 + `Merge3.merge` performs diff3 against a common ancestor. Clean 52 + regions are returned as `Resolved`; overlapping edits as `Conflict`. 53 + When both sides change the same line region differently, rendering 54 + the merge produces git-style markers: 55 + 56 + ```ocaml 57 + # let base = "a\nb\nc\n" 58 + and ours = "a\nB1\nc\n" 59 + and theirs = "a\nB2\nc\n" in 60 + print_string (Merge3.to_string (Merge3.merge ~base ~ours ~theirs ())) 61 + a 62 + <<<<<<< ours 63 + B1 64 + ======= 65 + B2 66 + >>>>>>> theirs 67 + c 68 + - : unit = () 69 + ``` 70 + 71 + `Merge3.has_conflicts` inspects a merge result without formatting it: 72 + 73 + ```ocaml 74 + # let chunks = 75 + Merge3.merge ~base:"a\nb\nc\n" 76 + ~ours:"a\nb\nc\n" 77 + ~theirs:"a\nb\nC\n" () in 78 + Merge3.has_conflicts chunks 79 + - : bool = false 80 + ``` 81 + 82 + ### Merge combinators 83 + 84 + Compose merge functions on structured types using Irmin-style 85 + combinators: 86 + 87 + ```ocaml 88 + # let merge_int = Merge3.default ~eq:Int.equal in 89 + let merge_pair = Merge3.pair merge_int (Merge3.option merge_int) in 90 + merge_pair ~old:(Some (1, None)) (1, Some 2) (1, Some 2) 91 + - : (int * int option) Merge3.result = Merge3.Ok (1, Some 2) 92 + ``` 93 + 94 + ## Licence 95 + 96 + ISC
+4
dune
··· 1 1 (env 2 2 (dev 3 3 (flags :standard %{dune-warnings}))) 4 + 5 + (mdx 6 + (files README.md) 7 + (libraries merge3))
+3 -1
dune-project
··· 1 1 (lang dune 3.21) 2 + (using mdx 0.4) 2 3 (name merge3) 3 4 (formatting (enabled_for ocaml)) 4 5 ··· 21 22 - Irmin-style composable merge combinators for custom datatypes") 22 23 (depends 23 24 (ocaml (>= 5.1.0)) 24 - (alcotest (and :with-test (>= 1.7.0))))) 25 + (alcotest (and :with-test (>= 1.7.0))) 26 + (mdx :with-test)))
+1
merge3.opam
··· 18 18 "dune" {>= "3.21"} 19 19 "ocaml" {>= "5.1.0"} 20 20 "alcotest" {with-test & >= "1.7.0"} 21 + "mdx" {with-test} 21 22 "odoc" {with-doc} 22 23 ] 23 24 build: [