mirror of
https://github.com/jesseduffield/lazygit.git
synced 2024-12-12 11:15:00 +02:00
617 lines
11 KiB
Go
617 lines
11 KiB
Go
package patch
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
const simpleDiff = `diff --git a/filename b/filename
|
|
index dcd3485..1ba5540 100644
|
|
--- a/filename
|
|
+++ b/filename
|
|
@@ -1,5 +1,5 @@
|
|
apple
|
|
-orange
|
|
+grape
|
|
...
|
|
...
|
|
...
|
|
`
|
|
|
|
const addNewlineToEndOfFile = `diff --git a/filename b/filename
|
|
index 80a73f1..e48a11c 100644
|
|
--- a/filename
|
|
+++ b/filename
|
|
@@ -60,4 +60,4 @@ grape
|
|
...
|
|
...
|
|
...
|
|
-last line
|
|
\ No newline at end of file
|
|
+last line
|
|
`
|
|
|
|
const removeNewlinefromEndOfFile = `diff --git a/filename b/filename
|
|
index e48a11c..80a73f1 100644
|
|
--- a/filename
|
|
+++ b/filename
|
|
@@ -60,4 +60,4 @@ grape
|
|
...
|
|
...
|
|
...
|
|
-last line
|
|
+last line
|
|
\ No newline at end of file
|
|
`
|
|
|
|
const twoHunks = `diff --git a/filename b/filename
|
|
index e48a11c..b2ab81b 100644
|
|
--- a/filename
|
|
+++ b/filename
|
|
@@ -1,5 +1,5 @@
|
|
apple
|
|
-grape
|
|
+orange
|
|
...
|
|
...
|
|
...
|
|
@@ -8,6 +8,8 @@ grape
|
|
...
|
|
...
|
|
...
|
|
+pear
|
|
+lemon
|
|
...
|
|
...
|
|
...
|
|
`
|
|
|
|
const twoChangesInOneHunk = `diff --git a/filename b/filename
|
|
index 9320895..6d79956 100644
|
|
--- a/filename
|
|
+++ b/filename
|
|
@@ -1,5 +1,5 @@
|
|
apple
|
|
-grape
|
|
+kiwi
|
|
orange
|
|
-pear
|
|
+banana
|
|
lemon
|
|
`
|
|
|
|
const newFile = `diff --git a/newfile b/newfile
|
|
new file mode 100644
|
|
index 0000000..4e680cc
|
|
--- /dev/null
|
|
+++ b/newfile
|
|
@@ -0,0 +1,3 @@
|
|
+apple
|
|
+orange
|
|
+grape
|
|
`
|
|
|
|
const addNewlineToPreviouslyEmptyFile = `diff --git a/newfile b/newfile
|
|
index e69de29..c6568ea 100644
|
|
--- a/newfile
|
|
+++ b/newfile
|
|
@@ -0,0 +1 @@
|
|
+new line
|
|
\ No newline at end of file
|
|
`
|
|
|
|
const exampleHunk = `@@ -1,5 +1,5 @@
|
|
apple
|
|
-grape
|
|
+orange
|
|
...
|
|
...
|
|
...
|
|
`
|
|
|
|
func TestTransform(t *testing.T) {
|
|
type scenario struct {
|
|
testName string
|
|
filename string
|
|
diffText string
|
|
firstLineIndex int
|
|
lastLineIndex int
|
|
reverse bool
|
|
expected string
|
|
}
|
|
|
|
scenarios := []scenario{
|
|
{
|
|
testName: "nothing selected",
|
|
filename: "filename",
|
|
firstLineIndex: -1,
|
|
lastLineIndex: -1,
|
|
diffText: simpleDiff,
|
|
expected: "",
|
|
},
|
|
{
|
|
testName: "only context selected",
|
|
filename: "filename",
|
|
firstLineIndex: 5,
|
|
lastLineIndex: 5,
|
|
diffText: simpleDiff,
|
|
expected: "",
|
|
},
|
|
{
|
|
testName: "whole range selected",
|
|
filename: "filename",
|
|
firstLineIndex: 0,
|
|
lastLineIndex: 11,
|
|
diffText: simpleDiff,
|
|
expected: `--- a/filename
|
|
+++ b/filename
|
|
@@ -1,5 +1,5 @@
|
|
apple
|
|
-orange
|
|
+grape
|
|
...
|
|
...
|
|
...
|
|
`,
|
|
},
|
|
{
|
|
testName: "only removal selected",
|
|
filename: "filename",
|
|
firstLineIndex: 6,
|
|
lastLineIndex: 6,
|
|
diffText: simpleDiff,
|
|
expected: `--- a/filename
|
|
+++ b/filename
|
|
@@ -1,5 +1,4 @@
|
|
apple
|
|
-orange
|
|
...
|
|
...
|
|
...
|
|
`,
|
|
},
|
|
{
|
|
testName: "only addition selected",
|
|
filename: "filename",
|
|
firstLineIndex: 7,
|
|
lastLineIndex: 7,
|
|
diffText: simpleDiff,
|
|
expected: `--- a/filename
|
|
+++ b/filename
|
|
@@ -1,5 +1,6 @@
|
|
apple
|
|
orange
|
|
+grape
|
|
...
|
|
...
|
|
...
|
|
`,
|
|
},
|
|
{
|
|
testName: "range that extends beyond diff bounds",
|
|
filename: "filename",
|
|
firstLineIndex: -100,
|
|
lastLineIndex: 100,
|
|
diffText: simpleDiff,
|
|
expected: `--- a/filename
|
|
+++ b/filename
|
|
@@ -1,5 +1,5 @@
|
|
apple
|
|
-orange
|
|
+grape
|
|
...
|
|
...
|
|
...
|
|
`,
|
|
},
|
|
{
|
|
testName: "add newline to end of file",
|
|
filename: "filename",
|
|
firstLineIndex: -100,
|
|
lastLineIndex: 100,
|
|
diffText: addNewlineToEndOfFile,
|
|
expected: `--- a/filename
|
|
+++ b/filename
|
|
@@ -60,4 +60,4 @@ grape
|
|
...
|
|
...
|
|
...
|
|
-last line
|
|
\ No newline at end of file
|
|
+last line
|
|
`,
|
|
},
|
|
{
|
|
testName: "add newline to end of file, reversed",
|
|
filename: "filename",
|
|
firstLineIndex: -100,
|
|
lastLineIndex: 100,
|
|
reverse: true,
|
|
diffText: addNewlineToEndOfFile,
|
|
expected: `--- a/filename
|
|
+++ b/filename
|
|
@@ -60,4 +60,4 @@ grape
|
|
...
|
|
...
|
|
...
|
|
-last line
|
|
\ No newline at end of file
|
|
+last line
|
|
`,
|
|
},
|
|
{
|
|
testName: "remove newline from end of file",
|
|
filename: "filename",
|
|
firstLineIndex: -100,
|
|
lastLineIndex: 100,
|
|
diffText: removeNewlinefromEndOfFile,
|
|
expected: `--- a/filename
|
|
+++ b/filename
|
|
@@ -60,4 +60,4 @@ grape
|
|
...
|
|
...
|
|
...
|
|
-last line
|
|
+last line
|
|
\ No newline at end of file
|
|
`,
|
|
},
|
|
{
|
|
testName: "remove newline from end of file, reversed",
|
|
filename: "filename",
|
|
firstLineIndex: -100,
|
|
lastLineIndex: 100,
|
|
reverse: true,
|
|
diffText: removeNewlinefromEndOfFile,
|
|
expected: `--- a/filename
|
|
+++ b/filename
|
|
@@ -60,4 +60,4 @@ grape
|
|
...
|
|
...
|
|
...
|
|
-last line
|
|
+last line
|
|
\ No newline at end of file
|
|
`,
|
|
},
|
|
{
|
|
testName: "remove newline from end of file, removal only",
|
|
filename: "filename",
|
|
firstLineIndex: 8,
|
|
lastLineIndex: 8,
|
|
diffText: removeNewlinefromEndOfFile,
|
|
expected: `--- a/filename
|
|
+++ b/filename
|
|
@@ -60,4 +60,3 @@ grape
|
|
...
|
|
...
|
|
...
|
|
-last line
|
|
`,
|
|
},
|
|
{
|
|
testName: "remove newline from end of file, removal only, reversed",
|
|
filename: "filename",
|
|
firstLineIndex: 8,
|
|
lastLineIndex: 8,
|
|
reverse: true,
|
|
diffText: removeNewlinefromEndOfFile,
|
|
expected: `--- a/filename
|
|
+++ b/filename
|
|
@@ -60,5 +60,4 @@ grape
|
|
...
|
|
...
|
|
...
|
|
-last line
|
|
last line
|
|
\ No newline at end of file
|
|
`,
|
|
},
|
|
{
|
|
testName: "remove newline from end of file, addition only",
|
|
filename: "filename",
|
|
firstLineIndex: 9,
|
|
lastLineIndex: 9,
|
|
diffText: removeNewlinefromEndOfFile,
|
|
expected: `--- a/filename
|
|
+++ b/filename
|
|
@@ -60,4 +60,5 @@ grape
|
|
...
|
|
...
|
|
...
|
|
last line
|
|
+last line
|
|
\ No newline at end of file
|
|
`,
|
|
},
|
|
{
|
|
testName: "remove newline from end of file, addition only, reversed",
|
|
filename: "filename",
|
|
firstLineIndex: 9,
|
|
lastLineIndex: 9,
|
|
reverse: true,
|
|
diffText: removeNewlinefromEndOfFile,
|
|
expected: `--- a/filename
|
|
+++ b/filename
|
|
@@ -60,3 +60,4 @@ grape
|
|
...
|
|
...
|
|
...
|
|
+last line
|
|
\ No newline at end of file
|
|
`,
|
|
},
|
|
{
|
|
testName: "staging two whole hunks",
|
|
filename: "filename",
|
|
firstLineIndex: -100,
|
|
lastLineIndex: 100,
|
|
diffText: twoHunks,
|
|
expected: `--- a/filename
|
|
+++ b/filename
|
|
@@ -1,5 +1,5 @@
|
|
apple
|
|
-grape
|
|
+orange
|
|
...
|
|
...
|
|
...
|
|
@@ -8,6 +8,8 @@ grape
|
|
...
|
|
...
|
|
...
|
|
+pear
|
|
+lemon
|
|
...
|
|
...
|
|
...
|
|
`,
|
|
},
|
|
{
|
|
testName: "staging part of both hunks",
|
|
filename: "filename",
|
|
firstLineIndex: 7,
|
|
lastLineIndex: 15,
|
|
diffText: twoHunks,
|
|
expected: `--- a/filename
|
|
+++ b/filename
|
|
@@ -1,5 +1,6 @@
|
|
apple
|
|
grape
|
|
+orange
|
|
...
|
|
...
|
|
...
|
|
@@ -8,6 +9,7 @@ grape
|
|
...
|
|
...
|
|
...
|
|
+pear
|
|
...
|
|
...
|
|
...
|
|
`,
|
|
},
|
|
{
|
|
testName: "adding a new file",
|
|
filename: "newfile",
|
|
firstLineIndex: -100,
|
|
lastLineIndex: 100,
|
|
diffText: newFile,
|
|
expected: `--- a/newfile
|
|
+++ b/newfile
|
|
@@ -0,0 +1,3 @@
|
|
+apple
|
|
+orange
|
|
+grape
|
|
`,
|
|
},
|
|
{
|
|
testName: "adding part of a new file",
|
|
filename: "newfile",
|
|
firstLineIndex: 6,
|
|
lastLineIndex: 7,
|
|
diffText: newFile,
|
|
expected: `--- a/newfile
|
|
+++ b/newfile
|
|
@@ -0,0 +1,2 @@
|
|
+apple
|
|
+orange
|
|
`,
|
|
},
|
|
{
|
|
testName: "adding a new line to a previously empty file",
|
|
filename: "newfile",
|
|
firstLineIndex: -100,
|
|
lastLineIndex: 100,
|
|
diffText: addNewlineToPreviouslyEmptyFile,
|
|
expected: `--- a/newfile
|
|
+++ b/newfile
|
|
@@ -0,0 +1 @@
|
|
+new line
|
|
\ No newline at end of file
|
|
`,
|
|
},
|
|
{
|
|
testName: "adding a new line to a previously empty file, reversed",
|
|
filename: "newfile",
|
|
firstLineIndex: -100,
|
|
lastLineIndex: 100,
|
|
diffText: addNewlineToPreviouslyEmptyFile,
|
|
reverse: true,
|
|
expected: `--- a/newfile
|
|
+++ b/newfile
|
|
@@ -0,0 +1 @@
|
|
+new line
|
|
\ No newline at end of file
|
|
`,
|
|
},
|
|
{
|
|
testName: "adding part of a hunk",
|
|
filename: "filename",
|
|
firstLineIndex: 6,
|
|
lastLineIndex: 7,
|
|
reverse: false,
|
|
diffText: twoChangesInOneHunk,
|
|
expected: `--- a/filename
|
|
+++ b/filename
|
|
@@ -1,5 +1,5 @@
|
|
apple
|
|
-grape
|
|
+kiwi
|
|
orange
|
|
pear
|
|
lemon
|
|
`,
|
|
},
|
|
{
|
|
testName: "adding part of a hunk, reverse",
|
|
filename: "filename",
|
|
firstLineIndex: 6,
|
|
lastLineIndex: 7,
|
|
reverse: true,
|
|
diffText: twoChangesInOneHunk,
|
|
expected: `--- a/filename
|
|
+++ b/filename
|
|
@@ -1,5 +1,5 @@
|
|
apple
|
|
-grape
|
|
+kiwi
|
|
orange
|
|
banana
|
|
lemon
|
|
`,
|
|
},
|
|
}
|
|
|
|
for _, s := range scenarios {
|
|
s := s
|
|
t.Run(s.testName, func(t *testing.T) {
|
|
lineIndices := ExpandRange(s.firstLineIndex, s.lastLineIndex)
|
|
|
|
result := Parse(s.diffText).
|
|
Transform(TransformOpts{
|
|
Reverse: s.reverse,
|
|
FileNameOverride: s.filename,
|
|
IncludedLineIndices: lineIndices,
|
|
}).
|
|
FormatPlain()
|
|
|
|
assert.Equal(t, s.expected, result)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParseAndFormatPlain(t *testing.T) {
|
|
scenarios := []struct {
|
|
testName string
|
|
patchStr string
|
|
}{
|
|
{
|
|
testName: "simpleDiff",
|
|
patchStr: simpleDiff,
|
|
},
|
|
{
|
|
testName: "addNewlineToEndOfFile",
|
|
patchStr: addNewlineToEndOfFile,
|
|
},
|
|
{
|
|
testName: "removeNewlinefromEndOfFile",
|
|
patchStr: removeNewlinefromEndOfFile,
|
|
},
|
|
{
|
|
testName: "twoHunks",
|
|
patchStr: twoHunks,
|
|
},
|
|
{
|
|
testName: "twoChangesInOneHunk",
|
|
patchStr: twoChangesInOneHunk,
|
|
},
|
|
{
|
|
testName: "newFile",
|
|
patchStr: newFile,
|
|
},
|
|
{
|
|
testName: "addNewlineToPreviouslyEmptyFile",
|
|
patchStr: addNewlineToPreviouslyEmptyFile,
|
|
},
|
|
{
|
|
testName: "exampleHunk",
|
|
patchStr: exampleHunk,
|
|
},
|
|
}
|
|
|
|
for _, s := range scenarios {
|
|
s := s
|
|
t.Run(s.testName, func(t *testing.T) {
|
|
// here we parse the patch, then format it, and ensure the result
|
|
// matches the original patch. Note that unified diffs allow omitting
|
|
// the new length in a hunk header if the value is 1, and currently we always
|
|
// omit the new length in such cases.
|
|
patch := Parse(s.patchStr)
|
|
result := formatPlain(patch)
|
|
assert.Equal(t, s.patchStr, result)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestLineNumberOfLine(t *testing.T) {
|
|
type scenario struct {
|
|
testName string
|
|
patchStr string
|
|
indexes []int
|
|
expecteds []int
|
|
}
|
|
|
|
scenarios := []scenario{
|
|
{
|
|
testName: "twoHunks",
|
|
patchStr: twoHunks,
|
|
// this is really more of a characteristic test than anything.
|
|
indexes: []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 1000},
|
|
expecteds: []int{1, 1, 1, 1, 1, 1, 2, 2, 3, 4, 5, 8, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 15, 15, 15},
|
|
},
|
|
}
|
|
|
|
for _, s := range scenarios {
|
|
s := s
|
|
t.Run(s.testName, func(t *testing.T) {
|
|
for i, idx := range s.indexes {
|
|
patch := Parse(s.patchStr)
|
|
result := patch.LineNumberOfLine(idx)
|
|
assert.Equal(t, s.expecteds[i], result)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetNextStageableLineIndex(t *testing.T) {
|
|
type scenario struct {
|
|
testName string
|
|
patchStr string
|
|
indexes []int
|
|
expecteds []int
|
|
}
|
|
|
|
scenarios := []scenario{
|
|
{
|
|
testName: "twoHunks",
|
|
patchStr: twoHunks,
|
|
indexes: []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 1000},
|
|
expecteds: []int{6, 6, 6, 6, 6, 6, 6, 7, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16},
|
|
},
|
|
}
|
|
|
|
for _, s := range scenarios {
|
|
s := s
|
|
t.Run(s.testName, func(t *testing.T) {
|
|
for i, idx := range s.indexes {
|
|
patch := Parse(s.patchStr)
|
|
result := patch.GetNextChangeIdx(idx)
|
|
assert.Equal(t, s.expecteds[i], result)
|
|
}
|
|
})
|
|
}
|
|
}
|