Numerous changes to setqflist

- Fix duplicate items appearing (#370)

- Make setqflist/setloclist async again

- setqflist('all') now also looks in the current working directory

- Automatically open the quickfix/location list on completion

- Make setloclist an alias of setqflist

- Refactor git.tl so now there is a separate 'Repo' object to allows us
  to create git objects for a directory.

Fixes #370
This commit is contained in:
Lewis Russell 2021-09-22 13:46:08 +01:00
parent d11b627d5a
commit a6d1574bab
11 changed files with 282 additions and 198 deletions

View File

@ -298,8 +298,9 @@ get_hunks({bufnr}) *gitsigns.get_hunks()*
• `"start"`: Line number (1-based)
• `"count"`: Line count
setqflist({target}) *gitsigns.setqflist()*
Populate the quickfix list with hunks.
setqflist({target}, {opts}) *gitsigns.setqflist()*
Populate the quickfix list with hunks. Automatically opens the
quickfix window.
Attributes: ~
{async}
@ -312,10 +313,23 @@ setqflist({target}) *gitsigns.setqflist()*
number. `0` for current buffer (default).
• `"attached"`: All attached buffers.
• `"all"`: All modified files for each git
directory of all attached buffers.
directory of all attached buffers in addition
to the current working directory.
{opts} (table|nil):
Additional options:
• {use_location_list}: (boolean)
Populate the location list instead of the
quickfix list. Default to `false`.
• {nr}: (integer)
Window number or ID when using location list.
Expand folds when navigating to a hunk which is
inside a fold. Defaults to `0`.
setloclist({nr}, {target}) *gitsigns.setloclist()*
Populate the location list with hunks.
Populate the location list with hunks. Automatically opens the
location list window.
Alias for: `setqflist({target}, { use_location_list = true, nr = {nr} }`
Attributes: ~
{async}

26
lua/gitsigns.lua generated
View File

@ -53,7 +53,7 @@ local handle_moved = function(bufnr, bcache, old_relpath)
end
do_update = true
elseif git_obj.orig_relpath then
local orig_file = git_obj.toplevel .. util.path_sep .. git_obj.orig_relpath
local orig_file = git_obj.repo.toplevel .. util.path_sep .. git_obj.orig_relpath
if git_obj:file_info(orig_file) then
dprintf('Moved file reset')
git_obj.relpath = git_obj.orig_relpath
@ -65,7 +65,7 @@ local handle_moved = function(bufnr, bcache, old_relpath)
end
if do_update then
git_obj.file = git_obj.toplevel .. util.path_sep .. git_obj.relpath
git_obj.file = git_obj.repo.toplevel .. util.path_sep .. git_obj.relpath
bcache.file = git_obj.file
bcache.git_obj:update_file_info()
scheduler()
@ -97,10 +97,10 @@ local watch_index = function(bufnr, gitdir)
local git_obj = bcache.git_obj
git_obj:update_abbrev_head()
git_obj.repo:update_abbrev_head()
scheduler()
Status:update(bufnr, { head = git_obj.abbrev_head })
Status:update(bufnr, { head = git_obj.repo.abbrev_head })
local was_tracked = git_obj.object_name ~= nil
local old_relpath = git_obj.relpath
@ -240,20 +240,21 @@ local attach0 = function(cbuf, aucmd)
end
local git_obj = git.Obj.new(file)
local repo = git_obj.repo
if not git_obj.gitdir then
if not repo.gitdir then
dprint('Not in git repo')
return
end
scheduler()
Status:update(cbuf, {
head = git_obj.abbrev_head,
root = git_obj.toplevel,
gitdir = git_obj.gitdir,
head = repo.abbrev_head,
root = repo.toplevel,
gitdir = repo.gitdir,
})
if vim.startswith(file, git_obj.gitdir .. util.path_sep) then
if vim.startswith(file, repo.gitdir .. util.path_sep) then
dprint('In non-standard git dir')
return
end
@ -286,7 +287,7 @@ local attach0 = function(cbuf, aucmd)
base = config.base,
file = file,
commit = commit,
index_watcher = watch_index(cbuf, git_obj.gitdir),
index_watcher = watch_index(cbuf, repo.gitdir),
git_obj = git_obj,
})
@ -413,8 +414,9 @@ local _update_cwd_head = function()
local cwd = vim.fn.getcwd()
local head
for _, bcache in pairs(cache) do
if bcache.git_obj.toplevel == cwd then
head = bcache.git_obj.abbrev_head
local repo = bcache.git_obj.repo
if repo.toplevel == cwd then
head = repo.abbrev_head
break
end
end

View File

@ -1,6 +1,5 @@
local void = require('plenary.async.async').void
local scheduler = require('plenary.async.util').scheduler
local block_on = require('plenary.async.util').block_on
local Status = require("gitsigns.status")
local config = require('gitsigns.config').config
@ -28,7 +27,12 @@ local NavHunkOpts = {}
local M = {}
local M = {QFListOpts = {}, }
@ -452,13 +456,13 @@ local function run_diff(a, b)
return f(a, b, diff_opts.algorithm, diff_opts.indent_heuristic)
end
local function get_blame_hunk(git_obj, info)
local function get_blame_hunk(repo, info)
local a = {}
if info.previous then
a = git_obj:get_show_text(info.previous_sha .. ':' .. info.previous_filename)
a = repo:get_show_text(info.previous_sha .. ':' .. info.previous_filename)
end
local b = git_obj:get_show_text(info.sha .. ':' .. info.filename)
local b = repo:get_show_text(info.sha .. ':' .. info.filename)
local hunks = run_diff(a, b)
local hunk, i = gs_hunks.find_hunk(info.orig_lnum, hunks)
return hunk, i, #hunks
@ -516,7 +520,7 @@ M.blame_line = void(function(full)
vim.list_extend(lines, commit_message)
if full then
hunk, ihunk, nhunk = get_blame_hunk(bcache.git_obj, result)
hunk, ihunk, nhunk = get_blame_hunk(bcache.git_obj.repo, result)
end
else
lines[#lines + 1] = result.author
@ -595,7 +599,7 @@ M.diffthis = void(function(base)
local err
local comp_obj = bcache:get_compare_obj(calc_base(base))
if base then
text, err = bcache.git_obj:get_show_text(comp_obj)
text, err = bcache.git_obj.repo:get_show_text(comp_obj)
if err then
print(err)
return
@ -607,7 +611,7 @@ M.diffthis = void(function(base)
local ft = api.nvim_buf_get_option(bufnr, 'filetype')
local bufname = string.format('gitsigns://%s/%s', bcache.git_obj.gitdir, comp_obj)
local bufname = string.format('gitsigns://%s/%s', bcache.git_obj.repo.gitdir, comp_obj)
vim.cmd("keepalt aboveleft vertical split " .. bufname)
@ -647,54 +651,59 @@ local function buildqflist(target)
local bufnr = target
if not cache[bufnr] then return end
hunks_to_qflist(bufnr, cache[bufnr].hunks, qflist)
elseif target == 'attached' or target == 'all' then
local gitdirs_done = {}
elseif target == 'attached' then
for bufnr, bcache in pairs(cache) do
hunks_to_qflist(bufnr, bcache.hunks, qflist)
end
elseif target == 'all' then
local repos = {}
for _, bcache in pairs(cache) do
local repo = bcache.git_obj.repo
repos[repo] = true
end
if target == 'all' then
local git_obj = bcache.git_obj
if not gitdirs_done[git_obj.gitdir] then
for _, f in ipairs(git_obj:files_changed()) do
local f_abs = git_obj.toplevel .. '/' .. f
local stat = vim.loop.fs_stat(f_abs)
if stat and stat.type == 'file' then
local hunks = run_diff(
git_obj:get_show_text(':0:' .. f),
util.file_lines(f_abs))
local repo = git.Repo.new(vim.fn.getcwd())
repos[repo] = true
hunks_to_qflist(f_abs, hunks, qflist)
end
end
for r, _ in pairs(repos) do
for _, f in ipairs(r:files_changed()) do
local f_abs = r.toplevel .. '/' .. f
local stat = vim.loop.fs_stat(f_abs)
if stat and stat.type == 'file' then
local a = r:get_show_text(':0:' .. f)
scheduler()
local hunks = run_diff(a, util.file_lines(f_abs))
hunks_to_qflist(f_abs, hunks, qflist)
end
gitdirs_done[git_obj.gitdir] = true
end
end
end
return qflist
end
M.setqflist = function(target)
block_on(function()
local qflist = buildqflist(target)
scheduler()
vim.fn.setqflist({}, ' ', {
items = qflist,
title = 'Hunks',
})
end)
end
M.setqflist = void(function(target, opts)
opts = opts or {}
local qfopts = {
items = buildqflist(target),
title = 'Hunks',
}
scheduler()
if opts.use_location_list then
local nr = opts.nr or 0
vim.fn.setloclist(nr, {}, ' ', qfopts)
vim.cmd([[lopen]])
else
vim.fn.setqflist({}, ' ', qfopts)
vim.cmd([[copen]])
end
end)
M.setloclist = function(nr, target)
block_on(function()
nr = nr or 0
local qflist = buildqflist(target)
scheduler()
vim.fn.setloclist(nr, {}, ' ', {
items = qflist,
title = 'Hunks',
})
end)
M.setqflist(target, {
nr = nr,
use_location_list = true,
})
end
M.get_actions = function()

View File

@ -54,7 +54,7 @@ M.update = void(function()
api.nvim_buf_set_extmark(bufnr, namespace, lnum - 1, 0, {
id = 1,
virt_text = config.current_line_blame_formatter(
bcache.git_obj.username,
bcache.git_obj.repo.username,
result,
config.current_line_blame_formatter_opts),

94
lua/gitsigns/git.lua generated
View File

@ -21,7 +21,14 @@ local GJobSpec = {}
local M = {BlameInfo = {}, Version = {}, Obj = {}, }
local M = {BlameInfo = {}, Version = {}, Repo = {}, Obj = {}, }
@ -87,6 +94,7 @@ local M = {BlameInfo = {}, Version = {}, Obj = {}, }
local Obj = M.Obj
local Repo = M.Repo
local function parse_version(version)
assert(version:match('%d+%.%d+%.%w+'), 'Invalid git version: ' .. version)
@ -216,16 +224,60 @@ end
Obj.command = function(self, args, spec)
Repo.command = function(self, args, spec)
spec = spec or {}
spec.cwd = self.toplevel
return M.command({ '--git-dir=' .. self.gitdir, unpack(args) }, spec)
end
Obj.update_abbrev_head = function(self)
Repo.files_changed = function(self)
local results = self:command({ 'status', '--porcelain', '--ignore-submodules' })
local ret = {}
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
Repo.get_show_text = function(self, object)
return self:command({ 'show', object }, { supress_stderr = true })
end
Repo.update_abbrev_head = function(self)
_, _, self.abbrev_head = M.get_repo_info(self.toplevel)
end
Repo.new = function(dir)
local self = setmetatable({}, { __index = Repo })
self.username = M.command({ 'config', 'user.name' })[1]
self.toplevel, self.gitdir, self.abbrev_head = M.get_repo_info(dir)
if M.enable_yadm and not self.gitdir then
if vim.startswith(dir, os.getenv('HOME')) and
#M.command({ 'ls-files', dir }, { command = 'yadm' }) ~= 0 then
self.toplevel, self.gitdir, self.abbrev_head =
M.get_repo_info(dir, 'yadm')
end
end
return self
end
Obj.command = function(self, args, spec)
return self.repo:command(args, spec)
end
Obj.update_file_info = function(self)
local old_object_name = self.object_name
_, self.object_name, self.mode_bits, self.has_conflicts = self:file_info()
@ -270,13 +322,8 @@ Obj.unstage_file = function(self)
self:command({ 'reset', self.file })
end
Obj.get_show_text = function(self, object)
return self:command({ 'show', object }, { supress_stderr = true })
end
Obj.run_blame = function(self, lines, lnum)
if not self.object_name or self.abbrev_head == '' then
if not self.object_name or self.repo.abbrev_head == '' then
@ -356,43 +403,20 @@ Obj.has_moved = function(self)
if orig_relpath == orig then
self.orig_relpath = orig_relpath
self.relpath = new
self.file = self.toplevel .. '/' .. new
self.file = self.repo.toplevel .. '/' .. new
return new
end
end
end
end
Obj.files_changed = function(self)
local results = self:command({ 'status', '--porcelain', '--ignore-submodules' })
local ret = {}
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
Obj.new = function(file)
local self = setmetatable({}, { __index = Obj })
self.file = file
self.username = M.command({ 'config', 'user.name' })[1]
self.toplevel, self.gitdir, self.abbrev_head =
M.get_repo_info(util.dirname(file))
self.repo = Repo.new(util.dirname(file))
if M.enable_yadm and not self.gitdir then
if vim.startswith(file, os.getenv('HOME')) and
#M.command({ 'ls-files', file }, { command = 'yadm' }) ~= 0 then
self.toplevel, self.gitdir, self.abbrev_head =
M.get_repo_info(util.dirname(file), 'yadm')
end
end
if not self.gitdir then
if not self.repo.gitdir then
return self
end

View File

@ -228,7 +228,7 @@ local update0 = function(bufnr, bcache)
end
if not bcache.compare_text or config._refresh_staged_on_update then
bcache.compare_text = git_obj:get_show_text(compare_object)
bcache.compare_text = git_obj.repo:get_show_text(compare_object)
end
bcache.hunks = run_diff(bcache.compare_text, buftext,
@ -243,7 +243,7 @@ local update0 = function(bufnr, bcache)
M.apply_win_signs(bufnr, bcache.pending_signs)
end
local summary = gs_hunks.get_summary(bcache.hunks)
summary.head = git_obj.abbrev_head
summary.head = git_obj.repo.abbrev_head
Status:update(bufnr, summary)
update_cnt = update_cnt + 1

View File

@ -53,7 +53,7 @@ local handle_moved = function(bufnr: integer, bcache: CacheEntry, old_relpath: s
end
do_update = true
elseif git_obj.orig_relpath then
local orig_file = git_obj.toplevel..util.path_sep..git_obj.orig_relpath
local orig_file = git_obj.repo.toplevel..util.path_sep..git_obj.orig_relpath
if git_obj:file_info(orig_file) then
dprintf('Moved file reset')
git_obj.relpath = git_obj.orig_relpath
@ -65,7 +65,7 @@ local handle_moved = function(bufnr: integer, bcache: CacheEntry, old_relpath: s
end
if do_update then
git_obj.file = git_obj.toplevel..util.path_sep..git_obj.relpath
git_obj.file = git_obj.repo.toplevel..util.path_sep..git_obj.relpath
bcache.file = git_obj.file
bcache.git_obj:update_file_info()
scheduler()
@ -97,10 +97,10 @@ local watch_index = function(bufnr: integer, gitdir: string): uv.FSPollObj
local git_obj = bcache.git_obj
git_obj:update_abbrev_head()
git_obj.repo:update_abbrev_head()
scheduler()
Status:update(bufnr, { head = git_obj.abbrev_head})
Status:update(bufnr, { head = git_obj.repo.abbrev_head})
local was_tracked = git_obj.object_name ~= nil
local old_relpath = git_obj.relpath
@ -240,20 +240,21 @@ local attach0 = function(cbuf: integer, aucmd: string)
end
local git_obj = git.Obj.new(file)
local repo = git_obj.repo
if not git_obj.gitdir then
if not repo.gitdir then
dprint('Not in git repo')
return
end
scheduler()
Status:update(cbuf, {
head = git_obj.abbrev_head,
root = git_obj.toplevel,
gitdir = git_obj.gitdir,
head = repo.abbrev_head,
root = repo.toplevel,
gitdir = repo.gitdir,
})
if vim.startswith(file, git_obj.gitdir..util.path_sep) then
if vim.startswith(file, repo.gitdir..util.path_sep) then
dprint('In non-standard git dir')
return
end
@ -286,7 +287,7 @@ local attach0 = function(cbuf: integer, aucmd: string)
base = config.base,
file = file,
commit = commit,
index_watcher = watch_index(cbuf, git_obj.gitdir),
index_watcher = watch_index(cbuf, repo.gitdir),
git_obj = git_obj
}
@ -413,8 +414,9 @@ local _update_cwd_head = function()
local cwd = vim.fn.getcwd()
local head: string
for _, bcache in pairs(cache as {number:CacheEntry}) do
if bcache.git_obj.toplevel == cwd then
head = bcache.git_obj.abbrev_head
local repo = bcache.git_obj.repo
if repo.toplevel == cwd then
head = repo.abbrev_head
break
end
end

View File

@ -1,6 +1,5 @@
local void = require('plenary.async.async').void
local scheduler = require('plenary.async.util').scheduler
local block_on = require('plenary.async.util').block_on
local Status = require("gitsigns.status")
local config = require('gitsigns.config').config
@ -48,7 +47,12 @@ local record M
reset_base : function(global: boolean)
diffthis : function -- function(base: string)
setqflist : function(target:integer|string)
record QFListOpts
use_location_list: boolean
nr: integer
end
setqflist : function(target:integer|string, opts: QFListOpts, callback: function)
setloclist : function(nr: integer, target:integer|string)
user_range : {integer, integer}
@ -452,13 +456,13 @@ local function run_diff(a: {string}, b: {string}): {Hunk}
return f(a, b, diff_opts.algorithm, diff_opts.indent_heuristic)
end
local function get_blame_hunk(git_obj: git.Obj, info: git.BlameInfo): Hunk, integer, integer
local function get_blame_hunk(repo: git.Repo, info: git.BlameInfo): Hunk, integer, integer
local a = {}
-- If no previous so sha of blame added the file
if info.previous then
a = git_obj:get_show_text(info.previous_sha..':'..info.previous_filename)
a = repo:get_show_text(info.previous_sha..':'..info.previous_filename)
end
local b = git_obj:get_show_text(info.sha..':'..info.filename)
local b = repo:get_show_text(info.sha..':'..info.filename)
local hunks = run_diff(a, b)
local hunk, i = gs_hunks.find_hunk(info.orig_lnum, hunks)
return hunk, i, #hunks
@ -516,7 +520,7 @@ M.blame_line = void(function(full: boolean)
vim.list_extend(lines, commit_message)
if full then
hunk, ihunk, nhunk = get_blame_hunk(bcache.git_obj, result)
hunk, ihunk, nhunk = get_blame_hunk(bcache.git_obj.repo, result)
end
else
lines[#lines+1] = result.author
@ -595,7 +599,7 @@ M.diffthis = void(function(base: string)
local err: string
local comp_obj = bcache:get_compare_obj(calc_base(base))
if base then
text, err = bcache.git_obj:get_show_text(comp_obj)
text, err = bcache.git_obj.repo:get_show_text(comp_obj)
if err then
print(err)
return
@ -607,7 +611,7 @@ M.diffthis = void(function(base: string)
local ft = api.nvim_buf_get_option(bufnr, 'filetype')
local bufname = string.format('gitsigns://%s/%s', bcache.git_obj.gitdir, comp_obj)
local bufname = string.format('gitsigns://%s/%s', bcache.git_obj.repo.gitdir, comp_obj)
-- TDOD lewis6991 (27/05/21): Respect 'vertical' in diffopt
vim.cmd("keepalt aboveleft vertical split "..bufname)
@ -647,54 +651,59 @@ local function buildqflist(target: integer|string): {vim.fn.QFItem}
local bufnr = target as integer
if not cache[bufnr] then return end
hunks_to_qflist(bufnr, cache[bufnr].hunks, qflist)
elseif target == 'attached' or target == 'all' then
local gitdirs_done: {string:boolean} = {}
elseif target == 'attached' then
for bufnr, bcache in pairs(cache as {integer:CacheEntry}) do
hunks_to_qflist(bufnr, bcache.hunks, qflist)
end
elseif target == 'all' then
local repos: {git.Repo:boolean} = {}
for _, bcache in pairs(cache as {integer:CacheEntry}) do
local repo = bcache.git_obj.repo
repos[repo] = true
end
if target == 'all' then
local git_obj = bcache.git_obj
if not gitdirs_done[git_obj.gitdir] then
for _, f in ipairs(git_obj:files_changed()) do
local f_abs = git_obj.toplevel..'/'..f
local stat = vim.loop.fs_stat(f_abs)
if stat and stat.type == 'file' then
local hunks = run_diff(
git_obj:get_show_text(':0:'..f),
util.file_lines(f_abs)
)
hunks_to_qflist(f_abs, hunks, qflist)
end
end
local repo = git.Repo.new(vim.fn.getcwd())
repos[repo] = true
for r, _ in pairs(repos) do
for _, f in ipairs(r:files_changed()) do
local f_abs = r.toplevel..'/'..f
local stat = vim.loop.fs_stat(f_abs)
if stat and stat.type == 'file' then
local a = r:get_show_text(':0:'..f)
scheduler()
local hunks = run_diff(a, util.file_lines(f_abs))
hunks_to_qflist(f_abs, hunks, qflist)
end
gitdirs_done[git_obj.gitdir] = true
end
end
end
return qflist
end
M.setqflist = function(target: integer|string)
block_on(function()
local qflist = buildqflist(target)
scheduler()
vim.fn.setqflist({}, ' ', {
items = qflist,
title = 'Hunks'
})
end)
end
M.setqflist = void(function(target: integer|string, opts: M.QFListOpts)
opts = opts or {}
local qfopts = {
items = buildqflist(target),
title = 'Hunks'
}
scheduler()
if opts.use_location_list then
local nr = opts.nr or 0
vim.fn.setloclist(nr, {}, ' ', qfopts)
vim.cmd[[lopen]]
else
vim.fn.setqflist({}, ' ', qfopts)
vim.cmd[[copen]]
end
end)
M.setloclist = function(nr: integer, target: integer|string)
block_on(function()
nr = nr or 0
local qflist = buildqflist(target)
scheduler()
vim.fn.setloclist(nr, {}, ' ', {
items = qflist,
title = 'Hunks'
})
end)
M.setqflist(target, {
nr = nr,
use_location_list = true
})
end
M.get_actions = function(): {string:function}

View File

@ -54,7 +54,7 @@ M.update = void(function()
api.nvim_buf_set_extmark(bufnr, namespace, lnum-1, 0, {
id = 1,
virt_text = config.current_line_blame_formatter(
bcache.git_obj.username,
bcache.git_obj.repo.username,
result,
config.current_line_blame_formatter_opts
),

View File

@ -58,12 +58,22 @@ local record M
get_repo_info: function(path: string, cmd: string): string,string,string
command : function(args: {string}, spec: GJobSpec): {string}, string
record Repo
toplevel : string
gitdir : string
abbrev_head: string
username : string
command : function(Repo, {string}, GJobSpec): {string}, string
files_changed : function(Repo): {string}
get_show_text : function(Repo, string): {string}, string
update_abbrev_head : function(Repo)
new : function(string): Repo
end
record Obj
toplevel : string
gitdir : string
repo : Repo
file : string
abbrev_head : string
username : string
relpath : string
orig_relpath : string -- Use for tracking moved files
object_name : string
@ -71,22 +81,20 @@ local record M
has_conflicts : boolean
command : function(Obj, {string}, GJobSpec): {string}, string
update_abbrev_head : function(Obj)
update_file_info : function(Obj): boolean
unstage_file : function(Obj, string, string)
get_show_text : function(Obj, string): {string}, string
run_blame : function(Obj, {string}, number): BlameInfo
file_info : function(Obj, string): string, string, string, boolean
ensure_file_in_index : function(Obj)
stage_hunks : function(Obj, {Hunk}, boolean)
has_moved : function(Obj): string
files_changed : function(Obj): {string}
new : function(string): Obj
end
end
local Obj = M.Obj
local Repo = M.Repo
local function parse_version(version: string): M.Version
assert(version:match('%d+%.%d+%.%w+'), 'Invalid git version: '..version)
@ -212,20 +220,64 @@ M.set_version = function(version: string)
end
--------------------------------------------------------------------------------
-- Git object methods
-- Git repo object methods
--------------------------------------------------------------------------------
--- Run git command the with the objects gitdir and toplevel
Obj.command = function(self: Obj, args: {string}, spec: GJobSpec): {string}, string
Repo.command = function(self: Repo, args: {string}, spec: GJobSpec): {string}, string
spec = spec or {}
spec.cwd = self.toplevel
return M.command({'--git-dir='..self.gitdir, unpack(args)}, spec)
end
Obj.update_abbrev_head = function(self: Obj)
Repo.files_changed = function(self: Repo): {string}
local results = self:command({ 'status', '--porcelain', '--ignore-submodules' })
local ret: {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
--- Get version of file in the index, return array lines
Repo.get_show_text = function(self: Repo, object: string): {string}, string
return self:command({'show', object}, {supress_stderr = true})
end
Repo.update_abbrev_head = function(self: Repo)
_, _, self.abbrev_head = M.get_repo_info(self.toplevel)
end
Repo.new = function(dir: string): Repo
local self = setmetatable({} as Repo, {__index = Repo})
self.username = M.command({'config', 'user.name'})[1]
self.toplevel, self.gitdir, self.abbrev_head = M.get_repo_info(dir)
-- Try yadm
if M.enable_yadm and not self.gitdir then
if vim.startswith(dir, os.getenv('HOME'))
and #M.command({'ls-files', dir}, {command = 'yadm'}) ~= 0 then
self.toplevel, self.gitdir, self.abbrev_head =
M.get_repo_info(dir, 'yadm')
end
end
return self
end
--------------------------------------------------------------------------------
-- Git object methods
--------------------------------------------------------------------------------
--- Run git command the with the objects gitdir and toplevel
Obj.command = function(self: Obj, args: {string}, spec: GJobSpec): {string}, string
return self.repo:command(args, spec)
end
Obj.update_file_info = function(self: Obj): boolean
local old_object_name = self.object_name
_, self.object_name, self.mode_bits, self.has_conflicts = self:file_info()
@ -270,13 +322,8 @@ Obj.unstage_file = function(self: Obj)
self:command{'reset', self.file }
end
--- Get version of file in the index, return array lines
Obj.get_show_text = function(self: Obj, object: string): {string}, string
return self:command({'show', object}, { supress_stderr = true })
end
Obj.run_blame = function(self: Obj, lines: {string}, lnum: number): M.BlameInfo
if not self.object_name or self.abbrev_head == '' then
if not self.object_name or self.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
@ -356,43 +403,20 @@ Obj.has_moved = function(self: Obj): string
if orig_relpath == orig then
self.orig_relpath = orig_relpath
self.relpath = new
self.file = self.toplevel..'/'..new
self.file = self.repo.toplevel..'/'..new
return new
end
end
end
end
Obj.files_changed = function(self: Obj): {string}
local results = self:command{'status', '--porcelain', '--ignore-submodules'}
local ret: {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
Obj.new = function(file: string): Obj
local self = setmetatable({} as Obj, {__index = Obj})
self.file = file
self.username = M.command({'config', 'user.name'})[1]
self.toplevel, self.gitdir, self.abbrev_head =
M.get_repo_info(util.dirname(file))
self.repo = Repo.new(util.dirname(file))
-- Try yadm
if M.enable_yadm and not self.gitdir then
if vim.startswith(file, os.getenv('HOME'))
and #M.command({'ls-files', file}, {command = 'yadm'}) ~= 0 then
self.toplevel, self.gitdir, self.abbrev_head =
M.get_repo_info(util.dirname(file), 'yadm')
end
end
if not self.gitdir then
if not self.repo.gitdir then
return self
end

View File

@ -228,7 +228,7 @@ local update0 = function(bufnr: integer, bcache: CacheEntry)
end
if not bcache.compare_text or config._refresh_staged_on_update then
bcache.compare_text = git_obj:get_show_text(compare_object)
bcache.compare_text = git_obj.repo:get_show_text(compare_object)
end
bcache.hunks = run_diff(bcache.compare_text, buftext,
@ -243,7 +243,7 @@ local update0 = function(bufnr: integer, bcache: CacheEntry)
M.apply_win_signs(bufnr, bcache.pending_signs)
end
local summary = gs_hunks.get_summary(bcache.hunks)
summary.head = git_obj.abbrev_head
summary.head = git_obj.repo.abbrev_head
Status:update(bufnr, summary)
update_cnt = update_cnt + 1