1

Update generated neovim config

This commit is contained in:
2024-08-15 14:28:54 +02:00
parent 07409c223d
commit 25cfcf2941
3809 changed files with 351157 additions and 0 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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