From 0fe09643855724a5dd9ef801fea7598af1811a91 Mon Sep 17 00:00:00 2001 From: Tim Pope Date: Thu, 30 Aug 2018 16:25:06 -0400 Subject: [PATCH] Enhance fugitive#Prepare() --- autoload/fugitive.vim | 89 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 75 insertions(+), 14 deletions(-) diff --git a/autoload/fugitive.vim b/autoload/fugitive.vim index fe33314..1cc3d44 100644 --- a/autoload/fugitive.vim +++ b/autoload/fugitive.vim @@ -204,17 +204,23 @@ function! s:Tree(...) abort return FugitiveTreeForGitDir(a:0 ? a:1 : get(b:, 'git_dir', '')) endfunction -function! s:PreparePathArgs(cmd, dir) abort - if fugitive#GitVersion() !~# '^[01]\.' +function! s:PreparePathArgs(cmd, dir, literal) abort + let literal_supported = fugitive#GitVersion() !~# '^0\|^1\.[1-8]\.' + if a:literal && literal_supported call insert(a:cmd, '--literal-pathspecs') endif let split = index(a:cmd, '--') - let tree = s:Tree(a:dir) - if empty(tree) || split < 0 + if split < 0 return a:cmd endif for i in range(split + 1, len(a:cmd) - 1) - let a:cmd[i] = fugitive#Path(a:cmd[i], './', a:dir) + if type(a:cmd[i]) == type(0) + let a:cmd[i] = fugitive#Path(bufname(a:cmd[i]), './', a:dir) + elseif a:literal + let a:cmd[i] = fugitive#Path(a:cmd[i], './', a:dir) + elseif !literal_supported + let a:cmd[i] = substitute(a:cmd[i], '^:\%(/\|([^)]*)\)\=:\=', './', '') + endif endfor return a:cmd endfunction @@ -222,7 +228,7 @@ endfunction function! s:TreeChomp(...) abort let args = copy(type(a:1) == type([]) ? a:1 : a:000) let dir = a:0 > 1 && type(a:1) == type([]) ? a:2 : b:git_dir - call s:PreparePathArgs(args, dir) + call s:PreparePathArgs(args, dir, 1) let tree = s:Tree(dir) let pre = '' if empty(tree) @@ -238,15 +244,66 @@ function! s:TreeChomp(...) abort \ join(map(args, 's:shellesc(v:val)'))), '\n$', '') endfunction -function! fugitive#Prepare(cmd, ...) abort - let dir = a:0 ? a:1 : get(b:, 'git_dir', '') - let tree = s:Tree(dir) - let args = type(a:cmd) == type([]) ? join(map(s:PreparePathArgs(copy(a:cmd), dir), 's:shellesc(v:val)')) : a:cmd +let s:prepare_env = { + \ 'sequence.editor': 'GIT_SEQUENCE_EDITOR', + \ 'core.editor': 'GIT_EDITOR', + \ 'core.askpass': 'GIT_ASKPASS', + \ } +function! fugitive#Prepare(...) abort + if !a:0 + return g:fugitive_git_executable + endif + if type(a:1) ==# type([]) + let cmd = a:000[1:-1] + a:1 + else + let cmd = copy(a:000) + endif let pre = '' - if empty(tree) || (type(a:cmd) == type([]) && index(a:cmd, '--') == len(a:cmd) - 1) + let i = 0 + while i < len(cmd) + if cmd[i] =~# '^$\|[\/.]' && cmd[i] !~# '^-' + let dir = remove(cmd, 0) + elseif type(cmd[i]) ==# type(0) + let dir = getbufvar(remove(cmd, i), 'git_dir') + elseif cmd[i] ==# '-c' && len(cmd) > i + 1 + let key = matchstr(cmd[i+1], '^[^=]*') + if has_key(s:prepare_env, tolower(key)) || key !~# '\.' + let var = get(s:prepare_env, tolower(key), key) + let val = matchstr(cmd[i+1], '=\zs.*') + if s:winshell() + let pre .= 'set ' . var . '=' . s:shellesc(val) . ' & ' + else + let pre = (len(pre) ? pre : 'env ') . var . '=' . s:shellesc(val) . ' ' + endif + endif + if fugitive#GitVersion() =~# '^0\|^1\.[1-7]\.' || cmd[i+1] !~# '\.' + call remove(cmd, i, i + 1) + else + let i += 2 + endif + elseif cmd[i] =~# '^--.*pathspecs$' + let explicit_pathspec_option = 1 + if fugitive#GitVersion() =~# '^0\|^1\.[1-8]\.' + call remove(cmd, i) + else + let i += 1 + endif + elseif cmd[i] !~# '^-' + break + else + let i += 1 + endif + endwhile + if !exists('dir') + let dir = get(b:, 'git_dir', '') + endif + let tree = s:Tree(dir) + call s:PreparePathArgs(cmd, dir, !exists('explicit_pathspec_option')) + let args = join(map(copy(cmd), 's:shellesc(v:val)')) + if empty(tree) || index(cmd, '--') == len(cmd) - 1 let args = s:shellesc('--git-dir=' . dir) . ' ' . args - elseif fugitive#GitVersion() =~# '^[01]\.' - let pre = 'cd ' . s:shellesc(tree) . (s:winshell() ? ' & ' : '; ') + elseif fugitive#GitVersion() =~# '^0\|^1\.[1-8]\.' + let pre = 'cd ' . s:shellesc(tree) . (s:winshell() ? ' & ' : '; ') . pre else let args = '-C ' . s:shellesc(tree) . ' ' . args endif @@ -377,6 +434,10 @@ endfunction call s:add_methods('repo',['dir','tree','bare','route','translate','head']) +function! s:repo_prepare(...) dict abort + return call('fugitive#Prepare', [self.git_dir] + a:000) +endfunction + function! s:repo_git_command(...) dict abort let git = s:UserCommand() . ' --git-dir='.s:shellesc(self.git_dir) return git.join(map(copy(a:000),'" ".s:shellesc(v:val)'),'') @@ -401,7 +462,7 @@ function! s:repo_rev_parse(rev) dict abort return fugitive#RevParse(a:rev, self.git_dir) endfunction -call s:add_methods('repo',['git_command','git_chomp','git_chomp_in_tree','rev_parse']) +call s:add_methods('repo',['prepare','git_command','git_chomp','git_chomp_in_tree','rev_parse']) function! s:repo_superglob(base) dict abort return map(fugitive#Complete(a:base, self.git_dir), 'substitute(v:val, ''\\\(.\)'', ''\1'', "g")')