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)