diff --git a/pkg/gui/controllers/working_tree_diff_actions.go b/pkg/gui/controllers/working_tree_diff_actions.go index a8b7d3d8e..ec430b3db 100644 --- a/pkg/gui/controllers/working_tree_diff_actions.go +++ b/pkg/gui/controllers/working_tree_diff_actions.go @@ -122,7 +122,8 @@ func (self *WorkingTreeDiffActions) EditHunk( } parsedPatch := patch.Parse(self.c.Git().WorkingTree.WorktreeFileDiff(file, git_commands.DiffModePlain, onStagedSide)) - lineIndices := changeLineIndices(parsedPatch, infos[:1]) + lineIndices := patch.ChangeLineIndicesForLines(parsedPatch, + []patch.LineIdentity{infos[0].PatchLineIdentity()}) if len(lineIndices) == 0 { return nil } @@ -280,7 +281,10 @@ func (self *WorkingTreeDiffActions) applyDiffLines( ) (bool, error) { parsedPatch := patch.Parse(self.c.Git().WorkingTree.WorktreeFileDiff(file, git_commands.DiffModePlain, sourceCached)) - patchLineIndices := changeLineIndices(parsedPatch, infos) + patchLineIndices := patch.ChangeLineIndicesForLines(parsedPatch, + lo.Map(infos, func(info types.DiffLineInfo, _ int) patch.LineIdentity { + return info.PatchLineIdentity() + })) changesLeft := len(patchLineIndices) < changeLineCount(parsedPatch) @@ -311,42 +315,6 @@ func (self *WorkingTreeDiffActions) applyDiffLines( return changesLeft, self.c.Git().Patch.ApplyPatch(patchToApply, opts) } -// changeLineIndices says which lines of a parsed patch the given diff rows are, as the -// indices a patch is built in terms of. Each row is looked for by where it sits in the -// file: an addition by its place in the new version, a deletion by its place in the -// old one, which is what tells the two halves of a changed line apart. -func changeLineIndices(parsedPatch *patch.Patch, infos []types.DiffLineInfo) []int { - type changeLine struct { - lineNumber int - isDeletion bool - } - selected := set.New[changeLine]() - for _, info := range infos { - if info.Type == types.DiffLineDeleted { - selected.Add(changeLine{info.OldLine, true}) - } else { - selected.Add(changeLine{info.NewLine, false}) - } - } - - var indices []int - for idx, line := range parsedPatch.Lines() { - var key changeLine - switch { - case line.IsAddition(): - key = changeLine{parsedPatch.LineNumberOfLine(idx), false} - case line.IsDeletion(): - key = changeLine{parsedPatch.OldLineNumberOfLine(idx), true} - default: - continue - } - if selected.Includes(key) { - indices = append(indices, idx) - } - } - return indices -} - // changeLineCount returns how many of a patch's lines are changes rather than context // or header. A selection of the whole diff covers exactly that many. func changeLineCount(p *patch.Patch) int { diff --git a/pkg/gui/types/diff_line_info.go b/pkg/gui/types/diff_line_info.go index 6326837c2..12fed2053 100644 --- a/pkg/gui/types/diff_line_info.go +++ b/pkg/gui/types/diff_line_info.go @@ -1,5 +1,7 @@ package types +import "github.com/jesseduffield/lazygit/pkg/commands/patch" + // DiffLineType classifies a row of a rendered diff. type DiffLineType int @@ -41,6 +43,16 @@ func (self DiffLineInfo) IsChange() bool { return self.Type == DiffLineAdded || self.Type == DiffLineDeleted } +// PatchLineIdentity says which change line of the file the row is, in the terms a patch +// of that file is built and read in: an addition by where it sits in the new version of +// the file, a deletion by where it sat in the old one. Only meaningful for a change row. +func (self DiffLineInfo) PatchLineIdentity() patch.LineIdentity { + if self.Type == DiffLineDeleted { + return patch.LineIdentity{LineNumber: self.OldLine, IsDeletion: true} + } + return patch.LineIdentity{LineNumber: self.NewLine} +} + // IsContent reports whether the row is a line of the file itself — a change or a // context line — as opposed to a header or a marker. Those are the rows that have a // position in the file, and so can be looked for in another rendering of the same