changeset 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 59c51f0d6008
files autoload/lawrencium/diff.vim
diffstat 1 files changed, 53 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/autoload/lawrencium/diff.vim	Sat Feb 08 20:52:39 2020 +1100
+++ b/autoload/lawrencium/diff.vim	Sat Oct 10 09:30:27 2020 -0700
@@ -88,13 +88,21 @@
         " Make it part of the diff group.
         call s:HgDiff_DiffThis(l:diff_id)
     else
-        let l:rev_path = s:GetLawrenciumPath(l:path, l:rev1)
+        let l:rev_path = l:repo.GetLawrenciumPath(l:path, 'rev', l:rev1)
         if a:split == 2
             " See comments above about avoiding `tabedit`.
             tabnew
             let l:cleanupbufnr = bufnr('%')
         endif
         execute 'edit ' . fnameescape(l:rev_path)
+        if s:is_empty_buf()
+            " The buffer is empty. That can happen if the file was moved
+            " since this revision.
+            let l:rev_path = s:GetLawrenciumRevisionPathMaybeMoved(l:repo, l:path, l:rev1)
+            if l:rev_path != ''
+                execute 'edit ' . fnameescape(l:rev_path)
+            endif
+        endif
         " Make it part of the diff group.
         call s:HgDiff_DiffThis(l:diff_id)
     endif
@@ -112,28 +120,52 @@
     if l:rev2 == ''
         execute l:diffsplit . ' ' . fnameescape(l:path)
     else
-        let l:rev_path = s:GetLawrenciumPath(l:path, l:rev2)
+        let l:rev_path = l:repo.GetLawrenciumPath(l:path, 'rev', l:rev2)
         execute l:diffsplit . ' ' . fnameescape(l:rev_path)
+        if s:is_empty_buf()
+            let l:rev_path = s:GetLawrenciumRevisionPathMaybeMoved(l:repo, l:path, l:rev2)
+            if l:rev_path != ''
+                execute 'edit ' . fnameescape(l:rev_path)
+            endif
+        endif
     endif
     call s:HgDiff_DiffThis(l:diff_id)
 endfunction
 
-function! s:GetLawrenciumPath(path, rev)
-    return lawrencium#hg_repo().GetLawrenciumPath(s:absolute_pathname(a:path, a:rev), 'rev', a:rev)
+function! s:GetLawrenciumRevisionPathMaybeMoved(repo, path, rev)
+    let l:abs_path = s:get_real_path_if_copied(a:repo, a:path, a:rev)
+    if l:abs_path != ''
+        return a:repo.GetLawrenciumPath(l:abs_path, 'rev', a:rev)
+    else
+        return ''
+    endif
 endfunction
 
-function! s:absolute_pathname(current_absolute_pathname, revision)
-    let l:repo = lawrencium#hg_repo()
-    if s:is_tip_revision(a:revision)
-        let name_of_copied_file = matchstr(
-                    \ l:repo.RunCommand('status', '--copies', a:current_absolute_pathname),
-                    \ '^A .\{-}\n  \zs[^\n]\+')
-        return !empty(name_of_copied_file)
-                    \ ? l:repo.root_dir . '/' . name_of_copied_file
-                    \ : a:current_absolute_pathname
+function! s:GetLawrenciumDiffPathMaybeMoved(repo, path, rev)
+    let l:abs_path = s:get_real_path_if_copied(a:repo, a:path, a:rev)
+    if l:abs_path != ''
+        return a:repo.GetLawrenciumPath(l:abs_path, 'diff', a:rev)
+    else
+        return ''
     endif
-    " TODO: handle !s:is_tip_revision(a:revision)
-    return a:current_absolute_pathname
+endfunction
+
+function! s:is_empty_buf()
+    return getpos('$') == [0, 1, 1, 0]
+endfunction
+
+function! s:get_real_path_if_copied(repo, path, revision)
+    let l:status_out = a:repo.RunCommand('status', '--copies', '--rev', a:revision, a:path)
+    let l:copied_name = matchstr(
+                \ l:status_out,
+                \ '^A .\{-}\n  \zs[^\n]\+')
+    if !empty(l:copied_name)
+        let l:copied_path = (a:repo.root_dir . '/' . l:copied_name)
+        call lawrencium#trace("Found move: ".a:path." -> ".l:copied_path)
+        return l:copied_path
+    else
+        return ''
+    endif
 endfunction
 
 function! s:is_tip_revision(rev)
@@ -304,6 +336,12 @@
         execute l:target_winnr . "wincmd w"
     endif
     execute 'keepalt ' . l:cmd . fnameescape(l:special)
+    if s:is_empty_buf()
+        let l:special = s:GetLawrenciumDiffPathMaybeMoved(l:repo, l:path, l:revs)
+        if l:special != ''
+            execute 'keepalt edit ' . fnameescape(l:special)
+        endif
+    endif
 
     " Set the reuse ID if we had one.
     if l:reuse_id != ''