fix: pre-release cleanup for v0.2.0 (#102)
## Problem Three minor issues remain before the v0.2.0 release: 1. Git quotes filenames containing spaces, unicode, or special characters in the fugitive status buffer. `parse_file_line` passed the quotes through verbatim, causing file-not-found errors on diff operations. 2. Navigation wrap-around in both conflict and merge modules was silent, giving no indication when jumping past the last/first item back to the beginning/end. 3. `resolved_hunks` and `(resolved)` virtual text in the merge module persisted across buffer re-reads, showing stale markers for hunks that were no longer resolved. ## Solution 1. Add an `unquote()` helper to fugitive.lua that strips surrounding quotes and unescapes `\\`, `\"`, `\n`, `\t`, and octal `\NNN` sequences. Applied to both return paths in `parse_file_line`. 2. Add `vim.notify` before the wrap-around jump in all four navigation functions (`goto_next`/`goto_prev` in conflict.lua and merge.lua). 3. Clear `resolved_hunks[bufnr]` and the merge namespace at the top of `setup_keymaps` so each buffer init starts fresh. Closes #66
This commit is contained in:
parent
b5d28e9f2b
commit
35067151e4
11 changed files with 393 additions and 931 deletions
|
|
@ -87,28 +87,6 @@ describe('fugitive', function()
|
|||
vim.api.nvim_buf_delete(buf, { force = true })
|
||||
end)
|
||||
|
||||
it('parses added file', function()
|
||||
local buf = create_status_buffer({
|
||||
'Staged (1)',
|
||||
'A newfile.lua',
|
||||
})
|
||||
local filename, section = fugitive.get_file_at_line(buf, 2)
|
||||
assert.equals('newfile.lua', filename)
|
||||
assert.equals('staged', section)
|
||||
vim.api.nvim_buf_delete(buf, { force = true })
|
||||
end)
|
||||
|
||||
it('parses deleted file', function()
|
||||
local buf = create_status_buffer({
|
||||
'Staged (1)',
|
||||
'D oldfile.lua',
|
||||
})
|
||||
local filename, section = fugitive.get_file_at_line(buf, 2)
|
||||
assert.equals('oldfile.lua', filename)
|
||||
assert.equals('staged', section)
|
||||
vim.api.nvim_buf_delete(buf, { force = true })
|
||||
end)
|
||||
|
||||
it('parses renamed file and returns both names', function()
|
||||
local buf = create_status_buffer({
|
||||
'Staged (1)',
|
||||
|
|
@ -157,28 +135,6 @@ describe('fugitive', function()
|
|||
vim.api.nvim_buf_delete(buf, { force = true })
|
||||
end)
|
||||
|
||||
it('handles renamed file in subdirectory', function()
|
||||
local buf = create_status_buffer({
|
||||
'Staged (1)',
|
||||
'R src/old.lua -> src/new.lua',
|
||||
})
|
||||
local filename, _, _, old_filename = fugitive.get_file_at_line(buf, 2)
|
||||
assert.equals('src/new.lua', filename)
|
||||
assert.equals('src/old.lua', old_filename)
|
||||
vim.api.nvim_buf_delete(buf, { force = true })
|
||||
end)
|
||||
|
||||
it('handles renamed file moved to different directory', function()
|
||||
local buf = create_status_buffer({
|
||||
'Staged (1)',
|
||||
'R old/file.lua -> new/file.lua',
|
||||
})
|
||||
local filename, _, _, old_filename = fugitive.get_file_at_line(buf, 2)
|
||||
assert.equals('new/file.lua', filename)
|
||||
assert.equals('old/file.lua', old_filename)
|
||||
vim.api.nvim_buf_delete(buf, { force = true })
|
||||
end)
|
||||
|
||||
it('KNOWN LIMITATION: filename containing arrow parsed incorrectly', function()
|
||||
local buf = create_status_buffer({
|
||||
'Staged (1)',
|
||||
|
|
@ -190,77 +146,54 @@ describe('fugitive', function()
|
|||
vim.api.nvim_buf_delete(buf, { force = true })
|
||||
end)
|
||||
|
||||
it('handles double extensions', function()
|
||||
it('unquotes git-quoted filenames with spaces', function()
|
||||
local buf = create_status_buffer({
|
||||
'Unstaged (1)',
|
||||
'M "path with spaces/file.lua"',
|
||||
})
|
||||
local filename = fugitive.get_file_at_line(buf, 2)
|
||||
assert.equals('path with spaces/file.lua', filename)
|
||||
vim.api.nvim_buf_delete(buf, { force = true })
|
||||
end)
|
||||
|
||||
it('unquotes escaped quotes in filenames', function()
|
||||
local buf = create_status_buffer({
|
||||
'Unstaged (1)',
|
||||
'M "file\\"name.lua"',
|
||||
})
|
||||
local filename = fugitive.get_file_at_line(buf, 2)
|
||||
assert.equals('file"name.lua', filename)
|
||||
vim.api.nvim_buf_delete(buf, { force = true })
|
||||
end)
|
||||
|
||||
it('unquotes octal escapes in filenames', function()
|
||||
local buf = create_status_buffer({
|
||||
'Unstaged (1)',
|
||||
'M "\\303\\251le.lua"',
|
||||
})
|
||||
local filename = fugitive.get_file_at_line(buf, 2)
|
||||
assert.equals('\195\169le.lua', filename)
|
||||
vim.api.nvim_buf_delete(buf, { force = true })
|
||||
end)
|
||||
|
||||
it('passes through unquoted filenames unchanged', function()
|
||||
local buf = create_status_buffer({
|
||||
'Unstaged (1)',
|
||||
'M normal.lua',
|
||||
})
|
||||
local filename = fugitive.get_file_at_line(buf, 2)
|
||||
assert.equals('normal.lua', filename)
|
||||
vim.api.nvim_buf_delete(buf, { force = true })
|
||||
end)
|
||||
|
||||
it('unquotes renamed files with quotes', function()
|
||||
local buf = create_status_buffer({
|
||||
'Staged (1)',
|
||||
'M test.spec.lua',
|
||||
'R100 "old name.lua" -> "new name.lua"',
|
||||
})
|
||||
local filename, _, _, old_filename = fugitive.get_file_at_line(buf, 2)
|
||||
assert.equals('test.spec.lua', filename)
|
||||
assert.is_nil(old_filename)
|
||||
vim.api.nvim_buf_delete(buf, { force = true })
|
||||
end)
|
||||
|
||||
it('handles hyphenated filenames', function()
|
||||
local buf = create_status_buffer({
|
||||
'Unstaged (1)',
|
||||
'M my-component-test.lua',
|
||||
})
|
||||
local filename, section = fugitive.get_file_at_line(buf, 2)
|
||||
assert.equals('my-component-test.lua', filename)
|
||||
assert.equals('unstaged', section)
|
||||
vim.api.nvim_buf_delete(buf, { force = true })
|
||||
end)
|
||||
|
||||
it('handles underscores and numbers', function()
|
||||
local buf = create_status_buffer({
|
||||
'Staged (1)',
|
||||
'A test_file_123.lua',
|
||||
})
|
||||
local filename = fugitive.get_file_at_line(buf, 2)
|
||||
assert.equals('test_file_123.lua', filename)
|
||||
vim.api.nvim_buf_delete(buf, { force = true })
|
||||
end)
|
||||
|
||||
it('handles dotfiles', function()
|
||||
local buf = create_status_buffer({
|
||||
'Unstaged (1)',
|
||||
'M .gitignore',
|
||||
})
|
||||
local filename = fugitive.get_file_at_line(buf, 2)
|
||||
assert.equals('.gitignore', filename)
|
||||
vim.api.nvim_buf_delete(buf, { force = true })
|
||||
end)
|
||||
|
||||
it('handles renamed with complex names', function()
|
||||
local buf = create_status_buffer({
|
||||
'Staged (1)',
|
||||
'R src/old-file.spec.lua -> src/new-file.spec.lua',
|
||||
})
|
||||
local filename, _, _, old_filename = fugitive.get_file_at_line(buf, 2)
|
||||
assert.equals('src/new-file.spec.lua', filename)
|
||||
assert.equals('src/old-file.spec.lua', old_filename)
|
||||
vim.api.nvim_buf_delete(buf, { force = true })
|
||||
end)
|
||||
|
||||
it('handles deeply nested paths', function()
|
||||
local buf = create_status_buffer({
|
||||
'Unstaged (1)',
|
||||
'M lua/diffs/ui/components/diff-view.lua',
|
||||
})
|
||||
local filename = fugitive.get_file_at_line(buf, 2)
|
||||
assert.equals('lua/diffs/ui/components/diff-view.lua', filename)
|
||||
vim.api.nvim_buf_delete(buf, { force = true })
|
||||
end)
|
||||
|
||||
it('parses untracked file', function()
|
||||
local buf = create_status_buffer({
|
||||
'Untracked (1)',
|
||||
'? untracked.lua',
|
||||
})
|
||||
local filename, section = fugitive.get_file_at_line(buf, 2)
|
||||
assert.equals('untracked.lua', filename)
|
||||
assert.equals('untracked', section)
|
||||
assert.equals('new name.lua', filename)
|
||||
assert.equals('old name.lua', old_filename)
|
||||
vim.api.nvim_buf_delete(buf, { force = true })
|
||||
end)
|
||||
|
||||
|
|
@ -321,30 +254,6 @@ describe('fugitive', function()
|
|||
vim.api.nvim_buf_delete(buf, { force = true })
|
||||
end)
|
||||
|
||||
it('detects section header for Unstaged', function()
|
||||
local buf = create_status_buffer({
|
||||
'Unstaged (3)',
|
||||
'M file1.lua',
|
||||
})
|
||||
local filename, section, is_header = fugitive.get_file_at_line(buf, 1)
|
||||
assert.is_nil(filename)
|
||||
assert.equals('unstaged', section)
|
||||
assert.is_true(is_header)
|
||||
vim.api.nvim_buf_delete(buf, { force = true })
|
||||
end)
|
||||
|
||||
it('detects section header for Untracked', function()
|
||||
local buf = create_status_buffer({
|
||||
'Untracked (1)',
|
||||
'? newfile.lua',
|
||||
})
|
||||
local filename, section, is_header = fugitive.get_file_at_line(buf, 1)
|
||||
assert.is_nil(filename)
|
||||
assert.equals('untracked', section)
|
||||
assert.is_true(is_header)
|
||||
vim.api.nvim_buf_delete(buf, { force = true })
|
||||
end)
|
||||
|
||||
it('returns is_header=false for file lines', function()
|
||||
local buf = create_status_buffer({
|
||||
'Staged (1)',
|
||||
|
|
@ -406,22 +315,6 @@ describe('fugitive', function()
|
|||
vim.api.nvim_buf_delete(buf, { force = true })
|
||||
end)
|
||||
|
||||
it('returns hunk header and offset for - line', function()
|
||||
local buf = create_status_buffer({
|
||||
'Unstaged (1)',
|
||||
'M file.lua',
|
||||
'@@ -1,3 +1,3 @@',
|
||||
' local M = {}',
|
||||
'-local old = false',
|
||||
' return M',
|
||||
})
|
||||
local pos = fugitive.get_hunk_position(buf, 5)
|
||||
assert.is_not_nil(pos)
|
||||
assert.equals('@@ -1,3 +1,3 @@', pos.hunk_header)
|
||||
assert.equals(2, pos.offset)
|
||||
vim.api.nvim_buf_delete(buf, { force = true })
|
||||
end)
|
||||
|
||||
it('returns hunk header and offset for context line', function()
|
||||
local buf = create_status_buffer({
|
||||
'Unstaged (1)',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue