echasnovski / mini.nvim

Library of 40+ independent Lua modules improving overall Neovim (version 0.8 and higher) experience with minimal effort
MIT License
4.54k stars 175 forks source link

mini.diff: all lines shown as changed if git index eol is CRLF #870

Closed bockel closed 1 month ago

bockel commented 2 months ago

Contributing guidelines

Module(s)

mini-diff

Description

Diff is not properly handled if the git index line endings are set to CRLF. Looking at the return information for git ls-files --eol:

i/lf    w/crlf  attr/text=auto eol=crlf file1.ps1
i/crlf  w/crlf  attr/text=auto eol=crlf file2.ps1

Both files open in nvim with the correct CRLF endings ff=dos. However, file1.ps1 is diffed correctly and file2.ps1 shows all lines as being changed. The only difference between the files is the git index eol value. My guess is that the diff algorithm is assuming LF eol when compairing against the git index and flagging all lines with i/crlf as changes.

git diff does not show any differences. This case appears to be handled correctly in lewis6991/gitsigns.nvim.

The i/crlf issue can be worked around by setting eol=crlf in .gitattributes and ensuring git config --local --add core.autocrlf true. Then you can run git add --renormalize path/to/files and commit to switch the git index version to LF.

Neovim version

v0.10.0-dev-3103+gca735c755

Steps to reproduce

  1. Configure nvim with default mini-diff (using lazy.nvim): require('mini.diff').setup()
  2. Configure .gitattributes to have *.ps1 text eol=crlf
  3. Check in a file to git with CRLF line endings and git config --local --add core.autocrlf input
  4. Open a file with i/crlf w/crlf attr/text=auto eol=crlf

Expected behavior

There will be no lines with changes

Actual behavior

While git diff shows no changes, every line is shown by mini.diff to have changed

echasnovski commented 2 months ago

Thanks for the issue!

Indeed, 'mini.diff' does not account for different eol, mostly because I do not have experience (and hence problems) with them. It is good to have some example which I can rely on to potentially fix the issue. I'll take a look.

echasnovski commented 1 month ago

I have finally had the energy to look at this. As it is quite a confusing topic for me right now.

I think you are right and the issue is indeed "the diff algorithm is assuming LF eol when compairing against the git index". @bockel, would you mind confirming it?

Could you replace this line in your installed copy of 'mini.nvim' / 'mini.diff' with the following:

H.vimdiff_opts = { result_type = 'indices', ctxlen = 0, interhunkctxlen = 0, ignore_cr_at_eol = true }

... and try to reproduce the issue? This seems to solve it when I try to emulate i/crlf with MiniDiff.set_ref_text() directly, but I want to be sure.

echasnovski commented 1 month ago

I managed to reproduce locally and the latest main should fix this issue. It also now should work properly for staging hunks.

bockel commented 1 month ago

I just pulled the latest and this fixes the issue for me! Great job!