104 lines
2.1 KiB
Go
104 lines
2.1 KiB
Go
package testhelper
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
"math"
|
|
"strings"
|
|
|
|
"github.com/aryann/difflib"
|
|
)
|
|
|
|
func Diff(want, got string, context int) (string, bool) {
|
|
records := difflib.Diff(
|
|
strings.Split(want, "\n"),
|
|
strings.Split(got, "\n"),
|
|
)
|
|
|
|
w := &bytes.Buffer{}
|
|
|
|
changed := checkAndPrintRecords(w, records, context)
|
|
|
|
return w.String(), changed
|
|
}
|
|
|
|
func checkAndPrintRecords(w io.Writer, records []difflib.DiffRecord, context int) bool {
|
|
var changed bool
|
|
if context >= 0 {
|
|
distances := calculateDistances(records)
|
|
omitting := false
|
|
for i, diff := range records {
|
|
if diff.Delta != difflib.Common {
|
|
changed = true
|
|
}
|
|
if distances[i] > context {
|
|
if !omitting {
|
|
fmt.Fprintln(w, "...")
|
|
omitting = true
|
|
}
|
|
} else {
|
|
omitting = false
|
|
fmt.Fprintln(w, formatRecord(diff))
|
|
}
|
|
}
|
|
} else {
|
|
for _, diff := range records {
|
|
if diff.Delta != difflib.Common {
|
|
changed = true
|
|
}
|
|
fmt.Fprintln(w, formatRecord(diff))
|
|
}
|
|
}
|
|
return changed
|
|
}
|
|
|
|
func formatRecord(diff difflib.DiffRecord) string {
|
|
var prefix string
|
|
switch diff.Delta {
|
|
case difflib.RightOnly:
|
|
prefix = "+ "
|
|
case difflib.LeftOnly:
|
|
prefix = "- "
|
|
case difflib.Common:
|
|
prefix = " "
|
|
}
|
|
|
|
return prefix + diff.Payload
|
|
}
|
|
|
|
// Shamelessly and thankfully copied from https://github.com/databus23/helm-diff/blob/99b8474af7726ca6f57b37b0b8b8f3cd36c991e8/diff/diff.go#L116
|
|
func calculateDistances(diffs []difflib.DiffRecord) map[int]int {
|
|
distances := map[int]int{}
|
|
|
|
// Iterate forwards through diffs, set 'distance' based on closest 'change' before this line
|
|
change := -1
|
|
for i, diff := range diffs {
|
|
if diff.Delta != difflib.Common {
|
|
change = i
|
|
}
|
|
distance := math.MaxInt32
|
|
if change != -1 {
|
|
distance = i - change
|
|
}
|
|
distances[i] = distance
|
|
}
|
|
|
|
// Iterate backwards through diffs, reduce 'distance' based on closest 'change' after this line
|
|
change = -1
|
|
for i := len(diffs) - 1; i >= 0; i-- {
|
|
diff := diffs[i]
|
|
if diff.Delta != difflib.Common {
|
|
change = i
|
|
}
|
|
if change != -1 {
|
|
distance := change - i
|
|
if distance < distances[i] {
|
|
distances[i] = distance
|
|
}
|
|
}
|
|
}
|
|
|
|
return distances
|
|
}
|