Skip to content

fix(git): make mark_ignored async #621

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Dec 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 71 additions & 29 deletions lua/neo-tree/git/ignored.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
local Job = require("plenary.job")

local utils = require("neo-tree.utils")
local log = require("neo-tree.log")
local git_utils = require("neo-tree.git.utils")
Expand Down Expand Up @@ -38,10 +40,11 @@ local get_root_for_item = function(item)
return root
end

M.mark_ignored = function(state, items)
M.mark_ignored = function(state, items, callback)
local folders = {}
log.trace("================================================================================")
log.trace("IGNORED: mark_ignore BEGIN...")

for _, item in ipairs(items) do
local folder = utils.split_path(item.path)
if folder then
Expand All @@ -52,19 +55,7 @@ M.mark_ignored = function(state, items)
end
end

local all_results = {}
for folder, folder_items in pairs(folders) do
local cmd = { "git", "-C", folder, "check-ignore" }
for _, item in ipairs(folder_items) do
table.insert(cmd, item)
end
log.trace("IGNORED: Running cmd: ", cmd)
local result = vim.fn.systemlist(cmd)
if vim.v.shell_error == 128 then
log.debug("Failed to load ignored files for", state.path, ":", result)
result = {}
end

local function process_result(result)
if utils.is_windows then
--on Windows, git seems to return quotes and double backslash "path\\directory"
result = vim.tbl_map(function(item)
Expand All @@ -83,26 +74,77 @@ M.mark_ignored = function(state, items)
end
end
end
return result
end

vim.list_extend(all_results, result)
local function finalize(all_results)
local show_anyway = state.filtered_items and state.filtered_items.hide_gitignored == false
log.trace("IGNORED: Comparing results to mark items as ignored, show_anyway:", show_anyway)
local ignored, not_ignored = 0, 0
for _, item in ipairs(items) do
if M.is_ignored(all_results, item.path, item.type) then
item.filtered_by = item.filtered_by or {}
item.filtered_by.gitignored = true
item.filtered_by.show_anyway = show_anyway
ignored = ignored + 1
else
not_ignored = not_ignored + 1
end
end
log.trace("IGNORED: mark_ignored is complete, ignored:", ignored, ", not ignored:", not_ignored)
log.trace("================================================================================")
end

local show_anyway = state.filtered_items and state.filtered_items.hide_gitignored == false
log.trace("IGNORED: Comparing results to mark items as ignored, show_anyway:", show_anyway)
local ignored, not_ignored = 0, 0
for _, item in ipairs(items) do
if M.is_ignored(all_results, item.path, item.type) then
item.filtered_by = item.filtered_by or {}
item.filtered_by.gitignored = true
item.filtered_by.show_anyway = show_anyway
ignored = ignored + 1
else
not_ignored = not_ignored + 1
local all_results = {}
if type(callback) == "function" then
local jobs = {}
local progress = 0
for folder, folder_items in pairs(folders) do
local args = { "-C", folder, "check-ignore", "--stdin" }
local job = Job:new({
command = "git",
args = args,
enabled_recording = true,
writer = folder_items,
on_start = function()
log.trace("IGNORED: Running async git with args: ", args)
end,
on_exit = function(self, code, _)
local result
if code ~= 0 then
log.debug("Failed to load ignored files for", state.path, ":", self:stderr_result())
result = {}
else
result = self:result()
end
vim.list_extend(all_results, process_result(result))
progress = progress + 1
if progress == #jobs then
finalize(all_results)
callback(all_results)
end
end,
})
table.insert(jobs, job)
end

for _, job in ipairs(jobs) do
job:start()
end
else
for folder, folder_items in pairs(folders) do
local cmd = { "git", "-C", folder, "check-ignore", unpack(folder_items) }
log.trace("IGNORED: Running cmd: ", cmd)
local result = vim.fn.systemlist(cmd)
if vim.v.shell_error == 128 then
log.debug("Failed to load ignored files for", state.path, ":", result)
result = {}
end
vim.list_extend(all_results, process_result(result))
end
finalize(all_results)
return all_results
end
log.trace("IGNORED: mark_ignored is complete, ignored:", ignored, ", not ignored:", not_ignored)
log.trace("================================================================================")
return all_results
end

return M
38 changes: 29 additions & 9 deletions lua/neo-tree/sources/filesystem/lib/fs_scan.lua
Original file line number Diff line number Diff line change
Expand Up @@ -71,18 +71,10 @@ local dir_complete = function(context, dir_path)
return next_path
end

local job_complete = function(context)
local render_context = function(context)
local state = context.state
local root = context.root
local parent_id = context.parent_id
if state.filtered_items.hide_gitignored or state.enable_git_status then
local git_ignored = git.mark_ignored(state, context.all_items)
if parent_id then
vim.list_extend(state.git_ignored, git_ignored)
else
state.git_ignored = git_ignored
end
end

if not parent_id and state.use_libuv_file_watcher and state.enable_git_status then
log.trace("Starting .git folder watcher")
Expand Down Expand Up @@ -111,6 +103,34 @@ local job_complete = function(context)
context = nil
end

local job_complete = function(context)
local state = context.state
local parent_id = context.parent_id
if state.filtered_items.hide_gitignored or state.enable_git_status then
if require("neo-tree").config.git_status_async then
git.mark_ignored(state, context.all_items, function(all_items)
if parent_id then
vim.list_extend(state.git_ignored, all_items)
else
state.git_ignored = all_items
end
vim.schedule(function()
render_context(context)
end)
end)
return
else
local all_items = git.mark_ignored(state, context.all_items)
if parent_id then
vim.list_extend(state.git_ignored, all_items)
else
state.git_ignored = all_items
end
end
end
render_context(context)
end

-- async_scan scans all the directories in context.paths_to_load
-- and adds them as items to render in the UI.
local function async_scan(context, path)
Expand Down
8 changes: 8 additions & 0 deletions tests/neo-tree/ui/icons_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ describe("ui/icons", function()

vim.api.nvim_win_set_cursor(winid, { 3, 0 })
u.feedkeys("<CR>")

vim.wait(100)

u.assert_buf_lines(bufnr, {
string.format("  %s", fs_tree.abspath):sub(1, 42),
Expand Down Expand Up @@ -105,6 +107,8 @@ describe("ui/icons", function()

vim.api.nvim_win_set_cursor(winid, { 3, 0 })
u.feedkeys("<CR>")

vim.wait(100)

u.assert_buf_lines(bufnr, {
vim.fn.strcharpart(string.format("  %s", fs_tree.abspath), 0, 40),
Expand Down Expand Up @@ -166,6 +170,8 @@ describe("ui/icons", function()

vim.api.nvim_win_set_cursor(winid, { 3, 0 })
u.feedkeys("<CR>")

vim.wait(100)

u.assert_buf_lines(bufnr, {
string.format(" o %s", fs_tree.abspath):sub(1, 40),
Expand Down Expand Up @@ -203,6 +209,8 @@ describe("ui/icons", function()

vim.api.nvim_win_set_cursor(winid, { 3, 0 })
u.feedkeys("<CR>")

vim.wait(100)

u.assert_buf_lines(bufnr, {
vim.fn.strcharpart(string.format(" o %s", fs_tree.abspath), 0, 40),
Expand Down