Improve :Gstatus support for renames

Closes https://github.com/tpope/vim-fugitive/issues/1175
This commit is contained in:
Tim Pope
2019-06-27 23:30:19 -04:00
parent 8e024f9bcc
commit 198e9c4128

View File

@@ -2117,11 +2117,13 @@ function! s:StageInfo(...) abort
let index += 1 let index += 1
endif endif
endwhile endwhile
let text = matchstr(getline(lnum), '^[A-Z?] \zs.*')
return {'section': section, return {'section': section,
\ 'heading': getline(slnum), \ 'heading': getline(slnum),
\ 'sigil': sigil, \ 'sigil': sigil,
\ 'offset': offset, \ 'offset': offset,
\ 'filename': matchstr(getline(lnum), '^[A-Z?] \zs.*'), \ 'filename': text,
\ 'paths': reverse(split(text, ' -> ')),
\ 'commit': matchstr(getline(lnum), '^\%(\%(\x\x\x\)\@!\l\+\s\+\)\=\zs[0-9a-f]\{4,\}\ze '), \ 'commit': matchstr(getline(lnum), '^\%(\%(\x\x\x\)\@!\l\+\s\+\)\=\zs[0-9a-f]\{4,\}\ze '),
\ 'status': matchstr(getline(lnum), '^[A-Z?]\ze \|^\%(\x\x\x\)\@!\l\+\ze [0-9a-f]'), \ 'status': matchstr(getline(lnum), '^[A-Z?]\ze \|^\%(\x\x\x\)\@!\l\+\ze [0-9a-f]'),
\ 'index': index} \ 'index': index}
@@ -2325,7 +2327,7 @@ function! s:StageInline(mode, ...) abort
let lnum = lnum1 + 1 let lnum = lnum1 + 1
if a:0 > 1 && a:2 == 0 if a:0 > 1 && a:2 == 0
let info = s:StageInfo(lnum - 1) let info = s:StageInfo(lnum - 1)
if empty(info.filename) && len(info.section) if empty(info.paths) && len(info.section)
while len(getline(lnum)) while len(getline(lnum))
let lnum += 1 let lnum += 1
endwhile endwhile
@@ -2355,7 +2357,7 @@ function! s:StageInline(mode, ...) abort
endif endif
continue continue
endif endif
if !has_key(b:fugitive_diff, info.section) || info.status !~# '^[ADM]$' || a:mode ==# 'hide' if !has_key(b:fugitive_diff, info.section) || info.status !~# '^[ADMR]$' || a:mode ==# 'hide'
continue continue
endif endif
let mode = '' let mode = ''
@@ -2372,9 +2374,9 @@ function! s:StageInline(mode, ...) abort
endif endif
let start = index let start = index
let mode = 'head' let mode = 'head'
elseif mode ==# 'head' && substitute(line, "\t$", '', '') ==# '--- ' . info.filename elseif mode ==# 'head' && substitute(line, "\t$", '', '') ==# '--- ' . info.paths[-1]
let mode = 'await' let mode = 'await'
elseif mode ==# 'head' && substitute(line, "\t$", '', '') ==# '+++ ' . info.filename elseif mode ==# 'head' && substitute(line, "\t$", '', '') ==# '+++ ' . info.paths[0]
let mode = 'await' let mode = 'await'
elseif mode ==# 'capture' elseif mode ==# 'capture'
call add(diff, line) call add(diff, line)
@@ -2414,32 +2416,31 @@ function! s:StageDiff(diff) abort
let lnum = line('.') let lnum = line('.')
let info = s:StageInfo(lnum) let info = s:StageInfo(lnum)
let prefix = info.offset > 0 ? '+' . info.offset : '' let prefix = info.offset > 0 ? '+' . info.offset : ''
if empty(info.filename) && info.section ==# 'Staged' if empty(info.paths) && info.section ==# 'Staged'
return 'Git! diff --no-ext-diff --cached' return 'Git! diff --no-ext-diff --cached'
elseif empty(info.filename) elseif empty(info.paths)
return 'Git! diff --no-ext-diff' return 'Git! diff --no-ext-diff'
elseif info.filename =~# ' -> ' elseif len(info.paths) > 1
let [old, new] = split(info.filename,' -> ') execute 'Gedit' . prefix s:fnameescape(':0:' . info.paths[0])
execute 'Gedit' . prefix s:fnameescape(':0:'.new) return a:diff.' HEAD:'.s:fnameescape(info.paths[1])
return a:diff.' HEAD:'.s:fnameescape(old)
elseif info.section ==# 'Staged' && info.sigil ==# '-' elseif info.section ==# 'Staged' && info.sigil ==# '-'
execute 'Gedit' prefix s:fnameescape('@:'.info.filename) execute 'Gedit' prefix s:fnameescape('@:'.info.paths[0])
return a:diff.'! :0' return a:diff.'! :0'
elseif info.section ==# 'Staged' elseif info.section ==# 'Staged'
execute 'Gedit' prefix s:fnameescape(':0:'.info.filename) execute 'Gedit' prefix s:fnameescape(':0:'.info.paths[0])
return a:diff . (info.sigil ==# '+' ? '!' : '') . ' -' return a:diff . (info.sigil ==# '+' ? '!' : '') . ' -'
elseif info.sigil ==# '-' elseif info.sigil ==# '-'
execute 'Gedit' prefix s:fnameescape(':0:'.info.filename) execute 'Gedit' prefix s:fnameescape(':0:'.info.paths[0])
return a:diff . '!' return a:diff . '!'
else else
execute 'Gedit' prefix s:fnameescape(':(top)'.info.filename) execute 'Gedit' prefix s:fnameescape(':(top)'.info.paths[0])
return a:diff . (info.sigil ==# '+' ? '!' : '') return a:diff . (info.sigil ==# '+' ? '!' : '')
endif endif
endfunction endfunction
function! s:StageDiffEdit() abort function! s:StageDiffEdit() abort
let info = s:StageInfo(line('.')) let info = s:StageInfo(line('.'))
let arg = (empty(info.filename) ? '.' : info.filename) let arg = (empty(info.paths) ? '.' : info.paths[0])
if info.section ==# 'Staged' if info.section ==# 'Staged'
return 'Git! diff --no-ext-diff --cached '.s:shellesc(arg) return 'Git! diff --no-ext-diff --cached '.s:shellesc(arg)
elseif info.status ==# '?' elseif info.status ==# '?'
@@ -2451,6 +2452,9 @@ function! s:StageDiffEdit() abort
endfunction endfunction
function! s:StageApply(info, reverse, extra) abort function! s:StageApply(info, reverse, extra) abort
if a:info.status ==# 'R'
call s:throw('fugitive: patching renamed file not yet supported')
endif
let cmd = ['apply', '-p0', '--recount'] + a:extra let cmd = ['apply', '-p0', '--recount'] + a:extra
let info = a:info let info = a:info
let start = info.patch let start = info.patch
@@ -2531,7 +2535,7 @@ function! s:StageDelete(lnum, count) abort
exe s:ReloadStatus() exe s:ReloadStatus()
let @@ = hash let @@ = hash
return 'checktime|redraw|echomsg ' . return 'checktime|redraw|echomsg ' .
\ string('To restore, :Git cat-file blob '.hash[0:6].' > '.info.filename) \ string('To restore, :Git cat-file blob '.hash[0:6].' > '.info.paths[0])
endfunction endfunction
function! s:DoToggleHeadHeader(value) abort function! s:DoToggleHeadHeader(value) abort
@@ -2628,20 +2632,18 @@ function! s:StagePatch(lnum1,lnum2) abort
for lnum in range(a:lnum1,a:lnum2) for lnum in range(a:lnum1,a:lnum2)
let info = s:StageInfo(lnum) let info = s:StageInfo(lnum)
if empty(info.filename) && info.section ==# 'Staged' if empty(info.paths) && info.section ==# 'Staged'
return 'Git reset --patch' return 'Git reset --patch'
elseif empty(info.filename) && info.section ==# 'Unstaged' elseif empty(info.paths) && info.section ==# 'Unstaged'
return 'Git add --patch' return 'Git add --patch'
elseif info.filename ==# '' elseif empty(info.paths) ==# ''
continue continue
endif endif
execute lnum execute lnum
if info.filename =~ ' -> ' if info.section ==# 'Staged'
let reset += [split(info.filename,' -> ')[1]] let reset += info.paths
elseif info.section ==# 'Staged'
let reset += [info.filename]
elseif info.status !~# '^D' elseif info.status !~# '^D'
let add += [info.filename] let add += info.paths
endif endif
endfor endfor
try try
@@ -4398,16 +4400,16 @@ function! s:StatusCfile(...) abort
let lead = s:cpath(tree, getcwd()) ? './' : tree . '/' let lead = s:cpath(tree, getcwd()) ? './' : tree . '/'
let info = s:StageInfo() let info = s:StageInfo()
let line = getline('.') let line = getline('.')
if len(info.sigil) && len(info.section) && len(info.filename) if len(info.sigil) && len(info.section) && len(info.paths)
if info.section ==# 'Unstaged' && info.sigil !=# '-' if info.section ==# 'Unstaged' && info.sigil !=# '-'
return [lead . info.filename, info.offset, 'normal!zv'] return [lead . info.paths[0], info.offset, 'normal!zv']
elseif info.section ==# 'Staged' && info.sigil ==# '-' elseif info.section ==# 'Staged' && info.sigil ==# '-'
return ['@:' . info.filename, info.offset, 'normal!zv'] return ['@:' . info.paths[0], info.offset, 'normal!zv']
else else
return [':0:' . info.filename, info.offset, 'normal!zv'] return [':0:' . info.paths[0], info.offset, 'normal!zv']
endif endif
elseif len(info.filename) elseif len(info.paths)
return [lead . info.filename] return [lead . info.paths[0]]
elseif len(info.commit) elseif len(info.commit)
return [info.commit] return [info.commit]
elseif line =~# '^\%(Head\|Merge\|Rebase\|Upstream\|Pull\|Push\): ' elseif line =~# '^\%(Head\|Merge\|Rebase\|Upstream\|Pull\|Push\): '