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,6 +1617,54 @@ 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 b:fugitive_files = {'Staged': {}, 'Unstaged': {}}
let [staged, unstaged, untracked] = [[], [], []]
if fugitive#GitVersion(2, 11)
let cmd += ['status', '--porcelain=v2', '-bz']
let [output, message, exec_error] = s:NullError(cmd)
if exec_error
throw 'fugitive: ' . message
endif
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
endwhile
else " git < 2.11
let cmd += ['status', '--porcelain', '-bz'] let cmd += ['status', '--porcelain', '-bz']
let [output, message, exec_error] = s:NullError(cmd) let [output, message, exec_error] = s:NullError(cmd)
if exec_error if exec_error
@@ -1635,8 +1683,6 @@ function! fugitive#BufReadStatus() abort
let branch = head let branch = head
endif endif
let b:fugitive_files = {'Staged': {}, 'Unstaged': {}}
let [staged, unstaged, untracked] = [[], [], []]
let i = 0 let i = 0
while i < len(output) while i < len(output)
let line = output[i] let line = output[i]
@@ -1659,6 +1705,7 @@ function! fugitive#BufReadStatus() abort
call add(unstaged, {'type': 'File', 'status': line[1], 'filename': files}) call add(unstaged, {'type': 'File', 'status': line[1], 'filename': files})
endif endif
endwhile 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