commit f779b90fbd65c2a656b77d23d369d15dffbf2b92 (tree)
parent 80aa8a9aea72f2054fb2ad8582461f60b0db9757
Author: Maksim Odnoletkov <odnoletkov@mail.ru>
Date: Thu, 12 Sep 2019 00:19:27 +0100
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
Diffstat:
| M | autoload/fugitive.vim | | | 117 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------ |
1 file changed, 82 insertions(+), 35 deletions(-)
diff --git a/autoload/fugitive.vim b/autoload/fugitive.vim
@@ -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)
let cmd += ['-c', 'GIT_INDEX_FILE=' . amatch]
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 [staged, unstaged, untracked] = [[], [], []]
- let i = 0
- while i < len(output)
- let line = output[i]
- let file = line[3:-1]
- let files = file
- let i += 1
- if line[2] !=# ' '
- continue
+
+ 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
- if line[0:1] =~# '[RC]'
- let files = output[i] . ' -> ' . file
- let i += 1
+
+ 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
- if line[0] !~# '[ ?!#]'
- call add(staged, {'type': 'File', 'status': line[0], 'filename': files})
+
+ 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 [output, message, exec_error] = s:NullError(cmd)
+ if exec_error
+ throw 'fugitive: ' . message
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})
+
+ 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
- endwhile
+
+ let i = 0
+ while i < len(output)
+ let line = output[i]
+ let file = line[3:-1]
+ 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
let b:fugitive_files['Staged'][dict.filename] = dict