Merge pull request #27 from kyazdani42/fix-git-calls

optimize git with buffering
This commit is contained in:
Kiyan Yazdani 2020-05-31 00:57:40 +02:00 committed by GitHub
commit 5b69702a52
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 98 additions and 48 deletions

93
lua/lib/git.lua Normal file
View File

@ -0,0 +1,93 @@
local M = {}
local roots = {}
local not_git = 'not a git repo'
local function update_root_status(root)
local status = vim.fn.systemlist('cd '..root..' && git status --porcelain=v1')
roots[root] = {}
for _, v in pairs(status) do
local head = v:sub(0, 2)
local body = v:sub(4, -1)
if body:match('%->') ~= nil then
body = body:gsub('^.* %-> ', '')
end
roots[root][body] = head
end
end
function M.reload_roots()
for root, status in pairs(roots) do
if status ~= not_git then
update_root_status(root)
end
end
end
local function path_to_matching_str(path)
return path:gsub('(%-)', '(%%-)'):gsub('(%.)', '(%%.)')
end
local function get_git_root(path)
if roots[path] then
return path, roots[path]
end
for name, status in pairs(roots) do
if status ~= not_git then
if path:match(path_to_matching_str(name)) then
return name, status
end
end
end
end
local function create_root(cwd)
local git_root = vim.fn.system('cd '..cwd..' && git rev-parse --show-toplevel')
if not git_root or #git_root == 0 or git_root:match('fatal: not a git repository') then
roots[cwd] = not_git
return false
end
update_root_status(git_root:sub(0, -2))
return true
end
function M.update_status(entries, cwd)
local git_root, git_status = get_git_root(cwd)
if not git_root then
if not create_root(cwd) then
return
end
git_root, git_status = get_git_root(cwd)
elseif git_status == not_git then
return
end
local matching_cwd = path_to_matching_str(git_root..'/')
for _, node in pairs(entries) do
local relpath = node.absolute_path:gsub(matching_cwd, '')
if node.entries ~= nil then
relpath = relpath..'/'
node.git_status = nil
end
local status = git_status[relpath]
if status then
node.git_status = status
elseif node.entries ~= nil then
local matcher = '^'..path_to_matching_str(relpath)
for key, _ in pairs(git_status) do
if key:match(matcher) then
node.git_status = 'dirty'
break
end
end
else
node.git_status = nil
end
end
end
return M

View File

@ -1,4 +1,5 @@
local config = require'lib.config' local config = require'lib.config'
local git = require'lib.git'
local icon_config = config.get_icon_state() local icon_config = config.get_icon_state()
local api = vim.api local api = vim.api
@ -190,52 +191,7 @@ function M.populate(entries, cwd)
return return
end end
M.update_git_status(entries, cwd) git.update_status(entries, cwd)
end
function M.update_git_status(entries, cwd)
local git_root = vim.fn.system('cd '..cwd..' && git rev-parse --show-toplevel')
if not git_root or #git_root == 0 or git_root:match('fatal: not a git repository') then
return
end
git_root = git_root:sub(0, -2)
local git_statuslist = vim.fn.systemlist('cd '..cwd..' && git status --porcelain=v1')
local git_status = {}
for _, v in pairs(git_statuslist) do
local head = v:sub(0, 2)
local body = v:sub(4, -1)
if body:match('%->') ~= nil then
body = body:gsub('^.* %-> ', '')
end
git_status[body] = head
end
local matching_cwd = path_to_matching_str(git_root..'/')
for _, node in pairs(entries) do
local relpath = node.absolute_path:gsub(matching_cwd, '')
if node.entries ~= nil then
relpath = relpath..'/'
node.git_status = nil
end
local status = git_status[relpath]
if status then
node.git_status = status
elseif node.entries ~= nil then
local matcher = '^'..path_to_matching_str(relpath)
for key, _ in pairs(git_status) do
if key:match(matcher) then
node.git_status = 'dirty'
break
end
end
else
node.git_status = nil
end
end
end end
return M return M

View File

@ -3,10 +3,10 @@ local luv = vim.loop
local renderer = require'lib.renderer' local renderer = require'lib.renderer'
local config = require'lib.config' local config = require'lib.config'
local git = require'lib.git'
local pops = require'lib.populate' local pops = require'lib.populate'
local populate = pops.populate local populate = pops.populate
local refresh_entries = pops.refresh_entries local refresh_entries = pops.refresh_entries
local update_git = pops.update_git_status
local M = {} local M = {}
@ -98,7 +98,7 @@ function M.unroll_dir(node)
end end
local function refresh_git(node) local function refresh_git(node)
update_git(node.entries, node.absolute_path or node.cwd) git.update_status(node.entries, node.absolute_path or node.cwd)
for _, entry in pairs(node.entries) do for _, entry in pairs(node.entries) do
if entry.entries ~= nil then if entry.entries ~= nil then
refresh_git(entry) refresh_git(entry)
@ -122,6 +122,7 @@ function M.refresh_tree()
refresh_nodes(M.Tree) refresh_nodes(M.Tree)
-- end -- end
if config.get_icon_state().show_git_icon then if config.get_icon_state().show_git_icon then
git.reload_roots()
refresh_git(M.Tree) refresh_git(M.Tree)
end end
if M.Tree.winnr ~= nil then if M.Tree.winnr ~= nil then