1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-02-04 05:50:06 +08:00
SpaceVim/bundle/neo-tree.nvim/lua/neo-tree/git/ignored.lua
2023-05-30 21:09:18 +08:00

157 lines
4.9 KiB
Lua

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")
local M = {}
local sep = utils.path_separator
M.is_ignored = function(ignored, path, _type)
if _type == "directory" and not utils.is_windows then
path = path .. sep
end
return vim.tbl_contains(ignored, path)
end
local git_root_cache = {
known_roots = {},
dir_lookup = {},
}
local get_root_for_item = function(item)
local dir = item.type == "directory" and item.path or item.parent_path
if type(git_root_cache.dir_lookup[dir]) ~= "nil" then
return git_root_cache.dir_lookup[dir]
end
--for _, root in ipairs(git_root_cache.known_roots) do
-- if vim.startswith(dir, root) then
-- git_root_cache.dir_lookup[dir] = root
-- return root
-- end
--end
local root = git_utils.get_repository_root(dir)
if root then
git_root_cache.dir_lookup[dir] = root
table.insert(git_root_cache.known_roots, root)
else
git_root_cache.dir_lookup[dir] = false
end
return root
end
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
if not folders[folder] then
folders[folder] = {}
end
table.insert(folders[folder], item.path)
end
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)
item = item:gsub("\\\\", "\\")
return item
end, result)
else
--check-ignore does not indicate directories the same as 'status' so we need to
--add the trailing slash to the path manually if not on Windows.
log.trace("IGNORED: Checking types of", #result, "items to see which ones are directories")
for i, item in ipairs(result) do
local stat = vim.loop.fs_stat(item)
if stat and stat.type == "directory" then
result[i] = item .. sep
end
end
end
result = vim.tbl_map(function(item)
-- remove leading and trailing " from git output
item = item:gsub('^"', ""):gsub('"$', "")
-- convert octal encoded lines to utf-8
item = git_utils.octal_to_utf8(item)
return item
end, result)
return result
end
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 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
end
return M