Skip to content

Commit 02a4b43

Browse files
committed
more gitignore refactoring
1 parent 9f448b7 commit 02a4b43

File tree

2 files changed

+110
-105
lines changed

2 files changed

+110
-105
lines changed

lua/neo-tree/git/init.lua

Lines changed: 109 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,18 @@ local co = coroutine
88
local M = {}
99

1010
---@type table<string, neotree.git.Status>
11-
M.cache = setmetatable({}, {
12-
__mode = "kv",
11+
M.status_cache = setmetatable({}, {
12+
__mode = "v",
1313
__newindex = function(_, root_dir, status)
1414
require("neo-tree.sources.filesystem.lib.fs_watch").on_destroyed(root_dir, function()
15-
rawset(M.cache, root_dir, nil)
15+
rawset(M.status_cache, root_dir, nil)
1616
end)
17-
rawset(M.cache, root_dir, status)
17+
rawset(M.status_cache, root_dir, status)
1818
end,
1919
})
2020

2121
---@class (exact) neotree.git.Context : neotree.Config.GitStatusAsync
22-
---@field git_status neotree.git.Status
22+
---@field git_status neotree.git.Status?
2323
---@field git_root string
2424
---@field lines_parsed integer
2525

@@ -188,7 +188,7 @@ local parse_porcelain_output = function(git_root, status_iter, batch_size, skip_
188188
yield_if_batch_completed()
189189
end
190190

191-
M.cache[git_root] = git_status
191+
M.status_cache[git_root] = git_status
192192
return git_status
193193
end
194194
---@alias neotree.git.Status table<string, string>
@@ -197,14 +197,11 @@ end
197197
---@param base string git ref base
198198
---@param skip_bubbling boolean? Whether to skip bubling up status to directories
199199
---@param path string? Path to run the git status command in, defaults to cwd.
200-
---@return neotree.git.Status, string? git_status the neotree.Git.Status of the given root
200+
---@return neotree.git.Status?, string? git_status the neotree.Git.Status of the given root, if there's a valid git status there
201201
M.status = function(base, skip_bubbling, path)
202202
local git_root = M.get_repository_root(path)
203203
if not utils.truthy(git_root) then
204-
if git_root then
205-
M.cache[git_root] = {}
206-
end
207-
return {}
204+
return nil
208205
end
209206
---@cast git_root -nil
210207

@@ -222,27 +219,27 @@ M.status = function(base, skip_bubbling, path)
222219
local status_result = vim.fn.system(status_cmd)
223220

224221
local status_ok = vim.v.shell_error == 0
225-
if not status_ok then
226-
M.cache[git_root] = {}
227-
return {}
228-
end
229-
230-
-- system() replaces \000 with \001
231-
local status_iter = vim.gsplit(status_result, "\001", { plain = true })
232-
local gs = parse_porcelain_output(git_root, status_iter, nil, skip_bubbling)
233-
222+
---@type neotree.git.Context
234223
local context = {
235224
git_root = git_root,
236-
git_status = gs,
225+
git_status = nil,
237226
lines_parsed = 0,
238227
}
239228

240-
vim.schedule(function()
241-
events.fire_event(events.GIT_STATUS_CHANGED, {
242-
git_root = context.git_root,
243-
git_status = context.git_status,
244-
})
245-
end)
229+
if status_ok then
230+
-- system() replaces \000 with \001
231+
local status_iter = vim.gsplit(status_result, "\001", { plain = true })
232+
local gs = parse_porcelain_output(git_root, status_iter, nil, skip_bubbling)
233+
234+
context.git_status = gs
235+
vim.schedule(function()
236+
events.fire_event(events.GIT_STATUS_CHANGED, {
237+
git_root = context.git_root,
238+
git_status = context.git_status,
239+
})
240+
end)
241+
M.status_cache[git_root] = {}
242+
end
246243

247244
return context.git_status, git_root
248245
end
@@ -252,10 +249,7 @@ end
252249
---@param opts neotree.Config.GitStatusAsync
253250
M.status_async = function(path, base, opts)
254251
M.get_repository_root(path, function(git_root)
255-
if not utils.truthy(git_root) then
256-
if git_root then
257-
M.cache[git_root] = {}
258-
end
252+
if not git_root then
259253
log.trace("status_async: not a git folder:", path)
260254
return
261255
end
@@ -297,22 +291,27 @@ M.status_async = function(path, base, opts)
297291
},
298292
stdio = { stdin, stdout, stderr },
299293
}, function(code, signal)
300-
log.assert(
301-
code == 0,
302-
"git status async process exited abnormally, code: %s, signal: %s",
303-
code,
304-
signal
305-
)
294+
if code ~= 0 then
295+
log.at.debug.format(
296+
"git status async process exited abnormally, code: %s, signal: %s",
297+
code,
298+
signal
299+
)
300+
return
301+
end
306302
local str = output_chunks[1]
307303
if #output_chunks > 1 then
308304
str = table.concat(output_chunks, "")
309305
end
310-
assert(str)
311306
local status_iter = vim.gsplit(str, "\000", { plain = true })
312307
local parsing_task = co.create(parse_porcelain_output)
313308
local _, git_status =
314309
log.assert(co.resume(parsing_task, git_root, status_iter, context.batch_size))
315310

311+
stdin:shutdown()
312+
stdout:shutdown()
313+
stderr:shutdown()
314+
316315
local do_next_batch_later
317316
do_next_batch_later = function()
318317
if co.status(parsing_task) ~= "dead" then
@@ -321,7 +320,7 @@ M.status_async = function(path, base, opts)
321320
return
322321
end
323322
context.git_status = git_status
324-
M.cache[git_root] = git_status
323+
M.status_cache[git_root] = git_status
325324
vim.schedule(function()
326325
events.fire_event(events.GIT_STATUS_CHANGED, {
327326
git_root = context.git_root,
@@ -350,30 +349,50 @@ M.status_async = function(path, base, opts)
350349
end)
351350
end
352351

353-
M.is_ignored = function(path)
354-
local git_root = M.get_repository_root(path)
355-
if not git_root then
356-
return false
357-
end
358-
if not M.cache[git_root] then
359-
M.status("HEAD", false, path)
360-
end
361-
local direct_lookup = M.cache[git_root][path] or M.cache[git_root][path .. utils.path_separator]
362-
if direct_lookup then
363-
vim.print(direct_lookup, path)
364-
return direct_lookup == "!"
352+
---@param state neotree.State
353+
---@param items neotree.FileItem[]
354+
M.mark_ignored = function(state, items)
355+
for _, i in ipairs(items) do
356+
repeat
357+
local path = i.path
358+
local git_root = M.get_repository_root(path)
359+
if not git_root then
360+
break
361+
end
362+
local status = M.status_cache[git_root] or M.status("HEAD", false, path)
363+
if not status then
364+
break
365+
end
366+
367+
local direct_lookup = M.status_cache[git_root][path]
368+
or M.status_cache[git_root][path .. utils.path_separator]
369+
if direct_lookup then
370+
i.filtered_by = i.filtered_by or {}
371+
i.filtered_by.gitignored = true
372+
end
373+
until true
365374
end
366375
end
367376

368377
---@type table<string, string|false>
369-
local git_rootdir_cache = setmetatable({}, { __mode = "kv" })
370-
---@param path string? Defaults to cwd
371-
---@param callback fun(git_root: string|false?)?
372-
---@return string?
373-
M.get_repository_root = function(path, callback)
374-
path = path or log.assert(vim.uv.cwd())
375-
376-
do -- direct lookup in cache
378+
do
379+
local git_rootdir_cache = setmetatable({}, { __mode = "kv" })
380+
local finalize = function(path, git_root)
381+
if utils.is_windows then
382+
git_root = utils.windowize_path(git_root)
383+
end
384+
385+
log.trace("GIT ROOT for '", path, "' is '", git_root, "'")
386+
git_rootdir_cache[path] = git_root
387+
git_rootdir_cache[git_root] = git_root
388+
end
389+
390+
---@param path string? Defaults to cwd
391+
---@param callback fun(git_root: string?)?
392+
---@return string?
393+
M.get_repository_root = function(path, callback)
394+
path = path or log.assert(vim.uv.cwd())
395+
377396
local cached_rootdir = git_rootdir_cache[path]
378397
if cached_rootdir ~= nil then
379398
log.trace("git.get_repository_root: cache hit for", path, "was", cached_rootdir)
@@ -383,9 +402,7 @@ M.get_repository_root = function(path, callback)
383402
end
384403
return cached_rootdir
385404
end
386-
end
387405

388-
do -- check parents in cache
389406
for parent in utils.path_parents(path, true) do
390407
local cached_parent_entry = git_rootdir_cache[parent]
391408
if cached_parent_entry ~= nil then
@@ -401,54 +418,42 @@ M.get_repository_root = function(path, callback)
401418
return cached_parent_entry
402419
end
403420
end
404-
end
405-
406-
log.trace("git.get_repository_root: cache miss for", path)
407-
local args = { "-C", path, "rev-parse", "--show-toplevel" }
408421

409-
if type(callback) == "function" then
410-
---@diagnostic disable-next-line: missing-fields
411-
Job:new({
412-
command = "git",
413-
args = args,
414-
enabled_recording = true,
415-
on_exit = function(self, code, _)
416-
if code ~= 0 then
417-
log.trace("GIT ROOT ERROR", self:stderr_result())
418-
git_rootdir_cache[path] = false
419-
callback(nil)
420-
return
421-
end
422-
local git_root = self:result()[1]
422+
log.trace("git.get_repository_root: cache miss for", path)
423+
local args = { "-C", path, "rev-parse", "--show-toplevel" }
423424

424-
if utils.is_windows then
425-
git_root = utils.windowize_path(git_root)
426-
end
425+
if type(callback) == "function" then
426+
---@diagnostic disable-next-line: missing-fields
427+
Job:new({
428+
command = "git",
429+
args = args,
430+
enabled_recording = true,
431+
on_exit = function(self, code, _)
432+
if code ~= 0 then
433+
log.trace("GIT ROOT ERROR", self:stderr_result())
434+
git_rootdir_cache[path] = false
435+
callback(nil)
436+
return
437+
end
438+
local git_root = self:result()[1]
427439

428-
log.trace("GIT ROOT for '", path, "' is '", git_root, "'")
429-
git_rootdir_cache[path] = git_root
430-
git_rootdir_cache[git_root] = git_root
431-
callback(git_root)
432-
end,
433-
}):start()
434-
return
435-
end
440+
finalize(path, git_root)
441+
callback(git_root)
442+
end,
443+
}):start()
444+
return
445+
end
436446

437-
local ok, git_output = utils.execute_command({ "git", unpack(args) })
438-
if not ok then
439-
log.trace("GIT ROOT ERROR", git_output)
440-
git_rootdir_cache[path] = false
441-
return nil
442-
end
443-
local git_root = git_output[1]
447+
local ok, git_output = utils.execute_command({ "git", unpack(args) })
448+
if not ok then
449+
log.trace("GIT ROOT NOT FOUND", git_output)
450+
git_rootdir_cache[path] = false
451+
return nil
452+
end
453+
local git_root = git_output[1]
444454

445-
if utils.is_windows then
446-
git_root = utils.windowize_path(git_root)
455+
finalize(path, git_root)
456+
return git_root
447457
end
448-
449-
log.trace("GIT ROOT for '", path, "' is '", git_root, "'")
450-
git_rootdir_cache[path] = path
451-
git_rootdir_cache[git_root] = git_root
452-
return git_root
453458
end
454459
return M

lua/neo-tree/sources/common/components.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ M.filtered_by = function(_, node, state)
354354
text = "(hide by pattern)",
355355
highlight = highlights.HIDDEN_BY_NAME,
356356
}
357-
elseif require("neo-tree.git").is_ignored(node.path) then
357+
elseif fby.gitignored then
358358
return {
359359
text = "(gitignored)",
360360
highlight = highlights.GIT_IGNORED,

0 commit comments

Comments
 (0)