1
0

upgrade vim-plug

This commit is contained in:
valeth 2016-05-01 15:33:08 +02:00
parent afe55434c5
commit b0b6abdb5d

View File

@ -11,9 +11,13 @@
" call plug#begin('~/.vim/plugged') " call plug#begin('~/.vim/plugged')
" "
" " Make sure you use single quotes " " Make sure you use single quotes
" Plug 'junegunn/seoul256.vim' "
" " Shorthand notation; fetches https://github.com/junegunn/vim-easy-align
" Plug 'junegunn/vim-easy-align' " Plug 'junegunn/vim-easy-align'
" "
" " Any valid git URL is allowed
" Plug 'https://github.com/junegunn/vim-github-dashboard.git'
"
" " Group dependencies, vim-snippets depends on ultisnips " " Group dependencies, vim-snippets depends on ultisnips
" Plug 'SirVer/ultisnips' | Plug 'honza/vim-snippets' " Plug 'SirVer/ultisnips' | Plug 'honza/vim-snippets'
" "
@ -21,12 +25,12 @@
" Plug 'scrooloose/nerdtree', { 'on': 'NERDTreeToggle' } " Plug 'scrooloose/nerdtree', { 'on': 'NERDTreeToggle' }
" Plug 'tpope/vim-fireplace', { 'for': 'clojure' } " Plug 'tpope/vim-fireplace', { 'for': 'clojure' }
" "
" " Using git URL
" Plug 'https://github.com/junegunn/vim-github-dashboard.git'
"
" " Using a non-master branch " " Using a non-master branch
" Plug 'rdnetto/YCM-Generator', { 'branch': 'stable' } " Plug 'rdnetto/YCM-Generator', { 'branch': 'stable' }
" "
" " Using a tagged release; wildcard allowed (requires git 1.9.2 or above)
" Plug 'fatih/vim-go', { 'tag': '*' }
"
" " Plugin options " " Plugin options
" Plug 'nsf/gocode', { 'tag': 'v.20150303', 'rtp': 'vim' } " Plug 'nsf/gocode', { 'tag': 'v.20150303', 'rtp': 'vim' }
" "
@ -40,10 +44,24 @@
" call plug#end() " call plug#end()
" "
" Then reload .vimrc and :PlugInstall to install plugins. " Then reload .vimrc and :PlugInstall to install plugins.
" Visit https://github.com/junegunn/vim-plug for more information. "
" Plug options:
"
"| Option | Description |
"| ----------------------- | ------------------------------------------------ |
"| `branch`/`tag`/`commit` | Branch/tag/commit of the repository to use |
"| `rtp` | Subdirectory that contains Vim plugin |
"| `dir` | Custom directory for the plugin |
"| `as` | Use different name for the plugin |
"| `do` | Post-update hook (string or funcref) |
"| `on` | On-demand loading: Commands or `<Plug>`-mappings |
"| `for` | On-demand loading: File types |
"| `frozen` | Do not update unless explicitly specified |
"
" More information: https://github.com/junegunn/vim-plug
" "
" "
" Copyright (c) 2015 Junegunn Choi " Copyright (c) 2016 Junegunn Choi
" "
" MIT License " MIT License
" "
@ -113,9 +131,9 @@ function! plug#begin(...)
endfunction endfunction
function! s:define_commands() function! s:define_commands()
command! -nargs=+ -bar Plug call s:add(<args>) command! -nargs=+ -bar Plug call plug#(<args>)
if !executable('git') if !executable('git')
return s:err('`git` executable not found. vim-plug requires git.') return s:err('`git` executable not found. Most commands will not be available. To suppress this message, prepend `silent!` to `call plug#begin(...)`.')
endif endif
command! -nargs=* -bar -bang -complete=customlist,s:names PlugInstall call s:install(<bang>0, [<f-args>]) command! -nargs=* -bar -bang -complete=customlist,s:names PlugInstall call s:install(<bang>0, [<f-args>])
command! -nargs=* -bar -bang -complete=customlist,s:names PlugUpdate call s:update(<bang>0, [<f-args>]) command! -nargs=* -bar -bang -complete=customlist,s:names PlugUpdate call s:update(<bang>0, [<f-args>])
@ -134,12 +152,19 @@ function! s:to_s(v)
return type(a:v) == s:TYPE.string ? a:v : join(a:v, "\n") . "\n" return type(a:v) == s:TYPE.string ? a:v : join(a:v, "\n") . "\n"
endfunction endfunction
function! s:glob(from, pattern)
return s:lines(globpath(a:from, a:pattern))
endfunction
function! s:source(from, ...) function! s:source(from, ...)
let found = 0
for pattern in a:000 for pattern in a:000
for vim in s:lines(globpath(a:from, pattern)) for vim in s:glob(a:from, pattern)
execute 'source' s:esc(vim) execute 'source' s:esc(vim)
let found = 1
endfor endfor
endfor endfor
return found
endfunction endfunction
function! s:assoc(dict, key, val) function! s:assoc(dict, key, val)
@ -200,7 +225,9 @@ function! plug#end()
if has_key(plug, 'for') if has_key(plug, 'for')
let types = s:to_a(plug.for) let types = s:to_a(plug.for)
if !empty(types) if !empty(types)
augroup filetypedetect
call s:source(s:rtp(plug), 'ftdetect/**/*.vim', 'after/ftdetect/**/*.vim') call s:source(s:rtp(plug), 'ftdetect/**/*.vim', 'after/ftdetect/**/*.vim')
augroup END
endif endif
for type in types for type in types
call s:assoc(lod.ft, type, name) call s:assoc(lod.ft, type, name)
@ -233,7 +260,9 @@ function! plug#end()
call s:reorg_rtp() call s:reorg_rtp()
filetype plugin indent on filetype plugin indent on
if has('vim_starting') if has('vim_starting')
syntax enable if has('syntax') && !exists('g:syntax_on')
syntax enable
end
else else
call s:reload() call s:reload()
endif endif
@ -264,8 +293,9 @@ function! s:version_requirement(val, min)
endfunction endfunction
function! s:git_version_requirement(...) function! s:git_version_requirement(...)
let s:git_version = get(s:, 'git_version', if !exists('s:git_version')
\ map(split(split(s:system('git --version'))[-1], '\.'), 'str2nr(v:val)')) let s:git_version = map(split(split(s:system('git --version'))[-1], '\.'), 'str2nr(v:val)')
endif
return s:version_requirement(s:git_version, a:000) return s:version_requirement(s:git_version, a:000)
endfunction endfunction
@ -312,7 +342,12 @@ function! s:err(msg)
echohl ErrorMsg echohl ErrorMsg
echom '[vim-plug] '.a:msg echom '[vim-plug] '.a:msg
echohl None echohl None
return 0 endfunction
function! s:warn(cmd, msg)
echohl WarningMsg
execute a:cmd 'a:msg'
echohl None
endfunction endfunction
function! s:esc(path) function! s:esc(path)
@ -361,6 +396,10 @@ function! s:reorg_rtp()
endif endif
endfunction endfunction
function! s:doautocmd(...)
execute 'doautocmd' ((v:version > 703 || has('patch442')) ? '<nomodeline>' : '') join(a:000)
endfunction
function! plug#load(...) function! plug#load(...)
if a:0 == 0 if a:0 == 0
return s:err('Argument missing: plugin name(s) required') return s:err('Argument missing: plugin name(s) required')
@ -396,7 +435,7 @@ function! s:remove_triggers(name)
call remove(s:triggers, a:name) call remove(s:triggers, a:name)
endfunction endfunction
function! s:lod(names, types) function! s:lod(names, types, ...)
for name in a:names for name in a:names
call s:remove_triggers(name) call s:remove_triggers(name)
let s:loaded[name] = 1 let s:loaded[name] = 1
@ -408,14 +447,21 @@ function! s:lod(names, types)
for dir in a:types for dir in a:types
call s:source(rtp, dir.'/**/*.vim') call s:source(rtp, dir.'/**/*.vim')
endfor endfor
if a:0
if !s:source(rtp, a:1) && !empty(s:glob(rtp, a:2))
execute 'runtime' a:1
endif
call s:source(rtp, a:2)
endif
if exists('#User#'.name) if exists('#User#'.name)
execute 'doautocmd User' name call s:doautocmd('User', name)
endif endif
endfor endfor
endfunction endfunction
function! s:lod_ft(pat, names) function! s:lod_ft(pat, names)
call s:lod(a:names, ['plugin', 'after/plugin', 'syntax', 'after/syntax']) let syn = 'syntax/'.a:pat.'.vim'
call s:lod(a:names, ['plugin', 'after/plugin'], syn, 'after/'.syn)
execute 'autocmd! PlugLOD FileType' a:pat execute 'autocmd! PlugLOD FileType' a:pat
if exists('#filetypeplugin#FileType') if exists('#filetypeplugin#FileType')
doautocmd filetypeplugin FileType doautocmd filetypeplugin FileType
@ -443,16 +489,16 @@ function! s:lod_map(map, names, prefix)
call feedkeys(a:prefix . substitute(a:map, '^<Plug>', "\<Plug>", '') . extra) call feedkeys(a:prefix . substitute(a:map, '^<Plug>', "\<Plug>", '') . extra)
endfunction endfunction
function! s:add(repo, ...) function! plug#(repo, ...)
if a:0 > 1 if a:0 > 1
return s:err('Invalid number of arguments (1..2)') return s:err('Invalid number of arguments (1..2)')
endif endif
try try
let repo = s:trim(a:repo) let repo = s:trim(a:repo)
let name = fnamemodify(repo, ':t:s?\.git$??') let opts = a:0 == 1 ? s:parse_options(a:1) : s:base_spec
let spec = extend(s:infer_properties(name, repo), let name = get(opts, 'as', fnamemodify(repo, ':t:s?\.git$??'))
\ a:0 == 1 ? s:parse_options(a:1) : s:base_spec) let spec = extend(s:infer_properties(name, repo), opts)
if !has_key(g:plugs, name) if !has_key(g:plugs, name)
call add(g:plugs_order, name) call add(g:plugs_order, name)
endif endif
@ -531,12 +577,14 @@ function! s:syntax()
syn match plugStar /^*/ syn match plugStar /^*/
syn match plugMessage /\(^- \)\@<=.*/ syn match plugMessage /\(^- \)\@<=.*/
syn match plugName /\(^- \)\@<=[^ ]*:/ syn match plugName /\(^- \)\@<=[^ ]*:/
syn match plugSha /\%(: \)\@<=[0-9a-z]\{4,}$/ syn match plugSha /\%(: \)\@<=[0-9a-f]\{4,}$/
syn match plugTag /(tag: [^)]\+)/ syn match plugTag /(tag: [^)]\+)/
syn match plugInstall /\(^+ \)\@<=[^:]*/ syn match plugInstall /\(^+ \)\@<=[^:]*/
syn match plugUpdate /\(^* \)\@<=[^:]*/ syn match plugUpdate /\(^* \)\@<=[^:]*/
syn match plugCommit /^ [0-9a-z]\{7} .*/ contains=plugRelDate,plugSha,plugTag syn match plugCommit /^ \X*[0-9a-f]\{7} .*/ contains=plugRelDate,plugEdge,plugTag
syn match plugSha /\(^ \)\@<=[0-9a-z]\{7}/ contained syn match plugEdge /^ \X\+$/
syn match plugEdge /^ \X*/ contained nextgroup=plugSha
syn match plugSha /[0-9a-f]\{7}/ contained
syn match plugRelDate /([^)]*)$/ contained syn match plugRelDate /([^)]*)$/ contained
syn match plugNotLoaded /(not loaded)$/ syn match plugNotLoaded /(not loaded)$/
syn match plugError /^x.*/ syn match plugError /^x.*/
@ -560,6 +608,7 @@ function! s:syntax()
hi def link plugError Error hi def link plugError Error
hi def link plugRelDate Comment hi def link plugRelDate Comment
hi def link plugEdge PreProc
hi def link plugSha Identifier hi def link plugSha Identifier
hi def link plugTag Constant hi def link plugTag Constant
@ -620,32 +669,45 @@ function! s:switch_out(...)
endif endif
endfunction endfunction
function! s:prepare() function! s:finish_bindings()
nnoremap <silent> <buffer> R :call <SID>retry()<cr>
nnoremap <silent> <buffer> D :PlugDiff<cr>
nnoremap <silent> <buffer> S :PlugStatus<cr>
nnoremap <silent> <buffer> U :call <SID>status_update()<cr>
xnoremap <silent> <buffer> U :call <SID>status_update()<cr>
nnoremap <silent> <buffer> ]] :silent! call <SID>section('')<cr>
nnoremap <silent> <buffer> [[ :silent! call <SID>section('b')<cr>
endfunction
function! s:prepare(...)
if empty(getcwd())
throw 'Invalid current working directory. Cannot proceed.'
endif
call s:job_abort() call s:job_abort()
if s:switch_in() if s:switch_in()
silent %d _ normal q
else
call s:new_window()
nnoremap <silent> <buffer> q :if b:plug_preview==1<bar>pc<bar>endif<bar>bd<cr>
nnoremap <silent> <buffer> R :silent! call <SID>retry()<cr>
nnoremap <silent> <buffer> D :PlugDiff<cr>
nnoremap <silent> <buffer> S :PlugStatus<cr>
nnoremap <silent> <buffer> U :call <SID>status_update()<cr>
xnoremap <silent> <buffer> U :call <SID>status_update()<cr>
nnoremap <silent> <buffer> ]] :silent! call <SID>section('')<cr>
nnoremap <silent> <buffer> [[ :silent! call <SID>section('b')<cr>
let b:plug_preview = -1
let s:plug_tab = tabpagenr()
let s:plug_buf = winbufnr(0)
call s:assign_name()
endif endif
call s:new_window()
nnoremap <silent> <buffer> q :if b:plug_preview==1<bar>pc<bar>endif<bar>bd<cr>
if a:0 == 0
call s:finish_bindings()
endif
let b:plug_preview = -1
let s:plug_tab = tabpagenr()
let s:plug_buf = winbufnr(0)
call s:assign_name()
silent! unmap <buffer> <cr> silent! unmap <buffer> <cr>
silent! unmap <buffer> L silent! unmap <buffer> L
silent! unmap <buffer> o silent! unmap <buffer> o
silent! unmap <buffer> X silent! unmap <buffer> X
setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile nowrap cursorline modifiable setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile nowrap cursorline modifiable
setf vim-plug setf vim-plug
call s:syntax() if exists('g:syntax_on')
call s:syntax()
endif
endfunction endfunction
function! s:assign_name() function! s:assign_name()
@ -660,6 +722,38 @@ function! s:assign_name()
silent! execute 'f' fnameescape(name) silent! execute 'f' fnameescape(name)
endfunction endfunction
function! s:chsh(swap)
let prev = [&shell, &shellredir]
if !s:is_win && a:swap
set shell=sh shellredir=>%s\ 2>&1
endif
return prev
endfunction
function! s:bang(cmd, ...)
try
let [sh, shrd] = s:chsh(a:0)
" FIXME: Escaping is incomplete. We could use shellescape with eval,
" but it won't work on Windows.
let cmd = a:0 ? s:with_cd(a:cmd, a:1) : a:cmd
let g:_plug_bang = '!'.escape(cmd, '#!%')
execute "normal! :execute g:_plug_bang\<cr>\<cr>"
finally
unlet g:_plug_bang
let [&shell, &shellredir] = [sh, shrd]
endtry
return v:shell_error ? 'Exit status: ' . v:shell_error : ''
endfunction
function! s:regress_bar()
let bar = substitute(getline(2)[1:-2], '.*\zs=', 'x', '')
call s:progress_bar(2, bar, len(bar))
endfunction
function! s:is_updated(dir)
return !empty(s:system_chomp('git log --pretty=format:"%h" "HEAD...HEAD@{1}"', a:dir))
endfunction
function! s:do(pull, force, todo) function! s:do(pull, force, todo)
for [name, spec] in items(a:todo) for [name, spec] in items(a:todo)
if !isdirectory(spec.dir) if !isdirectory(spec.dir)
@ -667,24 +761,14 @@ function! s:do(pull, force, todo)
endif endif
let installed = has_key(s:update.new, name) let installed = has_key(s:update.new, name)
let updated = installed ? 0 : let updated = installed ? 0 :
\ (a:pull && index(s:update.errors, name) < 0 && !empty(s:system_chomp('git log --pretty=format:"%h" "HEAD...HEAD@{1}"', spec.dir))) \ (a:pull && index(s:update.errors, name) < 0 && s:is_updated(spec.dir))
if a:force || installed || updated if a:force || installed || updated
execute 'cd' s:esc(spec.dir) execute 'cd' s:esc(spec.dir)
call append(3, '- Post-update hook for '. name .' ... ') call append(3, '- Post-update hook for '. name .' ... ')
let error = '' let error = ''
let type = type(spec.do) let type = type(spec.do)
if type == s:TYPE.string if type == s:TYPE.string
try let error = s:bang(spec.do)
" FIXME: Escaping is incomplete. We could use shellescape with eval,
" but it won't work on Windows.
let g:_plug_do = '!'.escape(spec.do, '#!%')
execute "normal! :execute g:_plug_do\<cr>\<cr>"
finally
if v:shell_error
let error = 'Exit status: ' . v:shell_error
endif
unlet g:_plug_do
endtry
elseif type == s:TYPE.funcref elseif type == s:TYPE.funcref
try try
let status = installed ? 'installed' : (updated ? 'updated' : 'unchanged') let status = installed ? 'installed' : (updated ? 'updated' : 'unchanged')
@ -697,6 +781,10 @@ function! s:do(pull, force, todo)
endif endif
call setline(4, empty(error) ? (getline(4) . 'OK') call setline(4, empty(error) ? (getline(4) . 'OK')
\ : ('x' . getline(4)[1:] . error)) \ : ('x' . getline(4)[1:] . error))
if !empty(error)
call add(s:update.errors, name)
call s:regress_bar()
endif
cd - cd -
endif endif
endfor endfor
@ -706,32 +794,14 @@ function! s:hash_match(a, b)
return stridx(a:a, a:b) == 0 || stridx(a:b, a:a) == 0 return stridx(a:a, a:b) == 0 || stridx(a:b, a:a) == 0
endfunction endfunction
function! s:checkout(plugs) function! s:checkout(spec)
for [name, spec] in items(a:plugs) let sha = a:spec.commit
let sha = spec.commit let output = s:system('git rev-parse HEAD', a:spec.dir)
call append(3, '- Checking out '.sha[:6].' of '.name.' ... ') if !v:shell_error && !s:hash_match(sha, s:lines(output)[0])
redraw let output = s:system(
\ 'git fetch --depth 999999 && git checkout '.s:esc(sha), a:spec.dir)
let error = [] endif
let output = s:lines(s:system('git rev-parse HEAD', spec.dir)) return output
if v:shell_error
let error = output
elseif !s:hash_match(sha, output[0])
let output = s:lines(s:system(
\ 'git fetch --depth 999999 && git checkout '.sha, spec.dir))
if v:shell_error
let error = output
endif
endif
if empty(error)
call setline(4, getline(4) . 'OK')
else
call setline(4, 'x'.getline(4)[1:] . 'Error')
for line in reverse(error)
call append(4, ' '.line)
endfor
endif
endfor
endfunction endfunction
function! s:finish(pull) function! s:finish(pull)
@ -740,7 +810,7 @@ function! s:finish(pull)
let s = new_frozen > 1 ? 's' : '' let s = new_frozen > 1 ? 's' : ''
call append(3, printf('- Installed %d frozen plugin%s', new_frozen, s)) call append(3, printf('- Installed %d frozen plugin%s', new_frozen, s))
endif endif
call append(3, '- Finishing ... ') call append(3, '- Finishing ... ') | 4
redraw redraw
call plug#helptags() call plug#helptags()
call plug#end() call plug#end()
@ -755,12 +825,14 @@ function! s:finish(pull)
call add(msgs, "Press 'D' to see the updated changes.") call add(msgs, "Press 'D' to see the updated changes.")
endif endif
echo join(msgs, ' ') echo join(msgs, ' ')
call s:finish_bindings()
endfunction endfunction
function! s:retry() function! s:retry()
if empty(s:update.errors) if empty(s:update.errors)
return return
endif endif
echo
call s:update_impl(s:update.pull, s:update.force, call s:update_impl(s:update.pull, s:update.force,
\ extend(copy(s:update.errors), [s:update.threads])) \ extend(copy(s:update.errors), [s:update.threads]))
endfunction endfunction
@ -773,6 +845,16 @@ function! s:names(...)
return sort(filter(keys(g:plugs), 'stridx(v:val, a:1) == 0 && s:is_managed(v:val)')) return sort(filter(keys(g:plugs), 'stridx(v:val, a:1) == 0 && s:is_managed(v:val)'))
endfunction endfunction
function! s:check_ruby()
silent! ruby require 'thread'; VIM::command('let g:plug_ruby = 1')
if get(g:, 'plug_ruby', 0)
unlet g:plug_ruby
return 1
endif
redraw!
return s:warn('echom', 'Warning: Ruby interface is broken')
endfunction
function! s:update_impl(pull, force, args) abort function! s:update_impl(pull, force, args) abort
let args = copy(a:args) let args = copy(a:args)
let threads = (len(args) > 0 && args[-1] =~ '^[1-9][0-9]*$') ? let threads = (len(args) > 0 && args[-1] =~ '^[1-9][0-9]*$') ?
@ -783,10 +865,7 @@ function! s:update_impl(pull, force, args) abort
\ filter(managed, 'index(args, v:key) >= 0') \ filter(managed, 'index(args, v:key) >= 0')
if empty(todo) if empty(todo)
echohl WarningMsg return s:warn('echo', 'No plugin to '. (a:pull ? 'update' : 'install'))
echo 'No plugin to '. (a:pull ? 'update' : 'install') . '.'
echohl None
return
endif endif
if !s:is_win && s:git_version_requirement(2, 3) if !s:is_win && s:git_version_requirement(2, 3)
@ -808,13 +887,11 @@ function! s:update_impl(pull, force, args) abort
endif endif
if has('nvim') && !exists('*jobwait') && threads > 1 if has('nvim') && !exists('*jobwait') && threads > 1
echohl WarningMsg call s:warn('echom', '[vim-plug] Update Neovim for parallel installer')
echomsg 'vim-plug: update Neovim for parallel installer'
echohl None
endif endif
let python = (has('python') || has('python3')) && (!s:nvim || has('vim_starting')) let python = (has('python') || has('python3')) && (!s:nvim || has('vim_starting'))
let ruby = has('ruby') && !s:nvim && (v:version >= 703 || v:version == 702 && has('patch374')) && !(s:is_win && has('gui_running')) let ruby = has('ruby') && !s:nvim && (v:version >= 703 || v:version == 702 && has('patch374')) && !(s:is_win && has('gui_running')) && s:check_ruby()
let s:update = { let s:update = {
\ 'start': reltime(), \ 'start': reltime(),
@ -829,7 +906,7 @@ function! s:update_impl(pull, force, args) abort
\ 'fin': 0 \ 'fin': 0
\ } \ }
call s:prepare() call s:prepare(1)
call append(0, ['', '']) call append(0, ['', ''])
normal! 2G normal! 2G
silent! redraw silent! redraw
@ -840,7 +917,7 @@ function! s:update_impl(pull, force, args) abort
" Python version requirement (>= 2.7) " Python version requirement (>= 2.7)
if python && !has('python3') && !ruby && !s:nvim && s:update.threads > 1 if python && !has('python3') && !ruby && !s:nvim && s:update.threads > 1
redir => pyv redir => pyv
silent python import platform; print(platform.python_version()) silent python import platform; print platform.python_version()
redir END redir END
let python = s:version_requirement( let python = s:version_requirement(
\ map(split(split(pyv)[0], '\.'), 'str2nr(v:val)'), [2, 6]) \ map(split(split(pyv)[0], '\.'), 'str2nr(v:val)'), [2, 6])
@ -882,13 +959,61 @@ function! s:update_impl(pull, force, args) abort
endif endif
endfunction endfunction
function! s:log4(name, msg)
call setline(4, printf('- %s (%s)', a:msg, a:name))
redraw
endfunction
function! s:update_finish() function! s:update_finish()
if exists('s:git_terminal_prompt') if exists('s:git_terminal_prompt')
let $GIT_TERMINAL_PROMPT = s:git_terminal_prompt let $GIT_TERMINAL_PROMPT = s:git_terminal_prompt
endif endif
if s:switch_in() if s:switch_in()
call s:checkout(filter(copy(s:update.all), 'has_key(v:val, "commit")')) call append(3, '- Updating ...') | 4
call s:do(s:update.pull, s:update.force, filter(copy(s:update.all), 'has_key(v:val, "do")')) for [name, spec] in items(filter(copy(s:update.all), 'index(s:update.errors, v:key) < 0 && (s:update.force || s:update.pull || has_key(s:update.new, v:key))'))
let pos = s:logpos(name)
if !pos
continue
endif
if has_key(spec, 'commit')
call s:log4(name, 'Checking out '.spec.commit)
let out = s:checkout(spec)
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 tag = tags[0]
call s:log4(name, printf('Latest tag for %s -> %s', spec.tag, tag))
call append(3, '')
endif
endif
call s:log4(name, 'Checking out '.tag)
let out = s:system('git checkout -q '.s:esc(tag).' 2>&1', spec.dir)
else
let branch = s:esc(get(spec, 'branch', 'master'))
call s:log4(name, 'Merging origin/'.branch)
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') &&
\ (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 = printf('%s %s: %s', v:shell_error ? 'x': '-', name, s:lastline(out))
if v:shell_error
call add(s:update.errors, name)
call s:regress_bar()
execute pos 'd _'
call append(4, msg) | 4
elseif !empty(out)
call setline(pos, msg)
endif
redraw
endfor
4 d _
call s:do(s:update.pull, s:update.force, filter(copy(s:update.all), 'index(s:update.errors, v:key) < 0 && has_key(v:val, "do")'))
call s:finish(s:update.pull) call s:finish(s:update.pull)
call setline(1, 'Updated. Elapsed time: ' . split(reltimestr(reltime(s:update.start)))[0] . ' sec.') call setline(1, 'Updated. Elapsed time: ' . split(reltimestr(reltime(s:update.start)))[0] . ' sec.')
call s:switch_out('normal! gg') call s:switch_out('normal! gg')
@ -976,7 +1101,7 @@ function! s:reap(name)
endif endif
let s:update.bar .= job.error ? 'x' : '=' let s:update.bar .= job.error ? 'x' : '='
call s:log(job.error ? 'x' : '-', a:name, job.result) call s:log(job.error ? 'x' : '-', a:name, empty(job.result) ? 'OK' : job.result)
call s:bar() call s:bar()
call remove(s:jobs, a:name) call remove(s:jobs, a:name)
@ -993,12 +1118,11 @@ function! s:bar()
endfunction endfunction
function! s:logpos(name) function! s:logpos(name)
for i in range(1, line('$')) for i in range(4, line('$'))
if getline(i) =~# '^[-+x*] '.a:name.':' if getline(i) =~# '^[-+x*] '.a:name.':'
return i return i
endif endif
endfor endfor
return 0
endfunction endfunction
function! s:log(bullet, name, lines) function! s:log(bullet, name, lines)
@ -1044,17 +1168,12 @@ while 1 " Without TCO, Vim stack is bound to explode
redraw redraw
let has_tag = has_key(spec, 'tag') let has_tag = has_key(spec, 'tag')
let checkout = s:shellesc(has_tag ? spec.tag : spec.branch)
let merge = s:shellesc(has_tag ? spec.tag : 'origin/'.spec.branch)
if !new if !new
let error = s:git_validate(spec, 0) let [error, _] = s:git_validate(spec, 0)
if empty(error) if empty(error)
if pull if pull
let fetch_opt = (has_tag && !empty(globpath(spec.dir, '.git/shallow'))) ? '--depth 99999999' : '' let fetch_opt = (has_tag && !empty(globpath(spec.dir, '.git/shallow'))) ? '--depth 99999999' : ''
call s:spawn(name, call s:spawn(name, printf('git fetch %s %s 2>&1', fetch_opt, prog), { 'dir': spec.dir })
\ printf('(git fetch %s %s 2>&1 && git checkout -q %s 2>&1 && git merge --ff-only %s 2>&1 && git submodule update --init --recursive 2>&1)',
\ fetch_opt, prog, checkout, merge), { 'dir': spec.dir })
else else
let s:jobs[name] = { 'running': 0, 'result': 'Already installed', 'error': 0 } let s:jobs[name] = { 'running': 0, 'result': 'Already installed', 'error': 0 }
endif endif
@ -1063,11 +1182,10 @@ while 1 " Without TCO, Vim stack is bound to explode
endif endif
else else
call s:spawn(name, call s:spawn(name,
\ printf('git clone %s %s --recursive %s -b %s %s 2>&1', \ printf('git clone %s %s %s %s 2>&1',
\ has_tag ? '' : s:clone_opt, \ has_tag ? '' : s:clone_opt,
\ prog, \ prog,
\ s:shellesc(spec.uri), \ s:shellesc(spec.uri),
\ checkout,
\ s:shellesc(s:trim(spec.dir))), { 'new': 1 }) \ s:shellesc(s:trim(spec.dir))), { 'new': 1 })
endif endif
@ -1296,10 +1414,7 @@ class Plugin(object):
self.args = args self.args = args
self.buf_q = buf_q self.buf_q = buf_q
self.lock = lock self.lock = lock
tag = args.get('tag', 0) self.tag = args.get('tag', 0)
self.checkout = esc(tag if tag else args['branch'])
self.merge = esc(tag if tag else 'origin/' + args['branch'])
self.tag = tag
def manage(self): def manage(self):
try: try:
@ -1335,15 +1450,15 @@ class Plugin(object):
self.write(Action.INSTALL, self.name, ['Installing ...']) self.write(Action.INSTALL, self.name, ['Installing ...'])
callback = functools.partial(self.write, Action.INSTALL, self.name) callback = functools.partial(self.write, Action.INSTALL, self.name)
cmd = 'git clone {0} {1} --recursive {2} -b {3} {4} 2>&1'.format( cmd = 'git clone {0} {1} {2} {3} 2>&1'.format(
'' if self.tag else G_CLONE_OPT, G_PROGRESS, self.args['uri'], '' if self.tag else G_CLONE_OPT, G_PROGRESS, self.args['uri'],
self.checkout, esc(target)) esc(target))
com = Command(cmd, None, G_TIMEOUT, callback, clean(target)) com = Command(cmd, None, G_TIMEOUT, callback, clean(target))
result = com.execute(G_RETRIES) result = com.execute(G_RETRIES)
self.write(Action.DONE, self.name, result[-1:]) self.write(Action.DONE, self.name, result[-1:])
def repo_uri(self): def repo_uri(self):
cmd = 'git rev-parse --abbrev-ref HEAD 2>&1 && git config remote.origin.url' cmd = 'git rev-parse --abbrev-ref HEAD 2>&1 && git config -f .git/config remote.origin.url'
command = Command(cmd, self.args['dir'], G_TIMEOUT,) command = Command(cmd, self.args['dir'], G_TIMEOUT,)
result = command.execute(G_RETRIES) result = command.execute(G_RETRIES)
return result[-1] return result[-1]
@ -1363,11 +1478,7 @@ class Plugin(object):
self.write(Action.UPDATE, self.name, ['Updating ...']) self.write(Action.UPDATE, self.name, ['Updating ...'])
callback = functools.partial(self.write, Action.UPDATE, self.name) callback = functools.partial(self.write, Action.UPDATE, self.name)
fetch_opt = '--depth 99999999' if self.tag and os.path.isfile(os.path.join(self.args['dir'], '.git/shallow')) else '' fetch_opt = '--depth 99999999' if self.tag and os.path.isfile(os.path.join(self.args['dir'], '.git/shallow')) else ''
cmds = ['git fetch {0} {1}'.format(fetch_opt, G_PROGRESS), cmd = 'git fetch {0} {1} 2>&1'.format(fetch_opt, G_PROGRESS)
'git checkout -q {0}'.format(self.checkout),
'git merge --ff-only {0}'.format(self.merge),
'git submodule update --init --recursive']
cmd = ' 2>&1 && '.join(cmds)
com = Command(cmd, self.args['dir'], G_TIMEOUT, callback) com = Command(cmd, self.args['dir'], G_TIMEOUT, callback)
result = com.execute(G_RETRIES) result = com.execute(G_RETRIES)
self.write(Action.DONE, self.name, result[-1:]) self.write(Action.DONE, self.name, result[-1:])
@ -1459,7 +1570,7 @@ def main():
while not buf_q.empty() or thr.active_count() != start_cnt: while not buf_q.empty() or thr.active_count() != start_cnt:
try: try:
action, name, msg = buf_q.get(True, 0.25) action, name, msg = buf_q.get(True, 0.25)
buf.write(action, name, msg) buf.write(action, name, ['OK'] if not msg else msg)
buf_q.task_done() buf_q.task_done()
except queue.Empty: except queue.Empty:
pass pass
@ -1553,7 +1664,7 @@ function! s:update_ruby()
end end
result = result =
if type || type.nil? if type || type.nil?
["#{b} #{name}: #{result.lines.to_a.last}"] ["#{b} #{name}: #{result.lines.to_a.last || 'OK'}"]
elsif result =~ /^Interrupted|^Timeout/ elsif result =~ /^Interrupted|^Timeout/
["#{b} #{name}: #{result}"] ["#{b} #{name}: #{result}"]
else else
@ -1643,15 +1754,12 @@ function! s:update_ruby()
threads << Thread.new { threads << Thread.new {
while pair = take1.call while pair = take1.call
name = pair.first name = pair.first
dir, uri, branch, tag = pair.last.values_at *%w[dir uri branch tag] dir, uri, tag = pair.last.values_at *%w[dir uri tag]
checkout = esc(tag ? tag : branch)
merge = esc(tag ? tag : "origin/#{branch}")
subm = "git submodule update --init --recursive 2>&1"
exists = File.directory? dir exists = File.directory? dir
ok, result = ok, result =
if exists if exists
chdir = "#{cd} #{iswin ? dir : esc(dir)}" chdir = "#{cd} #{iswin ? dir : esc(dir)}"
ret, data = bt.call "#{chdir} && git rev-parse --abbrev-ref HEAD 2>&1 && git config remote.origin.url", nil, nil, nil ret, data = bt.call "#{chdir} && git rev-parse --abbrev-ref HEAD 2>&1 && git config -f .git/config remote.origin.url", nil, nil, nil
current_uri = data.lines.to_a.last current_uri = data.lines.to_a.last
if !ret if !ret
if data =~ /^Interrupted|^Timeout/ if data =~ /^Interrupted|^Timeout/
@ -1667,7 +1775,7 @@ function! s:update_ruby()
if pull if pull
log.call name, 'Updating ...', :update log.call name, 'Updating ...', :update
fetch_opt = (tag && File.exist?(File.join(dir, '.git/shallow'))) ? '--depth 99999999' : '' fetch_opt = (tag && File.exist?(File.join(dir, '.git/shallow'))) ? '--depth 99999999' : ''
bt.call "#{chdir} && git fetch #{fetch_opt} #{progress} 2>&1 && git checkout -q #{checkout} 2>&1 && git merge --ff-only #{merge} 2>&1 && #{subm}", name, :update, nil bt.call "#{chdir} && git fetch #{fetch_opt} #{progress} 2>&1", name, :update, nil
else else
[true, skip] [true, skip]
end end
@ -1675,7 +1783,7 @@ function! s:update_ruby()
else else
d = esc dir.sub(%r{[\\/]+$}, '') d = esc dir.sub(%r{[\\/]+$}, '')
log.call name, 'Installing ...', :install log.call name, 'Installing ...', :install
bt.call "git clone #{clone_opt unless tag} #{progress} --recursive #{uri} -b #{checkout} #{d} 2>&1", name, :install, proc { bt.call "git clone #{clone_opt unless tag} #{progress} #{uri} #{d} 2>&1", name, :install, proc {
FileUtils.rm_rf dir FileUtils.rm_rf dir
} }
end end
@ -1697,7 +1805,7 @@ function! s:shellesc(arg)
endfunction endfunction
function! s:glob_dir(path) function! s:glob_dir(path)
return map(filter(s:lines(globpath(a:path, '**')), 'isdirectory(v:val)'), 's:dirpath(v:val)') return map(filter(s:glob(a:path, '**'), 'isdirectory(v:val)'), 's:dirpath(v:val)')
endfunction endfunction
function! s:progress_bar(line, bar, total) function! s:progress_bar(line, bar, total)
@ -1725,10 +1833,7 @@ endfunction
function! s:system(cmd, ...) function! s:system(cmd, ...)
try try
let [sh, shrd] = [&shell, &shellredir] let [sh, shrd] = s:chsh(1)
if !s:is_win
set shell=sh shellredir=>%s\ 2>&1
endif
let cmd = a:0 > 0 ? s:with_cd(a:cmd, a:1) : a:cmd let cmd = a:0 > 0 ? s:with_cd(a:cmd, a:1) : a:cmd
return system(s:is_win ? '('.cmd.')' : cmd) return system(s:is_win ? '('.cmd.')' : cmd)
finally finally
@ -1744,7 +1849,7 @@ endfunction
function! s:git_validate(spec, check_branch) function! s:git_validate(spec, check_branch)
let err = '' let err = ''
if isdirectory(a:spec.dir) if isdirectory(a:spec.dir)
let result = s:lines(s:system('git rev-parse --abbrev-ref HEAD 2>&1 && git config remote.origin.url', 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 remote = result[-1] let remote = result[-1]
if v:shell_error if v:shell_error
let err = join([remote, 'PlugClean required.'], "\n") let err = join([remote, 'PlugClean required.'], "\n")
@ -1776,11 +1881,18 @@ function! s:git_validate(spec, check_branch)
let err = printf('Invalid branch: %s (expected: %s). Try PlugUpdate.', let err = printf('Invalid branch: %s (expected: %s). Try PlugUpdate.',
\ branch, a:spec.branch) \ branch, a:spec.branch)
endif endif
if empty(err)
let commits = len(s:lines(s:system(printf('git rev-list origin/%s..HEAD', a:spec.branch), a:spec.dir)))
if !v:shell_error && commits
let err = join([printf('Diverged from origin/%s by %d commit(s).', a:spec.branch, commits),
\ 'Reinstall after PlugClean.'], "\n")
endif
endif
endif endif
else else
let err = 'Not found' let err = 'Not found'
endif endif
return err return [err, err =~# 'PlugClean']
endfunction endfunction
function! s:rm_rf(dir) function! s:rm_rf(dir)
@ -1791,15 +1903,23 @@ endfunction
function! s:clean(force) function! s:clean(force)
call s:prepare() call s:prepare()
call append(0, 'Searching for unused plugins in '.g:plug_home) call append(0, 'Searching for invalid plugins in '.g:plug_home)
call append(1, '') call append(1, '')
" List of valid directories " List of valid directories
let dirs = [] let dirs = []
let errs = {}
let [cnt, total] = [0, len(g:plugs)] let [cnt, total] = [0, len(g:plugs)]
for [name, spec] in items(g:plugs) for [name, spec] in items(g:plugs)
if !s:is_managed(name) || empty(s:git_validate(spec, 0)) if !s:is_managed(name)
call add(dirs, spec.dir) call add(dirs, spec.dir)
else
let [err, clean] = s:git_validate(spec, 1)
if clean
let errs[spec.dir] = s:lines(err)[0]
else
call add(dirs, spec.dir)
endif
endif endif
let cnt += 1 let cnt += 1
call s:progress_bar(2, repeat('=', cnt), total) call s:progress_bar(2, repeat('=', cnt), total)
@ -1823,11 +1943,14 @@ function! s:clean(force)
if !has_key(allowed, f) && isdirectory(f) if !has_key(allowed, f) && isdirectory(f)
call add(todo, f) call add(todo, f)
call append(line('$'), '- ' . f) call append(line('$'), '- ' . f)
if has_key(errs, f)
call append(line('$'), ' ' . errs[f])
endif
let found = filter(found, 'stridx(v:val, f) != 0') let found = filter(found, 'stridx(v:val, f) != 0')
end end
endwhile endwhile
normal! G 4
redraw redraw
if empty(todo) if empty(todo)
call append(line('$'), 'Already clean.') call append(line('$'), 'Already clean.')
@ -1836,12 +1959,12 @@ function! s:clean(force)
for dir in todo for dir in todo
call s:rm_rf(dir) call s:rm_rf(dir)
endfor endfor
call append(line('$'), 'Removed.') call append(3, ['Removed.', ''])
else else
call append(line('$'), 'Cancelled.') call append(3, ['Cancelled.', ''])
endif endif
endif endif
normal! G 4
endfunction endfunction
function! s:upgrade() function! s:upgrade()
@ -1888,7 +2011,7 @@ function! s:status()
for [name, spec] in items(g:plugs) for [name, spec] in items(g:plugs)
if has_key(spec, 'uri') if has_key(spec, 'uri')
if isdirectory(spec.dir) if isdirectory(spec.dir)
let err = s:git_validate(spec, 1) let [err, _] = s:git_validate(spec, 1)
let [valid, msg] = [empty(err), empty(err) ? 'OK' : err] let [valid, msg] = [empty(err), empty(err) ? 'OK' : err]
else else
let [valid, msg] = [0, 'Not found. Try PlugInstall.'] let [valid, msg] = [0, 'Not found. Try PlugInstall.']
@ -1952,7 +2075,6 @@ function! s:is_preview_window_open()
wincmd p wincmd p
return 1 return 1
endif endif
return 0
endfunction endfunction
function! s:find_name(lnum) function! s:find_name(lnum)
@ -1974,7 +2096,7 @@ function! s:preview_commit()
let b:plug_preview = !s:is_preview_window_open() let b:plug_preview = !s:is_preview_window_open()
endif endif
let sha = matchstr(getline('.'), '\(^ \)\@<=[0-9a-z]\{7}') let sha = matchstr(getline('.'), '^ \X*\zs[0-9a-f]\{7}')
if empty(sha) if empty(sha)
return return
endif endif
@ -1987,7 +2109,7 @@ function! s:preview_commit()
execute 'pedit' sha execute 'pedit' sha
wincmd P wincmd P
setlocal filetype=git buftype=nofile nobuflisted modifiable setlocal filetype=git buftype=nofile nobuflisted modifiable
execute 'silent read !cd' s:shellesc(g:plugs[name].dir) '&& git show --pretty=medium' sha execute 'silent read !cd' s:shellesc(g:plugs[name].dir) '&& git show --no-color --pretty=medium' sha
normal! gg"_dd normal! gg"_dd
setlocal nomodifiable setlocal nomodifiable
nnoremap <silent> <buffer> q :q<cr> nnoremap <silent> <buffer> q :q<cr>
@ -1999,10 +2121,15 @@ function! s:section(flags)
endfunction endfunction
function! s:format_git_log(line) function! s:format_git_log(line)
let [sha, refs, subject, date] = split(a:line, nr2char(1)) let indent = ' '
let tokens = split(a:line, nr2char(1))
if len(tokens) != 5
return indent.substitute(a:line, '\s*$', '', '')
endif
let [graph, sha, refs, subject, date] = tokens
let tag = matchstr(refs, 'tag: [^,)]\+') let tag = matchstr(refs, 'tag: [^,)]\+')
let tag = empty(tag) ? ' ' : ' ('.tag.') ' let tag = empty(tag) ? ' ' : ' ('.tag.') '
return printf(' %s%s%s (%s)', sha, tag, subject, date) return printf('%s%s%s%s%s (%s)', indent, graph, sha, tag, subject, date)
endfunction endfunction
function! s:append_ul(lnum, text) function! s:append_ul(lnum, text)
@ -2017,10 +2144,14 @@ function! s:diff()
let total = filter(copy(g:plugs), 's:is_managed(v:key) && isdirectory(v:val.dir)') let total = filter(copy(g:plugs), 's:is_managed(v:key) && isdirectory(v:val.dir)')
call s:progress_bar(2, bar, len(total)) call s:progress_bar(2, bar, len(total))
for origin in [1, 0] for origin in [1, 0]
let plugs = reverse(sort(items(filter(copy(total), (origin ? '' : '!').'(has_key(v:val, "commit") || has_key(v:val, "tag"))'))))
if empty(plugs)
continue
endif
call s:append_ul(2, origin ? 'Pending updates:' : 'Last update:') call s:append_ul(2, origin ? 'Pending updates:' : 'Last update:')
for [k, v] in reverse(sort(items(filter(copy(total), (origin ? '' : '!').'(has_key(v:val, "commit") || has_key(v:val, "tag"))')))) for [k, v] in plugs
let range = origin ? '..origin/'.v.branch : 'HEAD@{1}..' let range = origin ? '..origin/'.v.branch : 'HEAD@{1}..'
let diff = s:system_chomp('git log --pretty=format:"%h%x01%d%x01%s%x01%cr" '.s:shellesc(range), v.dir) let diff = s:system_chomp('git log --graph --color=never --pretty=format:"%x01%h%x01%d%x01%s%x01%cr" '.s:shellesc(range), v.dir)
if !empty(diff) if !empty(diff)
let ref = has_key(v, 'tag') ? (' (tag: '.v.tag.')') : has_key(v, 'commit') ? (' '.v.commit) : '' let ref = has_key(v, 'tag') ? (' (tag: '.v.tag.')') : has_key(v, 'commit') ? (' '.v.commit) : ''
call append(5, extend(['', '- '.k.':'.ref], map(s:lines(diff), 's:format_git_log(v:val)'))) call append(5, extend(['', '- '.k.':'.ref], map(s:lines(diff), 's:format_git_log(v:val)')))
@ -2115,4 +2246,3 @@ endif
let &cpo = s:cpo_save let &cpo = s:cpo_save
unlet s:cpo_save unlet s:cpo_save