feat(blame): support every file-shaped git:// URI
This commit is contained in:
+14
-2
@@ -192,14 +192,26 @@ local function resolve_source(buf)
|
|||||||
local name = vim.api.nvim_buf_get_name(buf)
|
local name = vim.api.nvim_buf_get_name(buf)
|
||||||
if util.is_uri(name) then
|
if util.is_uri(name) then
|
||||||
local rev = object.parse_uri(name)
|
local rev = object.parse_uri(name)
|
||||||
if not rev or not rev.base or not rev.path then
|
if not rev then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
local r = repo.find(buf)
|
local r = repo.find(buf)
|
||||||
if not r then
|
if not r then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
return { repo = r, rel = rev.path, revision = rev.base }
|
local rel = rev.path
|
||||||
|
if not rel then
|
||||||
|
local state = r:state(buf)
|
||||||
|
rel = state and state.blob_path or nil
|
||||||
|
if not rel then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local revision = nil
|
||||||
|
if rev.path and rev.base and rev.stage == nil then
|
||||||
|
revision = rev.base
|
||||||
|
end
|
||||||
|
return { repo = r, rel = rel, revision = revision }
|
||||||
end
|
end
|
||||||
if not repo.is_worktree_buf(buf) then
|
if not repo.is_worktree_buf(buf) then
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ end
|
|||||||
---@field immutable boolean?
|
---@field immutable boolean?
|
||||||
---@field index_writer boolean?
|
---@field index_writer boolean?
|
||||||
---@field index_mode string?
|
---@field index_mode string?
|
||||||
|
---@field blob_path string?
|
||||||
|
|
||||||
---@alias ow.Git.Repo.Event
|
---@alias ow.Git.Repo.Event
|
||||||
---| "change"
|
---| "change"
|
||||||
|
|||||||
@@ -321,6 +321,10 @@ local function side_buf(r, blob, path)
|
|||||||
if full then
|
if full then
|
||||||
local buf = M.buf_for(r, Revision.new({ base = full }))
|
local buf = M.buf_for(r, Revision.new({ base = full }))
|
||||||
set_ft_from_path(buf, path)
|
set_ft_from_path(buf, path)
|
||||||
|
local state = r:state(buf)
|
||||||
|
if state then
|
||||||
|
state.blob_path = path
|
||||||
|
end
|
||||||
return buf
|
return buf
|
||||||
end
|
end
|
||||||
local p = vim.fs.joinpath(r.worktree, path)
|
local p = vim.fs.joinpath(r.worktree, path)
|
||||||
|
|||||||
@@ -467,6 +467,89 @@ t.test("line popup works in a git:// object buffer", function()
|
|||||||
)
|
)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
t.test(
|
||||||
|
"line popup works in a git://<blob-sha> buffer with a recovered path",
|
||||||
|
function()
|
||||||
|
local object = require("git.object")
|
||||||
|
local dir = h.make_repo({ ["a.txt"] = "alpha\nbeta\ngamma\n" })
|
||||||
|
local sha = h.git(dir, "rev-parse", "HEAD").stdout
|
||||||
|
local blob = h.git(dir, "rev-parse", "HEAD:a.txt").stdout
|
||||||
|
local r = assert(require("git.core.repo").resolve(dir))
|
||||||
|
|
||||||
|
object.open(r, sha, { split = false })
|
||||||
|
local commit_buf = vim.api.nvim_get_current_buf()
|
||||||
|
local found ---@type integer?
|
||||||
|
for i, l in ipairs(vim.api.nvim_buf_get_lines(commit_buf, 0, -1, false)) do
|
||||||
|
if l == "+++ b/a.txt" then
|
||||||
|
found = i
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local lnum = assert(found, "expected a +++ b/a.txt line")
|
||||||
|
vim.api.nvim_win_set_cursor(0, { lnum, 0 })
|
||||||
|
t.truthy(object.open_under_cursor())
|
||||||
|
local gbuf = vim.api.nvim_get_current_buf()
|
||||||
|
t.eq(vim.api.nvim_buf_get_name(gbuf), "git://" .. blob)
|
||||||
|
|
||||||
|
vim.api.nvim_win_set_cursor(0, { 1, 0 })
|
||||||
|
blame.line_popup(gbuf)
|
||||||
|
local float = wait_float()
|
||||||
|
t.defer(function()
|
||||||
|
pcall(vim.api.nvim_win_close, float, true)
|
||||||
|
end)
|
||||||
|
local lines = vim.api.nvim_buf_get_lines(
|
||||||
|
vim.api.nvim_win_get_buf(float),
|
||||||
|
0,
|
||||||
|
-1,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
t.truthy(
|
||||||
|
vim.startswith(lines[1] or "", sha:sub(1, 8)),
|
||||||
|
"the popup blames the commit even in a bare-blob git:// buffer"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
|
||||||
|
t.test("line popup works in a git://:0: index buffer", function()
|
||||||
|
local object = require("git.object")
|
||||||
|
local Revision = require("git.core.revision")
|
||||||
|
local dir = h.make_repo({ ["a.txt"] = "alpha\nbeta\ngamma\n" })
|
||||||
|
local sha = h.git(dir, "rev-parse", "HEAD").stdout
|
||||||
|
local r = assert(require("git.core.repo").resolve(dir))
|
||||||
|
|
||||||
|
local ibuf = object.buf_for(r, Revision.new({ stage = 0, path = "a.txt" }))
|
||||||
|
vim.api.nvim_set_current_buf(ibuf)
|
||||||
|
vim.api.nvim_win_set_cursor(0, { 1, 0 })
|
||||||
|
blame.line_popup(ibuf)
|
||||||
|
local float = wait_float()
|
||||||
|
t.defer(function()
|
||||||
|
pcall(vim.api.nvim_win_close, float, true)
|
||||||
|
end)
|
||||||
|
local lines = vim.api.nvim_buf_get_lines(
|
||||||
|
vim.api.nvim_win_get_buf(float),
|
||||||
|
0,
|
||||||
|
-1,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
t.truthy(
|
||||||
|
vim.startswith(lines[1] or "", sha:sub(1, 8)),
|
||||||
|
"the popup blames the commit for an index entry"
|
||||||
|
)
|
||||||
|
end)
|
||||||
|
|
||||||
|
t.test("line popup skips a bare git://<commit-sha> object dump", function()
|
||||||
|
local object = require("git.object")
|
||||||
|
local dir = h.make_repo({ ["a.txt"] = "alpha\n" })
|
||||||
|
local r = assert(require("git.core.repo").resolve(dir))
|
||||||
|
|
||||||
|
object.open(r, "HEAD", { split = false })
|
||||||
|
local cbuf = vim.api.nvim_get_current_buf()
|
||||||
|
t.quietly(function()
|
||||||
|
blame.line_popup(cbuf)
|
||||||
|
end)
|
||||||
|
t.eq(blame.state(cbuf), nil, "no blame state on a commit dump")
|
||||||
|
end)
|
||||||
|
|
||||||
t.test("open_commit opens the commit that last touched the line", function()
|
t.test("open_commit opens the commit that last touched the line", function()
|
||||||
local _, buf = setup("alpha\nbeta\ngamma\n")
|
local _, buf = setup("alpha\nbeta\ngamma\n")
|
||||||
vim.api.nvim_set_current_buf(buf)
|
vim.api.nvim_set_current_buf(buf)
|
||||||
|
|||||||
Reference in New Issue
Block a user