Mercurial > vim-lawrencium
comparison autoload/lawrencium/diff.vim @ 150:7aa118f73e8c
Improve support for moved files in diff commands.
Now we only check for moved files if we get an empty diff/cat output from
the normal codepath. We also do that for both sides of a diff, and for
the diff-summary commands.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Sat, 10 Oct 2020 09:30:27 -0700 |
parents | 5e72afea669c |
children |
comparison
equal
deleted
inserted
replaced
149:5e72afea669c | 150:7aa118f73e8c |
---|---|
86 endif | 86 endif |
87 endif | 87 endif |
88 " Make it part of the diff group. | 88 " Make it part of the diff group. |
89 call s:HgDiff_DiffThis(l:diff_id) | 89 call s:HgDiff_DiffThis(l:diff_id) |
90 else | 90 else |
91 let l:rev_path = s:GetLawrenciumPath(l:path, l:rev1) | 91 let l:rev_path = l:repo.GetLawrenciumPath(l:path, 'rev', l:rev1) |
92 if a:split == 2 | 92 if a:split == 2 |
93 " See comments above about avoiding `tabedit`. | 93 " See comments above about avoiding `tabedit`. |
94 tabnew | 94 tabnew |
95 let l:cleanupbufnr = bufnr('%') | 95 let l:cleanupbufnr = bufnr('%') |
96 endif | 96 endif |
97 execute 'edit ' . fnameescape(l:rev_path) | 97 execute 'edit ' . fnameescape(l:rev_path) |
98 if s:is_empty_buf() | |
99 " The buffer is empty. That can happen if the file was moved | |
100 " since this revision. | |
101 let l:rev_path = s:GetLawrenciumRevisionPathMaybeMoved(l:repo, l:path, l:rev1) | |
102 if l:rev_path != '' | |
103 execute 'edit ' . fnameescape(l:rev_path) | |
104 endif | |
105 endif | |
98 " Make it part of the diff group. | 106 " Make it part of the diff group. |
99 call s:HgDiff_DiffThis(l:diff_id) | 107 call s:HgDiff_DiffThis(l:diff_id) |
100 endif | 108 endif |
101 if l:cleanupbufnr >= 0 && bufloaded(l:cleanupbufnr) | 109 if l:cleanupbufnr >= 0 && bufloaded(l:cleanupbufnr) |
102 execute 'bdelete ' . l:cleanupbufnr | 110 execute 'bdelete ' . l:cleanupbufnr |
110 let l:diffsplit = 'vsplit' | 118 let l:diffsplit = 'vsplit' |
111 endif | 119 endif |
112 if l:rev2 == '' | 120 if l:rev2 == '' |
113 execute l:diffsplit . ' ' . fnameescape(l:path) | 121 execute l:diffsplit . ' ' . fnameescape(l:path) |
114 else | 122 else |
115 let l:rev_path = s:GetLawrenciumPath(l:path, l:rev2) | 123 let l:rev_path = l:repo.GetLawrenciumPath(l:path, 'rev', l:rev2) |
116 execute l:diffsplit . ' ' . fnameescape(l:rev_path) | 124 execute l:diffsplit . ' ' . fnameescape(l:rev_path) |
125 if s:is_empty_buf() | |
126 let l:rev_path = s:GetLawrenciumRevisionPathMaybeMoved(l:repo, l:path, l:rev2) | |
127 if l:rev_path != '' | |
128 execute 'edit ' . fnameescape(l:rev_path) | |
129 endif | |
130 endif | |
117 endif | 131 endif |
118 call s:HgDiff_DiffThis(l:diff_id) | 132 call s:HgDiff_DiffThis(l:diff_id) |
119 endfunction | 133 endfunction |
120 | 134 |
121 function! s:GetLawrenciumPath(path, rev) | 135 function! s:GetLawrenciumRevisionPathMaybeMoved(repo, path, rev) |
122 return lawrencium#hg_repo().GetLawrenciumPath(s:absolute_pathname(a:path, a:rev), 'rev', a:rev) | 136 let l:abs_path = s:get_real_path_if_copied(a:repo, a:path, a:rev) |
123 endfunction | 137 if l:abs_path != '' |
124 | 138 return a:repo.GetLawrenciumPath(l:abs_path, 'rev', a:rev) |
125 function! s:absolute_pathname(current_absolute_pathname, revision) | 139 else |
126 let l:repo = lawrencium#hg_repo() | 140 return '' |
127 if s:is_tip_revision(a:revision) | 141 endif |
128 let name_of_copied_file = matchstr( | 142 endfunction |
129 \ l:repo.RunCommand('status', '--copies', a:current_absolute_pathname), | 143 |
130 \ '^A .\{-}\n \zs[^\n]\+') | 144 function! s:GetLawrenciumDiffPathMaybeMoved(repo, path, rev) |
131 return !empty(name_of_copied_file) | 145 let l:abs_path = s:get_real_path_if_copied(a:repo, a:path, a:rev) |
132 \ ? l:repo.root_dir . '/' . name_of_copied_file | 146 if l:abs_path != '' |
133 \ : a:current_absolute_pathname | 147 return a:repo.GetLawrenciumPath(l:abs_path, 'diff', a:rev) |
134 endif | 148 else |
135 " TODO: handle !s:is_tip_revision(a:revision) | 149 return '' |
136 return a:current_absolute_pathname | 150 endif |
151 endfunction | |
152 | |
153 function! s:is_empty_buf() | |
154 return getpos('$') == [0, 1, 1, 0] | |
155 endfunction | |
156 | |
157 function! s:get_real_path_if_copied(repo, path, revision) | |
158 let l:status_out = a:repo.RunCommand('status', '--copies', '--rev', a:revision, a:path) | |
159 let l:copied_name = matchstr( | |
160 \ l:status_out, | |
161 \ '^A .\{-}\n \zs[^\n]\+') | |
162 if !empty(l:copied_name) | |
163 let l:copied_path = (a:repo.root_dir . '/' . l:copied_name) | |
164 call lawrencium#trace("Found move: ".a:path." -> ".l:copied_path) | |
165 return l:copied_path | |
166 else | |
167 return '' | |
168 endif | |
137 endfunction | 169 endfunction |
138 | 170 |
139 function! s:is_tip_revision(rev) | 171 function! s:is_tip_revision(rev) |
140 return a:rev ==# 'tip' || a:rev ==# 'p1()' || a:rev == '-1' " TODO: Check for other ways of specifying the tip revision. | 172 return a:rev ==# 'tip' || a:rev ==# 'p1()' || a:rev == '-1' " TODO: Check for other ways of specifying the tip revision. |
141 endfunction | 173 endfunction |
302 " All good now, proceed. | 334 " All good now, proceed. |
303 if l:target_winnr > 0 | 335 if l:target_winnr > 0 |
304 execute l:target_winnr . "wincmd w" | 336 execute l:target_winnr . "wincmd w" |
305 endif | 337 endif |
306 execute 'keepalt ' . l:cmd . fnameescape(l:special) | 338 execute 'keepalt ' . l:cmd . fnameescape(l:special) |
339 if s:is_empty_buf() | |
340 let l:special = s:GetLawrenciumDiffPathMaybeMoved(l:repo, l:path, l:revs) | |
341 if l:special != '' | |
342 execute 'keepalt edit ' . fnameescape(l:special) | |
343 endif | |
344 endif | |
307 | 345 |
308 " Set the reuse ID if we had one. | 346 " Set the reuse ID if we had one. |
309 if l:reuse_id != '' | 347 if l:reuse_id != '' |
310 call lawrencium#trace("Setting reuse ID '".l:reuse_id."' on buffer: ".bufnr('%')) | 348 call lawrencium#trace("Setting reuse ID '".l:reuse_id."' on buffer: ".bufnr('%')) |
311 call setbufvar('%', l:reuse_id, 1) | 349 call setbufvar('%', l:reuse_id, 1) |