mirror of
https://github.com/zoriya/jj.nvim.git
synced 2026-08-05 02:36:07 +00:00
fix(file): show files added since the diffed revision as empty instead of erroring (#130)
Co-authored-by: Roman Konoval <roman@jiko.io>
This commit is contained in:
co-authored by
Roman Konoval
parent
cffc74128a
commit
ca6d751de6
@@ -42,14 +42,15 @@ end
|
||||
--- @param silent boolean|nil Optional to silent the notification
|
||||
--- @return string|nil output Raw stdout bytes, or nil if failed
|
||||
--- @return boolean success Whether the command succeeded
|
||||
--- @return string stderr The command's stderr (empty on success)
|
||||
function M.execute_command_raw(cmd, error_prefix, silent)
|
||||
local result = vim.system({ "sh", "-c", cmd }):wait()
|
||||
if result.code ~= 0 then
|
||||
local msg = result.stderr ~= "" and result.stderr or result.stdout or ""
|
||||
error_notify(msg, error_prefix, silent)
|
||||
return nil, false
|
||||
return nil, false, msg
|
||||
end
|
||||
return result.stdout or "", true
|
||||
return result.stdout or "", true, ""
|
||||
end
|
||||
|
||||
--- Execute a system command synchronously and call success callback.
|
||||
|
||||
@@ -172,8 +172,10 @@ diff.register_backend("codediff", {
|
||||
-- side is decoded in the same way as the current file.
|
||||
-- Assumes the encoding didn't change between revisions.
|
||||
local enc = file.get_buf_encoding(0)
|
||||
local base_lines, base_had_eol, ok_read = file.get_file_content(revset, path, enc)
|
||||
if not ok_read then
|
||||
-- A file added since `revset` has no content there; show it as empty
|
||||
-- so it diffs as fully added rather than aborting the diff.
|
||||
local base_lines, base_had_eol, ok_read, _, absent = file.get_file_content(revset, path, enc)
|
||||
if not ok_read and not absent then
|
||||
utils.notify(string.format("Could not read `%s` from `%s` for CodeDiff", path, revset), vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
|
||||
@@ -28,8 +28,10 @@ local function open_revision(rev, path, enc)
|
||||
return
|
||||
end
|
||||
|
||||
local lines, had_eol, ok_read, used_enc = file.get_file_content(change_id, rel_path, enc)
|
||||
if not ok_read then
|
||||
-- A file added since `rev` has no content there; show it as empty so it
|
||||
-- diffs as fully added rather than aborting the diff.
|
||||
local lines, had_eol, ok_read, used_enc, absent = file.get_file_content(change_id, rel_path, enc)
|
||||
if not ok_read and not absent then
|
||||
utils.notify(string.format("Could not read `%s` from `%s`", rel_path, change_id), vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
|
||||
+11
-7
@@ -219,23 +219,26 @@ M._encode = encode
|
||||
--- (default: auto-detected from content)
|
||||
--- @return string[] lines
|
||||
--- @return boolean had_eol Whether the content had a trailing newline
|
||||
--- @return boolean ok Whether the command succeeded
|
||||
--- @return boolean ok Whether the read succeeded
|
||||
--- @return jj.file.enc used_enc The encoding used to decode the content
|
||||
--- @return boolean absent True when the path does not exist in `rev` (e.g. a
|
||||
--- file added since `rev`).
|
||||
local function get_file_content(rev, path, enc)
|
||||
local raw, ok = runner.execute_command_raw(
|
||||
local raw, ok, stderr = runner.execute_command_raw(
|
||||
string.format("jj file show -r %s %s", vim.fn.shellescape(rev), vim.fn.shellescape(path)),
|
||||
nil,
|
||||
true
|
||||
)
|
||||
if not ok or not raw then
|
||||
return {}, false, false, enc or { fenc = "", bomb = false, ff = "unix" }
|
||||
local absent = stderr ~= nil and stderr:find("No such path", 1, true) ~= nil
|
||||
return {}, false, false, enc or { fenc = "", bomb = false, ff = "unix" }, absent
|
||||
end
|
||||
local lines, had_eol, used_enc = decode(raw, enc)
|
||||
if not lines then
|
||||
utils.notify(had_eol --[[@as string]], vim.log.levels.ERROR)
|
||||
return {}, false, false, used_enc
|
||||
return {}, false, false, used_enc, false
|
||||
end
|
||||
return lines, had_eol --[[@as boolean]], true, used_enc
|
||||
return lines, had_eol --[[@as boolean]], true, used_enc, false
|
||||
end
|
||||
M.get_file_content = get_file_content
|
||||
|
||||
@@ -436,8 +439,9 @@ function M.register_command()
|
||||
local name = vim.api.nvim_buf_get_name(0)
|
||||
local change_id, path = utils.parse_jj_uri(name)
|
||||
if not change_id or not path then return end
|
||||
local lines, had_eol, ok_read, used_enc = get_file_content(change_id, path)
|
||||
if not ok_read then
|
||||
-- Keep reloads of an added-file diff buffer empty rather than erroring.
|
||||
local lines, had_eol, ok_read, used_enc, absent = get_file_content(change_id, path)
|
||||
if not ok_read and not absent then
|
||||
utils.notify(string.format("Could not read `%s` from `%s`", path, change_id), vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
|
||||
@@ -793,6 +793,63 @@ run_test("decode: roundtrip reproduces the bytes exactly", function()
|
||||
end
|
||||
end)
|
||||
|
||||
print("\n=== Running get_file_content tests ===\n")
|
||||
|
||||
run_test("get_file_content: reads existing file content", function()
|
||||
local runner = require("jj.core.runner")
|
||||
local original = runner.execute_command_raw
|
||||
runner.execute_command_raw = function()
|
||||
return "a\nb\n", true, ""
|
||||
end
|
||||
local ok_test, err = pcall(function()
|
||||
local lines, had_eol, ok, _, absent = jj_file.get_file_content("abc123", "src/file.py")
|
||||
assert_table_equals({ "a", "b" }, lines)
|
||||
assert_equals(true, had_eol)
|
||||
assert_equals(true, ok)
|
||||
assert_equals(false, absent)
|
||||
end)
|
||||
runner.execute_command_raw = original
|
||||
if not ok_test then
|
||||
error(err)
|
||||
end
|
||||
end)
|
||||
|
||||
run_test("get_file_content: absent path in revision reports absent (not a read error)", function()
|
||||
local runner = require("jj.core.runner")
|
||||
local original = runner.execute_command_raw
|
||||
runner.execute_command_raw = function()
|
||||
return nil, false, "Error: No such path: src/new_file.py\n"
|
||||
end
|
||||
local ok_test, err = pcall(function()
|
||||
local lines, had_eol, ok, _, absent = jj_file.get_file_content("abc123", "src/new_file.py")
|
||||
assert_table_equals({}, lines)
|
||||
assert_equals(false, had_eol)
|
||||
assert_equals(false, ok)
|
||||
assert_equals(true, absent)
|
||||
end)
|
||||
runner.execute_command_raw = original
|
||||
if not ok_test then
|
||||
error(err)
|
||||
end
|
||||
end)
|
||||
|
||||
run_test("get_file_content: genuine read error returns failure without absent", function()
|
||||
local runner = require("jj.core.runner")
|
||||
local original = runner.execute_command_raw
|
||||
runner.execute_command_raw = function()
|
||||
return nil, false, "Error: Revision `nope` doesn't exist\n"
|
||||
end
|
||||
local ok_test, err = pcall(function()
|
||||
local _, _, ok, _, absent = jj_file.get_file_content("nope", "src/file.py")
|
||||
assert_equals(false, ok)
|
||||
assert_equals(false, absent)
|
||||
end)
|
||||
runner.execute_command_raw = original
|
||||
if not ok_test then
|
||||
error(err)
|
||||
end
|
||||
end)
|
||||
|
||||
-- Print summary
|
||||
print(string.format("\n=== Test Summary ==="))
|
||||
print(string.format("Passed: %d", tests_passed))
|
||||
|
||||
Reference in New Issue
Block a user