Handle quoted filenames in diff --git headers

This commit is contained in:
Tim Pope
2022-06-14 13:50:29 -04:00
parent 3f5975e906
commit 6ae79e75a4

View File

@@ -203,6 +203,10 @@ let s:quote_chars = {
\ "\007": 'a', "\010": 'b', "\011": 't', "\012": 'n', "\013": 'v', "\014": 'f', "\015": 'r', \ "\007": 'a', "\010": 'b', "\011": 't', "\012": 'n', "\013": 'v', "\014": 'f', "\015": 'r',
\ '"': '"', '\': '\'} \ '"': '"', '\': '\'}
let s:unquote_chars = {
\ 'a': "\007", 'b': "\010", 't': "\011", 'n': "\012", 'v': "\013", 'f': "\014", 'r': "\015",
\ '"': '"', '\': '\'}
function! s:Quote(string) abort function! s:Quote(string) abort
let string = substitute(a:string, "[\001-\037\"\\\177]", '\="\\" . get(s:quote_chars, submatch(0), printf("%03o", char2nr(submatch(0))))', 'g') let string = substitute(a:string, "[\001-\037\"\\\177]", '\="\\" . get(s:quote_chars, submatch(0), printf("%03o", char2nr(submatch(0))))', 'g')
if string !=# a:string if string !=# a:string
@@ -212,6 +216,15 @@ function! s:Quote(string) abort
endif endif
endfunction endfunction
function! fugitive#Unquote(string) abort
let string = substitute(a:string, "\t*$", '', '')
if string =~# '^".*"$'
return substitute(string[1:-2], '\\\(\o\o\o\|.\)', '\=get(s:unquote_chars, submatch(1), iconv(nr2char("0" . submatch(1)), "utf-8", "latin1"))', 'g')
else
return string
endif
endfunction
let s:executables = {} let s:executables = {}
function! s:executable(binary) abort function! s:executable(binary) abort
@@ -7495,6 +7508,11 @@ function! s:NavigateUp(count) abort
return rev return rev
endfunction endfunction
function! s:ParseDiffHeader(str) abort
let list = matchlist(a:str, '\Cdiff --git \("\=[^/].*\|/dev/null\) \("\=[^/].*\|/dev/null\)$')
return [fugitive#Unquote(get(list, 1, '')), fugitive#Unquote(get(list, 2, ''))]
endfunction
function! s:MapMotion(lhs, rhs) abort function! s:MapMotion(lhs, rhs) abort
let maps = [ let maps = [
\ s:Map('n', a:lhs, ":<C-U>" . a:rhs . "<CR>", "<silent>"), \ s:Map('n', a:lhs, ":<C-U>" . a:rhs . "<CR>", "<silent>"),
@@ -7728,6 +7746,7 @@ function! s:BranchCfile(result) abort
return matchstr(getline('.'), '^. \zs\S\+') return matchstr(getline('.'), '^. \zs\S\+')
endfunction endfunction
let s:diff_header_pattern = '^diff --git \%("\=[abciow12]/.*\|/dev/null\) \%("\=[abciow12]/.*\|/dev/null\)$'
function! s:cfile() abort function! s:cfile() abort
let temp_state = s:TempState() let temp_state = s:TempState()
let name = substitute(get(get(temp_state, 'args', []), 0, ''), '\%(^\|-\)\(\l\)', '\u\1', 'g') let name = substitute(get(get(temp_state, 'args', []), 0, ''), '\%(^\|-\)\(\l\)', '\u\1', 'g')
@@ -7825,8 +7844,8 @@ function! s:cfile() abort
let dcmds = ['', 'Gdiffsplit! >' . myhash . '^:' . fnameescape(files[0])] let dcmds = ['', 'Gdiffsplit! >' . myhash . '^:' . fnameescape(files[0])]
endif endif
elseif getline('.') =~# '^[+-]\{3\} [abciow12]\=/' elseif getline('.') =~# '^[+-]\{3\} "\=[abciow12]\=/'
let ref = getline('.')[4:] let ref = fugitive#Unquote(getline('.')[4:])
elseif getline('.') =~# '^[+-]' && search('^@@ -\d\+\%(,\d\+\)\= +\d\+','bnW') elseif getline('.') =~# '^[+-]' && search('^@@ -\d\+\%(,\d\+\)\= +\d\+','bnW')
let type = getline('.')[0] let type = getline('.')[0]
@@ -7839,7 +7858,7 @@ function! s:cfile() abort
let lnum -= 1 let lnum -= 1
endwhile endwhile
let offset += matchstr(getline(lnum), type.'\zs\d\+') let offset += matchstr(getline(lnum), type.'\zs\d\+')
let ref = getline(search('^'.type.'\{3\} [abciow12]/','bnW'))[4:-1] let ref = fugitive#Unquote(getline(search('^'.type.'\{3\} "\=[abciow12]/','bnW'))[4:-1])
let dcmds = [offset, 'normal!zv'] let dcmds = [offset, 'normal!zv']
elseif getline('.') =~# '^rename from ' elseif getline('.') =~# '^rename from '
@@ -7848,22 +7867,18 @@ function! s:cfile() abort
let ref = 'b/'.getline('.')[10:] let ref = 'b/'.getline('.')[10:]
elseif getline('.') =~# '^@@ -\d\+\%(,\d\+\)\= +\d\+' elseif getline('.') =~# '^@@ -\d\+\%(,\d\+\)\= +\d\+'
let diff = getline(search('^diff --git \%([abciow12]/.*\|/dev/null\) \%([abciow12]/.*\|/dev/null\)', 'bcnW')) let diff = getline(search(s:diff_header_pattern, 'bcnW'))
let offset = matchstr(getline('.'), '+\zs\d\+') let offset = matchstr(getline('.'), '+\zs\d\+')
let dref = matchstr(diff, '\Cdiff --git \zs\%([abciow12]/.*\|/dev/null\)\ze \%([abciow12]/.*\|/dev/null\)') let [dref, ref] = s:ParseDiffHeader(diff)
let ref = matchstr(diff, '\Cdiff --git \%([abciow12]/.*\|/dev/null\) \zs\%([abciow12]/.*\|/dev/null\)')
let dcmd = 'Gdiffsplit! +'.offset let dcmd = 'Gdiffsplit! +'.offset
elseif getline('.') =~# '^diff --git \%([abciow12]/.*\|/dev/null\) \%([abciow12]/.*\|/dev/null\)' elseif getline('.') =~# s:diff_header_pattern
let dref = matchstr(getline('.'),'\Cdiff --git \zs\%([abciow12]/.*\|/dev/null\)\ze \%([abciow12]/.*\|/dev/null\)') let [dref, ref] = s:ParseDiffHeader(getline('.'))
let ref = matchstr(getline('.'),'\Cdiff --git \%([abciow12]/.*\|/dev/null\) \zs\%([abciow12]/.*\|/dev/null\)')
let dcmd = 'Gdiffsplit!' let dcmd = 'Gdiffsplit!'
elseif getline('.') =~# '^index ' && getline(line('.')-1) =~# '^diff --git \%([abciow12]/.*\|/dev/null\) \%([abciow12]/.*\|/dev/null\)' elseif getline('.') =~# '^index ' && getline(line('.')-1) =~# s:diff_header_pattern
let line = getline(line('.')-1) let [dref, ref] = s:ParseDiffHeader(getline(line('.') - '.'))
let dref = matchstr(line,'\Cdiff --git \zs\%([abciow12]/.*\|/dev/null\)\ze \%([abciow12]/.*\|/dev/null\)')
let ref = matchstr(line,'\Cdiff --git \%([abciow12]/.*\|/dev/null\) \zs\%([abciow12]/.*\|/dev/null\)')
let dcmd = 'Gdiffsplit!' let dcmd = 'Gdiffsplit!'
elseif line('$') == 1 && getline('.') =~ '^\x\{40,\}$' elseif line('$') == 1 && getline('.') =~ '^\x\{40,\}$'
@@ -7986,8 +8001,8 @@ function! fugitive#Foldtext() abort
let filename = '' let filename = ''
for lnum in range(v:foldstart, v:foldend) for lnum in range(v:foldstart, v:foldend)
let line = getline(lnum) let line = getline(lnum)
if filename ==# '' && line =~# '^[+-]\{3\} [abciow12]/' if filename ==# '' && line =~# '^[+-]\{3\} "\=[abciow12]/'
let filename = line[6:-1] let filename = fugitive#Unquote(line[4:-1])[2:-1]
endif endif
if line =~# '^+' if line =~# '^+'
let add += 1 let add += 1
@@ -7998,7 +8013,7 @@ function! fugitive#Foldtext() abort
endif endif
endfor endfor
if filename ==# '' if filename ==# ''
let filename = matchstr(line_foldstart, '^diff .\{-\} [abciow12]/\zs.*\ze [abciow12]/') let filename = fugitive#Unquote(matchstr(line_foldstart, '^diff .\{-\} \zs"\=[abciow12]/\zs.*\ze "\=[abciow12]/'))[2:-1]
endif endif
if filename ==# '' if filename ==# ''
let filename = line_foldstart[5:-1] let filename = line_foldstart[5:-1]