sindrets / diffview.nvim

Single tabpage interface for easily cycling through diffs for all modified files for any git rev.
Other
3.6k stars 101 forks source link

[Bug] Issue with diffing files hosted in a WSL instance accessed as a Network Drive in Windows #372

Closed pidgeon777 closed 1 year ago

pidgeon777 commented 1 year ago

Description

I am facing a problem with Neovim v0.9.0 for Windows. In my setup, I have a repository hosted in a WSL instance at the path /home/root/git-projects/buildroot. From my Windows 10 x64 machine, I can access the repository using the network path \\wsl.localhost\Ubuntu1804\home\root\git-projects\buildroot, and I have also created a Network Drive W: to access the WSL content as W:\home\root\git-projects\buildroot. When I open a repository file in Neovim and execute the DiffViewOpen command, a split is created in the DiffView panel with two buffers: one with the path diffview:///wsl.localhost/Ubuntu1804/home/root/git-projects/buildroot/.git/:0:/folder/file (referred to as diff_git_path), and the other with the path W:\home\root\git-projects\buildroot\wsl.localhost\Ubuntu1804\home\root\git-projects\buildroot\folder\file (referred to as diff_loc_path). The issue is that only the buffers taken from the git index (diff_git_path) are shown, and the buffers associated with the local file being diffed (diff_loc_path) are not displayed.

Expected behavior

I expected the DiffViewOpen command to display both the buffers from the git index (diff_git_path) and the buffers associated with the local file being diffed (diff_loc_path).

Actual behavior

The DiffViewOpen command only shows the buffers taken from the git index (diff_git_path), and it does not include the buffers associated with the local file being diffed (diff_loc_path).

Steps to reproduce

  1. Open a repository file in Neovim v0.9.0 for Windows.
  2. Execute the DiffViewOpen command.
  3. Select a file in the DiffView panel for a diff.

Health check

Output of :checkhealth diffview ``` diffview: - ERROR No healthcheck found for "diffview" plugin. ```

Log info

Relevant info from :DiffviewLog ``` Command not available ```

Neovim version

NVIM v0.9.0

Operating system and version

Windows 10 x64

Minimal config

No response

sindrets commented 1 year ago

Health check and :DiffviewLog output is needed here.

pidgeon777 commented 1 year ago

checkhealth diffview:

diffview: require("diffview.health").check()

Checking plugin dependencies ~
- OK nvim-web-devicons installed.

Checking VCS tools ~
- The plugin requires at least one of the supported VCS tools to be valid.
- OK Git found.
- OK Git is up-to-date. (2.37.3.windows.1)
- WARNING Configured `hg_cmd` is not executable: 'hg'

DiffViewLog:

[INFO  2023-06-08 10:06:17.413 +0200] ...im/site/pack/lazy/opt/diffview.nvim/lua/diffview/lib.lua:24: [command call] :DiffviewOpen 
[INFO  2023-06-08 10:06:32.379 +0200] ...iffview.nvim/lua/diffview/scene/views/diff/diff_view.lua:483: [DiffView] Completed update for 422 files successfully (14429.227 ms)
[INFO  2023-06-08 10:07:26.954 +0200] ...im/site/pack/lazy/opt/diffview.nvim/lua/diffview/lib.lua:74: [command call] :DiffviewFileHistory %
[INFO  2023-06-08 10:07:29.327 +0200] ...iffview.nvim/lua/diffview/scene/views/diff/diff_view.lua:483: [DiffView] Completed update for 422 files successfully (14152.113 ms)
[INFO  2023-06-08 10:07:32.392 +0200] ...diffview/scene/views/file_history/file_history_panel.lua:264: [FileHistory] Completed update for 243 entries successfully (4537.050 ms).
[INFO  2023-06-08 10:09:07.875 +0200] ...im/site/pack/lazy/opt/diffview.nvim/lua/diffview/lib.lua:24: [command call] :DiffviewOpen 
[INFO  2023-06-08 10:09:22.311 +0200] ...iffview.nvim/lua/diffview/scene/views/diff/diff_view.lua:483: [DiffView] Completed update for 422 files successfully (14053.295 ms)
sindrets commented 1 year ago

Okay, I believe I know what the problem is. Our path lib is expanding the absolute path incorrectly because I didn't know that \\ was a valid root segment in a Windows path.

But also: why are you interacting with the file system this way? Am I understanding you correctly in that you are using the Windows version of nvim, but you have a repository cloned into the virtual FS of a WSL instance? Why don't you just clone the repo into your normal FS? You're clearly paying a hefty price here in terms of IO performance. 14000+ ms for updating a file list of 400 entries in a diffview? That takes <300 ms on linux. And I know IO is slow on Windows, but I'm fairly confident the performance would be better if you didn't go through the WSL FS.

pidgeon777 commented 1 year ago

@sindrets I supposed it could be related to an incorrect path handling, glad you confirmed it 👍.

I've cloned a repository of a Linux Kernel in my WSL, and not directly on Windows because I have to compile it with WSL.

Cloning the repository in Windows, wouldn't make it possible to handle symbolic links, and/or file permissions, of the tracked repository files.

Also, cloning it in Windows and accessing it from WSL, would make compilation time much, much slower, given the continuous I/O access between WSL and Windows filesystems.

Also, mounting the WSL path as a Network Drive with a drive letter (e.g. W:), ensures better compatibility with some Neovim plugins running on Windows when opening those files hosted in WSL (it would be better for them to "see" a file path as W:\path\to\file, instead of \\wsl.ubuntu\Ubuntu1804\path\to\file).

Finally, do you know a trick which could help me with shortening the time needed by DiffView, so that those 14 seconds may be abbreviated when accessing that repo?

I don't know, maybe by excluding certain repository folders, excluding un-tracked files, or else?

sindrets commented 1 year ago

Should be fixed now in the latest commit, but let me know if you still encounter any problems.

Finally, do you know a trick which could help me with shortening the time needed by DiffView, so that those 14 seconds may be abbreviated when accessing that repo?

One piece of advice - that would solve this problem - is one that you probably don't want to hear (perhaps because it's not even up to you, in which case I sympathize). Which is: use Linux. Your performance problems are likely mostly tied to the fact that Windows has to do a huge number of cross interactions between your real FS and the virtual WSL FS. Git performs a lot of IO operations, constantly interacting with the local object database in the repository. Since you're using the Windows version of Git, all these operations have to go through some virtual FS server.

That's one aspect. The second is that process forking is really expensive on Windows while being trivially cheap on Linux. Which also matters here, because the plugin is quite frequently spawning Git processes to get info about the state of the repository.

While you remain on Windows I would probably set watch_index=false in the diffview config, to disable automatic updates and FS polling of the git index.

Have you tried using nvim under WSL instead? I don't know if it would be better, but might be worth a try. It would eliminate the back and forth between your real FS and the virtual FS.

I don't know, maybe by excluding certain repository folders, excluding un-tracked files, or else?

You can do this, I feel like it probably won't make much of a difference, but you can give it a try:

:DiffviewOpen -uno -- :!exclude/this/path :!and/this
pidgeon777 commented 1 year ago

Should be fixed now in the latest commit, but let me know if you still encounter any problems.

I can confirm it now works, great work! 👍

One piece of advice - that would solve this problem - is one that you probably don't want to hear (perhaps because it's not even up to you, in which case I sympathize). Which is: use Linux. Your performance problems are likely mostly tied to the fact that Windows has to do a huge number of cross interactions between your real FS and the virtual WSL FS. Git performs a lot of IO operations, constantly interacting with the local object database in the repository. Since you're using the Windows version of Git, all these operations have to go through some virtual FS server.

Great advice and I already thought about that! The fact is that most of my company tools are Windows only.

That's one aspect. The second is that process forking is really expensive on Windows while being trivially cheap on Linux. Which also matters here, because the plugin is quite frequently spawning Git processes to get info about the state of the repository.

While you remain on Windows I would probably set watch_index=false in the diffview config, to disable automatic updates and FS polling of the git index.

Good advice. In that case, how could I do a "manual" index polling/refresh?

Have you tried using nvim under WSL instead? I don't know if it would be better, but might be worth a try. It would eliminate the back and forth between your real FS and the virtual FS.

Yes, I thought of that. The problem is that I would have to port and test all of my Windows Neovim config to Linux, and it could take quite a lot of time with testing and so on.

I don't know, maybe by excluding certain repository folders, excluding un-tracked files, or else?

You can do this, I feel like it probably won't make much of a difference, but you can give it a try:

:DiffviewOpen -uno -- :!exclude/this/path :!and/this
  • -uno disables untracked files.
  • :!exclude/this/path uses git pathspec to ignore a path. You can read more about that in the man gitglossary. It also accepts globs.

Tried that, but the performance seems to be similar. Thanks anyway for the advice 👍.

zegervdv commented 1 year ago

Just a random thought: could you run the wsl git from the windows nvim by setting your git command to wsl git?

Not sure how that will work with paths and naming conventions though.

sindrets commented 1 year ago

Good advice. In that case, how could I do a "manual" index polling/refresh?

@pidgeon777 :DiffviewRefresh or the default key mapping R from the file panel will force an update.