fix(fugitive): handle renamed files correctly

Parse both old and new filenames from rename lines (R old -> new).
When diffing staged renames, use old filename as base to correctly
show content changes rather than treating the file as entirely new.

Also adds comprehensive tests for filename edge cases:
- Double extensions, hyphens, underscores, dotfiles
- Deep nested paths, complex renames
- Documents known limitation with filenames containing ' -> '
This commit is contained in:
Barrett Ruth 2026-02-04 23:12:30 -05:00
parent 6072dd0156
commit 9ed0639005
3 changed files with 165 additions and 22 deletions

View file

@ -92,6 +92,7 @@ end
---@field vertical? boolean
---@field staged? boolean
---@field untracked? boolean
---@field old_filepath? string
---@param filepath string
---@param opts? diffs.GdiffFileOpts
@ -104,6 +105,8 @@ function M.gdiff_file(filepath, opts)
return
end
local old_rel_path = opts.old_filepath and git.get_relative_path(opts.old_filepath) or rel_path
local old_lines, new_lines, err
local diff_label
@ -116,7 +119,7 @@ function M.gdiff_file(filepath, opts)
end
diff_label = 'untracked'
elseif opts.staged then
old_lines, err = git.get_file_content('HEAD', filepath)
old_lines, err = git.get_file_content('HEAD', opts.old_filepath or filepath)
if not old_lines then
old_lines = {}
end
@ -126,9 +129,9 @@ function M.gdiff_file(filepath, opts)
end
diff_label = 'staged'
else
old_lines, err = git.get_index_content(filepath)
old_lines, err = git.get_index_content(opts.old_filepath or filepath)
if not old_lines then
old_lines, err = git.get_file_content('HEAD', filepath)
old_lines, err = git.get_file_content('HEAD', opts.old_filepath or filepath)
if not old_lines then
old_lines = {}
diff_label = 'untracked'
@ -144,7 +147,7 @@ function M.gdiff_file(filepath, opts)
end
end
local diff_lines = generate_unified_diff(old_lines, new_lines, rel_path, rel_path)
local diff_lines = generate_unified_diff(old_lines, new_lines, old_rel_path, rel_path)
if #diff_lines == 0 then
vim.notify('[diffs.nvim]: no changes', vim.log.levels.INFO)