Skip to content

Commit

Permalink
fix(update): always get object contents from object names
Browse files Browse the repository at this point in the history
Fixes #847
  • Loading branch information
lewis6991 committed May 22, 2024
1 parent d6a3bf0 commit a28bb1d
Show file tree
Hide file tree
Showing 12 changed files with 147 additions and 89 deletions.
7 changes: 5 additions & 2 deletions lua/gitsigns/actions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1026,7 +1026,10 @@ end
--- @param bcache Gitsigns.CacheEntry
--- @param base string?
local function update_buf_base(bcache, base)
bcache.base = base
bcache.file_mode = base == 'FILE'
if not bcache.file_mode then
bcache.git_obj:update_revision(base)
end
bcache:invalidate(true)
update(bcache.bufnr)
end
Expand Down Expand Up @@ -1064,7 +1067,7 @@ end
--- @param base string|nil The object/revision to diff against.
--- @param global boolean|nil Change the base of all buffers.
M.change_base = async.create(2, function(base, global)
base = util.calc_base(base)
base = util.norm_base(base)

if global then
config.base = base
Expand Down
19 changes: 10 additions & 9 deletions lua/gitsigns/attach.lua
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,7 @@ local function parse_gitsigns_uri(name)
-- TODO(lewis6991): Support submodules
--- @type any, any, string?, string?, string
local _, _, root_path, commit, rel_path = name:find([[^gitsigns://(.*)/%.git/(.*):(.*)]])
if commit == ':0' then
-- ':0' means the index so clear commit so we attach normally
commit = nil
end
commit = util.norm_base(commit)
if root_path then
name = root_path .. '/' .. rel_path
end
Expand Down Expand Up @@ -186,7 +183,6 @@ end)
--- @field file string
--- @field toplevel? string
--- @field gitdir? string
--- @field commit? string
--- @field base? string

--- @param bufnr integer
Expand Down Expand Up @@ -215,7 +211,13 @@ local function get_buf_context(bufnr)
file = file,
gitdir = gitdir,
toplevel = toplevel,
commit = commit,
-- Commit buffers have there base set back one revision with '^'
-- Stage buffers always compare against the common ancestor (':1')
-- :0: index
-- :1: common ancestor
-- :2: target commit (HEAD)
-- :3: commit which is being merged
base = commit and (commit:match('^:[1-3]') and ':1' or commit .. '^') or nil,
}
end

Expand Down Expand Up @@ -267,7 +269,8 @@ local attach_throttled = throttle_by_id(function(cbuf, ctx, aucmd)
file = ctx.toplevel .. util.path_sep .. file
end

local git_obj = git.Obj.new(file, encoding, ctx.gitdir, ctx.toplevel)
local revision = ctx.base or config.base
local git_obj = git.Obj.new(file, revision, encoding, ctx.gitdir, ctx.toplevel)

if not git_obj and not passed_ctx then
git_obj = try_worktrees(cbuf, file, encoding)
Expand Down Expand Up @@ -322,9 +325,7 @@ local attach_throttled = throttle_by_id(function(cbuf, ctx, aucmd)

cache[cbuf] = gs_cache.new({
bufnr = cbuf,
base = ctx.base or config.base,
file = file,
commit = ctx.commit,
git_obj = git_obj,
})

Expand Down
24 changes: 2 additions & 22 deletions lua/gitsigns/cache.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,42 +9,22 @@ local M = {
--- @class (exact) Gitsigns.CacheEntry
--- @field bufnr integer
--- @field file string
--- @field base? string
--- @field compare_text? string[]
--- @field hunks? Gitsigns.Hunk.Hunk[]
--- @field force_next_update? boolean
--- @field file_mode? boolean
---
--- @field compare_text_head? string[]
--- @field hunks_staged? Gitsigns.Hunk.Hunk[]
---
--- @field staged_diffs? Gitsigns.Hunk.Hunk[]
--- @field gitdir_watcher? uv.uv_fs_event_t
--- @field git_obj Gitsigns.GitObj
--- @field commit? string
--- @field blame? table<integer,Gitsigns.BlameInfo?>
local CacheEntry = M.CacheEntry

function CacheEntry:get_compare_rev(base)
base = base or self.base
if base then
return base
end

if self.commit then
-- Buffer is a fugitive commit so compare against the parent of the commit
if config._signs_staged_enable then
return self.commit
else
return string.format('%s^', self.commit)
end
end

local stage = self.git_obj.has_conflicts and 1 or 0
return string.format(':%d', stage)
end

function CacheEntry:get_rev_bufname(rev)
rev = rev or self:get_compare_rev()
rev = rev or self.git_obj.revision or ':0'
return string.format('gitsigns://%s/%s:%s', self.git_obj.repo.gitdir, rev, self.git_obj.relpath)
end

Expand Down
32 changes: 21 additions & 11 deletions lua/gitsigns/debug.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,29 @@ local M = {}
local function process(raw_item, path)
--- @diagnostic disable-next-line:undefined-field
if path[#path] == vim.inspect.METATABLE then
return nil
return
elseif type(raw_item) == 'function' then
return nil
elseif type(raw_item) == 'table' then
local key = path[#path]
if key == 'compare_text' or key == 'compare_text_head' then
local item = raw_item
--- @diagnostic disable-next-line:no-unknown
return { '...', length = #item, head = item[1] }
elseif not vim.tbl_isempty(raw_item) and key == 'staged_diffs' then
return { '...', length = #vim.tbl_keys(raw_item) }
end
return
elseif type(raw_item) ~= 'table' then
return raw_item
end
--- @cast raw_item table<any,any>

local key = path[#path]
if
vim.tbl_contains({
'compare_text',
'compare_text_head',
'hunks',
'hunks_staged',
'staged_diffs',
}, key)
then
return { '...', length = #vim.tbl_keys(raw_item), head = raw_item[next(raw_item)] }
elseif key == 'blame' then
return { '...', length = #vim.tbl_keys(raw_item) }
end

return raw_item
end

Expand Down
3 changes: 3 additions & 0 deletions lua/gitsigns/debug/log.lua
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ function M.eprintf(fmt, ...)
eprint(fmt:format(...), 1)
end

--- @param cond boolean
--- @param msg string
--- @return boolean
function M.assert(cond, msg)
if not cond then
eprint(msg, 1)
Expand Down
19 changes: 10 additions & 9 deletions lua/gitsigns/diffthis.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ local M = {}
--- @param base string?
local function bufread(bufnr, dbufnr, base)
local bcache = cache[bufnr]
local comp_rev = bcache:get_compare_rev(util.calc_base(base))
base = util.norm_base(base)
local text --- @type string[]
if util.calc_base(base) == util.calc_base(bcache.base) then
if base == bcache.git_obj.revision then
text = assert(bcache.compare_text)
else
local err
text, err = bcache.git_obj:get_show_text(comp_rev)
text, err = bcache.git_obj:get_show_text(base)
if err then
error(err, 2)
end
Expand All @@ -39,7 +39,7 @@ local function bufread(bufnr, dbufnr, base)

local modifiable = vim.bo[dbufnr].modifiable
vim.bo[dbufnr].modifiable = true
Status:update(dbufnr, { head = comp_rev })
Status:update(dbufnr, { head = base })

util.set_lines(dbufnr, 0, -1, text)

Expand All @@ -54,15 +54,16 @@ end
local bufwrite = async.create(3, function(bufnr, dbufnr, base)
local bcache = cache[bufnr]
local buftext = util.buf_lines(dbufnr)
base = util.norm_base(base)
bcache.git_obj:stage_lines(buftext)
async.scheduler()
if not api.nvim_buf_is_valid(bufnr) then
return
end
vim.bo[dbufnr].modified = false
-- If diff buffer base matches the bcache base then also update the
-- If diff buffer base matches the git_obj revision then also update the
-- signs.
if util.calc_base(base) == util.calc_base(bcache.base) then
if base == bcache.git_obj.revision then
bcache.compare_text = buftext
manager.update(bufnr)
end
Expand All @@ -75,9 +76,9 @@ end)
--- @return string? buf Buffer name
local function create_show_buf(bufnr, base)
local bcache = assert(cache[bufnr])
base = util.norm_base(base)

local revision = bcache:get_compare_rev(util.calc_base(base))
local bufname = bcache:get_rev_bufname(revision)
local bufname = bcache:get_rev_bufname(base)

if util.bufexists(bufname) then
return bufname
Expand All @@ -95,7 +96,7 @@ local function create_show_buf(bufnr, base)
end

-- allow editing the index revision
if revision == ':0' then
if not bcache.git_obj.revision then
vim.bo[dbuf].buftype = 'acwrite'

api.nvim_create_autocmd('BufReadCmd', {
Expand Down
Loading

0 comments on commit a28bb1d

Please sign in to comment.