summaryrefslogtreecommitdiffstats
path: root/pkg/commands/patch
diff options
context:
space:
mode:
authorStefan Haller <stefan@haller-berlin.de>2023-02-26 13:48:10 +0100
committerStefan Haller <stefan@haller-berlin.de>2023-03-07 09:49:34 +0100
commitc79e3605840cf5c48c2008113ec006ad671f8c24 (patch)
tree2056a329a35ef28c2e60615afefec5c17f8eb2b5 /pkg/commands/patch
parentf76cc2795601a14ce8e622a28f1d9f94028a3d06 (diff)
Add patch option WillBeAppliedReverse
It's not used yet, but covered with tests already.
Diffstat (limited to 'pkg/commands/patch')
-rw-r--r--pkg/commands/patch/hunk.go16
-rw-r--r--pkg/commands/patch/patch_modifier.go12
-rw-r--r--pkg/commands/patch/patch_modifier_test.go73
3 files changed, 86 insertions, 15 deletions
diff --git a/pkg/commands/patch/hunk.go b/pkg/commands/patch/hunk.go
index 98d932126..a2727f2c9 100644
--- a/pkg/commands/patch/hunk.go
+++ b/pkg/commands/patch/hunk.go
@@ -45,7 +45,7 @@ func headerInfo(header string) (int, int, string) {
return oldStart, newStart, heading
}
-func (hunk *PatchHunk) updatedLines(lineIndices []int, reverse bool) []string {
+func (hunk *PatchHunk) updatedLines(lineIndices []int, reverse bool, willBeAppliedReverse bool) []string {
skippedNewlineMessageIndex := -1
newLines := []string{}
@@ -58,7 +58,7 @@ func (hunk *PatchHunk) updatedLines(lineIndices []int, reverse bool) []string {
isLineSelected := lo.Contains(lineIndices, lineIdx)
firstChar, content := line[:1], line[1:]
- transformedFirstChar := transformedFirstChar(firstChar, reverse, isLineSelected)
+ transformedFirstChar := transformedFirstChar(firstChar, reverse, willBeAppliedReverse, isLineSelected)
if isLineSelected || (transformedFirstChar == "\\" && skippedNewlineMessageIndex != lineIdx) || transformedFirstChar == " " {
newLines = append(newLines, transformedFirstChar+content)
@@ -74,7 +74,7 @@ func (hunk *PatchHunk) updatedLines(lineIndices []int, reverse bool) []string {
return newLines
}
-func transformedFirstChar(firstChar string, reverse bool, isLineSelected bool) string {
+func transformedFirstChar(firstChar string, reverse bool, willBeAppliedReverse bool, isLineSelected bool) string {
if reverse {
if !isLineSelected && firstChar == "+" {
return " "
@@ -87,7 +87,11 @@ func transformedFirstChar(firstChar string, reverse bool, isLineSelected bool) s
}
}
- if !isLineSelected && firstChar == "-" {
+ linesToKeepInPatchContext := "-"
+ if willBeAppliedReverse {
+ linesToKeepInPatchContext = "+"
+ }
+ if !isLineSelected && firstChar == linesToKeepInPatchContext {
return " "
}
@@ -98,8 +102,8 @@ func (hunk *PatchHunk) formatHeader(oldStart int, oldLength int, newStart int, n
return fmt.Sprintf("@@ -%d,%d +%d,%d @@%s\n", oldStart, oldLength, newStart, newLength, heading)
}
-func (hunk *PatchHunk) formatWithChanges(lineIndices []int, reverse bool, startOffset int) (int, string) {
- bodyLines := hunk.updatedLines(lineIndices, reverse)
+func (hunk *PatchHunk) formatWithChanges(lineIndices []int, reverse bool, willBeAppliedReverse bool, startOffset int) (int, string) {
+ bodyLines := hunk.updatedLines(lineIndices, reverse, willBeAppliedReverse)
startOffset, header, ok := hunk.updatedHeader(bodyLines, startOffset, reverse)
if !ok {
return startOffset, ""
diff --git a/pkg/commands/patch/patch_modifier.go b/pkg/commands/patch/patch_modifier.go
index 5d9da3b60..fa20c7917 100644
--- a/pkg/commands/patch/patch_modifier.go
+++ b/pkg/commands/patch/patch_modifier.go
@@ -18,6 +18,15 @@ type PatchOptions struct {
// generating the patch.
Reverse bool
+ // If true, we're building a patch that we are going to apply using
+ // "git apply --reverse". In other words, we are not flipping the '+' and
+ // '-' ourselves while creating the patch, but git is going to do that when
+ // applying. This has consequences for which lines we need to keep or
+ // discard when filtering lines from partial hunks.
+ //
+ // Currently incompatible with Reverse.
+ WillBeAppliedReverse bool
+
// Whether to keep or discard the original diff header including the
// "index deadbeef..fa1afe1 100644" line.
KeepOriginalHeader bool
@@ -105,7 +114,8 @@ outer:
formattedHunks := ""
var formattedHunk string
for _, hunk := range hunksInRange {
- startOffset, formattedHunk = hunk.formatWithChanges(lineIndices, opts.Reverse, startOffset)
+ startOffset, formattedHunk = hunk.formatWithChanges(
+ lineIndices, opts.Reverse, opts.WillBeAppliedReverse, startOffset)
formattedHunks += formattedHunk
}
diff --git a/pkg/commands/patch/patch_modifier_test.go b/pkg/commands/patch/patch_modifier_test.go
index 618473d4b..c97fd89be 100644
--- a/pkg/commands/patch/patch_modifier_test.go
+++ b/pkg/commands/patch/patch_modifier_test.go
@@ -69,6 +69,20 @@ index e48a11c..b2ab81b 100644
...
`
+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
@@ -101,13 +115,14 @@ const exampleHunk = `@@ -1,5 +1,5 @@
// TestModifyPatchForRange is a function.
func TestModifyPatchForRange(t *testing.T) {
type scenario struct {
- testName string
- filename string
- diffText string
- firstLineIndex int
- lastLineIndex int
- reverse bool
- expected string
+ testName string
+ filename string
+ diffText string
+ firstLineIndex int
+ lastLineIndex int
+ reverse bool
+ willBeAppliedReverse bool
+ expected string
}
scenarios := []scenario{
@@ -508,13 +523,55 @@ func TestModifyPatchForRange(t *testing.T) {
\ No newline at end of file
`,
},
+ {
+ testName: "adding part of a hunk",
+ filename: "filename",
+ firstLineIndex: 6,
+ lastLineIndex: 7,
+ reverse: false,
+ willBeAppliedReverse: false,
+ diffText: twoChangesInOneHunk,
+ expected: `--- a/filename
++++ b/filename
+@@ -1,5 +1,5 @@
+ apple
+-grape
++kiwi
+ orange
+ pear
+ lemon
+`,
+ },
+ {
+ testName: "adding part of a hunk, will-be-applied-reverse",
+ filename: "filename",
+ firstLineIndex: 6,
+ lastLineIndex: 7,
+ reverse: false,
+ willBeAppliedReverse: 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) {
result := ModifiedPatchForRange(nil, s.filename, s.diffText, s.firstLineIndex, s.lastLineIndex,
- PatchOptions{Reverse: s.reverse, KeepOriginalHeader: false})
+ PatchOptions{
+ Reverse: s.reverse,
+ WillBeAppliedReverse: s.willBeAppliedReverse,
+ KeepOriginalHeader: false,
+ })
if !assert.Equal(t, s.expected, result) {
fmt.Println(result)
}