Update generated neovim config
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,37 @@
|
||||
local _MODREV, _SPECREV = 'scm', '-1'
|
||||
|
||||
rockspec_format = "3.0"
|
||||
package = 'gitsigns.nvim'
|
||||
version = _MODREV .. _SPECREV
|
||||
|
||||
description = {
|
||||
summary = 'Git signs written in pure lua',
|
||||
detailed = [[
|
||||
Super fast git decorations implemented purely in Lua.
|
||||
]],
|
||||
homepage = 'http://github.com/lewis6991/gitsigns.nvim',
|
||||
license = 'MIT/X11',
|
||||
labels = { 'neovim' }
|
||||
}
|
||||
|
||||
dependencies = {
|
||||
'lua == 5.1',
|
||||
}
|
||||
|
||||
source = {
|
||||
url = 'http://github.com/lewis6991/gitsigns.nvim/archive/v' .. _MODREV .. '.zip',
|
||||
dir = 'gitsigns.nvim-' .. _MODREV,
|
||||
}
|
||||
|
||||
if _MODREV == 'scm' then
|
||||
source = {
|
||||
url = 'git://github.com/lewis6991/gitsigns.nvim',
|
||||
}
|
||||
end
|
||||
|
||||
build = {
|
||||
type = 'builtin',
|
||||
copy_directories = {
|
||||
'doc'
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
rock_manifest = {
|
||||
doc = {
|
||||
["gitsigns.txt"] = "ed2c2a9eac117833753afc9dd55adcf4"
|
||||
},
|
||||
["gitsigns.nvim-scm-1.rockspec"] = "a9b165d604ce401cfeea760a9366418d",
|
||||
lua = {
|
||||
gitsigns = {
|
||||
["actions.lua"] = "ac0661d45e50424f5f59924528b1c031",
|
||||
["async.lua"] = "ab34c767e5b6c917335d19f2acc6fd36",
|
||||
["attach.lua"] = "44664690d66389b4487d934ebcad98e6",
|
||||
["blame.lua"] = "05feea95e221a2409a8d44334c47529f",
|
||||
["cache.lua"] = "523c72aa06168f06b3ecd34fd04cbe9d",
|
||||
cli = {
|
||||
["argparse.lua"] = "fb6c9ffda01b2090f3c252ecaf00f68a"
|
||||
},
|
||||
["cli.lua"] = "00273191aa1ca467c5edbd9531f8fd9d",
|
||||
["config.lua"] = "8743742b5a5b0a0713f0352ff4e88db0",
|
||||
["current_line_blame.lua"] = "48e477d836e39ab98e58c2b027dd9db8",
|
||||
["debounce.lua"] = "5a28036b5ac45c1f93f9883b855e564f",
|
||||
debug = {
|
||||
["log.lua"] = "f7e994b68e9cbcf91adfeb5bc379d7b1"
|
||||
},
|
||||
["debug.lua"] = "6a819b17a531b74ee11622145097afae",
|
||||
["diff.lua"] = "0c462ae71c77899e81da151dcfdf77eb",
|
||||
["diff_ext.lua"] = "31454455cd645f1518d8363446e8d0f6",
|
||||
["diff_int.lua"] = "8e73883f55811dcb68ad481d389aa687",
|
||||
["diffthis.lua"] = "aaac58016e9982bb14e942f9e4e24c52",
|
||||
git = {
|
||||
["blame.lua"] = "e779f4344bcc41cdb92c1a1be5eb2815",
|
||||
["cmd.lua"] = "449c03c67b7ae516babc41d6da0dc66e",
|
||||
["repo.lua"] = "1efe3178f64b77e0fc22cad55d9586a0",
|
||||
["version.lua"] = "068a582ed4565978eb1f6eb089a6fa6c"
|
||||
},
|
||||
["git.lua"] = "0d3e8859ff8cf7ebd3beb739b64a8c49",
|
||||
["highlight.lua"] = "f0bf039b629818fbfae8a6fad161f9a2",
|
||||
["hunks.lua"] = "ee058ee8b056b055cd8404460ca6921f",
|
||||
["manager.lua"] = "f6e7e2430f2f28a4dbcfd2479f2c8480",
|
||||
["message.lua"] = "523ee4df9da4a7fa9b5ab2100eb27ac4",
|
||||
["popup.lua"] = "2fcf3052f95d81cb5c0bb04ca4e06aae",
|
||||
["repeat.lua"] = "798544de97c774bc8e10eecfd6479585",
|
||||
["signs.lua"] = "a22dd6943d762dffcdbb8d2db4d885bb",
|
||||
["status.lua"] = "a229a7213a3fbecfcf2d98aaf587fcab",
|
||||
system = {
|
||||
["compat.lua"] = "05d2b6d08602fba46be9b540288091e7"
|
||||
},
|
||||
["system.lua"] = "d73fac4f6e734cc8ce9f13d6be027503",
|
||||
["test.lua"] = "082f7c7a556bf27352a378d047b8e79b",
|
||||
["util.lua"] = "d30ad092850bd48a1446ce069320f5a7",
|
||||
["watcher.lua"] = "978875698d84bc1f715c55fefa72bcc1"
|
||||
},
|
||||
["gitsigns.lua"] = "bf3f49482d8340f4be41060d7f461fd1"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,173 @@
|
||||
commands = {}
|
||||
dependencies = {
|
||||
["gitsigns.nvim"] = {
|
||||
["scm-1"] = {
|
||||
{
|
||||
constraints = {
|
||||
{
|
||||
op = "==",
|
||||
version = {
|
||||
5, 1, string = "5.1"
|
||||
}
|
||||
}
|
||||
},
|
||||
name = "lua"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
modules = {
|
||||
gitsigns = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
},
|
||||
["gitsigns.actions"] = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
},
|
||||
["gitsigns.async"] = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
},
|
||||
["gitsigns.attach"] = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
},
|
||||
["gitsigns.blame"] = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
},
|
||||
["gitsigns.cache"] = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
},
|
||||
["gitsigns.cli"] = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
},
|
||||
["gitsigns.cli.argparse"] = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
},
|
||||
["gitsigns.config"] = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
},
|
||||
["gitsigns.current_line_blame"] = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
},
|
||||
["gitsigns.debounce"] = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
},
|
||||
["gitsigns.debug"] = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
},
|
||||
["gitsigns.debug.log"] = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
},
|
||||
["gitsigns.diff"] = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
},
|
||||
["gitsigns.diff_ext"] = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
},
|
||||
["gitsigns.diff_int"] = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
},
|
||||
["gitsigns.diffthis"] = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
},
|
||||
["gitsigns.git"] = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
},
|
||||
["gitsigns.git.blame"] = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
},
|
||||
["gitsigns.git.cmd"] = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
},
|
||||
["gitsigns.git.repo"] = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
},
|
||||
["gitsigns.git.version"] = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
},
|
||||
["gitsigns.highlight"] = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
},
|
||||
["gitsigns.hunks"] = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
},
|
||||
["gitsigns.manager"] = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
},
|
||||
["gitsigns.message"] = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
},
|
||||
["gitsigns.popup"] = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
},
|
||||
["gitsigns.repeat"] = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
},
|
||||
["gitsigns.signs"] = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
},
|
||||
["gitsigns.status"] = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
},
|
||||
["gitsigns.system"] = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
},
|
||||
["gitsigns.system.compat"] = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
},
|
||||
["gitsigns.test"] = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
},
|
||||
["gitsigns.util"] = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
},
|
||||
["gitsigns.watcher"] = {
|
||||
"gitsigns.nvim/scm-1"
|
||||
}
|
||||
}
|
||||
repository = {
|
||||
["gitsigns.nvim"] = {
|
||||
["scm-1"] = {
|
||||
{
|
||||
arch = "installed",
|
||||
commands = {},
|
||||
dependencies = {},
|
||||
modules = {
|
||||
gitsigns = "gitsigns.lua",
|
||||
["gitsigns.actions"] = "gitsigns/actions.lua",
|
||||
["gitsigns.async"] = "gitsigns/async.lua",
|
||||
["gitsigns.attach"] = "gitsigns/attach.lua",
|
||||
["gitsigns.blame"] = "gitsigns/blame.lua",
|
||||
["gitsigns.cache"] = "gitsigns/cache.lua",
|
||||
["gitsigns.cli"] = "gitsigns/cli.lua",
|
||||
["gitsigns.cli.argparse"] = "gitsigns/cli/argparse.lua",
|
||||
["gitsigns.config"] = "gitsigns/config.lua",
|
||||
["gitsigns.current_line_blame"] = "gitsigns/current_line_blame.lua",
|
||||
["gitsigns.debounce"] = "gitsigns/debounce.lua",
|
||||
["gitsigns.debug"] = "gitsigns/debug.lua",
|
||||
["gitsigns.debug.log"] = "gitsigns/debug/log.lua",
|
||||
["gitsigns.diff"] = "gitsigns/diff.lua",
|
||||
["gitsigns.diff_ext"] = "gitsigns/diff_ext.lua",
|
||||
["gitsigns.diff_int"] = "gitsigns/diff_int.lua",
|
||||
["gitsigns.diffthis"] = "gitsigns/diffthis.lua",
|
||||
["gitsigns.git"] = "gitsigns/git.lua",
|
||||
["gitsigns.git.blame"] = "gitsigns/git/blame.lua",
|
||||
["gitsigns.git.cmd"] = "gitsigns/git/cmd.lua",
|
||||
["gitsigns.git.repo"] = "gitsigns/git/repo.lua",
|
||||
["gitsigns.git.version"] = "gitsigns/git/version.lua",
|
||||
["gitsigns.highlight"] = "gitsigns/highlight.lua",
|
||||
["gitsigns.hunks"] = "gitsigns/hunks.lua",
|
||||
["gitsigns.manager"] = "gitsigns/manager.lua",
|
||||
["gitsigns.message"] = "gitsigns/message.lua",
|
||||
["gitsigns.popup"] = "gitsigns/popup.lua",
|
||||
["gitsigns.repeat"] = "gitsigns/repeat.lua",
|
||||
["gitsigns.signs"] = "gitsigns/signs.lua",
|
||||
["gitsigns.status"] = "gitsigns/status.lua",
|
||||
["gitsigns.system"] = "gitsigns/system.lua",
|
||||
["gitsigns.system.compat"] = "gitsigns/system/compat.lua",
|
||||
["gitsigns.test"] = "gitsigns/test.lua",
|
||||
["gitsigns.util"] = "gitsigns/util.lua",
|
||||
["gitsigns.watcher"] = "gitsigns/watcher.lua"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,400 @@
|
||||
local async = require('gitsigns.async')
|
||||
local cache = require('gitsigns.cache').cache
|
||||
local log = require('gitsigns.debug.log')
|
||||
local util = require('gitsigns.util')
|
||||
|
||||
local api = vim.api
|
||||
|
||||
local hash_colors = {} --- @type table<integer,string>
|
||||
|
||||
local ns = api.nvim_create_namespace('gitsigns_blame_win')
|
||||
local ns_hl = api.nvim_create_namespace('gitsigns_blame_win_hl')
|
||||
|
||||
--- Convert a hex char to a rgb color component
|
||||
---
|
||||
--- Taken from vim-fugitive:
|
||||
--- Avoid color components lower than 0x20 and higher than 0xdf to help
|
||||
--- avoid colors that blend into the background, light or dark.
|
||||
--- @param x string hex char
|
||||
--- @return integer
|
||||
local function mod(x)
|
||||
local y = tonumber(x, 16)
|
||||
return math.min(0xdf, 0x20 + math.floor((y * 0x10 + (15 - y)) * 0.75))
|
||||
end
|
||||
|
||||
--- Taken from vim-fugitive
|
||||
--- Use 3 characters of the commit hash, limiting the maximum total colors to
|
||||
--- 4,096.
|
||||
--- @param sha string
|
||||
--- @return string
|
||||
local function get_hash_color(sha)
|
||||
local r, g, b = sha:match('(%x)%x(%x)%x(%x)')
|
||||
local color = mod(r) * 0x10000 + mod(g) * 0x100 + mod(b)
|
||||
|
||||
if hash_colors[sha] then
|
||||
return hash_colors[sha]
|
||||
end
|
||||
|
||||
local hl_name = string.format('GitSignsBlameColor.%s%s%s', r, g, b)
|
||||
api.nvim_set_hl(0, hl_name, { fg = color })
|
||||
hash_colors[color] = hl_name
|
||||
|
||||
return hl_name
|
||||
end
|
||||
|
||||
---@param amount integer
|
||||
---@param text string
|
||||
---@return string
|
||||
local function lalign(amount, text)
|
||||
local len = vim.str_utfindex(text)
|
||||
return text .. string.rep(' ', math.max(0, amount - len))
|
||||
end
|
||||
|
||||
local chars = {
|
||||
first = '┍',
|
||||
mid = '│',
|
||||
last = '┕',
|
||||
single = '╺',
|
||||
}
|
||||
|
||||
local M = {}
|
||||
|
||||
--- @param blame table<integer,Gitsigns.BlameInfo?>
|
||||
--- @param win integer
|
||||
--- @param main_win integer
|
||||
--- @param buf_sha string
|
||||
local function render(blame, win, main_win, buf_sha)
|
||||
local max_author_len = 0
|
||||
|
||||
for _, blame_info in pairs(blame) do
|
||||
max_author_len = math.max(max_author_len, (vim.str_utfindex(blame_info.commit.author)))
|
||||
end
|
||||
|
||||
local lines = {} --- @type string[]
|
||||
local last_sha --- @type string?
|
||||
local cnt = 0
|
||||
local commit_lines = {} --- @type table<integer,true>
|
||||
for i, hl in pairs(blame) do
|
||||
local sha = hl.commit.abbrev_sha
|
||||
local next_sha = blame[i + 1] and blame[i + 1].commit.abbrev_sha or nil
|
||||
if sha == last_sha then
|
||||
cnt = cnt + 1
|
||||
local c = sha == next_sha and chars.mid or chars.last
|
||||
lines[i] = cnt == 1 and string.format('%s %s', c, hl.commit.summary) or c
|
||||
else
|
||||
cnt = 0
|
||||
commit_lines[i] = true
|
||||
lines[i] = string.format(
|
||||
'%s %s %s %s',
|
||||
chars.first,
|
||||
sha,
|
||||
lalign(max_author_len, hl.commit.author),
|
||||
util.expand_format('<author_time>', hl.commit)
|
||||
)
|
||||
end
|
||||
last_sha = sha
|
||||
end
|
||||
|
||||
local win_width = #lines[1]
|
||||
api.nvim_win_set_width(win, win_width + 1)
|
||||
|
||||
local bufnr = api.nvim_win_get_buf(win)
|
||||
local main_buf = api.nvim_win_get_buf(main_win)
|
||||
|
||||
api.nvim_buf_set_lines(bufnr, 0, -1, false, lines)
|
||||
|
||||
-- Apply highlights
|
||||
for i, blame_info in ipairs(blame) do
|
||||
local hash_color = get_hash_color(blame_info.commit.abbrev_sha)
|
||||
|
||||
api.nvim_buf_set_extmark(bufnr, ns, i - 1, 0, {
|
||||
end_col = commit_lines[i] and 12 or 1,
|
||||
hl_group = hash_color,
|
||||
})
|
||||
|
||||
if commit_lines[i] then
|
||||
local width = string.len(lines[i])
|
||||
api.nvim_buf_set_extmark(bufnr, ns, i - 1, width - 10, {
|
||||
end_col = width,
|
||||
hl_group = 'Title',
|
||||
})
|
||||
else
|
||||
api.nvim_buf_set_extmark(bufnr, ns, i - 1, 2, {
|
||||
end_row = i,
|
||||
end_col = 0,
|
||||
hl_group = 'Comment',
|
||||
})
|
||||
end
|
||||
|
||||
if buf_sha == blame_info.commit.sha then
|
||||
api.nvim_buf_set_extmark(bufnr, ns, i - 1, 0, {
|
||||
line_hl_group = '@markup.italic',
|
||||
})
|
||||
end
|
||||
|
||||
if commit_lines[i] and commit_lines[i + 1] then
|
||||
api.nvim_buf_set_extmark(bufnr, ns, i - 1, 0, {
|
||||
virt_lines = {
|
||||
{ { chars.last, hash_color }, { ' ' }, { blame[i].commit.summary, 'Comment' } },
|
||||
},
|
||||
})
|
||||
|
||||
local fillchar = string.rep(vim.opt.fillchars:get().diff or '-', 1000)
|
||||
|
||||
api.nvim_buf_set_extmark(main_buf, ns, i - 1, 0, {
|
||||
virt_lines = { { { fillchar, 'Comment' } } },
|
||||
virt_lines_leftcol = true,
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- @param blame table<integer,Gitsigns.BlameInfo?>
|
||||
--- @param win integer
|
||||
--- @param revision? string
|
||||
--- @param parent? boolean
|
||||
local function reblame(blame, win, revision, parent)
|
||||
local blm_win = api.nvim_get_current_win()
|
||||
local lnum = unpack(api.nvim_win_get_cursor(blm_win))
|
||||
local sha = blame[lnum].commit.sha
|
||||
if parent then
|
||||
sha = sha .. '^'
|
||||
end
|
||||
if sha == revision then
|
||||
return
|
||||
end
|
||||
|
||||
vim.cmd.quit()
|
||||
api.nvim_set_current_win(win)
|
||||
|
||||
require('gitsigns').show(
|
||||
sha,
|
||||
vim.schedule_wrap(function()
|
||||
local bufnr = api.nvim_get_current_buf()
|
||||
local ok = vim.wait(1000, function()
|
||||
return cache[bufnr] ~= nil
|
||||
end)
|
||||
if not ok then
|
||||
error('Timeout waiting for attach')
|
||||
end
|
||||
async.run(M.blame)
|
||||
end)
|
||||
)
|
||||
end
|
||||
|
||||
--- @param win integer
|
||||
--- @param open 'vsplit'|'tabnew'
|
||||
--- @param bcache Gitsigns.CacheEntry
|
||||
local show_commit = async.create(3, function(win, open, bcache)
|
||||
local cursor = api.nvim_win_get_cursor(win)[1]
|
||||
local sha = bcache.blame[cursor].commit.sha
|
||||
local res = bcache.git_obj.repo:command({ 'show', sha })
|
||||
async.scheduler()
|
||||
local commit_buf = api.nvim_create_buf(true, true)
|
||||
api.nvim_buf_set_name(commit_buf, bcache:get_rev_bufname(sha, true))
|
||||
api.nvim_buf_set_lines(commit_buf, 0, -1, false, res)
|
||||
vim.cmd[open]({ mods = { keepalt = true } })
|
||||
api.nvim_win_set_buf(0, commit_buf)
|
||||
vim.bo[commit_buf].filetype = 'git'
|
||||
end)
|
||||
|
||||
--- @param augroup integer
|
||||
--- @param wins integer[]
|
||||
local function sync_cursors(augroup, wins)
|
||||
local cursor_save --- @type integer?
|
||||
|
||||
---@param w integer
|
||||
local function sync_cursor(w)
|
||||
local b = api.nvim_win_get_buf(w)
|
||||
api.nvim_create_autocmd('BufLeave', {
|
||||
buffer = b,
|
||||
group = augroup,
|
||||
callback = function()
|
||||
cursor_save = unpack(api.nvim_win_get_cursor(w))
|
||||
end,
|
||||
})
|
||||
|
||||
api.nvim_create_autocmd('BufEnter', {
|
||||
group = augroup,
|
||||
buffer = b,
|
||||
callback = function()
|
||||
local cur_cursor, cur_cursor_col = unpack(api.nvim_win_get_cursor(w))
|
||||
if cursor_save and cursor_save ~= cur_cursor then
|
||||
api.nvim_win_set_cursor(w, { cursor_save, vim.o.startofline and 0 or cur_cursor_col })
|
||||
end
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
for _, w in ipairs(wins) do
|
||||
sync_cursor(w)
|
||||
end
|
||||
end
|
||||
|
||||
--- @param name string
|
||||
--- @param items [string, string][]
|
||||
local function menu(name, items)
|
||||
local max_len = 0
|
||||
for _, item in ipairs(items) do
|
||||
max_len = math.max(max_len, #item[1]) --- @type integer
|
||||
end
|
||||
|
||||
for _, item in ipairs(items) do
|
||||
local item_nm, action = item[1], item[2]
|
||||
local pad = string.rep(' ', max_len - #item_nm)
|
||||
local lhs = string.format('%s%s (%s)', item_nm, pad, action):gsub(' ', [[\ ]])
|
||||
local cmd = string.format('nmenu <silent> ]%s.%s %s', name, lhs, action)
|
||||
|
||||
vim.cmd(cmd)
|
||||
end
|
||||
end
|
||||
|
||||
--- @async
|
||||
M.blame = function()
|
||||
local __FUNC__ = 'blame'
|
||||
local bufnr = api.nvim_get_current_buf()
|
||||
local win = api.nvim_get_current_win()
|
||||
local bcache = cache[bufnr]
|
||||
if not bcache then
|
||||
log.dprint('Not attached')
|
||||
return
|
||||
end
|
||||
|
||||
bcache:get_blame()
|
||||
local blame = assert(bcache.blame)
|
||||
|
||||
-- Save position to align 'scrollbind'
|
||||
local top = vim.fn.line('w0') + vim.wo.scrolloff
|
||||
local current = vim.fn.line('.')
|
||||
|
||||
vim.cmd.vsplit({ mods = { keepalt = true, split = 'aboveleft' } })
|
||||
local blm_win = api.nvim_get_current_win()
|
||||
|
||||
local blm_bufnr = api.nvim_create_buf(false, true)
|
||||
api.nvim_win_set_buf(blm_win, blm_bufnr)
|
||||
|
||||
render(blame, blm_win, win, bcache.git_obj.revision)
|
||||
|
||||
local blm_bo = vim.bo[blm_bufnr]
|
||||
blm_bo.buftype = 'nofile'
|
||||
blm_bo.bufhidden = 'wipe'
|
||||
blm_bo.modifiable = false
|
||||
blm_bo.filetype = 'gitsigns-blame'
|
||||
|
||||
local blm_wlo = vim.wo[blm_win][0]
|
||||
blm_wlo.foldcolumn = '0'
|
||||
blm_wlo.foldenable = false
|
||||
blm_wlo.number = false
|
||||
blm_wlo.relativenumber = false
|
||||
blm_wlo.scrollbind = true
|
||||
blm_wlo.signcolumn = 'no'
|
||||
blm_wlo.spell = false
|
||||
blm_wlo.winfixwidth = true
|
||||
blm_wlo.wrap = false
|
||||
|
||||
if vim.wo[win].winbar ~= '' and blm_wlo.winbar == '' then
|
||||
local name = api.nvim_buf_get_name(bufnr)
|
||||
blm_wlo.winbar = vim.fn.fnamemodify(name, ':.')
|
||||
end
|
||||
|
||||
if vim.fn.exists('&winfixbuf') then
|
||||
blm_wlo.winfixbuf = true
|
||||
end
|
||||
|
||||
vim.cmd(tostring(top))
|
||||
vim.cmd('normal! zt')
|
||||
vim.cmd(tostring(current))
|
||||
vim.cmd('normal! 0')
|
||||
|
||||
local cur_wlo = vim.wo[win][0]
|
||||
local cur_orig_wlo = { cur_wlo.foldenable, cur_wlo.scrollbind, cur_wlo.wrap }
|
||||
cur_wlo.foldenable = false
|
||||
cur_wlo.scrollbind = true
|
||||
cur_wlo.wrap = false
|
||||
|
||||
vim.cmd.redraw()
|
||||
vim.cmd.syncbind()
|
||||
|
||||
vim.keymap.set('n', '<CR>', function()
|
||||
vim.cmd.popup(']GitsignsBlame')
|
||||
end, {
|
||||
desc = 'Open blame context menu',
|
||||
buffer = blm_bufnr,
|
||||
})
|
||||
|
||||
vim.keymap.set('n', 'r', function()
|
||||
reblame(blame, win, bcache.git_obj.revision)
|
||||
end, {
|
||||
desc = 'Reblame at commit',
|
||||
buffer = blm_bufnr,
|
||||
})
|
||||
|
||||
vim.keymap.set('n', 'R', function()
|
||||
reblame(blame, win, bcache.git_obj.revision, true)
|
||||
end, {
|
||||
desc = 'Reblame at commit parent',
|
||||
buffer = blm_bufnr,
|
||||
})
|
||||
|
||||
vim.keymap.set('n', 's', function()
|
||||
show_commit(blm_win, 'vsplit', bcache)
|
||||
end, {
|
||||
desc = 'Show commit in a vertical split',
|
||||
buffer = blm_bufnr,
|
||||
})
|
||||
|
||||
vim.keymap.set('n', 'S', function()
|
||||
show_commit(blm_win, 'tabnew', bcache)
|
||||
end, {
|
||||
desc = 'Show commit in a new tab',
|
||||
buffer = blm_bufnr,
|
||||
})
|
||||
|
||||
menu('GitsignsBlame', {
|
||||
{ 'Reblame at commit', 'r' },
|
||||
{ 'Reblame at commit parent', 'R' },
|
||||
{ 'Show commit (vsplit)', 's' },
|
||||
{ ' (tab)', 'S' },
|
||||
})
|
||||
|
||||
local group = api.nvim_create_augroup('GitsignsBlame', {})
|
||||
|
||||
api.nvim_create_autocmd({ 'CursorMoved', 'BufLeave' }, {
|
||||
buffer = blm_bufnr,
|
||||
group = group,
|
||||
callback = function()
|
||||
api.nvim_buf_clear_namespace(blm_bufnr, ns_hl, 0, -1)
|
||||
api.nvim_buf_clear_namespace(bufnr, ns_hl, 0, -1)
|
||||
end,
|
||||
})
|
||||
|
||||
-- Highlight the same commit under the cursor
|
||||
api.nvim_create_autocmd('CursorMoved', {
|
||||
buffer = blm_bufnr,
|
||||
group = group,
|
||||
callback = function()
|
||||
local cursor = unpack(api.nvim_win_get_cursor(blm_win))
|
||||
local cur_sha = blame[cursor].commit.abbrev_sha
|
||||
for i, info in pairs(blame) do
|
||||
if info.commit.abbrev_sha == cur_sha then
|
||||
api.nvim_buf_set_extmark(blm_bufnr, ns_hl, i - 1, 0, {
|
||||
line_hl_group = '@markup.strong',
|
||||
})
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
api.nvim_create_autocmd('WinClosed', {
|
||||
pattern = tostring(blm_win),
|
||||
group = group,
|
||||
callback = function()
|
||||
api.nvim_buf_clear_namespace(bufnr, ns, 0, -1)
|
||||
cur_wlo.foldenable, cur_wlo.scrollbind, cur_wlo.wrap = unpack(cur_orig_wlo)
|
||||
end,
|
||||
})
|
||||
|
||||
sync_cursors(group, { win, blm_win })
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,268 @@
|
||||
local uv = vim.uv or vim.loop
|
||||
|
||||
local error_once = require('gitsigns.message').error_once
|
||||
local log = require('gitsigns.debug.log')
|
||||
|
||||
--- @class Gitsigns.CommitInfo
|
||||
--- @field author string
|
||||
--- @field author_mail string
|
||||
--- @field author_time integer
|
||||
--- @field author_tz string
|
||||
--- @field committer string
|
||||
--- @field committer_mail string
|
||||
--- @field committer_time integer
|
||||
--- @field committer_tz string
|
||||
--- @field summary string
|
||||
--- @field sha string
|
||||
--- @field abbrev_sha string
|
||||
--- @field boundary? true
|
||||
|
||||
--- @class Gitsigns.BlameInfoPublic: Gitsigns.BlameInfo, Gitsigns.CommitInfo
|
||||
--- @field body? string[]
|
||||
--- @field hunk_no? integer
|
||||
--- @field num_hunks? integer
|
||||
--- @field hunk? string[]
|
||||
--- @field hunk_head? string
|
||||
|
||||
--- @class Gitsigns.BlameInfo
|
||||
--- @field orig_lnum integer
|
||||
--- @field final_lnum integer
|
||||
--- @field commit Gitsigns.CommitInfo
|
||||
--- @field filename string
|
||||
--- @field previous_filename? string
|
||||
--- @field previous_sha? string
|
||||
|
||||
local NOT_COMMITTED = {
|
||||
author = 'Not Committed Yet',
|
||||
author_mail = '<not.committed.yet>',
|
||||
committer = 'Not Committed Yet',
|
||||
committer_mail = '<not.committed.yet>',
|
||||
}
|
||||
|
||||
local M = {}
|
||||
|
||||
--- @param file string
|
||||
--- @return Gitsigns.CommitInfo
|
||||
local function not_committed(file)
|
||||
local time = os.time()
|
||||
return {
|
||||
sha = string.rep('0', 40),
|
||||
abbrev_sha = string.rep('0', 8),
|
||||
author = 'Not Committed Yet',
|
||||
author_mail = '<not.committed.yet>',
|
||||
author_tz = '+0000',
|
||||
author_time = time,
|
||||
committer = 'Not Committed Yet',
|
||||
committer_time = time,
|
||||
committer_mail = '<not.committed.yet>',
|
||||
committer_tz = '+0000',
|
||||
summary = 'Version of ' .. file,
|
||||
}
|
||||
end
|
||||
|
||||
--- @param file string
|
||||
--- @param lnum integer
|
||||
--- @return Gitsigns.BlameInfo
|
||||
function M.get_blame_nc(file, lnum)
|
||||
return {
|
||||
orig_lnum = 0,
|
||||
final_lnum = lnum,
|
||||
commit = not_committed(file),
|
||||
filename = file,
|
||||
}
|
||||
end
|
||||
|
||||
---@param x any
|
||||
---@return integer
|
||||
local function asinteger(x)
|
||||
return assert(tonumber(x))
|
||||
end
|
||||
|
||||
--- @param readline fun(): string?
|
||||
--- @param commits table<string,Gitsigns.CommitInfo>
|
||||
--- @param result table<integer,Gitsigns.BlameInfo>
|
||||
local function incremental_iter(readline, commits, result)
|
||||
local line = assert(readline())
|
||||
|
||||
--- @type string, string, string, string
|
||||
local sha, orig_lnum_str, final_lnum_str, size_str = line:match('(%x+) (%d+) (%d+) (%d+)')
|
||||
assert(sha)
|
||||
|
||||
local orig_lnum = asinteger(orig_lnum_str)
|
||||
local final_lnum = asinteger(final_lnum_str)
|
||||
local size = asinteger(size_str)
|
||||
|
||||
--- @type table<string,string|true>
|
||||
local commit = commits[sha] or {
|
||||
sha = sha,
|
||||
abbrev_sha = sha:sub(1, 8),
|
||||
}
|
||||
|
||||
--- @type string, string
|
||||
local previous_sha, previous_filename
|
||||
|
||||
line = assert(readline())
|
||||
|
||||
-- filename terminates the entry
|
||||
while not line:match('^filename ') do
|
||||
local key, value = line:match('^([^%s]+) (.*)')
|
||||
if key == 'previous' then
|
||||
previous_sha, previous_filename = line:match('^previous (%x+) (.*)')
|
||||
elseif key then
|
||||
key = key:gsub('%-', '_') --- @type string
|
||||
if vim.endswith(key, '_time') then
|
||||
value = tonumber(value)
|
||||
end
|
||||
commit[key] = value
|
||||
else
|
||||
commit[line] = true
|
||||
if line ~= 'boundary' then
|
||||
log.dprintf("Unknown tag: '%s'", line)
|
||||
end
|
||||
end
|
||||
line = assert(readline())
|
||||
end
|
||||
|
||||
local filename = assert(line:match('^filename (.*)'))
|
||||
|
||||
-- New in git 2.41:
|
||||
-- The output given by "git blame" that attributes a line to contents
|
||||
-- taken from the file specified by the "--contents" option shows it
|
||||
-- differently from a line attributed to the working tree file.
|
||||
if
|
||||
commit.author_mail == '<external.file>'
|
||||
or commit.author_mail == 'External file (--contents)'
|
||||
then
|
||||
commit = vim.tbl_extend('force', commit, NOT_COMMITTED)
|
||||
end
|
||||
commits[sha] = commit
|
||||
|
||||
for j = 0, size - 1 do
|
||||
result[final_lnum + j] = {
|
||||
final_lnum = final_lnum + j,
|
||||
orig_lnum = orig_lnum + j,
|
||||
commit = commits[sha],
|
||||
filename = filename,
|
||||
previous_filename = previous_filename,
|
||||
previous_sha = previous_sha,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
--- @param data string
|
||||
--- @return string[]
|
||||
local function data_to_lines(data)
|
||||
local lines = vim.split(data, '\n')
|
||||
if lines[#lines] == '' then
|
||||
lines[#lines] = nil
|
||||
end
|
||||
return lines
|
||||
end
|
||||
|
||||
--- @param f fun(readline: fun(): string?))
|
||||
--- @return fun(data: string?)
|
||||
local function bufferred_line_reader(f)
|
||||
--- @param data string?
|
||||
return coroutine.wrap(function(data)
|
||||
if not data then
|
||||
return
|
||||
end
|
||||
|
||||
local data_lines = data_to_lines(data)
|
||||
local i = 0
|
||||
|
||||
local function readline(peek)
|
||||
if not data_lines[i + 1] then
|
||||
data = coroutine.yield()
|
||||
if not data then
|
||||
return
|
||||
end
|
||||
data_lines = data_to_lines(data)
|
||||
i = 0
|
||||
end
|
||||
|
||||
if peek then
|
||||
return data_lines[ i+ 1]
|
||||
end
|
||||
i = i + 1
|
||||
return data_lines[i]
|
||||
end
|
||||
|
||||
while readline(true) do
|
||||
f(readline)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
--- @param obj Gitsigns.GitObj
|
||||
--- @param lines string[]
|
||||
--- @param lnum? integer
|
||||
--- @param revision? string
|
||||
--- @param opts? Gitsigns.BlameOpts
|
||||
--- @return table<integer, Gitsigns.BlameInfo>
|
||||
function M.run_blame(obj, lines, lnum, revision, opts)
|
||||
local ret = {} --- @type table<integer,Gitsigns.BlameInfo>
|
||||
|
||||
if not obj.object_name or obj.repo.abbrev_head == '' then
|
||||
-- As we support attaching to untracked files we need to return something if
|
||||
-- the file isn't isn't tracked in git.
|
||||
-- If abbrev_head is empty, then assume the repo has no commits
|
||||
local commit = not_committed(obj.file)
|
||||
for i in ipairs(lines) do
|
||||
ret[i] = {
|
||||
orig_lnum = 0,
|
||||
final_lnum = i,
|
||||
commit = commit,
|
||||
filename = obj.file,
|
||||
}
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
local args = { 'blame', '--contents', '-', '--incremental' }
|
||||
|
||||
opts = opts or {}
|
||||
|
||||
if opts.ignore_whitespace then
|
||||
args[#args + 1] = '-w'
|
||||
end
|
||||
|
||||
if lnum then
|
||||
vim.list_extend(args, { '-L', lnum .. ',+1' })
|
||||
end
|
||||
|
||||
if opts.extra_opts then
|
||||
vim.list_extend(args, opts.extra_opts)
|
||||
end
|
||||
|
||||
local ignore_file = obj.repo.toplevel .. '/.git-blame-ignore-revs'
|
||||
if uv.fs_stat(ignore_file) then
|
||||
vim.list_extend(args, { '--ignore-revs-file', ignore_file })
|
||||
end
|
||||
|
||||
args[#args + 1] = revision
|
||||
args[#args + 1] = '--'
|
||||
args[#args + 1] = obj.file
|
||||
|
||||
local commits = {} --- @type table<string,Gitsigns.CommitInfo>
|
||||
|
||||
local reader = bufferred_line_reader(function(readline)
|
||||
incremental_iter(readline, commits, ret)
|
||||
end)
|
||||
|
||||
--- @param data string?
|
||||
local function on_stdout(_, data)
|
||||
reader(data)
|
||||
end
|
||||
|
||||
local _, stderr = obj.repo:command(args, { stdin = lines, stdout = on_stdout, ignore_error = true })
|
||||
|
||||
if stderr then
|
||||
error_once('Error running git-blame: ' .. stderr)
|
||||
return {}
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
return M
|
||||
@ -0,0 +1,72 @@
|
||||
local async = require('gitsigns.async')
|
||||
local log = require('gitsigns.debug.log')
|
||||
|
||||
local system = require('gitsigns.system').system
|
||||
|
||||
--- @type fun(cmd: string[], opts?: vim.SystemOpts): vim.SystemCompleted
|
||||
local asystem = async.wrap(3, system)
|
||||
|
||||
--- @class Gitsigns.Git.JobSpec : vim.SystemOpts
|
||||
--- @field ignore_error? boolean
|
||||
|
||||
--- @async
|
||||
--- @param args string[]
|
||||
--- @param spec? Gitsigns.Git.JobSpec
|
||||
--- @return string[] stdout, string? stderr
|
||||
local function git_command(args, spec)
|
||||
spec = spec or {}
|
||||
|
||||
local cmd = {
|
||||
'git',
|
||||
'--no-pager',
|
||||
'--no-optional-locks',
|
||||
'--literal-pathspecs',
|
||||
'-c',
|
||||
'gc.auto=0', -- Disable auto-packing which emits messages to stderr
|
||||
unpack(args),
|
||||
}
|
||||
|
||||
if spec.text == nil then
|
||||
spec.text = true
|
||||
end
|
||||
|
||||
-- Fix #895. Only needed for Nvim 0.9 and older
|
||||
spec.clear_env = true
|
||||
|
||||
--- @type vim.SystemCompleted
|
||||
local obj = asystem(cmd, spec)
|
||||
|
||||
if not spec.ignore_error and obj.code > 0 then
|
||||
log.eprintf(
|
||||
"Received exit code %d when running command\n'%s':\n%s",
|
||||
obj.code,
|
||||
table.concat(cmd, ' '),
|
||||
obj.stderr
|
||||
)
|
||||
end
|
||||
|
||||
local stdout_lines = vim.split(obj.stdout or '', '\n')
|
||||
|
||||
if spec.text then
|
||||
-- If stdout ends with a newline, then remove the final empty string after
|
||||
-- the split
|
||||
if stdout_lines[#stdout_lines] == '' then
|
||||
stdout_lines[#stdout_lines] = nil
|
||||
end
|
||||
end
|
||||
|
||||
if log.verbose then
|
||||
log.vprintf('%d lines:', #stdout_lines)
|
||||
for i = 1, math.min(10, #stdout_lines) do
|
||||
log.vprintf('\t%s', stdout_lines[i])
|
||||
end
|
||||
end
|
||||
|
||||
if obj.stderr == '' then
|
||||
obj.stderr = nil
|
||||
end
|
||||
|
||||
return stdout_lines, obj.stderr
|
||||
end
|
||||
|
||||
return git_command
|
||||
@ -0,0 +1,265 @@
|
||||
local async = require('gitsigns.async')
|
||||
local git_command = require('gitsigns.git.cmd')
|
||||
local log = require('gitsigns.debug.log')
|
||||
local util = require('gitsigns.util')
|
||||
|
||||
local system = require('gitsigns.system').system
|
||||
local check_version = require('gitsigns.git.version').check
|
||||
|
||||
--- @type fun(cmd: string[], opts?: vim.SystemOpts): vim.SystemCompleted
|
||||
local asystem = async.wrap(3, system)
|
||||
|
||||
local uv = vim.uv or vim.loop
|
||||
|
||||
--- @class Gitsigns.RepoInfo
|
||||
--- @field gitdir string
|
||||
--- @field toplevel string
|
||||
--- @field detached boolean
|
||||
--- @field abbrev_head string
|
||||
|
||||
--- @class Gitsigns.Repo : Gitsigns.RepoInfo
|
||||
---
|
||||
--- Username configured for the repo.
|
||||
--- Needed for to determine "You" in current line blame.
|
||||
--- @field username string
|
||||
local M = {}
|
||||
|
||||
--- Run git command the with the objects gitdir and toplevel
|
||||
--- @async
|
||||
--- @param args string[]
|
||||
--- @param spec? Gitsigns.Git.JobSpec
|
||||
--- @return string[] stdout, string? stderr
|
||||
function M:command(args, spec)
|
||||
spec = spec or {}
|
||||
spec.cwd = self.toplevel
|
||||
|
||||
local args1 = { '--git-dir', self.gitdir }
|
||||
|
||||
if self.detached then
|
||||
vim.list_extend(args1, { '--work-tree', self.toplevel })
|
||||
end
|
||||
|
||||
vim.list_extend(args1, args)
|
||||
|
||||
return git_command(args1, spec)
|
||||
end
|
||||
|
||||
--- @param base string?
|
||||
--- @return string[]
|
||||
function M:files_changed(base)
|
||||
--- @type string[]
|
||||
local results
|
||||
if base and base ~= ':0' then
|
||||
results = self:command({ 'diff', '--name-status', base })
|
||||
|
||||
for i, result in ipairs(results) do
|
||||
results[i] = vim.split(string.gsub(result, '\t', ' '), ' ', { plain = true })[2]
|
||||
end
|
||||
return results
|
||||
else
|
||||
results = self:command({ 'status', '--porcelain', '--ignore-submodules' })
|
||||
|
||||
local ret = {} --- @type string[]
|
||||
for _, line in ipairs(results) do
|
||||
if line:sub(1, 2):match('^.M') then
|
||||
ret[#ret + 1] = line:sub(4, -1)
|
||||
end
|
||||
end
|
||||
return ret
|
||||
end
|
||||
end
|
||||
|
||||
--- @param encoding string
|
||||
--- @return boolean
|
||||
local function iconv_supported(encoding)
|
||||
-- TODO(lewis6991): needs https://github.com/neovim/neovim/pull/21924
|
||||
if vim.startswith(encoding, 'utf-16') then
|
||||
return false
|
||||
elseif vim.startswith(encoding, 'utf-32') then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
--- Get version of file in the index, return array lines
|
||||
--- @param object string
|
||||
--- @param encoding? string
|
||||
--- @return string[] stdout, string? stderr
|
||||
function M:get_show_text(object, encoding)
|
||||
local stdout, stderr = self:command({ 'show', object }, { text = false, ignore_error = true })
|
||||
|
||||
if encoding and encoding ~= 'utf-8' and iconv_supported(encoding) then
|
||||
for i, l in ipairs(stdout) do
|
||||
stdout[i] = vim.iconv(l, encoding, 'utf-8')
|
||||
end
|
||||
end
|
||||
|
||||
return stdout, stderr
|
||||
end
|
||||
|
||||
--- @async
|
||||
function M:update_abbrev_head()
|
||||
local info = M.get_info(self.toplevel)
|
||||
if not info then
|
||||
log.eprintf('Could not get info for repo at %s', self.gitdir)
|
||||
return
|
||||
end
|
||||
self.abbrev_head = info.abbrev_head
|
||||
end
|
||||
|
||||
--- @async
|
||||
--- @private
|
||||
--- @param info Gitsigns.RepoInfo
|
||||
--- @return Gitsigns.Repo
|
||||
local function new(info)
|
||||
local self = setmetatable({}, { __index = M })
|
||||
for k, v in
|
||||
pairs(info --[[@as table<string,any>]])
|
||||
do
|
||||
---@diagnostic disable-next-line:no-unknown
|
||||
self[k] = v
|
||||
end
|
||||
|
||||
self.username = self:command({ 'config', 'user.name' }, { ignore_error = true })[1]
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- @type table<string,[integer,Gitsigns.Repo]?>
|
||||
local repo_cache = setmetatable({}, { __mode = 'v' })
|
||||
|
||||
--- @async
|
||||
--- @param dir string
|
||||
--- @param gitdir? string
|
||||
--- @param toplevel? string
|
||||
--- @return Gitsigns.Repo?
|
||||
function M.get(dir, gitdir, toplevel)
|
||||
local info = M.get_info(dir, gitdir, toplevel)
|
||||
if not info then
|
||||
return
|
||||
end
|
||||
|
||||
gitdir = info.gitdir
|
||||
if not repo_cache[gitdir] then
|
||||
repo_cache[gitdir] = {1, new(info)}
|
||||
else
|
||||
local refcount = repo_cache[gitdir][1]
|
||||
repo_cache[gitdir][1] = refcount + 1
|
||||
end
|
||||
|
||||
return repo_cache[gitdir][2]
|
||||
end
|
||||
|
||||
function M:unref()
|
||||
local gitdir = self.gitdir
|
||||
local repo = repo_cache[gitdir]
|
||||
if not repo then
|
||||
-- Already reclaimed by GC
|
||||
return
|
||||
end
|
||||
local refcount = repo[1]
|
||||
if refcount <= 1 then
|
||||
repo_cache[gitdir] = nil
|
||||
else
|
||||
repo_cache[gitdir][1] = refcount - 1
|
||||
end
|
||||
end
|
||||
|
||||
local has_cygpath = jit and jit.os == 'Windows' and vim.fn.executable('cygpath') == 1
|
||||
|
||||
--- @generic S
|
||||
--- @param path S
|
||||
--- @return S
|
||||
local function normalize_path(path)
|
||||
if path and has_cygpath and not uv.fs_stat(path) then
|
||||
-- If on windows and path isn't recognizable as a file, try passing it
|
||||
-- through cygpath
|
||||
path = asystem({ 'cygpath', '-aw', path }).stdout
|
||||
end
|
||||
return path
|
||||
end
|
||||
|
||||
--- @async
|
||||
--- @param gitdir? string
|
||||
--- @param head_str string
|
||||
--- @param cwd string
|
||||
--- @return string
|
||||
local function process_abbrev_head(gitdir, head_str, cwd)
|
||||
if not gitdir then
|
||||
return head_str
|
||||
end
|
||||
if head_str == 'HEAD' then
|
||||
local short_sha = git_command({ 'rev-parse', '--short', 'HEAD' }, {
|
||||
ignore_error = true,
|
||||
cwd = cwd,
|
||||
})[1] or ''
|
||||
if log.debug_mode and short_sha ~= '' then
|
||||
short_sha = 'HEAD'
|
||||
end
|
||||
if
|
||||
util.path_exists(gitdir .. '/rebase-merge')
|
||||
or util.path_exists(gitdir .. '/rebase-apply')
|
||||
then
|
||||
return short_sha .. '(rebasing)'
|
||||
end
|
||||
return short_sha
|
||||
end
|
||||
return head_str
|
||||
end
|
||||
|
||||
--- @async
|
||||
--- @param cwd string
|
||||
--- @param gitdir? string
|
||||
--- @param toplevel? string
|
||||
--- @return Gitsigns.RepoInfo?
|
||||
function M.get_info(cwd, gitdir, toplevel)
|
||||
-- Does git rev-parse have --absolute-git-dir, added in 2.13:
|
||||
-- https://public-inbox.org/git/20170203024829.8071-16-szeder.dev@gmail.com/
|
||||
local has_abs_gd = check_version({ 2, 13 })
|
||||
|
||||
-- Wait for internal scheduler to settle before running command (#215)
|
||||
async.scheduler()
|
||||
|
||||
local args = {}
|
||||
|
||||
if gitdir then
|
||||
vim.list_extend(args, { '--git-dir', gitdir })
|
||||
end
|
||||
|
||||
if toplevel then
|
||||
vim.list_extend(args, { '--work-tree', toplevel })
|
||||
end
|
||||
|
||||
vim.list_extend(args, {
|
||||
'rev-parse',
|
||||
'--show-toplevel',
|
||||
has_abs_gd and '--absolute-git-dir' or '--git-dir',
|
||||
'--abbrev-ref',
|
||||
'HEAD',
|
||||
})
|
||||
|
||||
local stdout = git_command(args, {
|
||||
ignore_error = true,
|
||||
cwd = toplevel or cwd,
|
||||
})
|
||||
|
||||
if not stdout[1] then
|
||||
return
|
||||
end
|
||||
|
||||
local toplevel_r = normalize_path(stdout[1])
|
||||
local gitdir_r = normalize_path(stdout[2])
|
||||
|
||||
if not has_abs_gd then
|
||||
gitdir_r = assert(uv.fs_realpath(gitdir_r))
|
||||
end
|
||||
|
||||
return {
|
||||
toplevel = toplevel_r,
|
||||
gitdir = gitdir_r,
|
||||
abbrev_head = process_abbrev_head(gitdir_r, stdout[3], cwd),
|
||||
detached = toplevel_r and gitdir_r ~= toplevel_r .. '/.git',
|
||||
}
|
||||
end
|
||||
|
||||
return M
|
||||
Reference in New Issue
Block a user