patch 9.1.1439: Last diff folds not merged

Problem:  Last diff folds not merged (after v8.1.1922)
Solution: loop over all windows in the current tabpage and update all
          folds (Gary Johnson)

This commit fixes a bug where the last two folds of a diff are not
merged when the last difference between the two diff'd buffers is
resolved.

Normally, when two buffers are diff'd, folding is used to show only the
text that differs and to hide the text that is the same between the two
buffers.  When a difference is resolved by making a block of text the
same in both buffers, the folds are updated to merge that block with the
folds above and below it into one closed fold.

That updating of the folds did not occur when the block of text was the
last diff block in the buffers.

The bug was introduced by this patch on August 24, 2019:

    patch 8.1.1922: in diff mode global operations can be very slow

    Problem:    In diff mode global operations can be very slow.
    Solution:   Do not call diff_redraw() many times, call it once when
		redrawing.  And also don't update folds multiple times.

Unfortunately, folds were then not updated often enough.

The problem was fixed by adding a short loop to the ex_diffgetput()
function in diff.c to update all the folds in the current tab when the
last difference is removed.

A test for this was added to test_diffmode.vim.  Two of the reference
screen dumps for another test in that file,
Test_diffget_diffput_linematch(), had to be changed to have all the
folds closed rather than to have the last diff block remain open.

closes: #17457

Signed-off-by: Gary Johnson <garyjohn@spocom.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Gary Johnson
2025-06-08 16:00:06 +02:00
committed by Christian Brabandt
parent c4eb1cb17b
commit 3fa0d3514b
5 changed files with 79 additions and 31 deletions

View File

@ -4112,6 +4112,18 @@ theend:
check_cursor();
changed_line_abv_curs();
#ifdef FEAT_FOLDING
// If all diffs are gone, update folds in all diff windows.
if (curtab->tp_first_diff == NULL)
{
win_T *wp;
FOR_ALL_WINDOWS_IN_TAB(curtab, wp)
if (wp->w_p_diff && wp->w_p_fdm[0] == 'd' && wp->w_p_fen)
foldUpdateAll(wp);
}
#endif
if (diff_need_update)
// redraw already done by ex_diffupdate()
diff_need_update = FALSE;

View File

@ -1,16 +1,16 @@
| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
| +0#0000e05#a8a8a8255@1|A+0#0000000#ffffff0|B|C|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1>A+0#0000000#ffffff0|B|C|a|b|c| @28
| +0#0000e05#a8a8a8255@1|A+0#0000000#ffffff0|B|C|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|A+0#0000000#ffffff0|B|C|a|b|c| @28
| +0#0000e05#a8a8a8255@1|A+0#0000000#ffffff0|B|C|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|A+0#0000000#ffffff0|B|C|a|b|c| @28
| +0#0000e05#a8a8a8255@1|A+0#0000000#ffffff0|B|C|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|A+0#0000000#ffffff0|B|C|a|b|c| @28
| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25||+1&&| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25
|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35
|++0#0000e05#a8a8a8255| |+|-@1| |1|2| |l|i|n|e|s|:| |c|o|m@1|o|n| |l|i|n|e|-@9||+1#0000000#ffffff0|++0#0000e05#a8a8a8255| >+|-@1| |1|2| |l|i|n|e|s|:| |c|o|m@1|o|n| |l|i|n|e|-@9
|~+0#4040ff13#ffffff0| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35

View File

@ -1,20 +1,20 @@
| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34||+1&&| +0#0000e05#a8a8a8255@1| +0#0000000#ffffff0@34
| +0#0000e05#a8a8a8255@1>D+0#0000000#ffffff0|E|F|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28
| +0#0000e05#a8a8a8255@1|x+0#0000000#ffffff0|y|z| @31||+1&&| +0#0000e05#a8a8a8255@1|x+0#0000000#ffffff0|y|z| @31
| +0#0000e05#a8a8a8255@1|x+0#0000000#ffffff0|y|z| @31||+1&&| +0#0000e05#a8a8a8255@1|x+0#0000000#ffffff0|y|z| @31
| +0#0000e05#a8a8a8255@1|x+0#0000000#ffffff0|y|z| @31||+1&&| +0#0000e05#a8a8a8255@1|x+0#0000000#ffffff0|y|z| @31
| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28
| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28
| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28||+1&&| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F|a|b|c| @28
| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F| @31||+1&&| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F| @31
| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23||+1&&| +0#0000e05#a8a8a8255@1|c+0#0000000#ffffff0|o|m@1|o|n| |l|i|n|e| @23
| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F| @31||+1&&| +0#0000e05#a8a8a8255@1|D+0#0000000#ffffff0|E|F| @31
| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25||+1&&| +0#0000e05#a8a8a8255@1|s+0#0000000#ffffff0|o|m|e|t|h|i|n|g| @25
|~+0#4040ff13&| @35||+1#0000000&|~+0#4040ff13&| @35
|++0#0000e05#a8a8a8255| >+|-@1| |1|7| |l|i|n|e|s|:| |c|o|m@1|o|n| |l|i|n|e|-@9||+1#0000000#ffffff0|++0#0000e05#a8a8a8255| |+|-@1| |1|7| |l|i|n|e|s|:| |c|o|m@1|o|n| |l|i|n|e|-@9
|~+0#4040ff13#ffffff0| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|X+3#0000000&|d|i|f|i|l|e|1| |[|+|]| @6|5|,|1| @11|A|l@1| |X+1&&|d|i|f|i|l|e|2| @10|5|,|1| @11|A|l@1
|:+0&&|4|,|1|2|d|i|f@1|g|e|t| @62

View File

@ -50,6 +50,40 @@ func Test_vert_split()
set diffopt&
endfunc
" Test for diff folding redraw after last diff is resolved
func Test_diff_fold_redraw()
" Set up two files with the minimal case
call writefile(['Paragraph 1', '', 'Paragraph 2', '', 'Paragraph 3'], 'Xfile1')
call writefile(['Paragraph 1', '', 'Paragraph 3'], 'Xfile2')
" Open in diff mode
exe 'edit Xfile1'
exe 'vert diffsplit Xfile2'
" Ensure both windows are in diff mode and folds are enabled
set foldmethod=diff
set foldenable
" Go to the diff and apply dp to copy Paragraph 2 to Xfile2
normal! ]c
normal! dp
" Redraw and check folds
redraw!
let win1_fold = foldclosed(1)
let win2_fold = foldclosed(1)
" Both windows should be fully folded (foldclosed returns 1 for top fold)
call assert_equal(1, win1_fold)
call assert_equal(1, win2_fold)
" Clean up
bwipe!
bwipe!
call delete('Xfile1')
call delete('Xfile2')
endfunc
func Test_vert_split_internal()
set diffopt=internal,filler
call Common_vert_split()

View File

@ -709,6 +709,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1439,
/**/
1438,
/**/