Skip to content

Commit 6fbf106

Browse files
authored
fix(review): skip unsupported files during file navigation (#417)
1 parent 7ab445c commit 6fbf106

2 files changed

Lines changed: 144 additions & 9 deletions

File tree

lua/diffs/commands.lua

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,19 +1248,23 @@ end
12481248

12491249
---@param state diffs.ReviewSplitState
12501250
---@param selected diffs.GeneratedFileSelection
1251-
---@return boolean
1252-
local function switch_review_split_file(state, selected)
1251+
---@param opts? { quiet?: boolean }
1252+
---@return boolean, boolean
1253+
local function switch_review_split_file(state, selected, opts)
1254+
opts = opts or {}
12531255
local diff_spec, diff_lines, err, level =
12541256
render_review_file_selection(state.review, state.repo_root, selected)
12551257
if not diff_spec or not diff_lines then
1256-
notify(err or 'cannot render review split file', level or vim.log.levels.WARN)
1257-
return false
1258+
if not opts.quiet then
1259+
notify(err or 'cannot render review split file', level or vim.log.levels.WARN)
1260+
end
1261+
return false, true
12581262
end
12591263

12601264
local left_win = first_window_for_buffer(state.left_buf)
12611265
local right_win = first_window_for_buffer(state.right_buf)
12621266
if not left_win or not right_win then
1263-
return false
1267+
return false, false
12641268
end
12651269

12661270
local opened, split_err = split.open({
@@ -1276,7 +1280,7 @@ local function switch_review_split_file(state, selected)
12761280
})
12771281
if not opened then
12781282
notify(split_err or 'cannot open review split', vim.log.levels.ERROR)
1279-
return false
1283+
return false, false
12801284
end
12811285

12821286
forget_review_split(state)
@@ -1290,7 +1294,7 @@ local function switch_review_split_file(state, selected)
12901294
review_split_states[state.left_buf] = state
12911295
review_split_states[state.right_buf] = state
12921296
attach_review_split_autocmds(state)
1293-
return true
1297+
return true, false
12941298
end
12951299

12961300
---@param state diffs.ReviewSplitState
@@ -1322,6 +1326,21 @@ local function announce_review_file(selection, index, count)
13221326
vim.api.nvim_echo({ { ('[diffs]: (%d of %d): %s'):format(index, count, entry) } }, false, {})
13231327
end
13241328

1329+
---@param skipped diffs.GeneratedFileSelection[]
1330+
local function notify_skipped_review_files(skipped)
1331+
if #skipped == 0 then
1332+
return
1333+
end
1334+
local paths = {}
1335+
for _, selection in ipairs(skipped) do
1336+
paths[#paths + 1] = selection.file
1337+
end
1338+
notify(
1339+
('review skipped %d file(s): %s'):format(#skipped, table.concat(paths, ', ')),
1340+
vim.log.levels.INFO
1341+
)
1342+
end
1343+
13251344
---@param state diffs.ReviewSplitState
13261345
---@param selection diffs.GeneratedFileSelection
13271346
---@param index integer
@@ -1344,8 +1363,22 @@ local function step_review_split_file(state, delta)
13441363
return
13451364
end
13461365
local current = review_index_of_current(files, state)
1347-
local target = ((current - 1 + delta) % count) + 1
1348-
goto_selection(state, files[target], target, count)
1366+
local skipped = {}
1367+
for offset = 1, count - 1 do
1368+
local target = ((current - 1 + delta * offset) % count) + 1
1369+
local switched, unsupported = switch_review_split_file(state, files[target], { quiet = true })
1370+
if switched then
1371+
notify_skipped_review_files(skipped)
1372+
announce_review_file(files[target], target, count)
1373+
return
1374+
end
1375+
if not unsupported then
1376+
notify_skipped_review_files(skipped)
1377+
return
1378+
end
1379+
skipped[#skipped + 1] = files[target]
1380+
end
1381+
notify_skipped_review_files(skipped)
13491382
end
13501383

13511384
---@param delta integer

spec/commands_spec.lua

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3423,6 +3423,42 @@ describe('commands', function()
34233423
return repo_root
34243424
end
34253425

3426+
local function create_binary_review_repo(opts)
3427+
opts = opts or {}
3428+
local repo_root = vim.fn.tempname()
3429+
vim.fn.mkdir(repo_root, 'p')
3430+
test_repos[#test_repos + 1] = repo_root
3431+
3432+
vim.fn.systemlist({ 'git', 'init', '-q', repo_root })
3433+
assert.are.equal(0, vim.v.shell_error)
3434+
git_cmd(repo_root, { 'config', 'user.email', 'test@example.com' })
3435+
git_cmd(repo_root, { 'config', 'user.name', 'Test' })
3436+
3437+
write_repo_file(repo_root, 'aaa-one.lua', { 'old one' })
3438+
write_binary_file(repo_root .. '/bbb-bin.dat', 'binary\\000old')
3439+
if opts.trailing ~= false then
3440+
write_repo_file(repo_root, 'ccc-two.lua', { 'old two' })
3441+
git_cmd(repo_root, { 'add', 'aaa-one.lua', 'bbb-bin.dat', 'ccc-two.lua' })
3442+
else
3443+
git_cmd(repo_root, { 'add', 'aaa-one.lua', 'bbb-bin.dat' })
3444+
end
3445+
git_cmd(repo_root, { 'commit', '-qm', 'base' })
3446+
git_cmd(repo_root, { 'branch', 'binary-base' })
3447+
3448+
git_cmd(repo_root, { 'checkout', '-qb', 'binary-topic' })
3449+
write_repo_file(repo_root, 'aaa-one.lua', { 'new one' })
3450+
write_binary_file(repo_root .. '/bbb-bin.dat', 'binary\\000new')
3451+
if opts.trailing ~= false then
3452+
write_repo_file(repo_root, 'ccc-two.lua', { 'new two' })
3453+
git_cmd(repo_root, { 'add', 'aaa-one.lua', 'bbb-bin.dat', 'ccc-two.lua' })
3454+
else
3455+
git_cmd(repo_root, { 'add', 'aaa-one.lua', 'bbb-bin.dat' })
3456+
end
3457+
git_cmd(repo_root, { 'commit', '-qm', 'target' })
3458+
3459+
return repo_root
3460+
end
3461+
34263462
it('opens review layout split as exactly two visible surfaces', function()
34273463
local repo_root = create_repo()
34283464
vim.fn.writefile({ 'line 1', 'line 2 changed' }, repo_root .. '/file.txt')
@@ -3719,6 +3755,72 @@ describe('commands', function()
37193755
assert_target_at_hunk(panes, 1)
37203756
end)
37213757

3758+
it('skips unsupported files when switching review files', function()
3759+
local repo_root = create_binary_review_repo()
3760+
edit_file(repo_root .. '/aaa-one.lua')
3761+
local notifications = capture_notifications()
3762+
mock_runtime_attach(function() end)
3763+
3764+
local left_buf = commands.review_command('++layout=split binary-base..binary-topic')
3765+
local panes = track_panes(left_buf)
3766+
assert.are.same(
3767+
diffspec.rev_to_rev('binary-base', 'binary-topic', 'aaa-one.lua'),
3768+
vim.api.nvim_buf_get_var(panes.left_buf, 'diffs_spec')
3769+
)
3770+
3771+
vim.api.nvim_set_current_win(panes.right_win)
3772+
commands.review_next_file()
3773+
panes = track_panes(panes.state.left_buf)
3774+
assert.are.same(
3775+
diffspec.rev_to_rev('binary-base', 'binary-topic', 'ccc-two.lua'),
3776+
vim.api.nvim_buf_get_var(panes.left_buf, 'diffs_spec')
3777+
)
3778+
assert.are.equal(vim.log.levels.INFO, notifications[#notifications].level)
3779+
assert.are.equal(
3780+
'[diffs]: review skipped 1 file(s): bbb-bin.dat',
3781+
notifications[#notifications].message
3782+
)
3783+
3784+
vim.api.nvim_set_current_win(panes.right_win)
3785+
commands.review_prev_file()
3786+
panes = track_panes(panes.state.left_buf)
3787+
assert.are.same(
3788+
diffspec.rev_to_rev('binary-base', 'binary-topic', 'aaa-one.lua'),
3789+
vim.api.nvim_buf_get_var(panes.left_buf, 'diffs_spec')
3790+
)
3791+
assert.are.equal(vim.log.levels.INFO, notifications[#notifications].level)
3792+
assert.are.equal(
3793+
'[diffs]: review skipped 1 file(s): bbb-bin.dat',
3794+
notifications[#notifications].message
3795+
)
3796+
end)
3797+
3798+
it('keeps the skipped-file message when no candidate switches', function()
3799+
local repo_root = create_binary_review_repo({ trailing = false })
3800+
edit_file(repo_root .. '/aaa-one.lua')
3801+
local notifications = capture_notifications()
3802+
mock_runtime_attach(function() end)
3803+
3804+
local left_buf = commands.review_command('++layout=split binary-base..binary-topic')
3805+
local panes = track_panes(left_buf)
3806+
assert.are.same(
3807+
diffspec.rev_to_rev('binary-base', 'binary-topic', 'aaa-one.lua'),
3808+
vim.api.nvim_buf_get_var(panes.left_buf, 'diffs_spec')
3809+
)
3810+
3811+
vim.api.nvim_set_current_win(panes.right_win)
3812+
commands.review_next_file()
3813+
panes = track_panes(panes.state.left_buf)
3814+
3815+
assert.are.same(
3816+
diffspec.rev_to_rev('binary-base', 'binary-topic', 'aaa-one.lua'),
3817+
vim.api.nvim_buf_get_var(panes.left_buf, 'diffs_spec')
3818+
)
3819+
assert.are.equal(1, #notifications)
3820+
assert.are.equal(vim.log.levels.INFO, notifications[1].level)
3821+
assert.are.equal('[diffs]: review skipped 1 file(s): bbb-bin.dat', notifications[1].message)
3822+
end)
3823+
37223824
it('exposes review_files/current/goto, the gO map, and the b:diffs_review marker', function()
37233825
local repo = create_review_repo()
37243826
edit_file(repo.repo_root .. '/lua/one.lua')

0 commit comments

Comments
 (0)