mirror of
https://github.com/neovim/neovim.git
synced 2025-10-16 06:46:07 +00:00
fix(difftool): fully resolve symlinks when comparing paths #36147
Fixes issue on mac where it was constantly reloading buffers as paths were not being normalized and resolved correctly (in relation to buffer name). Quickfix entry: /var/folders/pt/2s7dzyw12v36tsslrghfgpkr0000gn/T/git-difftool.m95lj8/right/app.vue Buffer name: /private/var/folders/pt/2s7dzyw12v36tsslrghfgpkr0000gn/T/git-difftool.m95lj8/right/app.vue /var was synlinked to /private/var and this was not being properly handled. Also added lazy redraw to avoid too many redraws when this happens in future and added test for symlink handling. Signed-off-by: Tomas Slusny <slusnucky@gmail.com>
This commit is contained in:
@@ -5,12 +5,20 @@ local M = {}
|
|||||||
--- @param file string
|
--- @param file string
|
||||||
--- @return number buffer number of the edited buffer
|
--- @return number buffer number of the edited buffer
|
||||||
M.edit_in = function(winnr, file)
|
M.edit_in = function(winnr, file)
|
||||||
|
local function resolved_path(path)
|
||||||
|
if not path or path == '' then
|
||||||
|
return ''
|
||||||
|
end
|
||||||
|
return vim.fn.resolve(vim.fs.abspath(path))
|
||||||
|
end
|
||||||
|
|
||||||
return vim.api.nvim_win_call(winnr, function()
|
return vim.api.nvim_win_call(winnr, function()
|
||||||
local current = vim.fs.abspath(vim.api.nvim_buf_get_name(vim.api.nvim_win_get_buf(winnr)))
|
local current_buf = vim.api.nvim_win_get_buf(winnr)
|
||||||
|
local current = resolved_path(vim.api.nvim_buf_get_name(current_buf))
|
||||||
|
|
||||||
-- Check if the current buffer is already the target file
|
-- Check if the current buffer is already the target file
|
||||||
if current == (file and vim.fs.abspath(file) or '') then
|
if current == resolved_path(file) then
|
||||||
return vim.api.nvim_get_current_buf()
|
return current_buf
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Read the file into the buffer
|
-- Read the file into the buffer
|
||||||
|
@@ -140,14 +140,16 @@ local function diff_dirs_diffr(left_dir, right_dir, opt)
|
|||||||
elseif right_exists then
|
elseif right_exists then
|
||||||
status = 'A'
|
status = 'A'
|
||||||
end
|
end
|
||||||
|
local left = vim.fn.resolve(vim.fs.abspath(modified_left))
|
||||||
|
local right = vim.fn.resolve(vim.fs.abspath(modified_right))
|
||||||
table.insert(qf_entries, {
|
table.insert(qf_entries, {
|
||||||
filename = modified_right,
|
filename = right,
|
||||||
text = status,
|
text = status,
|
||||||
user_data = {
|
user_data = {
|
||||||
diff = true,
|
diff = true,
|
||||||
rel = vim.fs.relpath(left_dir, modified_left),
|
rel = vim.fs.relpath(left_dir, modified_left),
|
||||||
left = vim.fs.abspath(modified_left),
|
left = left,
|
||||||
right = vim.fs.abspath(modified_right),
|
right = right,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
@@ -426,7 +428,7 @@ function M.open(left, right, opt)
|
|||||||
layout.group = vim.api.nvim_create_augroup('nvim.difftool.events', { clear = true })
|
layout.group = vim.api.nvim_create_augroup('nvim.difftool.events', { clear = true })
|
||||||
local hl_id = vim.api.nvim_create_namespace('nvim.difftool.hl')
|
local hl_id = vim.api.nvim_create_namespace('nvim.difftool.hl')
|
||||||
|
|
||||||
local function get_diff_entry()
|
local function get_diff_entry(bufnr)
|
||||||
--- @type {idx: number, items: table[], size: number}
|
--- @type {idx: number, items: table[], size: number}
|
||||||
local qf_info = vim.fn.getqflist({ idx = 0, items = 1, size = 1 })
|
local qf_info = vim.fn.getqflist({ idx = 0, items = 1, size = 1 })
|
||||||
if qf_info.size == 0 then
|
if qf_info.size == 0 then
|
||||||
@@ -434,7 +436,12 @@ function M.open(left, right, opt)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local entry = qf_info.items[qf_info.idx]
|
local entry = qf_info.items[qf_info.idx]
|
||||||
if not entry or not entry.user_data or not entry.user_data.diff then
|
if
|
||||||
|
not entry
|
||||||
|
or not entry.user_data
|
||||||
|
or not entry.user_data.diff
|
||||||
|
or (bufnr and entry.bufnr ~= bufnr)
|
||||||
|
then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -466,14 +473,16 @@ function M.open(left, right, opt)
|
|||||||
vim.api.nvim_create_autocmd('BufWinEnter', {
|
vim.api.nvim_create_autocmd('BufWinEnter', {
|
||||||
group = layout.group,
|
group = layout.group,
|
||||||
pattern = '*',
|
pattern = '*',
|
||||||
callback = function()
|
callback = function(args)
|
||||||
local entry = get_diff_entry()
|
local entry = get_diff_entry(args.buf)
|
||||||
if not entry then
|
if not entry then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
vim.w.lazyredraw = true
|
||||||
vim.schedule(function()
|
vim.schedule(function()
|
||||||
diff_files(entry.user_data.left, entry.user_data.right, true)
|
diff_files(entry.user_data.left, entry.user_data.right, true)
|
||||||
|
vim.w.lazyredraw = false
|
||||||
end)
|
end)
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
@@ -61,6 +61,31 @@ describe('nvim.difftool', function()
|
|||||||
)
|
)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('handles symlinks', function()
|
||||||
|
-- Create a symlink in right dir pointing to file2.txt in left dir
|
||||||
|
local symlink_path = vim.fs.joinpath(testdir_right, 'file2.txt')
|
||||||
|
local target_path = vim.fs.joinpath('..', testdir_left, 'file2.txt')
|
||||||
|
assert(vim.uv.fs_symlink(target_path, symlink_path) == true)
|
||||||
|
finally(function()
|
||||||
|
os.remove(symlink_path)
|
||||||
|
end)
|
||||||
|
assert(fn.getftype(symlink_path) == 'link')
|
||||||
|
|
||||||
|
-- Run difftool
|
||||||
|
command(('DiffTool %s %s'):format(testdir_left, testdir_right))
|
||||||
|
local qflist = fn.getqflist()
|
||||||
|
local entries = {}
|
||||||
|
for _, item in ipairs(qflist) do
|
||||||
|
table.insert(entries, { text = item.text, rel = item.user_data and item.user_data.rel })
|
||||||
|
end
|
||||||
|
|
||||||
|
-- file2.txt should not be reported as added or deleted anymore
|
||||||
|
eq({
|
||||||
|
{ text = 'M', rel = 'file1.txt' },
|
||||||
|
{ text = 'A', rel = 'file3.txt' },
|
||||||
|
}, entries)
|
||||||
|
end)
|
||||||
|
|
||||||
it('has autocmds when diff window is opened', function()
|
it('has autocmds when diff window is opened', function()
|
||||||
command(('DiffTool %s %s'):format(testdir_left, testdir_right))
|
command(('DiffTool %s %s'):format(testdir_left, testdir_right))
|
||||||
local autocmds = fn.nvim_get_autocmds({ group = 'nvim.difftool.events' })
|
local autocmds = fn.nvim_get_autocmds({ group = 'nvim.difftool.events' })
|
||||||
|
Reference in New Issue
Block a user