1// Package diff implements line oriented diffs, similar to the ancient
2// Unix diff command.
3//
4// The current implementation is just a wrapper around Sergi's
5// go-diff/diffmatchpatch library, which is a go port of Neil
6// Fraser's google-diff-match-patch code
7package diff
8
9import (
10 "bytes"
11 "time"
12
13 "github.com/sergi/go-diff/diffmatchpatch"
14)
15
16// Do computes the (line oriented) modifications needed to turn the src
17// string into the dst string. The underlying algorithm is Meyers,
18// its complexity is O(N*d) where N is min(lines(src), lines(dst)) and d
19// is the size of the diff.
20func Do(src, dst string) (diffs []diffmatchpatch.Diff) {
21 // the default timeout is time.Second which may be too small under heavy load
22 return DoWithTimeout(src, dst, time.Hour)
23}
24
25// DoWithTimeout computes the (line oriented) modifications needed to turn the src
26// string into the dst string. The `timeout` argument specifies the maximum
27// amount of time it is allowed to spend in this function. If the timeout
28// is exceeded, the parts of the strings which were not considered are turned into
29// a bulk delete+insert and the half-baked suboptimal result is returned at once.
30// The underlying algorithm is Meyers, its complexity is O(N*d) where N is
31// min(lines(src), lines(dst)) and d is the size of the diff.
32func DoWithTimeout(src, dst string, timeout time.Duration) (diffs []diffmatchpatch.Diff) {
33 dmp := diffmatchpatch.New()
34 dmp.DiffTimeout = timeout
35 wSrc, wDst, warray := dmp.DiffLinesToRunes(src, dst)
36 diffs = dmp.DiffMainRunes(wSrc, wDst, false)
37 diffs = dmp.DiffCharsToLines(diffs, warray)
38 return diffs
39}
40
41// Dst computes and returns the destination text.
42func Dst(diffs []diffmatchpatch.Diff) string {
43 var text bytes.Buffer
44 for _, d := range diffs {
45 if d.Type != diffmatchpatch.DiffDelete {
46 text.WriteString(d.Text)
47 }
48 }
49 return text.String()
50}
51
52// Src computes and returns the source text
53func Src(diffs []diffmatchpatch.Diff) string {
54 var text bytes.Buffer
55 for _, d := range diffs {
56 if d.Type != diffmatchpatch.DiffInsert {
57 text.WriteString(d.Text)
58 }
59 }
60 return text.String()
61}