@@ -8,18 +8,18 @@ local co = coroutine
88local 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
193193end
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
201201M .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
248245end
252249--- @param opts neotree.Config.GitStatusAsync
253250M .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 )
351350end
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
366375end
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
453458end
454459return M
0 commit comments