s:system supports list type for command
Objective is to reduce batchfiles on Windows. List type gives more flexibility on s:system() on how to pass the shell command to the builtin system(). If system() supports list type for command and there is no working directory, run it directly on system(). Targets Neovim only. Else, convert the list to an escaped command so that the user's shell can execute it.
This commit is contained in:
parent
c3b6b7c297
commit
eb00506f36
64
plug.vim
64
plug.vim
|
@ -372,7 +372,7 @@ endfunction
|
||||||
|
|
||||||
function! s:git_version_requirement(...)
|
function! s:git_version_requirement(...)
|
||||||
if !exists('s:git_version')
|
if !exists('s:git_version')
|
||||||
let s:git_version = map(split(split(s:system('git --version'))[2], '\.'), 'str2nr(v:val)')
|
let s:git_version = map(split(split(s:system(['git', '--version']))[2], '\.'), 'str2nr(v:val)')
|
||||||
endif
|
endif
|
||||||
return s:version_requirement(s:git_version, a:000)
|
return s:version_requirement(s:git_version, a:000)
|
||||||
endfunction
|
endfunction
|
||||||
|
@ -898,7 +898,7 @@ function! s:regress_bar()
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:is_updated(dir)
|
function! s:is_updated(dir)
|
||||||
return !empty(s:system_chomp('git log --pretty=format:"%h" "HEAD...HEAD@{1}"', a:dir))
|
return !empty(s:system_chomp(['git', 'log', '--pretty=format:%h', 'HEAD...HEAD@{1}'], a:dir))
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:do(pull, force, todo)
|
function! s:do(pull, force, todo)
|
||||||
|
@ -961,7 +961,7 @@ endfunction
|
||||||
|
|
||||||
function! s:checkout(spec)
|
function! s:checkout(spec)
|
||||||
let sha = a:spec.commit
|
let sha = a:spec.commit
|
||||||
let output = s:system('git rev-parse HEAD', a:spec.dir)
|
let output = s:system(['git', 'rev-parse', 'HEAD'], a:spec.dir)
|
||||||
if !v:shell_error && !s:hash_match(sha, s:lines(output)[0])
|
if !v:shell_error && !s:hash_match(sha, s:lines(output)[0])
|
||||||
let output = s:system(
|
let output = s:system(
|
||||||
\ 'git fetch --depth 999999 && git checkout '.plug#shellescape(sha).' --', a:spec.dir)
|
\ 'git fetch --depth 999999 && git checkout '.plug#shellescape(sha).' --', a:spec.dir)
|
||||||
|
@ -2055,6 +2055,19 @@ function! s:shellesc_sh(arg)
|
||||||
return "'".substitute(a:arg, "'", "'\\\\''", 'g')."'"
|
return "'".substitute(a:arg, "'", "'\\\\''", 'g')."'"
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
" Escape the shell argument based on the shell.
|
||||||
|
" Vim and Neovim's shellescape() are insufficient.
|
||||||
|
" 1. shellslash determines whether to use single/double quotes.
|
||||||
|
" Double-quote escaping is fragile for cmd.exe.
|
||||||
|
" 2. It does not work for powershell.
|
||||||
|
" 3. It does not work for *sh shells if the command is executed
|
||||||
|
" via cmd.exe (ie. cmd.exe /c sh -c command command_args)
|
||||||
|
" 4. It does not support batchfile syntax.
|
||||||
|
"
|
||||||
|
" Accepts an optional dictionary with the following keys:
|
||||||
|
" - shell: same as Vim/Neovim 'shell' option.
|
||||||
|
" If unset, fallback to 'cmd.exe' on Windows or 'sh'.
|
||||||
|
" - script: If truthy and shell is cmd.exe, escape for batchfile syntax.
|
||||||
function! plug#shellescape(arg, ...)
|
function! plug#shellescape(arg, ...)
|
||||||
let opts = a:0 > 0 && type(a:1) == s:TYPE.dict ? a:1 : {}
|
let opts = a:0 > 0 && type(a:1) == s:TYPE.dict ? a:1 : {}
|
||||||
let shell = get(opts, 'shell', s:is_win ? 'cmd.exe' : 'sh')
|
let shell = get(opts, 'shell', s:is_win ? 'cmd.exe' : 'sh')
|
||||||
|
@ -2105,8 +2118,24 @@ function! s:system(cmd, ...)
|
||||||
let batchfile = ''
|
let batchfile = ''
|
||||||
try
|
try
|
||||||
let [sh, shellcmdflag, shrd] = s:chsh(1)
|
let [sh, shellcmdflag, shrd] = s:chsh(1)
|
||||||
let cmd = a:0 > 0 ? s:with_cd(a:cmd, a:1) : a:cmd
|
if type(a:cmd) == s:TYPE.list
|
||||||
if s:is_win
|
" Neovim's system() supports list argument to bypass the shell
|
||||||
|
" but it cannot set the working directory for the command.
|
||||||
|
" Assume that the command does not rely on the shell.
|
||||||
|
if has('nvim') && a:0 == 0
|
||||||
|
return system(a:cmd)
|
||||||
|
endif
|
||||||
|
let cmd = join(map(copy(a:cmd), 'plug#shellescape(v:val, {"shell": &shell, "script": 0})'))
|
||||||
|
if &shell =~# 'powershell\.exe'
|
||||||
|
let cmd = '& ' . cmd
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
let cmd = a:cmd
|
||||||
|
endif
|
||||||
|
if a:0 > 0
|
||||||
|
let cmd = s:with_cd(cmd, a:1, type(a:cmd) != s:TYPE.list)
|
||||||
|
endif
|
||||||
|
if s:is_win && type(a:cmd) != s:TYPE.list
|
||||||
let [batchfile, cmd] = s:batchfile(cmd)
|
let [batchfile, cmd] = s:batchfile(cmd)
|
||||||
endif
|
endif
|
||||||
return system(cmd)
|
return system(cmd)
|
||||||
|
@ -2159,9 +2188,10 @@ function! s:git_validate(spec, check_branch)
|
||||||
\ branch, a:spec.branch)
|
\ branch, a:spec.branch)
|
||||||
endif
|
endif
|
||||||
if empty(err)
|
if empty(err)
|
||||||
let [ahead, behind] = split(s:lastline(s:system(printf(
|
let [ahead, behind] = split(s:lastline(s:system([
|
||||||
\ 'git rev-list --count --left-right HEAD...origin/%s',
|
\ 'git', 'rev-list', '--count', '--left-right',
|
||||||
\ a:spec.branch), a:spec.dir)), '\t')
|
\ printf('HEAD...origin/%s', a:spec.branch)
|
||||||
|
\ ], a:spec.dir)), '\t')
|
||||||
if !v:shell_error && ahead
|
if !v:shell_error && ahead
|
||||||
if behind
|
if behind
|
||||||
" Only mention PlugClean if diverged, otherwise it's likely to be
|
" Only mention PlugClean if diverged, otherwise it's likely to be
|
||||||
|
@ -2185,7 +2215,9 @@ endfunction
|
||||||
|
|
||||||
function! s:rm_rf(dir)
|
function! s:rm_rf(dir)
|
||||||
if isdirectory(a:dir)
|
if isdirectory(a:dir)
|
||||||
call s:system((s:is_win ? 'rmdir /S /Q ' : 'rm -rf ') . plug#shellescape(a:dir))
|
call s:system(s:is_win
|
||||||
|
\ ? 'rmdir /S /Q '.plug#shellescape(a:dir)
|
||||||
|
\ : ['rm', '-rf', a:dir])
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
@ -2294,7 +2326,7 @@ function! s:upgrade()
|
||||||
let new = tmp . '/plug.vim'
|
let new = tmp . '/plug.vim'
|
||||||
|
|
||||||
try
|
try
|
||||||
let out = s:system(printf('git clone --depth 1 %s %s', plug#shellescape(s:plug_src), plug#shellescape(tmp)))
|
let out = s:system(['git', 'clone', '--depth', '1', s:plug_src, tmp])
|
||||||
if v:shell_error
|
if v:shell_error
|
||||||
return s:err('Error upgrading vim-plug: '. out)
|
return s:err('Error upgrading vim-plug: '. out)
|
||||||
endif
|
endif
|
||||||
|
@ -2489,11 +2521,13 @@ function! s:diff()
|
||||||
call s:append_ul(2, origin ? 'Pending updates:' : 'Last update:')
|
call s:append_ul(2, origin ? 'Pending updates:' : 'Last update:')
|
||||||
for [k, v] in plugs
|
for [k, v] in plugs
|
||||||
let range = origin ? '..origin/'.v.branch : 'HEAD@{1}..'
|
let range = origin ? '..origin/'.v.branch : 'HEAD@{1}..'
|
||||||
let cmd = 'git log --graph --color=never '
|
let cmd = ['git', 'log', '--graph', '--color=never']
|
||||||
\ . (s:git_version_requirement(2, 10, 0) ? '--no-show-signature ' : '')
|
if s:git_version_requirement(2, 10, 0)
|
||||||
\ . join(map(['--pretty=format:%x01%h%x01%d%x01%s%x01%cr', range], 'plug#shellescape(v:val)'))
|
call add(cmd, '--no-show-signature')
|
||||||
|
endif
|
||||||
|
call extend(cmd, ['--pretty=format:%x01%h%x01%d%x01%s%x01%cr', range])
|
||||||
if has_key(v, 'rtp')
|
if has_key(v, 'rtp')
|
||||||
let cmd .= ' -- '.plug#shellescape(v.rtp)
|
call extend(cmd, ['--', v.rtp])
|
||||||
endif
|
endif
|
||||||
let diff = s:system_chomp(cmd, v.dir)
|
let diff = s:system_chomp(cmd, v.dir)
|
||||||
if !empty(diff)
|
if !empty(diff)
|
||||||
|
@ -2561,7 +2595,7 @@ function! s:snapshot(force, ...) abort
|
||||||
let names = sort(keys(filter(copy(g:plugs),
|
let names = sort(keys(filter(copy(g:plugs),
|
||||||
\'has_key(v:val, "uri") && !has_key(v:val, "commit") && isdirectory(v:val.dir)')))
|
\'has_key(v:val, "uri") && !has_key(v:val, "commit") && isdirectory(v:val.dir)')))
|
||||||
for name in reverse(names)
|
for name in reverse(names)
|
||||||
let sha = s:system_chomp('git rev-parse --short HEAD', g:plugs[name].dir)
|
let sha = s:system_chomp(['git', 'rev-parse', '--short', 'HEAD'], g:plugs[name].dir)
|
||||||
if !empty(sha)
|
if !empty(sha)
|
||||||
call append(anchor, printf("silent! let g:plugs['%s'].commit = '%s'", name, sha))
|
call append(anchor, printf("silent! let g:plugs['%s'].commit = '%s'", name, sha))
|
||||||
redraw
|
redraw
|
||||||
|
|
Loading…
Reference in New Issue
Block a user