mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-08-28 10:15:32 -05:00
When loading the files of a commit we passed --no-renames, so a rename showed up as a separate delete and add rather than a single R entry. That made it impossible to work with a rename that also modifies the file: the modifications were spread across a full deletion and a full addition instead of appearing as the handful of lines that actually changed. The staging view already shows renames and lets you stage their hunks, so there was no good reason for the patch builder to differ; the flag was only there because the commit-file parser couldn't cope with the rename record format. Switch the commit-file loader and the per-file diff to --find-renames, teach the parser about the rename record (a status followed by two paths), and carry the previous path through the patch builder so the diff for a rename is loaded with both paths, which is what makes git emit the rename in the first place. A whole-file selection keeps the rename in the header, so the rename moves or is discarded together with the file's contents. A partial selection instead strips the rename metadata and points the header at the new path, so applying the patch only changes the contents and leaves the rename in place; the blob index line is kept so that a 3-way apply can still fall back to a blob merge. Discarding a renamed file from a commit now discards both the new and the old path, so the new file is removed and the old one is restored. Changing the rename similarity threshold refreshes the commit files panel too, not just the files panel, so that a rename can turn into a delete and add or back. It is disabled while building a patch, however, because the patch builder caches each file's diff by path and would desync if a rename changed into a delete and add underneath it. Finally, copying a file's diff from the commit files panel now passes both paths for a rename, so the copied diff shows the rename instead of a new-file add. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
829 lines
15 KiB
Go
829 lines
15 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 renameWithModificationDiff = `diff --git a/oldname b/newname
|
|
similarity index 62%
|
|
rename from oldname
|
|
rename to newname
|
|
index dcd3485..1ba5540 100644
|
|
--- a/oldname
|
|
+++ b/newname
|
|
@@ -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 twoHunksWithMoreAdditionsThanRemovals = `diff --git a/filename b/filename
|
|
index bac359d75..6e5b89f36 100644
|
|
--- a/filename
|
|
+++ b/filename
|
|
@@ -1,5 +1,6 @@
|
|
apple
|
|
-grape
|
|
+orange
|
|
+kiwi
|
|
...
|
|
...
|
|
...
|
|
@@ -8,6 +9,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 deletedFile = `diff --git a/newfile b/newfile
|
|
deleted file mode 100644
|
|
index 4e680cc1f..000000000
|
|
--- a/newfile
|
|
+++ /dev/null
|
|
@@ -1,3 +0,0 @@
|
|
-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
|
|
stripRename 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
|
|
+grape
|
|
orange
|
|
...
|
|
...
|
|
...
|
|
`,
|
|
},
|
|
{
|
|
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
|
|
+orange
|
|
grape
|
|
...
|
|
...
|
|
...
|
|
@@ -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
|
|
`,
|
|
},
|
|
{
|
|
testName: "renamed file, whole change selected, strips the rename so only the content change is applied",
|
|
firstLineIndex: 9,
|
|
lastLineIndex: 10,
|
|
stripRename: true,
|
|
diffText: renameWithModificationDiff,
|
|
expected: `diff --git a/newname b/newname
|
|
index dcd3485..1ba5540 100644
|
|
--- a/newname
|
|
+++ b/newname
|
|
@@ -1,5 +1,5 @@
|
|
apple
|
|
-orange
|
|
+grape
|
|
...
|
|
...
|
|
...
|
|
`,
|
|
},
|
|
{
|
|
testName: "renamed file, only removal selected, strips the rename",
|
|
firstLineIndex: 9,
|
|
lastLineIndex: 9,
|
|
stripRename: true,
|
|
diffText: renameWithModificationDiff,
|
|
expected: `diff --git a/newname b/newname
|
|
index dcd3485..1ba5540 100644
|
|
--- a/newname
|
|
+++ b/newname
|
|
@@ -1,5 +1,4 @@
|
|
apple
|
|
-orange
|
|
...
|
|
...
|
|
...
|
|
`,
|
|
},
|
|
}
|
|
|
|
for _, s := range scenarios {
|
|
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,
|
|
StripRename: s.stripRename,
|
|
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: "deletedFile",
|
|
patchStr: deletedFile,
|
|
},
|
|
{
|
|
testName: "addNewlineToPreviouslyEmptyFile",
|
|
patchStr: addNewlineToPreviouslyEmptyFile,
|
|
},
|
|
{
|
|
testName: "exampleHunk",
|
|
patchStr: exampleHunk,
|
|
},
|
|
}
|
|
|
|
for _, s := range scenarios {
|
|
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},
|
|
},
|
|
{
|
|
testName: "twoHunksWithMoreAdditionsThanRemovals",
|
|
patchStr: twoHunksWithMoreAdditionsThanRemovals,
|
|
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, 6, 9, 9, 10, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16},
|
|
},
|
|
}
|
|
|
|
for _, s := range scenarios {
|
|
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 {
|
|
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)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAdjustLineNumber(t *testing.T) {
|
|
type scenario struct {
|
|
oldLineNumbers []int
|
|
expectedResults []int
|
|
}
|
|
scenarios := []scenario{
|
|
{
|
|
oldLineNumbers: []int{1, 2, 3, 4, 5, 6, 7},
|
|
expectedResults: []int{1, 2, 2, 3, 4, 7, 8},
|
|
},
|
|
}
|
|
|
|
// The following diff was generated from old.txt:
|
|
// 1
|
|
// 2a
|
|
// 2b
|
|
// 3
|
|
// 4
|
|
// 7
|
|
// 8
|
|
// against new.txt:
|
|
// 1
|
|
// 2
|
|
// 3
|
|
// 4
|
|
// 5
|
|
// 6
|
|
// 7
|
|
// 8
|
|
|
|
// This test setup makes the test easy to understand, because the resulting
|
|
// adjusted line numbers are the same as the content of the lines in new.txt.
|
|
|
|
diff := `--- old.txt 2024-12-16 18:04:29
|
|
+++ new.txt 2024-12-16 18:04:27
|
|
@@ -2,2 +2 @@
|
|
-2a
|
|
-2b
|
|
+2
|
|
@@ -5,0 +5,2 @@
|
|
+5
|
|
+6
|
|
`
|
|
|
|
patch := Parse(diff)
|
|
|
|
for _, s := range scenarios {
|
|
t.Run("TestAdjustLineNumber", func(t *testing.T) {
|
|
for idx, oldLineNumber := range s.oldLineNumbers {
|
|
result := patch.AdjustLineNumber(oldLineNumber)
|
|
assert.Equal(t, s.expectedResults[idx], result)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestIsSingleHunkForWholeFile(t *testing.T) {
|
|
scenarios := []struct {
|
|
testName string
|
|
patchStr string
|
|
expectedResult bool
|
|
}{
|
|
{
|
|
testName: "simpleDiff",
|
|
patchStr: simpleDiff,
|
|
expectedResult: false,
|
|
},
|
|
{
|
|
testName: "addNewlineToEndOfFile",
|
|
patchStr: addNewlineToEndOfFile,
|
|
expectedResult: false,
|
|
},
|
|
{
|
|
testName: "removeNewlinefromEndOfFile",
|
|
patchStr: removeNewlinefromEndOfFile,
|
|
expectedResult: false,
|
|
},
|
|
{
|
|
testName: "twoHunks",
|
|
patchStr: twoHunks,
|
|
expectedResult: false,
|
|
},
|
|
{
|
|
testName: "twoChangesInOneHunk",
|
|
patchStr: twoChangesInOneHunk,
|
|
expectedResult: false,
|
|
},
|
|
{
|
|
testName: "newFile",
|
|
patchStr: newFile,
|
|
expectedResult: true,
|
|
},
|
|
{
|
|
testName: "deletedFile",
|
|
patchStr: deletedFile,
|
|
expectedResult: true,
|
|
},
|
|
{
|
|
testName: "addNewlineToPreviouslyEmptyFile",
|
|
patchStr: addNewlineToPreviouslyEmptyFile,
|
|
expectedResult: true,
|
|
},
|
|
{
|
|
testName: "exampleHunk",
|
|
patchStr: exampleHunk,
|
|
expectedResult: false,
|
|
},
|
|
}
|
|
|
|
for _, s := range scenarios {
|
|
t.Run(s.testName, func(t *testing.T) {
|
|
patch := Parse(s.patchStr)
|
|
assert.Equal(t, s.expectedResult, patch.IsSingleHunkForWholeFile())
|
|
})
|
|
}
|
|
}
|