Skip to content

Commit 71d5559

Browse files
authored
fix: prevent "too many open files" errors from git ignored check (#1127)
fixes #1125, fixes #997
1 parent fee5845 commit 71d5559

File tree

3 files changed

+58
-18
lines changed

3 files changed

+58
-18
lines changed

lua/neo-tree/defaults.lua

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,9 @@ local config = {
444444
sidebar = "tab", -- sidebar is when position = left or right
445445
current = "window" -- current is when position = current
446446
},
447+
check_gitignore_in_search = true, -- check gitignore status for files/directories when searching
448+
-- setting this to false will speed up searches, but gitignored
449+
-- items won't be marked if they are visible.
447450
-- The renderer section provides the renderers that will be used to render the tree.
448451
-- The first level is the node type.
449452
-- For each node type, you can specify a list of components to render.

lua/neo-tree/git/ignored.lua

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,29 @@ M.mark_ignored = function(state, items, callback)
104104
local all_results = {}
105105
if type(callback) == "function" then
106106
local jobs = {}
107-
local progress = 0
107+
local running_jobs = 0
108+
local job_count = 0
109+
local completed_jobs = 0
110+
111+
-- This is called when a job completes, and starts the next job if there are any left
112+
-- or calls the callback if all jobs are complete.
113+
-- It is also called once at the start to start the first 50 jobs.
114+
--
115+
-- This is done to avoid running too many jobs at once, which can cause a crash from
116+
-- having too many open files.
117+
local run_more_jobs = function()
118+
while #jobs > 0 and running_jobs < 50 and job_count > completed_jobs do
119+
local next_job = table.remove(jobs, #jobs)
120+
next_job:start()
121+
running_jobs = running_jobs + 1
122+
end
123+
124+
if completed_jobs == job_count then
125+
finalize(all_results)
126+
callback(all_results)
127+
end
128+
end
129+
108130
for folder, folder_items in pairs(folders) do
109131
local args = { "-C", folder, "check-ignore", "--stdin" }
110132
local job = Job:new({
@@ -124,19 +146,17 @@ M.mark_ignored = function(state, items, callback)
124146
result = self:result()
125147
end
126148
vim.list_extend(all_results, process_result(result))
127-
progress = progress + 1
128-
if progress == #jobs then
129-
finalize(all_results)
130-
callback(all_results)
131-
end
149+
150+
running_jobs = running_jobs - 1
151+
completed_jobs = completed_jobs + 1
152+
run_more_jobs()
132153
end,
133154
})
134155
table.insert(jobs, job)
156+
job_count = job_count + 1
135157
end
136158

137-
for _, job in ipairs(jobs) do
138-
job:start()
139-
end
159+
run_more_jobs()
140160
else
141161
for folder, folder_items in pairs(folders) do
142162
local cmd = { "git", "-C", folder, "check-ignore", unpack(folder_items) }

lua/neo-tree/sources/filesystem/lib/fs_scan.lua

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,32 @@ local render_context = function(context)
103103
context = nil
104104
end
105105

106-
local job_complete_async = function(context)
106+
local should_check_gitignore = function (context)
107107
local state = context.state
108-
local parent_id = context.parent_id
109108
if #context.all_items == 0 then
110109
log.info("No items, skipping git ignored/status lookups")
111-
elseif state.filtered_items.hide_gitignored or state.enable_git_status then
110+
return false
111+
end
112+
if state.search_pattern and state.check_gitignore_in_search == false then
113+
return false
114+
end
115+
if state.filtered_items.hide_gitignored then
116+
return true
117+
end
118+
if not state.enable_git_status then
119+
return true
120+
end
121+
return false
122+
end
123+
124+
local job_complete_async = function(context)
125+
local state = context.state
126+
local parent_id = context.parent_id
127+
-- if state.search_pattern and #context.all_items > 50 then
128+
-- -- don't do git ignored/status lookups when searching unless we are down to a reasonable number of items
129+
-- return context
130+
-- end
131+
if should_check_gitignore(context) then
112132
local mark_ignored_async = async.wrap(function (_state, _all_items, _callback)
113133
git.mark_ignored(_state, _all_items, _callback)
114134
end, 3)
@@ -126,12 +146,7 @@ end
126146
local job_complete = function(context)
127147
local state = context.state
128148
local parent_id = context.parent_id
129-
if #context.all_items == 0 then
130-
log.info("No items, skipping git ignored/status lookups")
131-
render_context(context)
132-
return
133-
end
134-
if state.filtered_items.hide_gitignored or state.enable_git_status then
149+
if should_check_gitignore(context) then
135150
if require("neo-tree").config.git_status_async then
136151
git.mark_ignored(state, context.all_items, function(all_items)
137152
if parent_id then
@@ -153,6 +168,8 @@ local job_complete = function(context)
153168
end
154169
end
155170
render_context(context)
171+
else
172+
render_context(context)
156173
end
157174
end
158175

0 commit comments

Comments
 (0)