Skip to content

use job for s:system() on vim8 #594

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 61 additions & 21 deletions plug.vim
Original file line number Diff line number Diff line change
Expand Up @@ -865,8 +865,8 @@ endfunction

function! s:checkout(spec)
let sha = a:spec.commit
let output = s:system('git rev-parse HEAD', a:spec.dir)
if !v:shell_error && !s:hash_match(sha, s:lines(output)[0])
let [output, shellerror] = s:system_with_error('git rev-parse HEAD', a:spec.dir)
if !shellerror && !s:hash_match(sha, s:lines(output)[0])
let output = s:system(
\ 'git fetch --depth 999999 && git checkout '.s:esc(sha), a:spec.dir)
endif
Expand Down Expand Up @@ -1053,14 +1053,16 @@ function! s:update_finish()
if !pos
continue
endif
let shellerror = 0
if has_key(spec, 'commit')
call s:log4(name, 'Checking out '.spec.commit)
let out = s:checkout(spec)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s:checkout can fail. It used to set v:shell_error which is tested at line 1079, but now we have to update shellerror. The same goes for line 1072 and 1076.

elseif has_key(spec, 'tag')
let tag = spec.tag
if tag =~ '\*'
let tags = s:lines(s:system('git tag --list '.string(tag).' --sort -version:refname 2>&1', spec.dir))
if !v:shell_error && !empty(tags)
let [output, shellerror] = s:system_with_error('git tag --list '.string(tag).' --sort -version:refname 2>&1', spec.dir)
let tags = s:lines(output)
if !shellerror && !empty(tags)
let tag = tags[0]
call s:log4(name, printf('Latest tag for %s -> %s', spec.tag, tag))
call append(3, '')
Expand All @@ -1074,13 +1076,13 @@ function! s:update_finish()
let out = s:system('git checkout -q '.branch.' 2>&1'
\. (has_key(s:update.new, name) ? '' : ('&& git merge --ff-only origin/'.branch.' 2>&1')), spec.dir)
endif
if !v:shell_error && filereadable(spec.dir.'/.gitmodules') &&
if !shellerror && filereadable(spec.dir.'/.gitmodules') &&
\ (s:update.force || has_key(s:update.new, name) || s:is_updated(spec.dir))
call s:log4(name, 'Updating submodules. This may take a while.')
let out .= s:bang('git submodule update --init --recursive 2>&1', spec.dir)
endif
let msg = s:format_message(v:shell_error ? 'x': '-', name, out)
if v:shell_error
let msg = s:format_message(shellerror ? 'x': '-', name, out)
if shellerror
call add(s:update.errors, name)
call s:regress_bar()
silent execute pos 'd _'
Expand Down Expand Up @@ -1203,8 +1205,9 @@ function! s:spawn(name, cmd, opts)
endif
else
let params = has_key(a:opts, 'dir') ? [a:cmd, a:opts.dir] : [a:cmd]
let job.lines = s:lines(call('s:system', params))
let job.error = v:shell_error != 0
let [output, shellerror] = call('s:system_with_error', params)
let job.lines = s:lines(output)
let job.error = shellerror != 0
let job.running = 0
endif
endfunction
Expand Down Expand Up @@ -1979,34 +1982,70 @@ endfunction

function! s:system(cmd, ...)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s:system can be simplified to s:system_with_error(...)[0].

try
let maxfuncdepth = &maxfuncdepth
set maxfuncdepth=99999
let [sh, shrd] = s:chsh(1)
let cmd = a:0 > 0 ? s:with_cd(a:cmd, a:1) : a:cmd
if s:vim8
let out = ''
let job = job_start([&shell, &shellcmdflag, cmd], {'out_cb': {ch,msg->[execute("let out .= msg"), out]}, 'out_mode': 'raw'})
while job_status(job) == 'run'
sleep 10m
endwhile
return out
endif
return system(s:is_win ? '('.cmd.')' : cmd)
finally
let [&shell, &shellredir] = [sh, shrd]
let [&shell, &shellredir, &maxfuncdepth] = [sh, shrd, maxfuncdepth]
endtry
endfunction

function! s:system_with_error(cmd, ...)
try
let maxfuncdepth = &maxfuncdepth
set maxfuncdepth=99999
let [sh, shrd] = s:chsh(1)
let cmd = a:0 > 0 ? s:with_cd(a:cmd, a:1) : a:cmd
if s:vim8
let [out, exit_code] = ['', 0]
let job = job_start([&shell, &shellcmdflag, cmd], {
\ 'out_cb': {ch,msg->[execute("let out .= msg"), out]},
\ 'err_cb': {ch,msg->[execute("let out .= msg"), out]},
\ 'exit_cb': {job,code->[execute("let exit_code=code"), exit_code]},
\ 'out_mode': 'raw'})
while job_status(job) == 'run'
sleep 10m
endwhile
return [out, exit_code]
endif
return [system(s:is_win ? '('.cmd.')' : cmd), v:shell_error]
finally
let [&shell, &shellredir, &maxfuncdepth] = [sh, shrd, maxfuncdepth]
endtry
endfunction

function! s:system_chomp(...)
let ret = call('s:system', a:000)
return v:shell_error ? '' : substitute(ret, '\n$', '', '')
let [ret, shellerror] = call('s:system_with_error', a:000)
return shellerror ? '' : substitute(ret, '\n$', '', '')
endfunction

function! s:git_validate(spec, check_branch)
let err = ''
if isdirectory(a:spec.dir)
let result = s:lines(s:system('git rev-parse --abbrev-ref HEAD 2>&1 && git config -f .git/config remote.origin.url', a:spec.dir))
let [output, shellerror] = s:system_with_error('git rev-parse --abbrev-ref HEAD 2>&1 && git config -f .git/config remote.origin.url', a:spec.dir)
let result = s:lines(output)
let remote = result[-1]
if v:shell_error
if shellerror
let err = join([remote, 'PlugClean required.'], "\n")
elseif !s:compare_git_uri(remote, a:spec.uri)
let err = join(['Invalid URI: '.remote,
\ 'Expected: '.a:spec.uri,
\ 'PlugClean required.'], "\n")
elseif a:check_branch && has_key(a:spec, 'commit')
let result = s:lines(s:system('git rev-parse HEAD 2>&1', a:spec.dir))
let [output, shellerror] = s:system_with_error('git rev-parse HEAD 2>&1', a:spec.dir)
let result = s:lines(output)
let sha = result[-1]
if v:shell_error
if shellerror
let err = join(add(result, 'PlugClean required.'), "\n")
elseif !s:hash_match(sha, a:spec.commit)
let err = join([printf('Invalid HEAD (expected: %s, actual: %s)',
Expand All @@ -2028,10 +2067,11 @@ function! s:git_validate(spec, check_branch)
\ branch, a:spec.branch)
endif
if empty(err)
let [ahead, behind] = split(s:lastline(s:system(printf(
let [output, shellerror] = s:system_with_error(printf(
\ 'git rev-list --count --left-right HEAD...origin/%s',
\ a:spec.branch), a:spec.dir)), '\t')
if !v:shell_error && ahead
\ a:spec.branch), a:spec.dir)
let [ahead, behind] = split(s:lastline(output), '\t')
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, this can fail if output does not have \t because of an error, right? It was my oversight.

if !shellerror && ahead
if behind
" Only mention PlugClean if diverged, otherwise it's likely to be
" pushable (and probably not that messed up).
Expand Down Expand Up @@ -2163,8 +2203,8 @@ function! s:upgrade()
let new = tmp . '/plug.vim'

try
let out = s:system(printf('git clone --depth 1 %s %s', s:plug_src, tmp))
if v:shell_error
let [out, shellerror] = s:system_with_error(printf('git clone --depth 1 %s %s', s:plug_src, tmp))
if shellerror
return s:err('Error upgrading vim-plug: '. out)
endif

Expand Down