Skip to content

Commit 386c6f7

Browse files
authored
feat(watcher): fs_poll -> fs_event, destroy nodes/watchers (#1431)
1 parent be18bf8 commit 386c6f7

File tree

7 files changed

+56
-32
lines changed

7 files changed

+56
-32
lines changed

lua/nvim-tree/core.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ local first_init_done = false
1010

1111
function M.init(foldername)
1212
if TreeExplorer then
13-
TreeExplorer:_clear_watchers()
13+
TreeExplorer:destroy()
1414
end
1515
TreeExplorer = explorer.Explorer.new(foldername)
1616
if not first_init_done then

lua/nvim-tree/explorer/common.lua

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,16 @@ function M.update_git_status(node, parent_ignored, status)
4343
end
4444
end
4545

46+
function M.node_destroy(node)
47+
if not node then
48+
return
49+
end
50+
51+
if node.watcher then
52+
node.watcher:destroy()
53+
end
54+
end
55+
4656
function M.setup(opts)
4757
M.config = {
4858
git = opts.git,

lua/nvim-tree/explorer/init.lua

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ local uv = vim.loop
22

33
local git = require "nvim-tree.git"
44
local watch = require "nvim-tree.explorer.watch"
5+
local common = require "nvim-tree.explorer.common"
56

67
local M = {}
78

@@ -33,22 +34,16 @@ function Explorer:expand(node)
3334
self:_load(node)
3435
end
3536

36-
function Explorer.clear_watchers_for(root_node)
37+
function Explorer:destroy()
3738
local function iterate(node)
38-
if node.watcher then
39-
node.watcher:stop()
39+
common.node_destroy(node)
40+
if node.nodes then
4041
for _, child in pairs(node.nodes) do
41-
if child.watcher then
42-
iterate(child)
43-
end
42+
iterate(child)
4443
end
4544
end
4645
end
47-
iterate(root_node)
48-
end
49-
50-
function Explorer:_clear_watchers()
51-
Explorer.clear_watchers_for(self)
46+
iterate(self)
5247
end
5348

5449
function M.setup(opts)

lua/nvim-tree/explorer/reload.lua

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,12 @@ function M.reload(node, status)
6969
node.nodes = vim.tbl_map(
7070
update_status(nodes_by_path, node_ignored, status),
7171
vim.tbl_filter(function(n)
72-
return child_names[n.absolute_path]
72+
if child_names[n.absolute_path] then
73+
return child_names[n.absolute_path]
74+
else
75+
common.node_destroy(n)
76+
return nil
77+
end
7378
end, node.nodes)
7479
)
7580

lua/nvim-tree/explorer/watch.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ function M.create_watcher(absolute_path)
4646
end
4747

4848
log.line("watcher", "node start '%s'", absolute_path)
49-
Watcher.new {
49+
return Watcher.new {
5050
absolute_path = absolute_path,
5151
interval = M.interval,
5252
on_event = function(opts)

lua/nvim-tree/git/init.lua

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ function M.reload_project(project_root, path)
2929
return
3030
end
3131

32-
if path and not path:match("^" .. project_root) then
33-
path = nil
32+
if path and path:find(project_root, 1, true) ~= 1 then
33+
return
3434
end
3535

3636
local git_status = Runner.run {
@@ -43,7 +43,7 @@ function M.reload_project(project_root, path)
4343

4444
if path then
4545
for p in pairs(project.files) do
46-
if p:match("^" .. path) then
46+
if p:find(path, 1, true) == 1 then
4747
project.files[p] = nil
4848
end
4949
end

lua/nvim-tree/watcher.lua

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@ local M = {
99
local Watcher = {}
1010
Watcher.__index = Watcher
1111

12+
local FS_EVENT_FLAGS = {
13+
-- inotify or equivalent will be used; fallback to stat has not yet been implemented
14+
stat = false,
15+
-- recursive is not functional in neovim's libuv implementation
16+
recursive = false,
17+
}
18+
1219
function Watcher.new(opts)
1320
for _, existing in ipairs(M._watchers) do
1421
if existing._opts.absolute_path == opts.absolute_path then
@@ -35,48 +42,55 @@ function Watcher:start()
3542

3643
local rc, _, name
3744

38-
self._p, _, name = uv.new_fs_poll()
39-
if not self._p then
40-
self._p = nil
45+
self._e, _, name = uv.new_fs_event()
46+
if not self._e then
47+
self._e = nil
4148
utils.warn(
42-
string.format("Could not initialize an fs_poll watcher for path %s : %s", self._opts.absolute_path, name)
49+
string.format("Could not initialize an fs_event watcher for path %s : %s", self._opts.absolute_path, name)
4350
)
4451
return nil
4552
end
4653

47-
local poll_cb = vim.schedule_wrap(function(err)
54+
local event_cb = vim.schedule_wrap(function(err, filename, events)
4855
if err then
49-
log.line("watcher", "poll_cb for %s fail : %s", self._opts.absolute_path, err)
56+
log.line("watcher", "event_cb for %s fail : %s", self._opts.absolute_path, err)
5057
else
58+
log.line("watcher", "event_cb '%s' '%s' %s", self._opts.absolute_path, filename, vim.inspect(events))
5159
self._opts.on_event(self._opts)
5260
end
5361
end)
5462

55-
rc, _, name = uv.fs_poll_start(self._p, self._opts.absolute_path, self._opts.interval, poll_cb)
63+
rc, _, name = self._e:start(self._opts.absolute_path, FS_EVENT_FLAGS, event_cb)
5664
if rc ~= 0 then
57-
utils.warn(string.format("Could not start the fs_poll watcher for path %s : %s", self._opts.absolute_path, name))
65+
utils.warn(string.format("Could not start the fs_event watcher for path %s : %s", self._opts.absolute_path, name))
5866
return nil
5967
end
6068

6169
return self
6270
end
6371

64-
function Watcher:stop()
65-
log.line("watcher", "Watcher:stop '%s'", self._opts.absolute_path)
66-
if self._p then
67-
local rc, _, name = uv.fs_poll_stop(self._p)
72+
function Watcher:destroy()
73+
log.line("watcher", "Watcher:destroy '%s'", self._opts.absolute_path)
74+
if self._e then
75+
local rc, _, name = self._e:stop()
6876
if rc ~= 0 then
69-
utils.warn(string.format("Could not stop the fs_poll watcher for path %s : %s", self._opts.absolute_path, name))
77+
utils.warn(string.format("Could not stop the fs_event watcher for path %s : %s", self._opts.absolute_path, name))
78+
end
79+
self._e = nil
80+
end
81+
for i, w in ipairs(M._watchers) do
82+
if w == self then
83+
table.remove(M._watchers, i)
84+
break
7085
end
71-
self._p = nil
7286
end
7387
end
7488

7589
M.Watcher = Watcher
7690

7791
function M.purge_watchers()
7892
for _, watcher in pairs(M._watchers) do
79-
watcher:stop()
93+
watcher:destroy()
8094
end
8195
M._watchers = {}
8296
end

0 commit comments

Comments
 (0)