diff --git a/pkg/commands/patch/patch_manager.go b/pkg/commands/patch/patch_manager.go index 91adfecb4..71d6116d8 100644 --- a/pkg/commands/patch/patch_manager.go +++ b/pkg/commands/patch/patch_manager.go @@ -176,7 +176,8 @@ func (p *PatchManager) renderPlainPatchForFile(filename string, reverse bool, ke return info.diff case PART: // generate a new diff with just the selected lines - return ModifiedPatchForLines(p.Log, filename, info.diff, info.includedLineIndices, reverse, keepOriginalHeader) + return ModifiedPatchForLines(p.Log, filename, info.diff, info.includedLineIndices, + PatchOptions{Reverse: reverse, KeepOriginalHeader: keepOriginalHeader}) default: return "" } diff --git a/pkg/commands/patch/patch_modifier.go b/pkg/commands/patch/patch_modifier.go index fe0a896b1..5d9da3b60 100644 --- a/pkg/commands/patch/patch_modifier.go +++ b/pkg/commands/patch/patch_modifier.go @@ -13,6 +13,16 @@ var ( patchHeaderRegexp = regexp.MustCompile(`(?ms)(^diff.*?)^@@`) ) +type PatchOptions struct { + // Create a reverse patch; in other words, flip all the '+' and '-' while + // generating the patch. + Reverse bool + + // Whether to keep or discard the original diff header including the + // "index deadbeef..fa1afe1 100644" line. + KeepOriginalHeader bool +} + func GetHeaderFromDiff(diff string) string { match := patchHeaderRegexp.FindStringSubmatch(diff) if len(match) <= 1 { @@ -76,7 +86,7 @@ func NewPatchModifier(log *logrus.Entry, filename string, diffText string) *Patc } } -func (d *PatchModifier) ModifiedPatchForLines(lineIndices []int, reverse bool, keepOriginalHeader bool) string { +func (d *PatchModifier) ModifiedPatchForLines(lineIndices []int, opts PatchOptions) string { // step one is getting only those hunks which we care about hunksInRange := []*PatchHunk{} outer: @@ -95,7 +105,7 @@ outer: formattedHunks := "" var formattedHunk string for _, hunk := range hunksInRange { - startOffset, formattedHunk = hunk.formatWithChanges(lineIndices, reverse, startOffset) + startOffset, formattedHunk = hunk.formatWithChanges(lineIndices, opts.Reverse, startOffset) formattedHunks += formattedHunk } @@ -108,7 +118,7 @@ outer: // it makes git confused e.g. when dealing with deleted/added files // but with building and applying patches the original header gives git // information it needs to cleanly apply patches - if keepOriginalHeader { + if opts.KeepOriginalHeader { fileHeader = d.header } else { fileHeader = fmt.Sprintf("--- a/%s\n+++ b/%s\n", d.filename, d.filename) @@ -117,13 +127,13 @@ outer: return fileHeader + formattedHunks } -func (d *PatchModifier) ModifiedPatchForRange(firstLineIdx int, lastLineIdx int, reverse bool, keepOriginalHeader bool) string { +func (d *PatchModifier) ModifiedPatchForRange(firstLineIdx int, lastLineIdx int, opts PatchOptions) string { // generate array of consecutive line indices from our range selectedLines := []int{} for i := firstLineIdx; i <= lastLineIdx; i++ { selectedLines = append(selectedLines, i) } - return d.ModifiedPatchForLines(selectedLines, reverse, keepOriginalHeader) + return d.ModifiedPatchForLines(selectedLines, opts) } func (d *PatchModifier) OriginalPatchLength() int { @@ -134,14 +144,14 @@ func (d *PatchModifier) OriginalPatchLength() int { return d.hunks[len(d.hunks)-1].LastLineIdx() } -func ModifiedPatchForRange(log *logrus.Entry, filename string, diffText string, firstLineIdx int, lastLineIdx int, reverse bool, keepOriginalHeader bool) string { +func ModifiedPatchForRange(log *logrus.Entry, filename string, diffText string, firstLineIdx int, lastLineIdx int, opts PatchOptions) string { p := NewPatchModifier(log, filename, diffText) - return p.ModifiedPatchForRange(firstLineIdx, lastLineIdx, reverse, keepOriginalHeader) + return p.ModifiedPatchForRange(firstLineIdx, lastLineIdx, opts) } -func ModifiedPatchForLines(log *logrus.Entry, filename string, diffText string, includedLineIndices []int, reverse bool, keepOriginalHeader bool) string { +func ModifiedPatchForLines(log *logrus.Entry, filename string, diffText string, includedLineIndices []int, opts PatchOptions) string { p := NewPatchModifier(log, filename, diffText) - return p.ModifiedPatchForLines(includedLineIndices, reverse, keepOriginalHeader) + return p.ModifiedPatchForLines(includedLineIndices, opts) } // I want to know, given a hunk, what line a given index is on diff --git a/pkg/commands/patch/patch_modifier_test.go b/pkg/commands/patch/patch_modifier_test.go index ec79cbe32..618473d4b 100644 --- a/pkg/commands/patch/patch_modifier_test.go +++ b/pkg/commands/patch/patch_modifier_test.go @@ -513,7 +513,8 @@ func TestModifyPatchForRange(t *testing.T) { 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, s.reverse, false) + result := ModifiedPatchForRange(nil, s.filename, s.diffText, s.firstLineIndex, s.lastLineIndex, + PatchOptions{Reverse: s.reverse, KeepOriginalHeader: false}) if !assert.Equal(t, s.expected, result) { fmt.Println(result) } diff --git a/pkg/gui/controllers/staging_controller.go b/pkg/gui/controllers/staging_controller.go index 0cddfb841..840c18a18 100644 --- a/pkg/gui/controllers/staging_controller.go +++ b/pkg/gui/controllers/staging_controller.go @@ -181,7 +181,8 @@ func (self *StagingController) applySelection(reverse bool) error { } firstLineIdx, lastLineIdx := state.SelectedRange() - patch := patch.ModifiedPatchForRange(self.c.Log, path, state.GetDiff(), firstLineIdx, lastLineIdx, reverse, false) + patch := patch.ModifiedPatchForRange(self.c.Log, path, state.GetDiff(), firstLineIdx, lastLineIdx, + patch.PatchOptions{Reverse: reverse, KeepOriginalHeader: false}) if patch == "" { return nil @@ -227,7 +228,8 @@ func (self *StagingController) editHunk() error { hunk := state.CurrentHunk() patchText := patch.ModifiedPatchForRange( - self.c.Log, path, state.GetDiff(), hunk.FirstLineIdx, hunk.LastLineIdx(), self.staged, false, + self.c.Log, path, state.GetDiff(), hunk.FirstLineIdx, hunk.LastLineIdx(), + patch.PatchOptions{Reverse: self.staged, KeepOriginalHeader: false}, ) patchFilepath, err := self.git.WorkingTree.SaveTemporaryPatch(patchText) if err != nil { @@ -249,7 +251,8 @@ func (self *StagingController) editHunk() error { lineCount := strings.Count(editedPatchText, "\n") + 1 newPatchText := patch.ModifiedPatchForRange( - self.c.Log, path, editedPatchText, 0, lineCount, false, false, + self.c.Log, path, editedPatchText, 0, lineCount, + patch.PatchOptions{Reverse: false, KeepOriginalHeader: false}, ) if err := self.git.WorkingTree.ApplyPatch(newPatchText, "cached"); err != nil { return self.c.Error(err)