aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/sergi/go-diff
diff options
context:
space:
mode:
authorLauris BH <lauris@nix.lv>2020-03-17 18:19:58 +0200
committerGitHub <noreply@github.com>2020-03-17 12:19:58 -0400
commit43c09134a972dc421aa06fb303697671c828cf67 (patch)
tree6bf8da5bc0a23ce516cd5598ec982b6715fb6716 /vendor/github.com/sergi/go-diff
parent2f928316dbc2bb71137e857d97039d4f51f7d405 (diff)
downloadgitea-43c09134a972dc421aa06fb303697671c828cf67.tar.gz
gitea-43c09134a972dc421aa06fb303697671c828cf67.zip
Migrate to go-git/go-git v5.0.0 (#10735)
Diffstat (limited to 'vendor/github.com/sergi/go-diff')
-rw-r--r--vendor/github.com/sergi/go-diff/diffmatchpatch/diff.go141
-rw-r--r--vendor/github.com/sergi/go-diff/diffmatchpatch/operation_string.go17
2 files changed, 88 insertions, 70 deletions
diff --git a/vendor/github.com/sergi/go-diff/diffmatchpatch/diff.go b/vendor/github.com/sergi/go-diff/diffmatchpatch/diff.go
index 82ad7bc8f1..cb25b43757 100644
--- a/vendor/github.com/sergi/go-diff/diffmatchpatch/diff.go
+++ b/vendor/github.com/sergi/go-diff/diffmatchpatch/diff.go
@@ -25,6 +25,8 @@ import (
// Operation defines the operation of a diff item.
type Operation int8
+//go:generate stringer -type=Operation -trimprefix=Diff
+
const (
// DiffDelete item represents a delete diff.
DiffDelete Operation = -1
@@ -40,8 +42,41 @@ type Diff struct {
Text string
}
+// splice removes amount elements from slice at index index, replacing them with elements.
func splice(slice []Diff, index int, amount int, elements ...Diff) []Diff {
- return append(slice[:index], append(elements, slice[index+amount:]...)...)
+ if len(elements) == amount {
+ // Easy case: overwrite the relevant items.
+ copy(slice[index:], elements)
+ return slice
+ }
+ if len(elements) < amount {
+ // Fewer new items than old.
+ // Copy in the new items.
+ copy(slice[index:], elements)
+ // Shift the remaining items left.
+ copy(slice[index+len(elements):], slice[index+amount:])
+ // Calculate the new end of the slice.
+ end := len(slice) - amount + len(elements)
+ // Zero stranded elements at end so that they can be garbage collected.
+ tail := slice[end:]
+ for i := range tail {
+ tail[i] = Diff{}
+ }
+ return slice[:end]
+ }
+ // More new items than old.
+ // Make room in slice for new elements.
+ // There's probably an even more efficient way to do this,
+ // but this is simple and clear.
+ need := len(slice) - amount + len(elements)
+ for len(slice) < need {
+ slice = append(slice, Diff{})
+ }
+ // Shift slice elements right to make room for new elements.
+ copy(slice[index+len(elements):], slice[index+amount:])
+ // Copy in new elements.
+ copy(slice[index:], elements)
+ return slice
}
// DiffMain finds the differences between two texts.
@@ -145,7 +180,10 @@ func (dmp *DiffMatchPatch) diffCompute(text1, text2 []rune, checklines bool, dea
diffsA := dmp.diffMainRunes(text1A, text2A, checklines, deadline)
diffsB := dmp.diffMainRunes(text1B, text2B, checklines, deadline)
// Merge the results.
- return append(diffsA, append([]Diff{Diff{DiffEqual, string(midCommon)}}, diffsB...)...)
+ diffs := diffsA
+ diffs = append(diffs, Diff{DiffEqual, string(midCommon)})
+ diffs = append(diffs, diffsB...)
+ return diffs
} else if checklines && len(text1) > 100 && len(text2) > 100 {
return dmp.diffLineMode(text1, text2, deadline)
}
@@ -247,7 +285,7 @@ func (dmp *DiffMatchPatch) diffBisect(runes1, runes2 []rune, deadline time.Time)
k2end := 0
for d := 0; d < maxD; d++ {
// Bail out if deadline is reached.
- if !deadline.IsZero() && time.Now().After(deadline) {
+ if !deadline.IsZero() && d%16 == 0 && time.Now().After(deadline) {
break
}
@@ -434,48 +472,29 @@ func (dmp *DiffMatchPatch) DiffCommonSuffix(text1, text2 string) int {
// commonPrefixLength returns the length of the common prefix of two rune slices.
func commonPrefixLength(text1, text2 []rune) int {
- short, long := text1, text2
- if len(short) > len(long) {
- short, long = long, short
- }
- for i, r := range short {
- if r != long[i] {
- return i
+ // Linear search. See comment in commonSuffixLength.
+ n := 0
+ for ; n < len(text1) && n < len(text2); n++ {
+ if text1[n] != text2[n] {
+ return n
}
}
- return len(short)
+ return n
}
// commonSuffixLength returns the length of the common suffix of two rune slices.
func commonSuffixLength(text1, text2 []rune) int {
- n := min(len(text1), len(text2))
- for i := 0; i < n; i++ {
- if text1[len(text1)-i-1] != text2[len(text2)-i-1] {
- return i
+ // Use linear search rather than the binary search discussed at https://neil.fraser.name/news/2007/10/09/.
+ // See discussion at https://github.com/sergi/go-diff/issues/54.
+ i1 := len(text1)
+ i2 := len(text2)
+ for n := 0; ; n++ {
+ i1--
+ i2--
+ if i1 < 0 || i2 < 0 || text1[i1] != text2[i2] {
+ return n
}
}
- return n
-
- // TODO research and benchmark this, why is it not activated? https://github.com/sergi/go-diff/issues/54
- // Binary search.
- // Performance analysis: http://neil.fraser.name/news/2007/10/09/
- /*
- pointermin := 0
- pointermax := math.Min(len(text1), len(text2))
- pointermid := pointermax
- pointerend := 0
- for pointermin < pointermid {
- if text1[len(text1)-pointermid:len(text1)-pointerend] ==
- text2[len(text2)-pointermid:len(text2)-pointerend] {
- pointermin = pointermid
- pointerend = pointermin
- } else {
- pointermax = pointermid
- }
- pointermid = math.Floor((pointermax-pointermin)/2 + pointermin)
- }
- return pointermid
- */
}
// DiffCommonOverlap determines if the suffix of one string is the prefix of another.
@@ -628,11 +647,7 @@ func (dmp *DiffMatchPatch) diffHalfMatchI(l, s []rune, i int) [][]rune {
func (dmp *DiffMatchPatch) DiffCleanupSemantic(diffs []Diff) []Diff {
changes := false
// Stack of indices where equalities are found.
- type equality struct {
- data int
- next *equality
- }
- var equalities *equality
+ equalities := make([]int, 0, len(diffs))
var lastequality string
// Always equal to diffs[equalities[equalitiesLength - 1]][1]
@@ -645,11 +660,7 @@ func (dmp *DiffMatchPatch) DiffCleanupSemantic(diffs []Diff) []Diff {
for pointer < len(diffs) {
if diffs[pointer].Type == DiffEqual {
// Equality found.
-
- equalities = &equality{
- data: pointer,
- next: equalities,
- }
+ equalities = append(equalities, pointer)
lengthInsertions1 = lengthInsertions2
lengthDeletions1 = lengthDeletions2
lengthInsertions2 = 0
@@ -670,23 +681,20 @@ func (dmp *DiffMatchPatch) DiffCleanupSemantic(diffs []Diff) []Diff {
(len(lastequality) <= difference1) &&
(len(lastequality) <= difference2) {
// Duplicate record.
- insPoint := equalities.data
- diffs = append(
- diffs[:insPoint],
- append([]Diff{Diff{DiffDelete, lastequality}}, diffs[insPoint:]...)...)
+ insPoint := equalities[len(equalities)-1]
+ diffs = splice(diffs, insPoint, 0, Diff{DiffDelete, lastequality})
// Change second copy to insert.
diffs[insPoint+1].Type = DiffInsert
// Throw away the equality we just deleted.
- equalities = equalities.next
+ equalities = equalities[:len(equalities)-1]
- if equalities != nil {
- equalities = equalities.next
+ if len(equalities) > 0 {
+ equalities = equalities[:len(equalities)-1]
}
- if equalities != nil {
- pointer = equalities.data
- } else {
- pointer = -1
+ pointer = -1
+ if len(equalities) > 0 {
+ pointer = equalities[len(equalities)-1]
}
lengthInsertions1 = 0 // Reset the counters.
@@ -724,10 +732,7 @@ func (dmp *DiffMatchPatch) DiffCleanupSemantic(diffs []Diff) []Diff {
float64(overlapLength1) >= float64(len(insertion))/2 {
// Overlap found. Insert an equality and trim the surrounding edits.
- diffs = append(
- diffs[:pointer],
- append([]Diff{Diff{DiffEqual, insertion[:overlapLength1]}}, diffs[pointer:]...)...)
-
+ diffs = splice(diffs, pointer, 0, Diff{DiffEqual, insertion[:overlapLength1]})
diffs[pointer-1].Text =
deletion[0 : len(deletion)-overlapLength1]
diffs[pointer+1].Text = insertion[overlapLength1:]
@@ -738,10 +743,7 @@ func (dmp *DiffMatchPatch) DiffCleanupSemantic(diffs []Diff) []Diff {
float64(overlapLength2) >= float64(len(insertion))/2 {
// Reverse overlap found. Insert an equality and swap and trim the surrounding edits.
overlap := Diff{DiffEqual, deletion[:overlapLength2]}
- diffs = append(
- diffs[:pointer],
- append([]Diff{overlap}, diffs[pointer:]...)...)
-
+ diffs = splice(diffs, pointer, 0, overlap)
diffs[pointer-1].Type = DiffInsert
diffs[pointer-1].Text = insertion[0 : len(insertion)-overlapLength2]
diffs[pointer+1].Type = DiffDelete
@@ -954,8 +956,7 @@ func (dmp *DiffMatchPatch) DiffCleanupEfficiency(diffs []Diff) []Diff {
insPoint := equalities.data
// Duplicate record.
- diffs = append(diffs[:insPoint],
- append([]Diff{Diff{DiffDelete, lastequality}}, diffs[insPoint:]...)...)
+ diffs = splice(diffs, insPoint, 0, Diff{DiffDelete, lastequality})
// Change second copy to insert.
diffs[insPoint+1].Type = DiffInsert
@@ -1235,9 +1236,9 @@ func (dmp *DiffMatchPatch) DiffLevenshtein(diffs []Diff) int {
for _, aDiff := range diffs {
switch aDiff.Type {
case DiffInsert:
- insertions += len(aDiff.Text)
+ insertions += utf8.RuneCountInString(aDiff.Text)
case DiffDelete:
- deletions += len(aDiff.Text)
+ deletions += utf8.RuneCountInString(aDiff.Text)
case DiffEqual:
// A deletion and an insertion is one substitution.
levenshtein += max(insertions, deletions)
diff --git a/vendor/github.com/sergi/go-diff/diffmatchpatch/operation_string.go b/vendor/github.com/sergi/go-diff/diffmatchpatch/operation_string.go
new file mode 100644
index 0000000000..533ec0da7b
--- /dev/null
+++ b/vendor/github.com/sergi/go-diff/diffmatchpatch/operation_string.go
@@ -0,0 +1,17 @@
+// Code generated by "stringer -type=Operation -trimprefix=Diff"; DO NOT EDIT.
+
+package diffmatchpatch
+
+import "fmt"
+
+const _Operation_name = "DeleteEqualInsert"
+
+var _Operation_index = [...]uint8{0, 6, 11, 17}
+
+func (i Operation) String() string {
+ i -= -1
+ if i < 0 || i >= Operation(len(_Operation_index)-1) {
+ return fmt.Sprintf("Operation(%d)", i+-1)
+ }
+ return _Operation_name[_Operation_index[i]:_Operation_index[i+1]]
+}