@@ -5,7 +5,7 @@ local git_utils = require("nvim-tree.git.utils")
55local GitRunner = require (" nvim-tree.git.runner" )
66local Watcher = require (" nvim-tree.watcher" ).Watcher
77local Iterator = require (" nvim-tree.iterators.node-iterator" )
8- local DirectoryNode = nil -- circular dependency
8+ local DirectoryNode = require ( " nvim-tree.node.directory " )
99
1010--- @class GitStatus -- xy short-format statuses
1111--- @field file string ?
@@ -289,46 +289,67 @@ function M.load_project_status(path)
289289 end
290290end
291291
292- --- Git file and directory status for an absolute path with optional file fallback
293- --- @param parent_ignored boolean
294- --- @param status table | nil
295- --- @param path string
296- --- @param path_file string ? alternative file path when no other file status
297- --- @return GitStatus | nil
298- function M .git_status_dir (parent_ignored , status , path , path_file )
299- if parent_ignored then
300- return { file = " !!" }
301- end
292+ --- @param dir DirectoryNode
293+ --- @param project table ?
294+ --- @param root string ?
295+ function M .update_parent_statuses (dir , project , root )
296+ while project and dir do
297+ -- step up to the containing project
298+ if dir .absolute_path == root then
299+ -- stop at the top of the tree
300+ if not dir .parent then
301+ break
302+ end
302303
303- if status then
304- return {
305- file = status .files and (status .files [path ] or status .files [path_file ]),
306- dir = status .dirs and {
307- direct = status .dirs .direct and status .dirs .direct [path ],
308- indirect = status .dirs .indirect and status .dirs .indirect [path ],
309- },
310- }
304+ root = M .get_toplevel (dir .parent .absolute_path )
305+
306+ -- stop when no more projects
307+ if not root then
308+ break
309+ end
310+
311+ -- update the containing project
312+ project = M .get_project (root )
313+ M .reload_project (root , dir .absolute_path , nil )
314+ end
315+
316+ -- update status
317+ dir :update_git_status (dir .parent and dir .parent :is_git_ignored () or false , project )
318+
319+ -- maybe parent
320+ dir = dir .parent
311321 end
312322end
313323
314- --- Git file status for an absolute path with optional fallback
315- --- @param parent_ignored boolean
316- --- @param status table | nil
317- --- @param path string
318- --- @param path_fallback string ?
319- --- @return GitStatus
320- function M .git_status_file (parent_ignored , status , path , path_fallback )
321- if parent_ignored then
322- return { file = " !!" }
323- end
324+ --- Refresh contents and git status for a single directory
325+ --- @param dir DirectoryNode
326+ function M .refresh_dir (dir )
327+ local node = dir :get_parent_of_group () or dir
328+ local toplevel = M .get_toplevel (dir .absolute_path )
324329
325- if not status or not status .files then
326- return {}
327- end
330+ M .reload_project (toplevel , dir .absolute_path , function ()
331+ local project = M .get_project (toplevel ) or {}
328332
329- return {
330- file = status .files [path ] or status .files [path_fallback ]
331- }
333+ dir .explorer :reload (node , project )
334+
335+ M .update_parent_statuses (dir , project , toplevel )
336+
337+ dir .explorer .renderer :draw ()
338+ end )
339+ end
340+
341+ --- @param n DirectoryNode
342+ --- @param projects table
343+ function M .reload_node_status (n , projects )
344+ local toplevel = M .get_toplevel (n .absolute_path )
345+ local status = projects [toplevel ] or {}
346+ for _ , node in ipairs (n .nodes ) do
347+ node :update_git_status (n :is_git_ignored (), status )
348+ local dir = node :as (DirectoryNode )
349+ if dir and # dir .nodes > 0 then
350+ dir :reload_node_status (projects )
351+ end
352+ end
332353end
333354
334355function M .purge_state ()
355376function M .setup (opts )
356377 M .config .git = opts .git
357378 M .config .filesystem_watchers = opts .filesystem_watchers
358- DirectoryNode = require (" nvim-tree.node.directory" )
359379end
360380
361381return M
0 commit comments