refactor(git): split URI read from conditional refresh
This commit is contained in:
+6
-18
@@ -81,17 +81,13 @@ local function uri_split(opts, buf, rev)
|
|||||||
local object = require("git.object")
|
local object = require("git.object")
|
||||||
|
|
||||||
if opts.rev and opts.rev:find(":", 1, true) then
|
if opts.rev and opts.rev:find(":", 1, true) then
|
||||||
local content = util.exec(
|
if not r:rev_parse(opts.rev, true) then
|
||||||
{ "git", "cat-file", "-p", opts.rev },
|
|
||||||
{ cwd = r.worktree, silent = true }
|
|
||||||
)
|
|
||||||
if not content then
|
|
||||||
util.error("invalid rev: %s", opts.rev)
|
util.error("invalid rev: %s", opts.rev)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
place_pair(
|
place_pair(
|
||||||
buf,
|
buf,
|
||||||
object.buf_for(r, Revision.parse(opts.rev), content),
|
object.buf_for(r, Revision.parse(opts.rev)),
|
||||||
false,
|
false,
|
||||||
opts.vertical
|
opts.vertical
|
||||||
)
|
)
|
||||||
@@ -123,15 +119,11 @@ local function uri_split(opts, buf, rev)
|
|||||||
local m = mapping[rev.stage]
|
local m = mapping[rev.stage]
|
||||||
or { Revision.new({ stage = 0, path = rev.path }), true }
|
or { Revision.new({ stage = 0, path = rev.path }), true }
|
||||||
local other_rev, left = m[1], m[2]
|
local other_rev, left = m[1], m[2]
|
||||||
local content = util.exec(
|
if not r:rev_parse(other_rev:format(), true) then
|
||||||
{ "git", "cat-file", "-p", other_rev:format() },
|
|
||||||
{ cwd = r.worktree, silent = true }
|
|
||||||
)
|
|
||||||
if not content then
|
|
||||||
util.error("invalid rev: %s", other_rev:format())
|
util.error("invalid rev: %s", other_rev:format())
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
place_pair(buf, object.buf_for(r, other_rev, content), left, opts.vertical)
|
place_pair(buf, object.buf_for(r, other_rev), left, opts.vertical)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@class ow.Git.Diff.SplitOpts
|
---@class ow.Git.Diff.SplitOpts
|
||||||
@@ -172,15 +164,11 @@ function M.split(opts)
|
|||||||
else
|
else
|
||||||
rev = Revision.new({ base = opts.rev, path = rel })
|
rev = Revision.new({ base = opts.rev, path = rel })
|
||||||
end
|
end
|
||||||
local content = util.exec(
|
if not r:rev_parse(rev:format(), true) then
|
||||||
{ "git", "cat-file", "-p", rev:format() },
|
|
||||||
{ cwd = r.worktree, silent = true }
|
|
||||||
)
|
|
||||||
if not content then
|
|
||||||
util.error("invalid rev: %s", rev:format())
|
util.error("invalid rev: %s", rev:format())
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local buf = require("git.object").buf_for(r, rev, content)
|
local buf = require("git.object").buf_for(r, rev)
|
||||||
place_pair(buf, cur_buf, true, opts.vertical)
|
place_pair(buf, cur_buf, true, opts.vertical)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -71,7 +71,7 @@ function M.init()
|
|||||||
pattern = "git://*",
|
pattern = "git://*",
|
||||||
group = group,
|
group = group,
|
||||||
callback = function(args)
|
callback = function(args)
|
||||||
require("git.object").read_uri(args.buf, { force = true })
|
require("git.object").read_uri(args.buf)
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -49,10 +49,10 @@ local function fetch(worktree, max_count)
|
|||||||
end
|
end
|
||||||
|
|
||||||
---@param buf integer
|
---@param buf integer
|
||||||
local function populate(buf)
|
---@param r ow.Git.Repo
|
||||||
local r = repo.resolve(buf)
|
local function populate(buf, r)
|
||||||
local state = r and r:state(buf)
|
local state = r:state(buf)
|
||||||
if not r or not state then
|
if not state then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local stdout = fetch(r.worktree, state.log_max_count)
|
local stdout = fetch(r.worktree, state.log_max_count)
|
||||||
@@ -110,7 +110,7 @@ function M.read_uri(buf)
|
|||||||
end
|
end
|
||||||
|
|
||||||
attach_dispatch(buf)
|
attach_dispatch(buf)
|
||||||
populate(buf)
|
populate(buf, r)
|
||||||
end
|
end
|
||||||
|
|
||||||
---@class ow.Git.Log.OpenOpts
|
---@class ow.Git.Log.OpenOpts
|
||||||
@@ -144,7 +144,7 @@ function M.open(opts)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if was_loaded then
|
if was_loaded then
|
||||||
populate(buf)
|
populate(buf, r)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -183,6 +183,6 @@ function M.complete_glog(arg_lead)
|
|||||||
return matches
|
return matches
|
||||||
end
|
end
|
||||||
|
|
||||||
repo.on_uri_refresh(M.URI_PREFIX, M.read_uri)
|
repo.on_uri_refresh(M.URI_PREFIX, populate)
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
|||||||
+53
-40
@@ -71,6 +71,20 @@ local function is_zero(sha)
|
|||||||
return sha == nil or sha:match("^0+$") ~= nil
|
return sha == nil or sha:match("^0+$") ~= nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param rev ow.Git.Revision
|
||||||
|
---@return boolean
|
||||||
|
local function is_immutable_rev(rev)
|
||||||
|
if rev.stage ~= nil then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local base = rev.base
|
||||||
|
if not base then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local stripped = base:gsub("%^%b{}", ""):gsub("[%^~]%d*", "")
|
||||||
|
return stripped:match("^%x+$") ~= nil and #stripped >= 7
|
||||||
|
end
|
||||||
|
|
||||||
---@param buf integer
|
---@param buf integer
|
||||||
---@param r ow.Git.Repo
|
---@param r ow.Git.Repo
|
||||||
---@param path string
|
---@param path string
|
||||||
@@ -141,23 +155,16 @@ end
|
|||||||
|
|
||||||
---@param r ow.Git.Repo
|
---@param r ow.Git.Repo
|
||||||
---@param rev ow.Git.Revision
|
---@param rev ow.Git.Revision
|
||||||
---@param content string?
|
|
||||||
---@return integer
|
---@return integer
|
||||||
function M.buf_for(r, rev, content)
|
function M.buf_for(r, rev)
|
||||||
local buf = vim.fn.bufadd(M.format_uri(rev))
|
local buf = vim.fn.bufadd(M.format_uri(rev))
|
||||||
repo.bind(buf, r)
|
repo.bind(buf, r)
|
||||||
if content and not vim.api.nvim_buf_is_loaded(buf) then
|
|
||||||
local state = r:state(buf) --[[@as -nil]]
|
|
||||||
state.pending_content = content
|
|
||||||
end
|
|
||||||
vim.fn.bufload(buf)
|
vim.fn.bufload(buf)
|
||||||
return buf
|
return buf
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param buf integer
|
---@param buf integer
|
||||||
---@param opts { force?: boolean }?
|
function M.read_uri(buf)
|
||||||
function M.read_uri(buf, opts)
|
|
||||||
opts = opts or {}
|
|
||||||
local name = vim.api.nvim_buf_get_name(buf)
|
local name = vim.api.nvim_buf_get_name(buf)
|
||||||
local rev = M.parse_uri(name)
|
local rev = M.parse_uri(name)
|
||||||
if not rev then
|
if not rev then
|
||||||
@@ -176,27 +183,20 @@ function M.read_uri(buf, opts)
|
|||||||
vim.bo[buf].swapfile = false
|
vim.bo[buf].swapfile = false
|
||||||
vim.bo[buf].bufhidden = "hide"
|
vim.bo[buf].bufhidden = "hide"
|
||||||
|
|
||||||
---@type string?
|
local rev_sha = r:rev_parse(rev_str, true)
|
||||||
local stdout = state.pending_content
|
if not rev_sha then
|
||||||
state.pending_content = nil
|
return
|
||||||
if stdout == nil then
|
|
||||||
local rev_sha = r:rev_parse(rev_str, true)
|
|
||||||
if not rev_sha then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
if
|
|
||||||
not opts.force
|
|
||||||
and (rev_sha == state.sha or vim.bo[buf].modified)
|
|
||||||
then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
stdout = util.exec(
|
|
||||||
{ "git", "cat-file", "-p", rev_str },
|
|
||||||
{ cwd = r.worktree }
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if stdout and rev.path == nil then
|
local stdout = util.exec(
|
||||||
|
{ "git", "cat-file", "-p", rev_str },
|
||||||
|
{ cwd = r.worktree }
|
||||||
|
)
|
||||||
|
if not stdout then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if rev.path == nil then
|
||||||
local commit_sha = r:rev_parse(rev_str .. "^{commit}", true)
|
local commit_sha = r:rev_parse(rev_str .. "^{commit}", true)
|
||||||
if commit_sha then
|
if commit_sha then
|
||||||
local patch = util.exec({
|
local patch = util.exec({
|
||||||
@@ -216,12 +216,11 @@ function M.read_uri(buf, opts)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if stdout then
|
vim.bo[buf].modifiable = true
|
||||||
vim.bo[buf].modifiable = true
|
vim.api.nvim_buf_set_lines(buf, 0, -1, false, util.split_lines(stdout))
|
||||||
vim.api.nvim_buf_set_lines(buf, 0, -1, false, util.split_lines(stdout))
|
|
||||||
end
|
|
||||||
|
|
||||||
state.sha = r:rev_parse(rev_str, true)
|
state.sha = rev_sha
|
||||||
|
state.immutable = is_immutable_rev(rev)
|
||||||
|
|
||||||
if rev.stage == 0 and rev.path then
|
if rev.stage == 0 and rev.path then
|
||||||
vim.bo[buf].buftype = "acwrite"
|
vim.bo[buf].buftype = "acwrite"
|
||||||
@@ -249,6 +248,24 @@ function M.read_uri(buf, opts)
|
|||||||
vim.api.nvim_exec_autocmds("BufReadPost", { buffer = buf })
|
vim.api.nvim_exec_autocmds("BufReadPost", { buffer = buf })
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param buf integer
|
||||||
|
---@param r ow.Git.Repo
|
||||||
|
local function refresh(buf, r)
|
||||||
|
local state = r:state(buf)
|
||||||
|
if not state or state.immutable or vim.bo[buf].modified then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local rev = M.parse_uri(vim.api.nvim_buf_get_name(buf))
|
||||||
|
if not rev then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local rev_sha = r:rev_parse(rev:format(), true)
|
||||||
|
if not rev_sha or rev_sha == state.sha then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
M.read_uri(buf)
|
||||||
|
end
|
||||||
|
|
||||||
---@param r ow.Git.Repo
|
---@param r ow.Git.Repo
|
||||||
---@param blob string?
|
---@param blob string?
|
||||||
---@param path string
|
---@param path string
|
||||||
@@ -314,15 +331,11 @@ function M.open(r, rev, opts)
|
|||||||
parsed.base = sha
|
parsed.base = sha
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local content = util.exec(
|
if not r:rev_parse(parsed:format(), true) then
|
||||||
{ "git", "cat-file", "-p", parsed:format() },
|
|
||||||
{ cwd = r.worktree, silent = true }
|
|
||||||
)
|
|
||||||
if not content then
|
|
||||||
util.error("not a git object: %s", rev)
|
util.error("not a git object: %s", rev)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local buf = M.buf_for(r, parsed, content)
|
local buf = M.buf_for(r, parsed)
|
||||||
util.place_buf(buf, opts and opts.split)
|
util.place_buf(buf, opts and opts.split)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -384,6 +397,6 @@ function M.open_under_cursor()
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
repo.on_uri_refresh(M.URI_PREFIX, M.read_uri)
|
repo.on_uri_refresh(M.URI_PREFIX, refresh)
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
|||||||
+3
-3
@@ -16,10 +16,10 @@ end
|
|||||||
---@field repo ow.Git.Repo
|
---@field repo ow.Git.Repo
|
||||||
---@field sha string?
|
---@field sha string?
|
||||||
---@field parent_sha string?
|
---@field parent_sha string?
|
||||||
|
---@field immutable boolean?
|
||||||
---@field index_writer boolean?
|
---@field index_writer boolean?
|
||||||
---@field index_mode string?
|
---@field index_mode string?
|
||||||
---@field log_max_count integer?
|
---@field log_max_count integer?
|
||||||
---@field pending_content string?
|
|
||||||
|
|
||||||
---@alias ow.Git.Repo.Event "refresh"
|
---@alias ow.Git.Repo.Event "refresh"
|
||||||
|
|
||||||
@@ -208,7 +208,7 @@ function M.on(event, fn)
|
|||||||
end
|
end
|
||||||
|
|
||||||
---@param prefix string
|
---@param prefix string
|
||||||
---@param fn fun(buf: integer)
|
---@param fn fun(buf: integer, r: ow.Git.Repo)
|
||||||
---@return fun() unsubscribe
|
---@return fun() unsubscribe
|
||||||
function M.on_uri_refresh(prefix, fn)
|
function M.on_uri_refresh(prefix, fn)
|
||||||
return M.on("refresh", function(r)
|
return M.on("refresh", function(r)
|
||||||
@@ -216,7 +216,7 @@ function M.on_uri_refresh(prefix, fn)
|
|||||||
if vim.api.nvim_buf_is_valid(buf) then
|
if vim.api.nvim_buf_is_valid(buf) then
|
||||||
local name = vim.api.nvim_buf_get_name(buf)
|
local name = vim.api.nvim_buf_get_name(buf)
|
||||||
if name:sub(1, #prefix) == prefix then
|
if name:sub(1, #prefix) == prefix then
|
||||||
fn(buf)
|
fn(buf, r)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user