1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-07-28 16:02:01 +03:00

Use forward patches and --reverse flag for partial patches too

There's no reason to have two different ways of applying patches for whole-file
patches and partial patches; use --reverse for both. Not only does this simplify
the code a bit, but it fixes an actual problem: when reverseOnGenerate and
keepOriginalHeader are both true, the generated patch header is broken (the two
blobs in the line `index 6d1959b..6dc5f84 100644` are swapped). Git fails to do
a proper three-way merge in that case, as it expects the first of the two blobs
to be the common ancestor.

It would be possible to fix this by extending ModifiedPatchForLines to swap the
two blobs in this case; but this would prevent us from concatenating all patches
and apply them in one go, which we are going to do later in the branch.
This commit is contained in:
Stefan Haller
2023-02-23 18:44:52 +01:00
parent c79e360584
commit 9cc33c479b
3 changed files with 20 additions and 19 deletions

View File

@ -162,7 +162,7 @@ func (p *PatchManager) RemoveFileLineRange(filename string, firstLineIdx, lastLi
return nil return nil
} }
func (p *PatchManager) renderPlainPatchForFile(filename string, reverse bool, keepOriginalHeader bool) string { func (p *PatchManager) renderPlainPatchForFile(filename string, reverse bool, willBeAppliedReverse bool, keepOriginalHeader bool) string {
info, err := p.getFileInfo(filename) info, err := p.getFileInfo(filename)
if err != nil { if err != nil {
p.Log.Error(err) p.Log.Error(err)
@ -177,14 +177,18 @@ func (p *PatchManager) renderPlainPatchForFile(filename string, reverse bool, ke
case PART: case PART:
// generate a new diff with just the selected lines // generate a new diff with just the selected lines
return ModifiedPatchForLines(p.Log, filename, info.diff, info.includedLineIndices, return ModifiedPatchForLines(p.Log, filename, info.diff, info.includedLineIndices,
PatchOptions{Reverse: reverse, KeepOriginalHeader: keepOriginalHeader}) PatchOptions{
Reverse: reverse,
WillBeAppliedReverse: willBeAppliedReverse,
KeepOriginalHeader: keepOriginalHeader,
})
default: default:
return "" return ""
} }
} }
func (p *PatchManager) RenderPatchForFile(filename string, plain bool, reverse bool, keepOriginalHeader bool) string { func (p *PatchManager) RenderPatchForFile(filename string, plain bool, reverse bool, willBeAppliedReverse bool, keepOriginalHeader bool) string {
patch := p.renderPlainPatchForFile(filename, reverse, keepOriginalHeader) patch := p.renderPlainPatchForFile(filename, reverse, willBeAppliedReverse, keepOriginalHeader)
if plain { if plain {
return patch return patch
} }
@ -200,7 +204,7 @@ func (p *PatchManager) renderEachFilePatch(plain bool) []string {
sort.Strings(filenames) sort.Strings(filenames)
patches := slices.Map(filenames, func(filename string) string { patches := slices.Map(filenames, func(filename string) string {
return p.RenderPatchForFile(filename, plain, false, true) return p.RenderPatchForFile(filename, plain, false, false, true)
}) })
output := slices.Filter(patches, func(patch string) bool { output := slices.Filter(patches, func(patch string) bool {
return patch != "" return patch != ""
@ -241,27 +245,20 @@ func (p *PatchManager) GetFileIncLineIndices(filename string) ([]int, error) {
} }
func (p *PatchManager) ApplyPatches(reverse bool) error { func (p *PatchManager) ApplyPatches(reverse bool) error {
// for whole patches we'll apply the patch in reverse applyFlags := []string{"index", "3way"}
// but for part patches we'll apply a reverse patch forwards if reverse {
applyFlags = append(applyFlags, "reverse")
}
for filename, info := range p.fileInfoMap { for filename, info := range p.fileInfoMap {
if info.mode == UNSELECTED { if info.mode == UNSELECTED {
continue continue
} }
applyFlags := []string{"index", "3way"}
reverseOnGenerate := false
if reverse {
if info.mode == WHOLE {
applyFlags = append(applyFlags, "reverse")
} else {
reverseOnGenerate = true
}
}
var err error var err error
// first run we try with the original header, then without // first run we try with the original header, then without
for _, keepOriginalHeader := range []bool{true, false} { for _, keepOriginalHeader := range []bool{true, false} {
patch := p.RenderPatchForFile(filename, true, reverseOnGenerate, keepOriginalHeader) patch := p.RenderPatchForFile(filename, true, false, reverse, keepOriginalHeader)
if patch == "" { if patch == "" {
continue continue
} }

View File

@ -96,6 +96,10 @@ func NewPatchModifier(log *logrus.Entry, filename string, diffText string) *Patc
} }
func (d *PatchModifier) ModifiedPatchForLines(lineIndices []int, opts PatchOptions) string { func (d *PatchModifier) ModifiedPatchForLines(lineIndices []int, opts PatchOptions) string {
if opts.Reverse && opts.KeepOriginalHeader {
panic("reverse and keepOriginalHeader are not compatible")
}
// step one is getting only those hunks which we care about // step one is getting only those hunks which we care about
hunksInRange := []*PatchHunk{} hunksInRange := []*PatchHunk{}
outer: outer:

View File

@ -672,7 +672,7 @@ func (gui *Gui) refreshPatchBuildingPanel(opts types.OnFocusOpts) error {
return err return err
} }
secondaryDiff := gui.git.Patch.PatchManager.RenderPatchForFile(path, false, false, true) secondaryDiff := gui.git.Patch.PatchManager.RenderPatchForFile(path, false, false, false, true)
if err != nil { if err != nil {
return err return err
} }