Skip to content

Commit 29788cc

Browse files
authored
fix(git): git folder fixes and improvements (#1809)
* coding style * outlined git.show_on_open_dirs behavior * show some icon on opendir even if show_on_open_dir=false and show all children's status on parent * fixed renamed icon not showing * sorted icons * removed DU from deleted as file will show up in tree * fixed update_git_status in reloaders not tested * fixed Api.git.reload() Tested update_git_status in reloaders.lua * sort icon only if not git signcolumn * fixed crashing when root dir isn't git dir * made git.show_on_dirs doc more concise * git_statuses -> git_status for consistency * explorer/common.lua -> explorer/node.lua * fixed #1784 conflict * don't order icons * Revert "don't order icons" This reverts commit 23f6276.
1 parent 89c79cb commit 29788cc

File tree

13 files changed

+263
-189
lines changed

13 files changed

+263
-189
lines changed

doc/nvim-tree-lua.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -599,7 +599,7 @@ Git integration with icons and colors.
599599
Type: `boolean`, Default: `true`
600600

601601
*nvim-tree.git.show_on_open_dirs*
602-
Show status icons on directories that are open.
602+
Show status icons of children on directories that are open.
603603
Only relevant when `git.show_on_dirs` is `true`.
604604
Type: `boolean`, Default: `true`
605605

lua/nvim-tree/actions/moves/item.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ local utils = require "nvim-tree.utils"
22
local view = require "nvim-tree.view"
33
local core = require "nvim-tree.core"
44
local lib = require "nvim-tree.lib"
5-
local explorer_common = require "nvim-tree.explorer.common"
5+
local explorer_node = require "nvim-tree.explorer.node"
66

77
local M = {}
88

@@ -15,7 +15,7 @@ function M.fn(where, what)
1515
for line, node in pairs(nodes_by_line) do
1616
local valid = false
1717
if what == "git" then
18-
valid = explorer_common.shows_git_status(node)
18+
valid = explorer_node.get_git_status(node) ~= nil
1919
elseif what == "diag" then
2020
valid = node.diag_status ~= nil
2121
end

lua/nvim-tree/actions/reloaders/reloaders.lua

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ local view = require "nvim-tree.view"
33
local renderer = require "nvim-tree.renderer"
44
local explorer_module = require "nvim-tree.explorer"
55
local core = require "nvim-tree.core"
6+
local explorer_node = require "nvim-tree.explorer.node"
67

78
local M = {}
89

@@ -21,11 +22,7 @@ function M.reload_node_status(parent_node, projects)
2122
local project_root = git.get_project_root(parent_node.absolute_path)
2223
local status = projects[project_root] or {}
2324
for _, node in ipairs(parent_node.nodes) do
24-
if node.nodes then
25-
node.git_status = status.dirs and status.dirs[node.absolute_path]
26-
else
27-
node.git_status = status.files and status.files[node.absolute_path]
28-
end
25+
explorer_node.update_git_status(node, explorer_node.is_git_ignored(parent_node), status)
2926
if node.nodes and #node.nodes > 0 then
3027
M.reload_node_status(node, projects)
3128
end
@@ -50,7 +47,7 @@ function M.reload_explorer(_, unloaded_bufnr)
5047
end
5148

5249
function M.reload_git()
53-
if not core.get_explorer() or not git.config.enable or event_running then
50+
if not core.get_explorer() or not git.config.git.enable or event_running then
5451
return
5552
end
5653
event_running = true

lua/nvim-tree/explorer/common.lua

Lines changed: 0 additions & 74 deletions
This file was deleted.

lua/nvim-tree/explorer/explore.lua

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
local utils = require "nvim-tree.utils"
22
local builders = require "nvim-tree.explorer.node-builders"
3-
local common = require "nvim-tree.explorer.common"
3+
local explorer_node = require "nvim-tree.explorer.node"
44
local sorters = require "nvim-tree.explorer.sorters"
55
local filters = require "nvim-tree.explorer.filters"
66
local live_filter = require "nvim-tree.live-filter"
@@ -14,7 +14,7 @@ local function get_type_from(type_, cwd)
1414
end
1515

1616
local function populate_children(handle, cwd, node, git_status)
17-
local node_ignored = node.git_status == "!!"
17+
local node_ignored = explorer_node.is_git_ignored(node)
1818
local nodes_by_path = utils.bool_record(node.nodes, "absolute_path")
1919
local filter_status = filters.prepare(git_status)
2020
while true do
@@ -40,7 +40,7 @@ local function populate_children(handle, cwd, node, git_status)
4040
if child then
4141
table.insert(node.nodes, child)
4242
nodes_by_path[child.absolute_path] = true
43-
common.update_git_status(child, node_ignored, git_status)
43+
explorer_node.update_git_status(child, node_ignored, git_status)
4444
end
4545
end
4646
end
@@ -68,7 +68,7 @@ function M.explore(node, status)
6868
populate_children(handle, cwd, node, status)
6969

7070
local is_root = not node.parent
71-
local child_folder_only = common.has_one_child_folder(node) and node.nodes[1]
71+
local child_folder_only = explorer_node.has_one_child_folder(node) and node.nodes[1]
7272
if M.config.group_empty and not is_root and child_folder_only then
7373
node.group_next = child_folder_only
7474
local ns = M.explore(child_folder_only, status)

lua/nvim-tree/explorer/filters.lua

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,17 @@ local function git(path, git_status)
2424
end
2525

2626
-- default status to clean
27-
local status = git_status.files[path] or git_status.dirs[path] or " "
27+
local status = git_status.files[path]
28+
status = status or git_status.dirs.direct[path] and git_status.dirs.direct[path][1]
29+
status = status or git_status.dirs.indirect[path] and git_status.dirs.indirect[path][1]
2830

2931
-- filter ignored; overrides clean as they are effectively dirty
3032
if M.config.filter_git_ignored and status == "!!" then
3133
return true
3234
end
3335

3436
-- filter clean
35-
if M.config.filter_git_clean and status == " " then
37+
if M.config.filter_git_clean and not status then
3638
return true
3739
end
3840

lua/nvim-tree/explorer/init.lua

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
local git = require "nvim-tree.git"
22
local watch = require "nvim-tree.explorer.watch"
3-
local common = require "nvim-tree.explorer.common"
3+
local explorer_node = require "nvim-tree.explorer.node"
44

55
local M = {}
66

@@ -24,8 +24,8 @@ end
2424

2525
function Explorer:_load(node)
2626
local cwd = node.link_to or node.absolute_path
27-
local git_statuses = git.load_project_status(cwd)
28-
M.explore(node, git_statuses)
27+
local git_status = git.load_project_status(cwd)
28+
M.explore(node, git_status)
2929
end
3030

3131
function Explorer:expand(node)
@@ -34,7 +34,7 @@ end
3434

3535
function Explorer:destroy()
3636
local function iterate(node)
37-
common.node_destroy(node)
37+
explorer_node.node_destroy(node)
3838
if node.nodes then
3939
for _, child in pairs(node.nodes) do
4040
iterate(child)
@@ -45,7 +45,7 @@ function Explorer:destroy()
4545
end
4646

4747
function M.setup(opts)
48-
require("nvim-tree.explorer.common").setup(opts)
48+
require("nvim-tree.explorer.node").setup(opts)
4949
require("nvim-tree.explorer.explore").setup(opts)
5050
require("nvim-tree.explorer.filters").setup(opts)
5151
require("nvim-tree.explorer.sorters").setup(opts)

lua/nvim-tree/explorer/node.lua

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
local M = {}
2+
3+
-- node.git_status structure:
4+
-- {
5+
-- file = string | nil,
6+
-- dir = {
7+
-- direct = { string } | nil,
8+
-- indirect = { string } | nil,
9+
-- } | nil,
10+
-- }
11+
12+
local function get_dir_git_status(parent_ignored, status, absolute_path)
13+
if parent_ignored then
14+
return { file = "!!" }
15+
end
16+
17+
return {
18+
file = status.files and status.files[absolute_path],
19+
dir = status.dirs and {
20+
direct = status.dirs.direct[absolute_path],
21+
indirect = status.dirs.indirect[absolute_path],
22+
},
23+
}
24+
end
25+
26+
local function get_git_status(parent_ignored, status, absolute_path)
27+
local file_status = parent_ignored and "!!" or status.files and status.files[absolute_path]
28+
return { file = file_status }
29+
end
30+
31+
function M.has_one_child_folder(node)
32+
return #node.nodes == 1 and node.nodes[1].nodes and vim.loop.fs_access(node.nodes[1].absolute_path, "R")
33+
end
34+
35+
function M.update_git_status(node, parent_ignored, status)
36+
local get_status
37+
if node.nodes then
38+
get_status = get_dir_git_status
39+
else
40+
get_status = get_git_status
41+
end
42+
43+
-- status of the node's absolute path
44+
node.git_status = get_status(parent_ignored, status, node.absolute_path)
45+
46+
-- status of the link target, if the link itself is not dirty
47+
if node.link_to and not node.git_status then
48+
node.git_status = get_status(parent_ignored, status, node.link_to)
49+
end
50+
end
51+
52+
function M.get_git_status(node)
53+
local git_status = node.git_status
54+
if not git_status then
55+
-- status doesn't exist
56+
return nil
57+
end
58+
59+
if not node.nodes then
60+
-- file
61+
return git_status.file and { git_status.file }
62+
end
63+
64+
-- dir
65+
if not M.config.git.show_on_dirs then
66+
return nil
67+
end
68+
69+
local status = {}
70+
if not node.open or M.config.git.show_on_open_dirs then
71+
-- dir is closed or we should show on open_dirs
72+
if git_status.file ~= nil then
73+
table.insert(status, git_status.file)
74+
end
75+
if git_status.dir ~= nil then
76+
if git_status.dir.direct ~= nil then
77+
for _, s in pairs(node.git_status.dir.direct) do
78+
table.insert(status, s)
79+
end
80+
end
81+
if git_status.dir.indirect ~= nil then
82+
for _, s in pairs(node.git_status.dir.indirect) do
83+
table.insert(status, s)
84+
end
85+
end
86+
end
87+
else
88+
-- dir is open and we shouldn't show on open_dirs
89+
if git_status.file ~= nil then
90+
table.insert(status, git_status.file)
91+
end
92+
if git_status.dir ~= nil and git_status.dir.direct ~= nil then
93+
local deleted = {
94+
[" D"] = true,
95+
["D "] = true,
96+
["RD"] = true,
97+
["DD"] = true,
98+
}
99+
for _, s in pairs(node.git_status.dir.direct) do
100+
if deleted[s] then
101+
table.insert(status, s)
102+
end
103+
end
104+
end
105+
end
106+
if #status == 0 then
107+
return nil
108+
else
109+
return status
110+
end
111+
end
112+
113+
function M.is_git_ignored(node)
114+
return node.git_status and node.git_status.file == "!!"
115+
end
116+
117+
function M.node_destroy(node)
118+
if not node then
119+
return
120+
end
121+
122+
if node.watcher then
123+
node.watcher:destroy()
124+
end
125+
end
126+
127+
function M.setup(opts)
128+
M.config = {
129+
git = opts.git,
130+
}
131+
end
132+
133+
return M

0 commit comments

Comments
 (0)