feat: add unified diff conflict resolution for unmerged files
Problem: pressing du on a UU file in fugitive status fell through to the unstaged path, where get_index_content(:0:) fails because unmerged files have no stage 0 entry. The fallback produced a useless diff of HEAD vs working file with conflict markers shown as changes. Solution: add a merge.lua module that diffs git show :2: (ours) vs :3: (theirs), displays the result with full syntax and intra-line highlighting, and provides resolution keymaps (doo/dot/dob/don/]x/[x) that write back to the working file's conflict markers. Hunks are matched to conflict regions by comparing diff del-lines against each region's ours content. Resolved hunks are tracked per-buffer with virtual text. commands.lua gains an unmerged branch in gdiff_file and read_buffer, and plugin/diffs.lua registers Plug(diffs-merge-*) mappings.
This commit is contained in:
parent
d411ce0638
commit
7781904d65
3 changed files with 441 additions and 2 deletions
|
|
@ -138,6 +138,7 @@ end
|
|||
---@field vertical? boolean
|
||||
---@field staged? boolean
|
||||
---@field untracked? boolean
|
||||
---@field unmerged? boolean
|
||||
---@field old_filepath? string
|
||||
---@field hunk_position? { hunk_header: string, offset: integer }
|
||||
|
||||
|
|
@ -157,7 +158,17 @@ function M.gdiff_file(filepath, opts)
|
|||
local old_lines, new_lines, err
|
||||
local diff_label
|
||||
|
||||
if opts.untracked then
|
||||
if opts.unmerged then
|
||||
old_lines = git.get_file_content(':2', filepath)
|
||||
if not old_lines then
|
||||
old_lines = {}
|
||||
end
|
||||
new_lines = git.get_file_content(':3', filepath)
|
||||
if not new_lines then
|
||||
new_lines = {}
|
||||
end
|
||||
diff_label = 'unmerged'
|
||||
elseif opts.untracked then
|
||||
old_lines = {}
|
||||
new_lines, err = git.get_working_content(filepath)
|
||||
if not new_lines then
|
||||
|
|
@ -236,6 +247,14 @@ function M.gdiff_file(filepath, opts)
|
|||
end
|
||||
|
||||
M.setup_diff_buf(diff_buf)
|
||||
|
||||
if diff_label == 'unmerged' then
|
||||
vim.api.nvim_buf_set_var(diff_buf, 'diffs_unmerged', true)
|
||||
vim.api.nvim_buf_set_var(diff_buf, 'diffs_working_path', filepath)
|
||||
local conflict_config = require('diffs').get_conflict_config()
|
||||
require('diffs.merge').setup_keymaps(diff_buf, conflict_config)
|
||||
end
|
||||
|
||||
dbg('opened diff buffer %d for %s (%s)', diff_buf, rel_path, diff_label)
|
||||
|
||||
vim.schedule(function()
|
||||
|
|
@ -334,7 +353,10 @@ function M.read_buffer(bufnr)
|
|||
|
||||
local old_lines, new_lines
|
||||
|
||||
if label == 'untracked' then
|
||||
if label == 'unmerged' then
|
||||
old_lines = git.get_file_content(':2', abs_path) or {}
|
||||
new_lines = git.get_file_content(':3', abs_path) or {}
|
||||
elseif label == 'untracked' then
|
||||
old_lines = {}
|
||||
new_lines = git.get_working_content(abs_path) or {}
|
||||
elseif label == 'staged' then
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue