|
|
|
|
@@ -42,7 +42,7 @@ function! s:Uniq(list) abort
|
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
|
|
function! s:winshell() abort
|
|
|
|
|
return has('win32') && &shellcmdflag =~# '^/\|^-Command$'
|
|
|
|
|
return has('win32') && &shellcmdflag !~# '^-'
|
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
|
|
function! s:shellesc(arg) abort
|
|
|
|
|
@@ -225,6 +225,7 @@ function! s:QuickfixStream(nr, event, title, cmd, first, callback, ...) abort
|
|
|
|
|
let contexts = map(copy(buffer), 'get(v:val, "context", {})')
|
|
|
|
|
lockvar contexts
|
|
|
|
|
call extend(opts.context.items, contexts)
|
|
|
|
|
unlet contexts
|
|
|
|
|
call s:QuickfixSet(a:nr, remove(buffer, 0, -1), 'a')
|
|
|
|
|
redraw
|
|
|
|
|
endif
|
|
|
|
|
@@ -413,17 +414,24 @@ function! fugitive#PrepareDirEnvArgv(...) abort
|
|
|
|
|
return [dir, env, cmd]
|
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
|
|
function! s:BuildEnvPrefix(env) abort
|
|
|
|
|
let pre = ''
|
|
|
|
|
let env = items(a:env)
|
|
|
|
|
if empty(env)
|
|
|
|
|
return ''
|
|
|
|
|
elseif &shellcmdflag =~# '-Command'
|
|
|
|
|
return join(map(env, '"$Env:" . v:val[0] . " = ''" . substitute(v:val[1], "''", "''''", "g") . "''; "'), '')
|
|
|
|
|
elseif s:winshell()
|
|
|
|
|
return join(map(env, '"set " . substitute(join(v:val, "="), "[&|<>^]", "^^^&", "g") . "& "'), '')
|
|
|
|
|
else
|
|
|
|
|
return 'env ' . s:shellesc(map(env, 'join(v:val, "=")')) . ' '
|
|
|
|
|
endif
|
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
|
|
function! s:BuildShell(dir, env, args) abort
|
|
|
|
|
let cmd = copy(a:args)
|
|
|
|
|
let tree = s:Tree(a:dir)
|
|
|
|
|
let pre = ''
|
|
|
|
|
for [var, val] in items(a:env)
|
|
|
|
|
if s:winshell()
|
|
|
|
|
let pre .= 'set ' . var . '=' . s:shellesc(val) . '& '
|
|
|
|
|
else
|
|
|
|
|
let pre = (len(pre) ? pre : 'env ') . var . '=' . s:shellesc(val) . ' '
|
|
|
|
|
endif
|
|
|
|
|
endfor
|
|
|
|
|
let pre = s:BuildEnvPrefix(a:env)
|
|
|
|
|
if empty(tree) || index(cmd, '--') == len(cmd) - 1
|
|
|
|
|
call insert(cmd, '--git-dir=' . FugitiveGitPath(a:dir))
|
|
|
|
|
elseif fugitive#GitVersion(1, 8, 5)
|
|
|
|
|
@@ -1259,17 +1267,16 @@ function! fugitive#setfperm(url, perm) abort
|
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
|
|
function! s:TempCmd(out, cmd) abort
|
|
|
|
|
let prefix = ''
|
|
|
|
|
try
|
|
|
|
|
let cmd = (type(a:cmd) == type([]) ? fugitive#Prepare(a:cmd) : a:cmd)
|
|
|
|
|
let redir = ' > ' . a:out
|
|
|
|
|
if s:winshell()
|
|
|
|
|
if (s:winshell() || &shellcmdflag ==# '-Command') && !has('nvim')
|
|
|
|
|
let cmd_escape_char = &shellxquote == '(' ? '^' : '^^^'
|
|
|
|
|
return s:SystemError('cmd /c "' . prefix . s:gsub(cmd, '[<>]', cmd_escape_char . '&') . redir . '"')
|
|
|
|
|
return s:SystemError('cmd /c "' . s:gsub(cmd, '[<>%]', cmd_escape_char . '&') . redir . '"')
|
|
|
|
|
elseif &shell =~# 'fish'
|
|
|
|
|
return s:SystemError(' begin;' . prefix . cmd . redir . ';end ')
|
|
|
|
|
return s:SystemError(' begin;' . cmd . redir . ';end ')
|
|
|
|
|
else
|
|
|
|
|
return s:SystemError(' (' . prefix . cmd . redir . ') ')
|
|
|
|
|
return s:SystemError(' (' . cmd . redir . ') ')
|
|
|
|
|
endif
|
|
|
|
|
endtry
|
|
|
|
|
endfunction
|
|
|
|
|
@@ -1554,28 +1561,13 @@ function! s:ReplaceCmd(cmd) abort
|
|
|
|
|
if exec_error
|
|
|
|
|
call s:throw((len(err) ? err : filereadable(temp) ? join(readfile(temp), ' ') : 'unknown error running ' . a:cmd))
|
|
|
|
|
endif
|
|
|
|
|
let temp = s:Resolve(temp)
|
|
|
|
|
let fn = expand('%:p')
|
|
|
|
|
silent exe 'keepalt file '.temp
|
|
|
|
|
let modelines = &modelines
|
|
|
|
|
try
|
|
|
|
|
set modelines=0
|
|
|
|
|
silent keepjumps noautocmd edit!
|
|
|
|
|
finally
|
|
|
|
|
let &modelines = modelines
|
|
|
|
|
try
|
|
|
|
|
silent exe 'keepalt file '.s:fnameescape(fn)
|
|
|
|
|
catch /^Vim\%((\a\+)\)\=:E302:/
|
|
|
|
|
endtry
|
|
|
|
|
call delete(temp)
|
|
|
|
|
if s:cpath(fnamemodify(bufname('$'), ':p'), temp)
|
|
|
|
|
silent! execute 'bwipeout '.bufnr('$')
|
|
|
|
|
endif
|
|
|
|
|
endtry
|
|
|
|
|
silent exe 'keepalt $read ++edit' s:fnameescape(temp)
|
|
|
|
|
silent keepjumps 1delete _
|
|
|
|
|
call delete(temp)
|
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
|
|
function! s:QueryLog(refspec) abort
|
|
|
|
|
let lines = s:LinesError(['log', '-n', '256', '--format=%h%x09%s', a:refspec, '--'])[0]
|
|
|
|
|
let lines = s:LinesError(['log', '-n', '256', '--pretty=format:%h%x09%s', a:refspec, '--'])[0]
|
|
|
|
|
call map(lines, 'split(v:val, "\t")')
|
|
|
|
|
call map(lines, '{"type": "Log", "commit": v:val[0], "subject": v:val[-1]}')
|
|
|
|
|
return lines
|
|
|
|
|
@@ -1834,7 +1826,8 @@ function! fugitive#BufReadStatus() abort
|
|
|
|
|
if push !=# pull
|
|
|
|
|
call s:AddHeader('Push', push)
|
|
|
|
|
endif
|
|
|
|
|
if empty(s:Tree())
|
|
|
|
|
let tree = s:Tree()
|
|
|
|
|
if empty(tree)
|
|
|
|
|
call s:AddHeader('Bare', 'yes')
|
|
|
|
|
endif
|
|
|
|
|
call s:AddSection('Rebasing ' . rebasing_head, rebasing)
|
|
|
|
|
@@ -1852,7 +1845,8 @@ function! fugitive#BufReadStatus() abort
|
|
|
|
|
if &bufhidden ==# ''
|
|
|
|
|
setlocal bufhidden=delete
|
|
|
|
|
endif
|
|
|
|
|
let b:dispatch = ':Gfetch --all'
|
|
|
|
|
let b:dispatch = '-compiler=git -dir=' . s:fnameescape(FugitiveVimPath(len(tree) ? tree : s:Dir())) .
|
|
|
|
|
\ ' ' . s:UserCommand() . ' ' . s:shellesc(s:AskPassArgs(s:Dir())) . ' fetch --all'
|
|
|
|
|
call fugitive#MapJumps()
|
|
|
|
|
call s:Map('n', '-', ":<C-U>execute <SID>Do('Toggle',0)<CR>", '<silent>')
|
|
|
|
|
call s:Map('x', '-', ":<C-U>execute <SID>Do('Toggle',1)<CR>", '<silent>')
|
|
|
|
|
@@ -1915,7 +1909,7 @@ function! fugitive#BufReadStatus() abort
|
|
|
|
|
endfor
|
|
|
|
|
|
|
|
|
|
let b:fugitive_reltime = reltime()
|
|
|
|
|
return ''
|
|
|
|
|
return 'silent ' . s:DoAutocmd('User FugitiveIndex')
|
|
|
|
|
catch /^fugitive:/
|
|
|
|
|
return 'echoerr ' . string(v:exception)
|
|
|
|
|
endtry
|
|
|
|
|
@@ -2018,7 +2012,7 @@ function! fugitive#BufReadCmd(...) abort
|
|
|
|
|
setlocal endofline
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
silent doautocmd BufReadPre
|
|
|
|
|
silent exe s:DoAutocmd('BufReadPre')
|
|
|
|
|
if b:fugitive_type ==# 'tree'
|
|
|
|
|
let b:fugitive_display_format = b:fugitive_display_format % 2
|
|
|
|
|
if b:fugitive_display_format
|
|
|
|
|
@@ -2078,8 +2072,16 @@ function! fugitive#BufReadCmd(...) abort
|
|
|
|
|
endtry
|
|
|
|
|
|
|
|
|
|
setlocal modifiable
|
|
|
|
|
|
|
|
|
|
let browsex = maparg('<Plug>NetrwBrowseX', 'n')
|
|
|
|
|
let remote_check = '\Cnetrw#CheckIfRemote(\%(netrw#GX()\)\=)'
|
|
|
|
|
if browsex =~# remote_check
|
|
|
|
|
exe 'nnoremap <silent> <buffer> <Plug>NetrwBrowseX' substitute(browsex, remote_check, '0', 'g')
|
|
|
|
|
endif
|
|
|
|
|
|
|
|
|
|
return 'silent ' . s:DoAutocmd('BufReadPost') .
|
|
|
|
|
\ (modifiable ? '' : '|setl nomodifiable')
|
|
|
|
|
\ (modifiable ? '' : '|setl nomodifiable') . '|silent ' .
|
|
|
|
|
\ s:DoAutocmd('User Fugitive' . substitute(b:fugitive_type, '^\l', '\u&', ''))
|
|
|
|
|
catch /^fugitive:/
|
|
|
|
|
return 'echoerr ' . string(v:exception)
|
|
|
|
|
endtry
|
|
|
|
|
@@ -2170,19 +2172,26 @@ function! fugitive#Command(line1, line2, range, bang, mods, arg) abort
|
|
|
|
|
if exists('*s:' . name . 'Subcommand') && get(args, 1, '') !=# '--help'
|
|
|
|
|
try
|
|
|
|
|
exe s:DirCheck(dir)
|
|
|
|
|
return 'exe ' . string(s:{name}Subcommand(a:line1, a:line2, a:range, a:bang, a:mods, args[1:-1])) . after
|
|
|
|
|
let opts = s:{name}Subcommand(a:line1, a:line2, a:range, a:bang, a:mods, args[1:-1])
|
|
|
|
|
if type(opts) == type('')
|
|
|
|
|
return 'exe ' . string(opts) . after
|
|
|
|
|
endif
|
|
|
|
|
catch /^fugitive:/
|
|
|
|
|
return 'echoerr ' . string(v:exception)
|
|
|
|
|
endtry
|
|
|
|
|
else
|
|
|
|
|
let opts = {}
|
|
|
|
|
endif
|
|
|
|
|
if a:bang || args[0] =~# '^-P$\|^--no-pager$\|diff\%(tool\)\@!\|log\|^show$' ||
|
|
|
|
|
if a:bang || args[0] =~# '^-p$\|^--paginate$\|diff\%(tool\)\@!\|log\|^show$' ||
|
|
|
|
|
\ (args[0] ==# 'stash' && get(args, 1, '') ==# 'show') ||
|
|
|
|
|
\ (args[0] ==# 'help' || get(args, 1, '') ==# '--help') && !s:HasOpt(args, '--web')
|
|
|
|
|
if args[0] =~# '^-p$\|^--paginate$'
|
|
|
|
|
call remove(args, 0)
|
|
|
|
|
endif
|
|
|
|
|
return s:OpenExec((a:line2 > 0 ? a:line2 : '') . (a:line2 ? 'split' : 'edit'), a:mods, args, dir) . after
|
|
|
|
|
endif
|
|
|
|
|
if s:HasOpt(args, ['add', 'checkout', 'commit', 'stage', 'stash', 'reset'], '-p', '--patch') ||
|
|
|
|
|
\ s:HasOpt(args, ['add', 'clean', 'stage'], '-i', '--interactive') ||
|
|
|
|
|
\ index(['--paginate', '-p'], args[0]) >= 0
|
|
|
|
|
\ s:HasOpt(args, ['add', 'clean', 'stage'], '-i', '--interactive')
|
|
|
|
|
let mods = substitute(s:Mods(a:mods), '\<tab\>', '-tab', 'g')
|
|
|
|
|
let assign = len(dir) ? '|let b:git_dir = ' . string(dir) : ''
|
|
|
|
|
if has('nvim')
|
|
|
|
|
@@ -2193,13 +2202,14 @@ function! fugitive#Command(line1, line2, range, bang, mods, arg) abort
|
|
|
|
|
return 'exe ' . string(mods . 'terminal ' . (a:line2 ? '' : '++curwin ') . join(map(s:UserCommandList(dir) + args, 's:fnameescape(v:val)'))) . assign . after
|
|
|
|
|
endif
|
|
|
|
|
endif
|
|
|
|
|
let env = get(opts, 'env', {})
|
|
|
|
|
if has('gui_running') && !has('win32')
|
|
|
|
|
call insert(args, '--no-pager')
|
|
|
|
|
endif
|
|
|
|
|
let pre = ''
|
|
|
|
|
if has('nvim') && executable('env')
|
|
|
|
|
let pre .= 'env GIT_TERMINAL_PROMPT=0 '
|
|
|
|
|
if has('nvim')
|
|
|
|
|
let env.GIT_TERMINAL_PROMPT = '0'
|
|
|
|
|
endif
|
|
|
|
|
let pre = s:BuildEnvPrefix(env)
|
|
|
|
|
return 'exe ' . string('noautocmd !' . escape(pre . s:UserCommand(dir, args), '!#%')) .
|
|
|
|
|
\ '|call fugitive#ReloadStatus(' . string(dir) . ', 1)' .
|
|
|
|
|
\ after
|
|
|
|
|
@@ -3373,7 +3383,7 @@ function! s:CommitSubcommand(line1, line2, range, bang, mods, args, ...) abort
|
|
|
|
|
let msgfile = fugitive#Find('.git/COMMIT_EDITMSG', dir)
|
|
|
|
|
let outfile = tempname()
|
|
|
|
|
try
|
|
|
|
|
if s:winshell()
|
|
|
|
|
if s:winshell() || &shellcmdflag ==# '-Command'
|
|
|
|
|
let command = 'set GIT_EDITOR=false& '
|
|
|
|
|
else
|
|
|
|
|
let command = 'env GIT_EDITOR=false '
|
|
|
|
|
@@ -3528,7 +3538,7 @@ function! s:RebaseSequenceAborter() abort
|
|
|
|
|
\ 'echo exec false | cat - "$1" > "$1.fugitive"',
|
|
|
|
|
\ 'mv "$1.fugitive" "$1"'],
|
|
|
|
|
\ temp)
|
|
|
|
|
let s:rebase_sequence_aborter = temp
|
|
|
|
|
let s:rebase_sequence_aborter = FugitiveGitPath(temp)
|
|
|
|
|
endif
|
|
|
|
|
return s:rebase_sequence_aborter
|
|
|
|
|
endfunction
|
|
|
|
|
@@ -3661,13 +3671,7 @@ function! s:MergeRebase(cmd, bang, mods, args, ...) abort
|
|
|
|
|
\ . "%+EXUNG \u0110\u1ed8T %.%#,"
|
|
|
|
|
\ . "%+E\u51b2\u7a81 %.%#,"
|
|
|
|
|
\ . 'U%\t%f'
|
|
|
|
|
if a:cmd =~# '^merge' && empty(args) &&
|
|
|
|
|
\ (had_merge_msg || isdirectory(fugitive#Find('.git/rebase-apply', dir)) ||
|
|
|
|
|
\ !empty(s:TreeChomp(dir, 'diff-files', '--diff-filter=U')))
|
|
|
|
|
let cmd = g:fugitive_git_executable.' diff-files --name-status --diff-filter=U'
|
|
|
|
|
else
|
|
|
|
|
let cmd = s:UserCommand(dir, argv)
|
|
|
|
|
endif
|
|
|
|
|
let cmd = s:UserCommand(dir, argv)
|
|
|
|
|
if !empty($GIT_SEQUENCE_EDITOR) || has('win32')
|
|
|
|
|
let old_sequence_editor = $GIT_SEQUENCE_EDITOR
|
|
|
|
|
let $GIT_SEQUENCE_EDITOR = 'true'
|
|
|
|
|
@@ -3757,6 +3761,13 @@ function! s:RebaseClean(file) abort
|
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
|
|
function! s:MergeSubcommand(line1, line2, range, bang, mods, args) abort
|
|
|
|
|
let dir = s:Dir()
|
|
|
|
|
if empty(a:args) && (
|
|
|
|
|
\ filereadable(fugitive#Find('.git/MERGE_MSG', dir)) ||
|
|
|
|
|
\ isdirectory(fugitive#Find('.git/rebase-apply', dir)) ||
|
|
|
|
|
\ !empty(s:TreeChomp(dir, 'diff-files', '--diff-filter=U')))
|
|
|
|
|
return 'echohl WarningMsg|echo ":Git merge for loading conflicts is deprecated in favor of :Git mergetool"|echohl NONE|silent Git' . (a:bang ? '!' : '') . ' mergetool'
|
|
|
|
|
endif
|
|
|
|
|
return s:MergeRebase('merge', a:bang, a:mods, a:args)
|
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
|
|
@@ -3776,7 +3787,7 @@ endfunction
|
|
|
|
|
augroup fugitive_merge
|
|
|
|
|
autocmd!
|
|
|
|
|
autocmd VimLeavePre,BufDelete git-rebase-todo
|
|
|
|
|
\ if getbufvar(+expand('<abuf>'), '&bufhidden') ==# 'wipe' |
|
|
|
|
|
\ if type(getbufvar(+expand('<abuf>'), 'fugitive_rebase_shas')) == type({}) && getbufvar(+expand('<abuf>'), '&bufhidden') ==# 'wipe' |
|
|
|
|
|
\ call s:RebaseClean(expand('<afile>')) |
|
|
|
|
|
\ if getfsize(FugitiveFind('.git/rebase-merge/done', +expand('<abuf>'))) == 0 |
|
|
|
|
|
\ let s:rebase_continue = [FugitiveGitDir(+expand('<abuf>')), 1] |
|
|
|
|
|
@@ -3792,6 +3803,243 @@ augroup fugitive_merge
|
|
|
|
|
\ endif
|
|
|
|
|
augroup END
|
|
|
|
|
|
|
|
|
|
" Section: :Git difftool, :Git mergetool
|
|
|
|
|
|
|
|
|
|
function! s:ToolItems(state, from, to, offsets, text, ...) abort
|
|
|
|
|
let items = []
|
|
|
|
|
for i in range(len(a:state.diff))
|
|
|
|
|
let diff = a:state.diff[i]
|
|
|
|
|
let path = (i == len(a:state.diff) - 1) ? a:to : a:from
|
|
|
|
|
if empty(path)
|
|
|
|
|
return []
|
|
|
|
|
endif
|
|
|
|
|
let item = {
|
|
|
|
|
\ 'valid': a:0 ? a:1 : 1,
|
|
|
|
|
\ 'filename': diff.filename . FugitiveVimPath(path),
|
|
|
|
|
\ 'lnum': matchstr(get(a:offsets, i), '\d\+'),
|
|
|
|
|
\ 'text': a:text}
|
|
|
|
|
if len(get(diff, 'module', ''))
|
|
|
|
|
let item.module = diff.module . path
|
|
|
|
|
endif
|
|
|
|
|
call add(items, item)
|
|
|
|
|
endfor
|
|
|
|
|
let diff = items[0:-2]
|
|
|
|
|
let items[-1].context = {'diff': items[0:-2]}
|
|
|
|
|
return [items[-1]]
|
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
|
|
function! s:ToolToFrom(str) abort
|
|
|
|
|
if a:str =~# ' => '
|
|
|
|
|
let str = a:str =~# '{.* => .*}' ? a:str : '{' . a:str . '}'
|
|
|
|
|
return [substitute(str, '{.* => \(.*\)}', '\1', ''),
|
|
|
|
|
\ substitute(str, '{\(.*\) => .*}', '\1', '')]
|
|
|
|
|
else
|
|
|
|
|
return [a:str, a:str]
|
|
|
|
|
endif
|
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
|
|
function! s:ToolParse(state, line) abort
|
|
|
|
|
if type(a:line) !=# type('') || a:state.mode ==# 'hunk' && a:line =~# '^[ +-]'
|
|
|
|
|
return []
|
|
|
|
|
elseif a:line =~# '^diff '
|
|
|
|
|
let a:state.mode = 'diffhead'
|
|
|
|
|
let a:state.from = ''
|
|
|
|
|
let a:state.to = ''
|
|
|
|
|
elseif a:state.mode ==# 'diffhead' && a:line =~# '^--- [^/]'
|
|
|
|
|
let a:state.from = a:line[4:-1]
|
|
|
|
|
let a:state.to = a:state.from
|
|
|
|
|
elseif a:state.mode ==# 'diffhead' && a:line =~# '^+++ [^/]'
|
|
|
|
|
let a:state.to = a:line[4:-1]
|
|
|
|
|
if empty(get(a:state, 'from', ''))
|
|
|
|
|
let a:state.from = a:state.to
|
|
|
|
|
endif
|
|
|
|
|
elseif a:line[0] ==# '@'
|
|
|
|
|
let a:state.mode = 'hunk'
|
|
|
|
|
if has_key(a:state, 'from')
|
|
|
|
|
let offsets = split(matchstr(a:line, '^@\+ \zs[-+0-9, ]\+\ze @'), ' ')
|
|
|
|
|
return s:ToolItems(a:state, a:state.from, a:state.to, offsets, matchstr(a:line, ' @@\+ \zs.*'))
|
|
|
|
|
endif
|
|
|
|
|
elseif a:line =~# '^\* Unmerged path .'
|
|
|
|
|
let file = a:line[16:-1]
|
|
|
|
|
return s:ToolItems(a:state, file, file, [], '')
|
|
|
|
|
elseif a:line =~# '^[A-Z]\d*\t.\|^:.*\t.'
|
|
|
|
|
" --raw, --name-status
|
|
|
|
|
let [status; files] = split(a:line, "\t")
|
|
|
|
|
return s:ToolItems(a:state, files[0], files[-1], [], a:state.name_only ? '' : status)
|
|
|
|
|
elseif a:line =~# '^ \S.* |'
|
|
|
|
|
" --stat
|
|
|
|
|
let [_, to, changes; __] = matchlist(a:line, '^ \(.\{-\}\) \+|\zs \(.*\)$')
|
|
|
|
|
let [to, from] = s:ToolToFrom(to)
|
|
|
|
|
return s:ToolItems(a:state, from, to, [], changes)
|
|
|
|
|
elseif a:line =~# '^ *\([0-9.]\+%\) .'
|
|
|
|
|
" --dirstat
|
|
|
|
|
let [_, changes, to; __] = matchlist(a:line, '^ *\([0-9.]\+%\) \(.*\)')
|
|
|
|
|
return s:ToolItems(a:state, to, to, [], changes)
|
|
|
|
|
elseif a:line =~# '^\(\d\+\|-\)\t\(\d\+\|-\)\t.'
|
|
|
|
|
" --numstat
|
|
|
|
|
let [_, add, remove, to; __] = matchlist(a:line, '^\(\d\+\|-\)\t\(\d\+\|-\)\t\(.*\)')
|
|
|
|
|
let [to, from] = s:ToolToFrom(to)
|
|
|
|
|
return s:ToolItems(a:state, from, to, [], add ==# '-' ? 'Binary file' : '+' . add . ' -' . remove, add !=# '-')
|
|
|
|
|
elseif a:state.mode !=# 'diffhead' && a:state.mode !=# 'hunk' && len(a:line) || a:line =~# '^git: \|^usage: \|^error: \|^fatal: '
|
|
|
|
|
return [{'text': a:line}]
|
|
|
|
|
endif
|
|
|
|
|
return []
|
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
|
|
function! s:ToolStream(dir, line1, line2, range, bang, mods, args, state, title) abort
|
|
|
|
|
let i = 0
|
|
|
|
|
let argv = copy(a:args)
|
|
|
|
|
let prompt = 1
|
|
|
|
|
let state = a:state
|
|
|
|
|
while i < len(argv)
|
|
|
|
|
let match = matchlist(argv[i], '^\(-[a-zABDFH-KN-RT-Z]\)\ze\(.*\)')
|
|
|
|
|
if len(match) && len(match[2])
|
|
|
|
|
call insert(argv, match[1])
|
|
|
|
|
let argv[i+1] = '-' . match[2]
|
|
|
|
|
continue
|
|
|
|
|
endif
|
|
|
|
|
let arg = argv[i]
|
|
|
|
|
if arg =~# '^-t$\|^--tool=\|^--tool-help$\|^--help$'
|
|
|
|
|
return {}
|
|
|
|
|
elseif arg =~# '^-y$\|^--no-prompt$'
|
|
|
|
|
let prompt = 0
|
|
|
|
|
call remove(argv, i)
|
|
|
|
|
continue
|
|
|
|
|
elseif arg ==# '--prompt'
|
|
|
|
|
let prompt = 1
|
|
|
|
|
call remove(argv, i)
|
|
|
|
|
continue
|
|
|
|
|
elseif arg =~# '^--\%(no-\)\=\(symlinks\|trust-exit-code\|gui\)$'
|
|
|
|
|
call remove(argv, i)
|
|
|
|
|
continue
|
|
|
|
|
elseif arg ==# '--'
|
|
|
|
|
break
|
|
|
|
|
endif
|
|
|
|
|
let i += 1
|
|
|
|
|
endwhile
|
|
|
|
|
let a:state.mode = 'init'
|
|
|
|
|
let a:state.from = ''
|
|
|
|
|
let a:state.to = ''
|
|
|
|
|
let exec = s:UserCommandList(a:dir) + ['--no-pager', '-c', 'diff.context=0', 'diff', '--no-ext-diff', '--no-color', '--no-prefix'] + argv
|
|
|
|
|
if prompt
|
|
|
|
|
return s:QuickfixStream(a:line2, 'difftool', a:title, exec, !a:bang, s:function('s:ToolParse'), a:state)
|
|
|
|
|
else
|
|
|
|
|
let filename = ''
|
|
|
|
|
let cmd = []
|
|
|
|
|
let tabnr = tabpagenr() + 1
|
|
|
|
|
for line in split(s:SystemError(s:shellesc(exec))[0], "\n")
|
|
|
|
|
for item in s:ToolParse(a:state, line)
|
|
|
|
|
if len(get(item, 'filename', '')) && item.filename != filename
|
|
|
|
|
call add(cmd, 'tabedit ' . s:fnameescape(item.filename))
|
|
|
|
|
for i in reverse(range(len(get(item.context, 'diff', []))))
|
|
|
|
|
call add(cmd, (i ? 'rightbelow' : 'leftabove') . ' vert Gdiffsplit! ' . s:fnameescape(item.context.diff[i].filename))
|
|
|
|
|
endfor
|
|
|
|
|
call add(cmd, 'wincmd =')
|
|
|
|
|
let filename = item.filename
|
|
|
|
|
endif
|
|
|
|
|
endfor
|
|
|
|
|
endfor
|
|
|
|
|
return join(cmd, '|') . (empty(cmd) ? '' : '|' . tabnr . 'tabnext')
|
|
|
|
|
endif
|
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
|
|
function! s:MergetoolSubcommand(line1, line2, range, bang, mods, args) abort
|
|
|
|
|
let dir = s:Dir()
|
|
|
|
|
let i = 0
|
|
|
|
|
let argv = copy(a:args)
|
|
|
|
|
let prompt = 1
|
|
|
|
|
let title = ':Git mergetool' . (len(a:args) ? ' ' . s:fnameescape(a:args) : '')
|
|
|
|
|
let cmd = ['diff', '--diff-filter=U']
|
|
|
|
|
let state = {'name_only': 0}
|
|
|
|
|
let state.diff = [{'prefix': ':2:', 'module': ':2:'}, {'prefix': ':3:', 'module': ':3:'}, {'prefix': ':(top)'}]
|
|
|
|
|
call map(state.diff, 'extend(v:val, {"filename": fugitive#Find(v:val.prefix, dir)})')
|
|
|
|
|
return s:ToolStream(dir, a:line1, a:line2, a:range, a:bang, a:mods, ['--diff-filter=U'] + a:args, state, title)
|
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
|
|
function! s:DifftoolSubcommand(line1, line2, range, bang, mods, args) abort
|
|
|
|
|
let dir = s:Dir()
|
|
|
|
|
let i = 0
|
|
|
|
|
let argv = copy(a:args)
|
|
|
|
|
let commits = []
|
|
|
|
|
let cached = 0
|
|
|
|
|
let reverse = 1
|
|
|
|
|
let prompt = 1
|
|
|
|
|
let state = {'name_only': 0}
|
|
|
|
|
let merge_base_against = {}
|
|
|
|
|
let dash = (index(argv, '--') > i ? ['--'] : [])
|
|
|
|
|
while i < len(argv)
|
|
|
|
|
let match = matchlist(argv[i], '^\(-[a-zABDFH-KN-RT-Z]\)\ze\(.*\)')
|
|
|
|
|
if len(match) && len(match[2])
|
|
|
|
|
call insert(argv, match[1])
|
|
|
|
|
let argv[i+1] = '-' . match[2]
|
|
|
|
|
continue
|
|
|
|
|
endif
|
|
|
|
|
let arg = argv[i]
|
|
|
|
|
if arg ==# '--cached'
|
|
|
|
|
let cached = 1
|
|
|
|
|
elseif arg ==# '-R'
|
|
|
|
|
let reverse = 1
|
|
|
|
|
elseif arg ==# '--name-only'
|
|
|
|
|
let state.name_only = 1
|
|
|
|
|
let argv[0] = '--name-status'
|
|
|
|
|
elseif arg ==# '--'
|
|
|
|
|
break
|
|
|
|
|
elseif arg !~# '^-\|^\.\.\=\%(/\|$\)'
|
|
|
|
|
let parsed = s:LinesError(['rev-parse', '--revs-only', substitute(arg, ':.*', '', '')] + dash)[0]
|
|
|
|
|
call map(parsed, '{"uninteresting": v:val =~# "^\\^", "prefix": substitute(v:val, "^\\^", "", "") . ":"}')
|
|
|
|
|
let merge_base_against = {}
|
|
|
|
|
if arg =~# '\.\.\.' && len(parsed) > 2
|
|
|
|
|
let display = map(split(arg, '\.\.\.', 1), 'empty(v:val) ? "@" : v:val')
|
|
|
|
|
if len(display) == 2
|
|
|
|
|
let parsed[0].module = display[1] . ':'
|
|
|
|
|
let parsed[1].module = display[0] . ':'
|
|
|
|
|
endif
|
|
|
|
|
let parsed[2].module = arg . ':'
|
|
|
|
|
if empty(commits)
|
|
|
|
|
let merge_base_against = parsed[0]
|
|
|
|
|
let parsed = [parsed[2]]
|
|
|
|
|
endif
|
|
|
|
|
elseif arg =~# '\.\.' && len(parsed) == 2
|
|
|
|
|
let display = map(split(arg, '\.\.', 1), 'empty(v:val) ? "@" : v:val')
|
|
|
|
|
if len(display) == 2
|
|
|
|
|
let parsed[0].module = display[0] . ':'
|
|
|
|
|
let parsed[1].module = display[1] . ':'
|
|
|
|
|
endif
|
|
|
|
|
elseif len(parsed) == 1
|
|
|
|
|
let parsed[0].module = arg . ':'
|
|
|
|
|
endif
|
|
|
|
|
call extend(commits, parsed)
|
|
|
|
|
endif
|
|
|
|
|
let i += 1
|
|
|
|
|
endwhile
|
|
|
|
|
let title = ':Git difftool' . (len(a:args) ? ' ' . s:fnameescape(a:args) : '')
|
|
|
|
|
if len(merge_base_against)
|
|
|
|
|
call add(commits, merge_base_against)
|
|
|
|
|
endif
|
|
|
|
|
let commits = filter(copy(commits), 'v:val.uninteresting') + filter(commits, '!v:val.uninteresting')
|
|
|
|
|
if cached
|
|
|
|
|
if empty(commits)
|
|
|
|
|
call add(commits, {'prefix': '@:', 'module': '@:'})
|
|
|
|
|
endif
|
|
|
|
|
call add(commits, {'prefix': ':0:', 'module': ':0:'})
|
|
|
|
|
elseif len(commits) < 2
|
|
|
|
|
call add(commits, {'prefix': ':(top)'})
|
|
|
|
|
if len(commits) < 2
|
|
|
|
|
call insert(commits, {'prefix': ':0:', 'module': ':0:'})
|
|
|
|
|
endif
|
|
|
|
|
endif
|
|
|
|
|
if reverse
|
|
|
|
|
let commits = [commits[-1]] + repeat([commits[0]], len(commits) - 1)
|
|
|
|
|
call reverse(commits)
|
|
|
|
|
endif
|
|
|
|
|
if len(commits) > 2
|
|
|
|
|
call add(commits, remove(commits, 0))
|
|
|
|
|
endif
|
|
|
|
|
call map(commits, 'extend(v:val, {"filename": fugitive#Find(v:val.prefix, dir)})')
|
|
|
|
|
let state.diff = commits
|
|
|
|
|
return s:ToolStream(dir, a:line1, a:line2, a:range, a:bang, a:mods, argv, state, title)
|
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
|
|
" Section: :Ggrep, :Glog
|
|
|
|
|
|
|
|
|
|
if !exists('g:fugitive_summary_format')
|
|
|
|
|
@@ -3846,11 +4094,7 @@ function! s:GrepSubcommand(line1, line2, range, bang, mods, args) abort
|
|
|
|
|
call add(cmd, '--column')
|
|
|
|
|
endif
|
|
|
|
|
let tree = s:Tree(dir)
|
|
|
|
|
if type(a:args) == type([])
|
|
|
|
|
let [args, after] = [a:args, '']
|
|
|
|
|
else
|
|
|
|
|
let [args, after] = s:SplitExpandChain(a:args, tree)
|
|
|
|
|
endif
|
|
|
|
|
let args = a:args
|
|
|
|
|
let prefix = FugitiveVimPath(s:HasOpt(args, '--cached') || empty(tree) ? 'fugitive://' . dir . '//0/' : tree . '/')
|
|
|
|
|
let name_only = s:HasOpt(args, '-l', '--files-with-matches', '--name-only', '-L', '--files-without-match')
|
|
|
|
|
let title = [listnr < 0 ? ':Ggrep' : ':Glgrep'] + args
|
|
|
|
|
@@ -3873,9 +4117,9 @@ function! s:GrepSubcommand(line1, line2, range, bang, mods, args) abort
|
|
|
|
|
redraw
|
|
|
|
|
endif
|
|
|
|
|
if !a:bang && !empty(list)
|
|
|
|
|
return (listnr < 0 ? 'c' : 'l').'first' . after
|
|
|
|
|
return (listnr < 0 ? 'c' : 'l').'first'
|
|
|
|
|
else
|
|
|
|
|
return after[1:-1]
|
|
|
|
|
return ''
|
|
|
|
|
endif
|
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
|
|
@@ -4170,13 +4414,7 @@ function! s:OpenExec(cmd, mods, args, ...) abort
|
|
|
|
|
let dir = a:0 ? s:Dir(a:1) : s:Dir()
|
|
|
|
|
let temp = tempname()
|
|
|
|
|
let columns = get(g:, 'fugitive_columns', 80)
|
|
|
|
|
if columns <= 0
|
|
|
|
|
let env = ''
|
|
|
|
|
elseif s:winshell()
|
|
|
|
|
let env = 'set COLUMNS=' . columns . '& '
|
|
|
|
|
else
|
|
|
|
|
let env = 'env COLUMNS=' . columns . ' '
|
|
|
|
|
endif
|
|
|
|
|
let env = s:BuildEnvPrefix({'COLUMNS': columns})
|
|
|
|
|
silent! execute '!' . escape(env . s:UserCommand(dir, ['--no-pager'] + a:args), '!#%') .
|
|
|
|
|
\ (&shell =~# 'csh' ? ' >& ' . temp : ' > ' . temp . ' 2>&1')
|
|
|
|
|
redraw!
|
|
|
|
|
@@ -5472,7 +5710,12 @@ function! fugitive#BrowseCommand(line1, count, range, bang, mods, arg, args) abo
|
|
|
|
|
endif
|
|
|
|
|
let i = 0
|
|
|
|
|
while commit =~# '^ref: ' && i < 10
|
|
|
|
|
let commit = readfile(cdir . '/' . commit[5:-1], '', 1)[0]
|
|
|
|
|
let ref_file = cdir . '/' . commit[5:-1]
|
|
|
|
|
if getfsize(ref_file) > 0
|
|
|
|
|
let commit = readfile(ref_file, '', 1)[0]
|
|
|
|
|
else
|
|
|
|
|
let commit = fugitive#RevParse(commit[5:-1], dir)
|
|
|
|
|
endif
|
|
|
|
|
let i -= 1
|
|
|
|
|
endwhile
|
|
|
|
|
endif
|
|
|
|
|
@@ -5694,6 +5937,7 @@ function! fugitive#MapJumps(...) abort
|
|
|
|
|
|
|
|
|
|
nnoremap <buffer> cm<Space> :Git merge<Space>
|
|
|
|
|
nnoremap <buffer> cm<CR> :Git merge<CR>
|
|
|
|
|
nnoremap <buffer> cmt :Git mergetool
|
|
|
|
|
nnoremap <buffer> <silent> cm? :help fugitive_cm<CR>
|
|
|
|
|
|
|
|
|
|
nnoremap <buffer> cz<Space> :Git stash<Space>
|
|
|
|
|
|