Add --porcelain=v2 status parser

New submodule modifiers:

- 'M' if submodule commit is changed, otherwise
- '?' if there is modified or untracked content

Keep using v1 parser for git versions older than 2.11. This will display
'M' for any submodule changes.

Test with https://github.com/odnoletkov/git-status-test-suite

Fixes https://github.com/tpope/vim-fugitive/issues/1204
This commit is contained in:
Maksim Odnoletkov
2019-09-12 00:19:27 +01:00
committed by Tim Pope
parent 80aa8a9aea
commit f779b90fbd

View File

@@ -1617,48 +1617,95 @@ function! fugitive#BufReadStatus() abort
if s:cpath(fnamemodify($GIT_INDEX_FILE !=# '' ? $GIT_INDEX_FILE : fugitive#Find('.git/index'), ':p')) !=# s:cpath(amatch) if s:cpath(fnamemodify($GIT_INDEX_FILE !=# '' ? $GIT_INDEX_FILE : fugitive#Find('.git/index'), ':p')) !=# s:cpath(amatch)
let cmd += ['-c', 'GIT_INDEX_FILE=' . amatch] let cmd += ['-c', 'GIT_INDEX_FILE=' . amatch]
endif endif
let cmd += ['status', '--porcelain', '-bz']
let [output, message, exec_error] = s:NullError(cmd)
if exec_error
throw 'fugitive: ' . message
endif
let head = matchstr(output[0], '^## \zs\S\+\ze\%($\| \[\)')
let pull = ''
if head =~# '\.\.\.'
let [head, pull] = split(head, '\.\.\.')
let branch = head
elseif head ==# 'HEAD' || empty(head)
let head = FugitiveHead(11)
let branch = ''
else
let branch = head
endif
let b:fugitive_files = {'Staged': {}, 'Unstaged': {}} let b:fugitive_files = {'Staged': {}, 'Unstaged': {}}
let [staged, unstaged, untracked] = [[], [], []] let [staged, unstaged, untracked] = [[], [], []]
let i = 0
while i < len(output) if fugitive#GitVersion(2, 11)
let line = output[i] let cmd += ['status', '--porcelain=v2', '-bz']
let file = line[3:-1] let [output, message, exec_error] = s:NullError(cmd)
let files = file if exec_error
let i += 1 throw 'fugitive: ' . message
if line[2] !=# ' '
continue
endif endif
if line[0:1] =~# '[RC]'
let files = output[i] . ' -> ' . file let i = match(output, '^[^#]')
let head = matchlist(output[:i], '^# branch\.head \zs.*$')[0]
let pull = get(matchlist(output[:i], '^# branch\.upstream \zs.*$'), 0, '')
if len(pull)
let branch = head
elseif head ==# '(detached)'
let head = matchlist(output[:i], '^# branch\.oid \zs.*$')[0][:10]
let branch = ''
else
let branch = head
endif
while i < len(output)
let line = output[i]
if line[0] ==# '?'
call add(untracked, {'type': 'File', 'status': line[0], 'filename': line[2:-1]})
elseif line[0] !=# '#'
if line[0] ==# 'u'
let file = matchstr(line, '^.\{37\} \x\{40,\} \x\{40,\} \x\{40,\} \zs.*$')
else
let file = matchstr(line, '^.\{30\} \x\{40,\} \x\{40,\} \zs.*$')
endif
if line[0] ==# '2'
let i += 1
let file = output[i] . ' -> ' . matchstr(file, ' \zs.*')
endif
if line[2] !=# '.'
call add(staged, {'type': 'File', 'status': line[2], 'filename': file})
endif
if line[3] !=# '.'
let sub = matchstr(line, '^[12u] .. \zs....')
call add(unstaged, {'type': 'File', 'status': get({'C':'M','M':'?','U':'?'}, matchstr(sub, 'S\.*\zs[CMU]'), line[3]), 'filename': file})
endif
endif
let i += 1 let i += 1
endwhile
else " git < 2.11
let cmd += ['status', '--porcelain', '-bz']
let [output, message, exec_error] = s:NullError(cmd)
if exec_error
throw 'fugitive: ' . message
endif endif
if line[0] !~# '[ ?!#]'
call add(staged, {'type': 'File', 'status': line[0], 'filename': files}) let head = matchstr(output[0], '^## \zs\S\+\ze\%($\| \[\)')
let pull = ''
if head =~# '\.\.\.'
let [head, pull] = split(head, '\.\.\.')
let branch = head
elseif head ==# 'HEAD' || empty(head)
let head = FugitiveHead(11)
let branch = ''
else
let branch = head
endif endif
if line[0:1] ==# '??'
call add(untracked, {'type': 'File', 'status': line[1], 'filename': files}) let i = 0
elseif line[1] !~# '[ !#]' while i < len(output)
call add(unstaged, {'type': 'File', 'status': line[1], 'filename': files}) let line = output[i]
endif let file = line[3:-1]
endwhile let files = file
let i += 1
if line[2] !=# ' '
continue
endif
if line[0:1] =~# '[RC]'
let files = output[i] . ' -> ' . file
let i += 1
endif
if line[0] !~# '[ ?!#]'
call add(staged, {'type': 'File', 'status': line[0], 'filename': files})
endif
if line[0:1] ==# '??'
call add(untracked, {'type': 'File', 'status': line[1], 'filename': files})
elseif line[1] !~# '[ !#]'
call add(unstaged, {'type': 'File', 'status': line[1], 'filename': files})
endif
endwhile
endif
for dict in staged for dict in staged
let b:fugitive_files['Staged'][dict.filename] = dict let b:fugitive_files['Staged'][dict.filename] = dict