diff --git a/autoload/gitgutter/diff.vim b/autoload/gitgutter/diff.vim index f3d2f6304163c8044c77cfdbff8fb7eb9a9d19ef..2deebe00734fb7d206526f31012bb43549249206 100644 --- a/autoload/gitgutter/diff.vim +++ b/autoload/gitgutter/diff.vim @@ -123,7 +123,7 @@ function! gitgutter#diff#run_diff(bufnr, from, preserve_full_diff) abort endif " Write file from index to temporary file. - let index_name = gitgutter#utility#get_diff_base(a:bufnr).':'.s:base_path(a:bufnr) + let index_name = gitgutter#utility#get_diff_base(a:bufnr).':'.gitgutter#utility#base_path(a:bufnr) let cmd .= gitgutter#git().' --no-pager show --textconv '.index_name.' > '.from_file.' || exit 0) && (' elseif a:from ==# 'working_tree' @@ -425,70 +425,3 @@ endfunction function! s:save_last_seen_change(bufnr) abort call gitgutter#utility#setbufvar(a:bufnr, 'tick', getbufvar(a:bufnr, 'changedtick')) endfunction - - -" Returns the original path (shellescaped) at the buffer's diff base. -function! s:base_path(bufnr) - let diffbase = gitgutter#utility#get_diff_base(a:bufnr) - - " If we already know the original path at this diff base, return it. - let basepath = gitgutter#utility#getbufvar(a:bufnr, 'basepath', '') - if !empty(basepath) - let [base, bpath] = split(basepath, ':', 1) - if base == diffbase - return gitgutter#utility#shellescape(bpath) - endif - endif - - " Obtain buffers' paths. - let current_paths = {} - for bufnr in range(1, bufnr('$') + 1) - if gitgutter#utility#has_repo_path(bufnr) - let current_paths[gitgutter#utility#repo_path(bufnr, 0)] = bufnr - endif - endfor - - " Get a list of file renames at the buffer's diff base. - " Store the original paths on any corresponding buffers. - " If the buffer's file was one of them, return its original path. - let op = '' - let renames = s:obtain_file_renames(a:bufnr, diffbase) - for [current, original] in items(renames) - if has_key(current_paths, current) - let bufnr = current_paths[current] - let basepath = diffbase.':'.original - call gitgutter#utility#setbufvar(bufnr, 'basepath', basepath) - - if bufnr == a:bufnr - let op = original - endif - endif - endfor - if !empty(op) - return gitgutter#utility#shellescape(op) - endif - - " Buffer's file was not renamed, so store current path and return it. - let current_path = gitgutter#utility#repo_path(a:bufnr, 0) - let basepath = diffbase.':'.current_path - call gitgutter#utility#setbufvar(a:bufnr, 'basepath', basepath) - return gitgutter#utility#shellescape(current_path) -endfunction - - -" Returns a dict of current path to original path at the given base. -function! s:obtain_file_renames(bufnr, base) - let renames = {} - let cmd = gitgutter#git().' diff --diff-filter=R --name-status '.a:base - let [out, error_code] = gitgutter#utility#system(gitgutter#utility#cd_cmd(a:bufnr, cmd)) - if error_code - " Assume the problem is the diff base. - call gitgutter#utility#warn('g:gitgutter_diff_base ('.a:base.') is invalid') - return {} - endif - for line in split(out, '\n') - let [original, current] = split(line)[1:] - let renames[current] = original - endfor - return renames -endfunction diff --git a/autoload/gitgutter/utility.vim b/autoload/gitgutter/utility.vim index ff3ca7d1e12fa04c6420cbe880861b186089319c..47a311d33c0fbf03e5a48c84c0de3e7c962d34fa 100644 --- a/autoload/gitgutter/utility.vim +++ b/autoload/gitgutter/utility.vim @@ -236,6 +236,71 @@ function! gitgutter#utility#get_diff_base(bufnr) return g:gitgutter_diff_base endfunction +" Returns the original path (shellescaped) at the buffer's diff base. +function! gitgutter#utility#base_path(bufnr) + let diffbase = gitgutter#utility#get_diff_base(a:bufnr) + + " If we already know the original path at this diff base, return it. + let basepath = gitgutter#utility#getbufvar(a:bufnr, 'basepath', '') + if !empty(basepath) + let [base, bpath] = split(basepath, ':', 1) + if base == diffbase + return gitgutter#utility#shellescape(bpath) + endif + endif + + " Obtain buffers' paths. + let current_paths = {} + for bufnr in range(1, bufnr('$') + 1) + if gitgutter#utility#has_repo_path(bufnr) + let current_paths[gitgutter#utility#repo_path(bufnr, 0)] = bufnr + endif + endfor + + " Get a list of file renames at the buffer's diff base. + " Store the original paths on any corresponding buffers. + " If the buffer's file was one of them, return its original path. + let op = '' + let renames = s:obtain_file_renames(a:bufnr, diffbase) + for [current, original] in items(renames) + if has_key(current_paths, current) + let bufnr = current_paths[current] + let basepath = diffbase.':'.original + call gitgutter#utility#setbufvar(bufnr, 'basepath', basepath) + + if bufnr == a:bufnr + let op = original + endif + endif + endfor + if !empty(op) + return gitgutter#utility#shellescape(op) + endif + + " Buffer's file was not renamed, so store current path and return it. + let current_path = gitgutter#utility#repo_path(a:bufnr, 0) + let basepath = diffbase.':'.current_path + call gitgutter#utility#setbufvar(a:bufnr, 'basepath', basepath) + return gitgutter#utility#shellescape(current_path) +endfunction + +" Returns a dict of current path to original path at the given base. +function! s:obtain_file_renames(bufnr, base) + let renames = {} + let cmd = gitgutter#git().' diff --diff-filter=R --name-status '.a:base + let [out, error_code] = gitgutter#utility#system(gitgutter#utility#cd_cmd(a:bufnr, cmd)) + if error_code + " Assume the problem is the diff base. + call gitgutter#utility#warn('g:gitgutter_diff_base ('.a:base.') is invalid') + return {} + endif + for line in split(out, '\n') + let [original, current] = split(line)[1:] + let renames[current] = original + endfor + return renames +endfunction + function! s:abs_path(bufnr, shellesc) let p = resolve(expand('#'.a:bufnr.':p'))