`nvim-tree` allows the creation of files over `sshfs`, but they can't be accessed
Description
I'm using nosduco/remote-sshfs.nvim to work remotely over sshfs.
nvim-tree doesn't show anything from the mounted folder on the server, however, you can perform edit operations from nvim-tree directly, such as creating a new file (see image, I basically pressed a on top of the folder in nvim-tree panel).
I checked on server and the file was indeed created.
Thanks
Neovim version
NVIM v0.10.0
Build type: Release
LuaJIT 2.1.1716656478
"nvim-tree.lua": { "branch": "master", "commit": "517e4fbb9ef3c0986da7047f44b4b91a2400f93c" }
Operating system and version
macOS Sonoma 14.5 (23F79)
Windows variant
No response
nvim-tree version
{ "branch": "master", "commit": "517e4fbb9ef3c0986da7047f44b4b91a2400f93c" }
Clean room replication
vim.g.loaded_netrw = 1
vim.g.loaded_netrwPlugin = 1
vim.cmd [[set runtimepath=$VIMRUNTIME]]
vim.cmd [[set packpath=/tmp/nvt-min/site]]
local package_root = "/tmp/nvt-min/site/pack"
local install_path = package_root .. "/packer/start/packer.nvim"
local function load_plugins()
require("packer").startup {
{
"wbthomason/packer.nvim",
"nvim-tree/nvim-tree.lua",
"nvim-tree/nvim-web-devicons",
-- ADD PLUGINS THAT ARE _NECESSARY_ FOR REPRODUCING THE ISSUE
'nosduco/remote-sshfs.nvim',
"nvim-telescope/telescope.nvim", branch = "0.1.x",
"nvim-lua/plenary.nvim",
},
config = {
package_root = package_root,
compile_path = install_path .. "/plugin/packer_compiled.lua",
display = { non_interactive = true },
},
}
end
if vim.fn.isdirectory(install_path) == 0 then
print "Installing nvim-tree and dependencies."
vim.fn.system { "git", "clone", "--depth=1", "https://github.com/wbthomason/packer.nvim", install_path }
end
load_plugins()
require("packer").sync()
vim.cmd [[autocmd User PackerComplete ++once echo "Ready!" | lua setup()]]
vim.opt.termguicolors = true
vim.opt.cursorline = true
-- MODIFY NVIM-TREE SETTINGS THAT ARE _NECESSARY_ FOR REPRODUCING THE ISSUE
_G.setup = function()
require("nvim-tree").setup {}
require('remote-sshfs').setup {
connections = {
ssh_configs = { -- which ssh configs to parse for hosts list
vim.fn.expand "$HOME" .. "/.ssh/config",
"/etc/ssh/ssh_config",
},
sshfs_args = { -- arguments to pass to the sshfs command
"-o reconnect",
"-o auto_cache",
"-o Ciphers=aes128-ctr",
"-o ConnectTimeout=5",
"-C",
"-o cache_timeout=60",
"-o cache=yes",
},
},
mounts = {
base_dir = vim.fn.expand "$HOME" .. "/.sshfs/", -- base directory for mount points
unmount_on_exit = true, -- run sshfs as foreground, will unmount on vim exit
},
handlers = {
on_connect = {
change_dir = true, -- when connected change vim working directory to mount point
},
on_disconnect = {
clean_mount_folders = false, -- remove mount point folder on disconnect/unmount
},
on_edit = {}, -- not yet implemented
},
ui = {
select_prompts = false, -- not yet implemented
confirm = {
connect = true, -- prompt y/n when host is selected to connect to
change_dir = false, -- prompt y/n to change working directory on connection (only applicable if handlers.on_connect.change_dir is enabled)
},
},
log = {
enable = false, -- enable logging
truncate = false, -- truncate logs
types = { -- enabled log types
all = false,
util = false,
handler = false,
sshfs = false,
},
},
}
require('telescope').setup {}
end
-- UNCOMMENT this block for diagnostics issues, substituting pattern and cmd as appropriate.
-- Requires diagnostics.enable = true in setup.
--[[
vim.api.nvim_create_autocmd("FileType", {
pattern = "lua",
callback = function()
vim.lsp.start { cmd = { "lua-language-server" } }
end,
})
]]
Steps to reproduce
1. nvim -nu /tmp/nvt-min.lua
2. :RemoteSSHFSConnect (pick server; have it listed in your ~/.ssh/config)
3. :NvimTreeOpen
4. expand the mounted folder (should be ~ on your server)
Expected behavior
List all files, directories, normal navigation as one would have locally.
Actual behavior
Initial thoughts: this may be a file system notification issue. Does the folder show after you manually refresh R or restart vim?
I don't have any knowledge about ssh file systems however I imagine that libuv would have issues. It's definitely not something that nvim-tree is aware of or can handle.
Suggestion: raise an issue with nosduco/remote-sshfs.nvim and see what ideas they have then we can talk further. I notice they copied our log subsystem :)
Thanks, @alex-courtis. Unfortunately, no, I can only create files directly from nvim-tree explorer. I will try to check on their side. Will close this and will reopen if necessarry.
Upon further digging, this is definitely a nvim-tree issue.
The issue arises solely with the nvim-tree enabled, even when using the most basic clean configuration suggested by you (&pasted below), while mounting the folder with sshfs then nvim --clean [ mounted dir ] works.
vim.g.loaded_netrw = 1
vim.g.loaded_netrwPlugin = 1
vim.cmd [[set runtimepath=$VIMRUNTIME]]
vim.cmd [[set packpath=/tmp/nvt-min/site]]
local package_root = "/tmp/nvt-min/site/pack"
local install_path = package_root .. "/packer/start/packer.nvim"
local function load_plugins()
require("packer").startup {
{
"wbthomason/packer.nvim",
"nvim-tree/nvim-tree.lua",
"nvim-tree/nvim-web-devicons",
},
config = {
package_root = package_root,
compile_path = install_path .. "/plugin/packer_compiled.lua",
display = { non_interactive = true },
},
}
end
if vim.fn.isdirectory(install_path) == 0 then
print "Installing nvim-tree and dependencies."
vim.fn.system { "git", "clone", "--depth=1", "https://github.com/wbthomason/packer.nvim", install_path }
end
load_plugins()
require("packer").sync()
vim.cmd [[autocmd User PackerComplete ++once echo "Ready!" | lua setup()]]
vim.opt.termguicolors = true
vim.opt.cursorline = true
-- MODIFY NVIM-TREE SETTINGS THAT ARE _NECESSARY_ FOR REPRODUCING THE ISSUE
_G.setup = function()
require("nvim-tree").setup {}
end
-- UNCOMMENT this block for diagnostics issues, substituting pattern and cmd as appropriate.
-- Requires diagnostics.enable = true in setup.
--[[
vim.api.nvim_create_autocmd("FileType", {
pattern = "lua",
callback = function()
vim.lsp.start { cmd = { "lua-language-server" } }
end,
})
]]
Hi, facing the same issue. I have successfully used this plugin for fuse mounted file system using sshfs before, so it broke in some recent commit.
Thank you, I can reproduce this with sshfs and default nvim-tree config. The directories are seen by nvim-tree, but not enumerated.
Top level contains only directories: in this case baz and foo are seen, 2 is not. This behaviour is nondeterministic - sometimes baz and foo are not seen.
: ; find .
.
./baz
./baz/2
./foo
./foo/bar
./foo/bar/1
[2024-06-15 14:12:29] [profile] START core init /home/alex/src/nvim-tree/r/2794/sfs
[2024-06-15 14:12:29] [profile] START git toplevel git_dir /home/alex/src/nvim-tree/r/2794/sfs
[2024-06-15 14:12:29] [profile] END git toplevel git_dir /home/alex/src/nvim-tree/r/2794/sfs 3ms
[2024-06-15 14:12:29] [profile] START explore init /home/alex/src/nvim-tree/r/2794/sfs
[2024-06-15 14:12:29] [profile] START explore populate_children /home/alex/src/nvim-tree/r/2794/sfs/baz
[2024-06-15 14:12:29] [profile] END explore populate_children /home/alex/src/nvim-tree/r/2794/sfs/baz 1ms
[2024-06-15 14:12:29] [profile] START explore populate_children /home/alex/src/nvim-tree/r/2794/sfs/foo
[2024-06-15 14:12:29] [profile] END explore populate_children /home/alex/src/nvim-tree/r/2794/sfs/foo 1ms
[2024-06-15 14:12:29] [profile] END explore init /home/alex/src/nvim-tree/r/2794/sfs 2ms
[2024-06-15 14:12:29] [profile] END core init /home/alex/src/nvim-tree/r/2794/sfs 7ms
[2024-06-15 14:12:29] [profile] START view open
[2024-06-15 14:12:29] [profile] END view open 4ms
[2024-06-15 14:12:29] [profile] START draw
[2024-06-15 14:12:29] [profile] END draw 0ms
open baz
[2024-06-15 14:12:34] [profile] START git toplevel git_dir /home/alex/src/nvim-tree/r/2794/sfs/baz
[2024-06-15 14:12:34] [profile] END git toplevel git_dir /home/alex/src/nvim-tree/r/2794/sfs/baz 5ms
[2024-06-15 14:12:34] [profile] START explore init /home/alex/src/nvim-tree/r/2794/sfs/baz
[2024-06-15 14:12:34] [profile] START explore populate_children /home/alex/src/nvim-tree/r/2794/sfs/baz/2
[2024-06-15 14:12:34] [profile] END explore populate_children /home/alex/src/nvim-tree/r/2794/sfs/baz/2 0ms
[2024-06-15 14:12:34] [profile] END explore init /home/alex/src/nvim-tree/r/2794/sfs/baz 0ms
[2024-06-15 14:12:34] [profile] START draw
[2024-06-15 14:12:34] [profile] END draw 0ms
Add a file 0 next to foo, no change.
git bisect shows this to be the first bad commit
2d97059661c83787372c8c003e743c984ba3ac50
It appears to be the fs_scandir_next that is failing. fs_stat seems reliable:
---@param handle uv.uv_fs_t
---@param cwd string
---@param node Node
---@param git_status table
local function populate_children(handle, cwd, node, git_status)
local node_ignored = explorer_node.is_git_ignored(node)
local nodes_by_path = utils.bool_record(node.nodes, "absolute_path")
local filter_status = filters.prepare(git_status)
while true do
local name, t, err = vim.loop.fs_scandir_next(handle)
log.line("dev", "child next %s %s %s", name, t, err)
if not name then
break
end
local abs = utils.path_join { cwd, name }
local res, ok, errr = vim.loop.fs_stat(abs)
log.line("dev", "child stat %s %s %s", res, ok, errr)
[2024-06-15 14:39:32] [profile] START core init /home/alex/src/nvim-tree/r/2794/sfs
[2024-06-15 14:39:32] [watcher] Watcher:new '/home/alex/src/nvim-tree/r/2794/sfs' nil
[2024-06-15 14:39:32] [watcher] Event:new '/home/alex/src/nvim-tree/r/2794/sfs'
[2024-06-15 14:39:32] [watcher] Event:start '/home/alex/src/nvim-tree/r/2794/sfs'
[2024-06-15 14:39:32] [profile] START git toplevel git_dir /home/alex/src/nvim-tree/r/2794/sfs
[2024-06-15 14:39:32] [profile] END git toplevel git_dir /home/alex/src/nvim-tree/r/2794/sfs 2ms
[2024-06-15 14:39:32] [profile] START explore init /home/alex/src/nvim-tree/r/2794/sfs
[2024-06-15 14:39:32] [dev] child next baz nil nil
[2024-06-15 14:39:32] [dev] child stat table: 0x7b6359192200 nil nil
[2024-06-15 14:39:32] [profile] START explore populate_children /home/alex/src/nvim-tree/r/2794/sfs/baz
[2024-06-15 14:39:32] [profile] END explore populate_children /home/alex/src/nvim-tree/r/2794/sfs/baz 0ms
[2024-06-15 14:39:32] [dev] child next foo nil nil
[2024-06-15 14:39:32] [dev] child stat table: 0x7b63591937e8 nil nil
[2024-06-15 14:39:32] [profile] START explore populate_children /home/alex/src/nvim-tree/r/2794/sfs/foo
[2024-06-15 14:39:32] [profile] END explore populate_children /home/alex/src/nvim-tree/r/2794/sfs/foo 0ms
[2024-06-15 14:39:32] [dev] child next nil nil nil
[2024-06-15 14:39:32] [dev] nodes_by_path {}
[2024-06-15 14:39:32] [profile] END explore init /home/alex/src/nvim-tree/r/2794/sfs 0ms
[2024-06-15 14:39:32] [profile] END core init /home/alex/src/nvim-tree/r/2794/sfs 4ms
[2024-06-15 14:39:32] [profile] START view open
[2024-06-15 14:39:32] [profile] END view open 4ms
[2024-06-15 14:39:32] [profile] START draw
[2024-06-15 14:39:32] [profile] END draw 0ms
git bisect shows this to be the first bad commit
Very interesting, it does look like the type detection was changed there.
Are you interested in creating a pull request to fix this one @rag-hav ? I reckon you're the best one to find real world test cases ;)
Will look into it, but I don't really have any experience with this.
Thanks mate! Dev and contribution docs.
Out of curiousity, I checked out a previous commit, and found that this bug is actually a regression. I will run a git bisect to get the first bad commit.
Edit: according to git bisect, commit 2d97059 is the first bad commit.
Should be fixed in #2893. Waiting review and merge.
Thank you so much for fixing this. Now however, nvim-tree is extremely slow when using it on an sshfs mount, possibly because it is scanning the file system every time you open nvim tree. Is there a way to optimize this? Perhaps you could assume that when working on a mount, the current machine is the only one working on the file system and hence there is no need to update it every time?
@Thiggel I believe the slowness you are experiencing is network latency and not nvim-tree. Could you test the mount using a file explorer or ls/cd/cat to see if there is indeed network lag? I personally have not experienced slowness but I can investigate if the problem persists.
@mxple I have had a similar "lag" only when using R to reload the entire tree. Otherwise it was rather performant and enjoyable.
@Thiggel Unfortunately there's not much we can do here - nvim-tree has to look at each file.
Perhaps you could assume that when working on a mount, the current machine is the only one working on the file system and hence there is no need to update it every time?
You might like to experiment with filesystem watchers: disabling or enabling (default)
:help nvim-tree.filesystem_watchers.enable
You can be targeted about it, disabling them for specific directories:
:help nvim-tree.filesystem_watchers.ignore_dirs
@mxple I've had to revert #2920 this change as there was an issue with symlinks:
For symlinks:
vim.loop.fs_scandir_next returns a type "link"
vim.loop.fs_stat returns a type "file"
I'd be most grateful if we could work together to create a complete solution.
Hi @alex-courtis . Luckily, it seems there is a pretty simple fix where we replace fs_stat with fs_lstat in init.lua. I've tested it and it works. However, I noticed that a recent commit has broken sshfs compatibility. Running a bisect, it seems commit cd9c6db77f7c8b348dfa14d805ea28a69e5e718f is the first bad commit.
I believe I have fixed both issues in (#2922). Please test and review.
However, I noticed that a recent commit has broken sshfs compatibility. Running a bisect, it seems commit cd9c6db is the first bad commit.
Apologies, yes, that was a bad refactor/rebase.