diff --git a/plug.vim b/plug.vim index f479fba9..de5ae1fc 100644 --- a/plug.vim +++ b/plug.vim @@ -68,6 +68,7 @@ let s:mac_gui = has('gui_macvim') && has('gui_running') let s:is_win = has('win32') let s:nvim = has('nvim-0.2') || (has('nvim') && exists('*jobwait') && !s:is_win) let s:vim8 = has('patch-8.0.0039') && exists('*job_start') +let s:shell_error = 0 if s:is_win && &shellslash set noshellslash let s:me = resolve(expand(':p')) @@ -170,7 +171,7 @@ function! s:git_origin_branch(spec) " The command may not return the name of a branch in detached HEAD state let result = s:lines(s:system('git symbolic-ref --short HEAD', a:spec.dir)) - return v:shell_error ? '' : result[-1] + return s:shell_error ? '' : result[-1] endfunction if s:is_win @@ -1097,7 +1098,7 @@ function! s:checkout(spec) let credential_helper = s:disable_credential_helper() ? '-c credential.helper= ' : '' let output = s:system( \ 'git '.credential_helper.'fetch --depth 999999 && git checkout '.plug#shellescape(sha).' --', a:spec.dir) - let error = v:shell_error + let error = s:shell_error endif return [output, error] endfunction @@ -1303,7 +1304,7 @@ function! s:update_finish() let tag = spec.tag if tag =~ '\*' let tags = s:lines(s:system('git tag --list '.plug#shellescape(tag).' --sort -version:refname 2>&1', spec.dir)) - if !v:shell_error && !empty(tags) + if !s:shell_error && !empty(tags) let tag = tags[0] call s:log4(name, printf('Latest tag for %s -> %s', spec.tag, tag)) call append(3, '') @@ -1311,7 +1312,7 @@ function! s:update_finish() endif call s:log4(name, 'Checking out '.tag) let out = s:system('git checkout -q '.plug#shellescape(tag).' -- 2>&1', spec.dir) - let error = v:shell_error + let error = s:shell_error endif if !error && filereadable(spec.dir.'/.gitmodules') && \ (s:update.force || has_key(s:update.new, name) || s:is_updated(spec.dir)) @@ -1319,7 +1320,7 @@ function! s:update_finish() let out .= s:bang('git submodule update --init --recursive'.s:submodule_opt.' 2>&1', spec.dir) let error = v:shell_error endif - let msg = s:format_message(v:shell_error ? 'x': '-', name, out) + let msg = s:format_message(error ? 'x': '-', name, out) if error call add(s:update.errors, name) call s:regress_bar() @@ -1480,7 +1481,7 @@ function! s:spawn(name, spec, queue, opts) endif else let job.lines = s:lines(call('s:system', has_key(a:opts, 'dir') ? [argv, a:opts.dir] : [argv])) - let job.error = v:shell_error != 0 + let job.error = s:shell_error != 0 let job.running = 0 endif endfunction @@ -2334,6 +2335,22 @@ function! s:with_cd(cmd, dir, ...) return printf('%s %s %s %s', cd, plug#shellescape(a:dir, {'script': script, 'shell': &shell}), sep, a:cmd) endfunction +function! s:system_job(cmd) abort + let tmp = tempname() + let job = job_start(['/bin/sh', '-c', a:cmd], { + \ 'out_io': 'file', + \ 'out_name': tmp, + \ 'err_io': 'out', + \}) + while job_status(job) ==# 'run' + sleep 1m + endwhile + let s:shell_error = job_info(job).exitval + let result = filereadable(tmp) ? join(readfile(tmp, 'b'), "\n") : '' + silent! call delete(tmp) + return result +endfunction + function! s:system(cmd, ...) let batchfile = '' try @@ -2343,7 +2360,9 @@ function! s:system(cmd, ...) " 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) + let ret = system(a:cmd) + let s:shell_error = v:shell_error + return ret endif let cmd = join(map(copy(a:cmd), 'plug#shellescape(v:val, {"shell": &shell, "script": 0})')) if s:is_powershell(&shell) @@ -2358,7 +2377,12 @@ function! s:system(cmd, ...) if s:is_win && type(a:cmd) != s:TYPE.list let [batchfile, cmd] = s:batchfile(cmd) endif - return system(cmd) + if s:vim8 && has('gui_running') && !s:is_win + return s:system_job(cmd) + endif + let ret = system(cmd) + let s:shell_error = v:shell_error + return ret finally let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd] if s:is_win && filereadable(batchfile) @@ -2369,7 +2393,7 @@ endfunction function! s:system_chomp(...) let ret = call('s:system', a:000) - return v:shell_error ? '' : substitute(ret, '\n$', '', '') + return s:shell_error ? '' : substitute(ret, '\n$', '', '') endfunction function! s:git_validate(spec, check_branch) @@ -2412,7 +2436,7 @@ function! s:git_validate(spec, check_branch) \ 'git', 'rev-list', '--count', '--left-right', \ printf('HEAD...origin/%s', origin_branch) \ ], a:spec.dir)), '\t') - if v:shell_error || len(ahead_behind) != 2 + if s:shell_error || len(ahead_behind) != 2 let err = "Failed to compare with the origin. The default branch might have changed.\nPlugClean required." else let [ahead, behind] = ahead_behind @@ -2562,7 +2586,7 @@ function! s:upgrade() try let out = s:system(['git', 'clone', '--depth', '1', s:plug_src, tmp]) - if v:shell_error + if s:shell_error return s:err('Error upgrading vim-plug: '. out) endif