1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-08-07 22:02:56 +03:00

Also return hunks with only added lines from parseDiff

We aren't using them, yet, except for deciding whether to show the warning about
hunks with only added lines.

Add a bit of test coverage for parseDiff while we're at it.
This commit is contained in:
Stefan Haller
2024-05-19 17:41:30 +02:00
parent e1b4d625c7
commit 880528b2e4
2 changed files with 167 additions and 9 deletions

View File

@@ -26,6 +26,16 @@ func NewFixupHelper(
}
}
// hunk describes the lines in a diff hunk. Used for two distinct cases:
//
// - when the hunk contains some deleted lines. Because we're diffing with a
// context of 0, all deleted lines always come first, and then the added lines
// (if any). In this case, numLines is only the number of deleted lines, we
// ignore whether there are also some added lines in the hunk, as this is not
// relevant for our algorithm.
//
// - when the hunk contains only added lines, in which case (obviously) numLines
// is the number of added lines.
type hunk struct {
filename string
startLineIdx int
@@ -41,7 +51,7 @@ func (self *FixupHelper) HandleFindBaseCommitForFixupPress() error {
return errors.New(self.c.Tr.NoChangedFiles)
}
deletedLineHunks, hasHunksWithOnlyAddedLines := parseDiff(diff)
deletedLineHunks, addedLineHunks := parseDiff(diff)
if len(deletedLineHunks) == 0 {
return errors.New(self.c.Tr.NoDeletedLinesInDiff)
}
@@ -93,7 +103,7 @@ func (self *FixupHelper) HandleFindBaseCommitForFixupPress() error {
return self.c.PushContext(self.c.Contexts().LocalCommits)
}
if hasHunksWithOnlyAddedLines {
if len(addedLineHunks) > 0 {
return self.c.Confirm(types.ConfirmOpts{
Title: self.c.Tr.FindBaseCommitForFixup,
Prompt: self.c.Tr.HunksWithOnlyAddedLinesWarning,
@@ -122,24 +132,33 @@ func (self *FixupHelper) getDiff() (string, bool, error) {
return diff, hasStagedChanges, err
}
func parseDiff(diff string) ([]*hunk, bool) {
// Parse the diff output into hunks, and return two lists of hunks: the first
// are ones that contain deleted lines, the second are ones that contain only
// added lines.
func parseDiff(diff string) ([]*hunk, []*hunk) {
lines := strings.Split(strings.TrimSuffix(diff, "\n"), "\n")
deletedLineHunks := []*hunk{}
hasHunksWithOnlyAddedLines := false
addedLineHunks := []*hunk{}
hunkHeaderRegexp := regexp.MustCompile(`@@ -(\d+)(?:,\d+)? \+\d+(?:,\d+)? @@`)
var filename string
var currentHunk *hunk
numDeletedLines := 0
numAddedLines := 0
finishHunk := func() {
if currentHunk != nil {
if currentHunk.numLines > 0 {
if numDeletedLines > 0 {
currentHunk.numLines = numDeletedLines
deletedLineHunks = append(deletedLineHunks, currentHunk)
} else {
hasHunksWithOnlyAddedLines = true
} else if numAddedLines > 0 {
currentHunk.numLines = numAddedLines
addedLineHunks = append(addedLineHunks, currentHunk)
}
}
numDeletedLines = 0
numAddedLines = 0
}
for _, line := range lines {
if strings.HasPrefix(line, "diff --git") {
@@ -155,12 +174,14 @@ func parseDiff(diff string) ([]*hunk, bool) {
startIdx := utils.MustConvertToInt(match[1])
currentHunk = &hunk{filename, startIdx, 0}
} else if currentHunk != nil && line[0] == '-' {
currentHunk.numLines++
numDeletedLines++
} else if currentHunk != nil && line[0] == '+' {
numAddedLines++
}
}
finishHunk()
return deletedLineHunks, hasHunksWithOnlyAddedLines
return deletedLineHunks, addedLineHunks
}
// returns the list of commit hashes that introduced the lines which have now been deleted

View File

@@ -0,0 +1,137 @@
package helpers
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestFixupHelper_parseDiff(t *testing.T) {
scenarios := []struct {
name string
diff string
expectedDeletedLineHunks []*hunk
expectedAddedLineHunks []*hunk
}{
{
name: "no diff",
diff: "",
expectedDeletedLineHunks: []*hunk{},
expectedAddedLineHunks: []*hunk{},
},
{
name: "hunk with only deleted lines",
diff: `
diff --git a/file1.txt b/file1.txt
index 9ce8efb33..aaf2a4666 100644
--- a/file1.txt
+++ b/file1.txt
@@ -3 +2,0 @@ bbb
-xxx
`,
expectedDeletedLineHunks: []*hunk{
{
filename: "file1.txt",
startLineIdx: 3,
numLines: 1,
},
},
expectedAddedLineHunks: []*hunk{},
},
{
name: "hunk with deleted and added lines",
diff: `
diff --git a/file1.txt b/file1.txt
index 9ce8efb33..eb246cf98 100644
--- a/file1.txt
+++ b/file1.txt
@@ -3 +3 @@ bbb
-xxx
+yyy
`,
expectedDeletedLineHunks: []*hunk{
{
filename: "file1.txt",
startLineIdx: 3,
numLines: 1,
},
},
expectedAddedLineHunks: []*hunk{},
},
{
name: "hunk with only added lines",
diff: `
diff --git a/file1.txt b/file1.txt
index 9ce8efb33..fb5e469e7 100644
--- a/file1.txt
+++ b/file1.txt
@@ -4,0 +5,2 @@ ddd
+xxx
+yyy
`,
expectedDeletedLineHunks: []*hunk{},
expectedAddedLineHunks: []*hunk{
{
filename: "file1.txt",
startLineIdx: 4,
numLines: 2,
},
},
},
{
name: "several hunks in different files",
diff: `
diff --git a/file1.txt b/file1.txt
index 9ce8efb33..0632e41b0 100644
--- a/file1.txt
+++ b/file1.txt
@@ -2 +1,0 @@ aaa
-bbb
@@ -4 +3 @@ ccc
-ddd
+xxx
@@ -6,0 +6 @@ fff
+zzz
diff --git a/file2.txt b/file2.txt
index 9ce8efb33..0632e41b0 100644
--- a/file2.txt
+++ b/file2.txt
@@ -0,3 +1,0 @@ aaa
-aaa
-bbb
-ccc
`,
expectedDeletedLineHunks: []*hunk{
{
filename: "file1.txt",
startLineIdx: 2,
numLines: 1,
},
{
filename: "file1.txt",
startLineIdx: 4,
numLines: 1,
},
{
filename: "file2.txt",
startLineIdx: 0,
numLines: 3,
},
},
expectedAddedLineHunks: []*hunk{
{
filename: "file1.txt",
startLineIdx: 6,
numLines: 1,
},
},
},
}
for _, s := range scenarios {
t.Run(s.name, func(t *testing.T) {
deletedLineHunks, addedLineHunks := parseDiff(s.diff)
assert.Equal(t, s.expectedDeletedLineHunks, deletedLineHunks)
assert.Equal(t, s.expectedAddedLineHunks, addedLineHunks)
})
}
}