Обновление plug

This commit is contained in:
Andrei Astafev 2020-11-28 11:01:54 +03:00
parent ed6de8c1e4
commit 4a70c28c87
2 changed files with 170 additions and 46 deletions

View File

@ -25,7 +25,7 @@
" Plug 'scrooloose/nerdtree', { 'on': 'NERDTreeToggle' } " Plug 'scrooloose/nerdtree', { 'on': 'NERDTreeToggle' }
" Plug 'tpope/vim-fireplace', { 'for': 'clojure' } " Plug 'tpope/vim-fireplace', { 'for': 'clojure' }
" "
" " Using a non-master branch " " Using a non-default 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) " " Using a tagged release; wildcard allowed (requires git 1.9.2 or above)
@ -106,7 +106,7 @@ if s:is_win && &shellslash
else else
let s:me = resolve(expand('<sfile>:p')) let s:me = resolve(expand('<sfile>:p'))
endif endif
let s:base_spec = { 'branch': 'master', 'frozen': 0 } let s:base_spec = { 'branch': '', 'frozen': 0 }
let s:TYPE = { let s:TYPE = {
\ 'string': type(''), \ 'string': type(''),
\ 'list': type([]), \ 'list': type([]),
@ -116,6 +116,90 @@ let s:TYPE = {
let s:loaded = get(s:, 'loaded', {}) let s:loaded = get(s:, 'loaded', {})
let s:triggers = get(s:, 'triggers', {}) let s:triggers = get(s:, 'triggers', {})
function! s:isabsolute(dir) abort
return a:dir =~# '^/' || (has('win32') && a:dir =~? '^\%(\\\|[A-Z]:\)')
endfunction
function! s:git_dir(dir) abort
let gitdir = s:trim(a:dir) . '/.git'
if isdirectory(gitdir)
return gitdir
endif
if !filereadable(gitdir)
return ''
endif
let gitdir = matchstr(get(readfile(gitdir), 0, ''), '^gitdir: \zs.*')
if len(gitdir) && !s:isabsolute(gitdir)
let gitdir = a:dir . '/' . gitdir
endif
return isdirectory(gitdir) ? gitdir : ''
endfunction
function! s:git_origin_url(dir) abort
let gitdir = s:git_dir(a:dir)
let config = gitdir . '/config'
if empty(gitdir) || !filereadable(config)
return ''
endif
return matchstr(join(readfile(config)), '\[remote "origin"\].\{-}url\s*=\s*\zs\S*\ze')
endfunction
function! s:git_revision(dir) abort
let gitdir = s:git_dir(a:dir)
let head = gitdir . '/HEAD'
if empty(gitdir) || !filereadable(head)
return ''
endif
let line = get(readfile(head), 0, '')
let ref = matchstr(line, '^ref: \zs.*')
if empty(ref)
return line
endif
if filereadable(gitdir . '/' . ref)
return get(readfile(gitdir . '/' . ref), 0, '')
endif
if filereadable(gitdir . '/packed-refs')
for line in readfile(gitdir . '/packed-refs')
if line =~# ' ' . ref
return matchstr(line, '^[0-9a-f]*')
endif
endfor
endif
return ''
endfunction
function! s:git_local_branch(dir) abort
let gitdir = s:git_dir(a:dir)
let head = gitdir . '/HEAD'
if empty(gitdir) || !filereadable(head)
return ''
endif
let branch = matchstr(get(readfile(head), 0, ''), '^ref: refs/heads/\zs.*')
return len(branch) ? branch : 'HEAD'
endfunction
function! s:git_origin_branch(spec)
if len(a:spec.branch)
return a:spec.branch
endif
" The file may not be present if this is a local repository
let gitdir = s:git_dir(a:spec.dir)
let origin_head = gitdir.'/refs/remotes/origin/HEAD'
if len(gitdir) && filereadable(origin_head)
return matchstr(get(readfile(origin_head), 0, ''),
\ '^ref: refs/remotes/origin/\zs.*')
endif
" 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]
endfunction
if s:is_win if s:is_win
function! s:plug_call(fn, ...) function! s:plug_call(fn, ...)
let shellslash = &shellslash let shellslash = &shellslash
@ -179,7 +263,7 @@ function! s:define_commands()
endif endif
if has('win32') if has('win32')
\ && &shellslash \ && &shellslash
\ && (&shell =~# 'cmd\.exe' || &shell =~# 'powershell\.exe') \ && (&shell =~# 'cmd\(\.exe\)\?$' || &shell =~# 'powershell\(\.exe\)\?$')
return s:err('vim-plug does not support shell, ' . &shell . ', when shellslash is set.') return s:err('vim-plug does not support shell, ' . &shell . ', when shellslash is set.')
endif endif
if !has('nvim') if !has('nvim')
@ -419,7 +503,7 @@ if s:is_win
let batchfile = s:plug_tempname().'.bat' let batchfile = s:plug_tempname().'.bat'
call writefile(s:wrap_cmds(a:cmd), batchfile) call writefile(s:wrap_cmds(a:cmd), batchfile)
let cmd = plug#shellescape(batchfile, {'shell': &shell, 'script': 0}) let cmd = plug#shellescape(batchfile, {'shell': &shell, 'script': 0})
if &shell =~# 'powershell\.exe' if &shell =~# 'powershell\(\.exe\)\?$'
let cmd = '& ' . cmd let cmd = '& ' . cmd
endif endif
return [batchfile, cmd] return [batchfile, cmd]
@ -632,16 +716,38 @@ function! plug#(repo, ...)
let g:plugs[name] = spec let g:plugs[name] = spec
let s:loaded[name] = get(s:loaded, name, 0) let s:loaded[name] = get(s:loaded, name, 0)
catch catch
return s:err(v:exception) return s:err(repo . ' ' . v:exception)
endtry endtry
endfunction endfunction
function! s:parse_options(arg) function! s:parse_options(arg)
let opts = copy(s:base_spec) let opts = copy(s:base_spec)
let type = type(a:arg) let type = type(a:arg)
let opt_errfmt = 'Invalid argument for "%s" option of :Plug (expected: %s)'
if type == s:TYPE.string if type == s:TYPE.string
if empty(a:arg)
throw printf(opt_errfmt, 'tag', 'string')
endif
let opts.tag = a:arg let opts.tag = a:arg
elseif type == s:TYPE.dict elseif type == s:TYPE.dict
for opt in ['branch', 'tag', 'commit', 'rtp', 'dir', 'as']
if has_key(a:arg, opt)
\ && (type(a:arg[opt]) != s:TYPE.string || empty(a:arg[opt]))
throw printf(opt_errfmt, opt, 'string')
endif
endfor
for opt in ['on', 'for']
if has_key(a:arg, opt)
\ && type(a:arg[opt]) != s:TYPE.list
\ && (type(a:arg[opt]) != s:TYPE.string || empty(a:arg[opt]))
throw printf(opt_errfmt, opt, 'string or list')
endif
endfor
if has_key(a:arg, 'do')
\ && type(a:arg.do) != s:TYPE.funcref
\ && (type(a:arg.do) != s:TYPE.string || empty(a:arg.do))
throw printf(opt_errfmt, 'do', 'string or funcref')
endif
call extend(opts, a:arg) call extend(opts, a:arg)
if has_key(opts, 'dir') if has_key(opts, 'dir')
let opts.dir = s:dirpath(s:plug_expand(opts.dir)) let opts.dir = s:dirpath(s:plug_expand(opts.dir))
@ -698,7 +804,7 @@ function! s:syntax()
syn match plugNumber /[0-9]\+[0-9.]*/ contained syn match plugNumber /[0-9]\+[0-9.]*/ contained
syn match plugBracket /[[\]]/ contained syn match plugBracket /[[\]]/ contained
syn match plugX /x/ contained syn match plugX /x/ contained
syn match plugDash /^-/ syn match plugDash /^-\{1}\ /
syn match plugPlus /^+/ syn match plugPlus /^+/
syn match plugStar /^*/ syn match plugStar /^*/
syn match plugMessage /\(^- \)\@<=.*/ syn match plugMessage /\(^- \)\@<=.*/
@ -716,6 +822,7 @@ function! s:syntax()
syn match plugError /^x.*/ syn match plugError /^x.*/
syn region plugDeleted start=/^\~ .*/ end=/^\ze\S/ syn region plugDeleted start=/^\~ .*/ end=/^\ze\S/
syn match plugH2 /^.*:\n-\+$/ syn match plugH2 /^.*:\n-\+$/
syn match plugH2 /^-\{2,}/
syn keyword Function PlugInstall PlugStatus PlugUpdate PlugClean syn keyword Function PlugInstall PlugStatus PlugUpdate PlugClean
hi def link plug1 Title hi def link plug1 Title
hi def link plug2 Repeat hi def link plug2 Repeat
@ -868,9 +975,9 @@ function! s:chsh(swap)
set shell=sh set shell=sh
endif endif
if a:swap if a:swap
if &shell =~# 'powershell\.exe' || &shell =~# 'pwsh$' if &shell =~# 'powershell\(\.exe\)\?$' || &shell =~# 'pwsh$'
let &shellredir = '2>&1 | Out-File -Encoding UTF8 %s' let &shellredir = '2>&1 | Out-File -Encoding UTF8 %s'
elseif &shell =~# 'sh' || &shell =~# 'cmd\.exe' elseif &shell =~# 'sh' || &shell =~# 'cmd\(\.exe\)\?$'
set shellredir=>%s\ 2>&1 set shellredir=>%s\ 2>&1
endif endif
endif endif
@ -969,10 +1076,11 @@ 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:git_revision(a:spec.dir)
if !v:shell_error && !s:hash_match(sha, s:lines(output)[0]) if !empty(output) && !s:hash_match(sha, s:lines(output)[0])
let credential_helper = s:git_version_requirement(2) ? '-c credential.helper= ' : ''
let output = s:system( let output = s:system(
\ 'git fetch --depth 999999 && git checkout '.plug#shellescape(sha).' --', a:spec.dir) \ 'git '.credential_helper.'fetch --depth 999999 && git checkout '.plug#shellescape(sha).' --', a:spec.dir)
endif endif
return output return output
endfunction endfunction
@ -1184,7 +1292,7 @@ function! s:update_finish()
call s:log4(name, 'Checking out '.tag) call s:log4(name, 'Checking out '.tag)
let out = s:system('git checkout -q '.plug#shellescape(tag).' -- 2>&1', spec.dir) let out = s:system('git checkout -q '.plug#shellescape(tag).' -- 2>&1', spec.dir)
else else
let branch = get(spec, 'branch', 'master') let branch = s:git_origin_branch(spec)
call s:log4(name, 'Merging origin/'.s:esc(branch)) call s:log4(name, 'Merging origin/'.s:esc(branch))
let out = s:system('git checkout -q '.plug#shellescape(branch).' -- 2>&1' let out = s:system('git checkout -q '.plug#shellescape(branch).' -- 2>&1'
\. (has_key(s:update.new, name) ? '' : ('&& git merge --ff-only '.plug#shellescape('origin/'.branch).' 2>&1')), spec.dir) \. (has_key(s:update.new, name) ? '' : ('&& git merge --ff-only '.plug#shellescape('origin/'.branch).' 2>&1')), spec.dir)
@ -2106,9 +2214,9 @@ 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')
let script = get(opts, 'script', 1) let script = get(opts, 'script', 1)
if shell =~# 'cmd\.exe' if shell =~# 'cmd\(\.exe\)\?$'
return s:shellesc_cmd(a:arg, script) return s:shellesc_cmd(a:arg, script)
elseif shell =~# 'powershell\.exe' || shell =~# 'pwsh$' elseif shell =~# 'powershell\(\.exe\)\?$' || shell =~# 'pwsh$'
return s:shellesc_ps1(a:arg) return s:shellesc_ps1(a:arg)
endif endif
return s:shellesc_sh(a:arg) return s:shellesc_sh(a:arg)
@ -2160,7 +2268,7 @@ function! s:system(cmd, ...)
return system(a:cmd) return system(a:cmd)
endif endif
let cmd = join(map(copy(a:cmd), 'plug#shellescape(v:val, {"shell": &shell, "script": 0})')) let cmd = join(map(copy(a:cmd), 'plug#shellescape(v:val, {"shell": &shell, "script": 0})'))
if &shell =~# 'powershell\.exe' if &shell =~# 'powershell\(\.exe\)\?$'
let cmd = '& ' . cmd let cmd = '& ' . cmd
endif endif
else else
@ -2189,18 +2297,17 @@ 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 -f .git/config remote.origin.url', a:spec.dir)) let result = [s:git_local_branch(a:spec.dir), s:git_origin_url(a:spec.dir)]
let remote = result[-1] let remote = result[-1]
if v:shell_error if empty(remote)
let err = join([remote, 'PlugClean required.'], "\n") let err = join([remote, 'PlugClean required.'], "\n")
elseif !s:compare_git_uri(remote, a:spec.uri) elseif !s:compare_git_uri(remote, a:spec.uri)
let err = join(['Invalid URI: '.remote, let err = join(['Invalid URI: '.remote,
\ 'Expected: '.a:spec.uri, \ 'Expected: '.a:spec.uri,
\ 'PlugClean required.'], "\n") \ 'PlugClean required.'], "\n")
elseif a:check_branch && has_key(a:spec, 'commit') 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 sha = s:git_revision(a:spec.dir)
let sha = result[-1] if empty(sha)
if v:shell_error
let err = join(add(result, 'PlugClean required.'), "\n") let err = join(add(result, 'PlugClean required.'), "\n")
elseif !s:hash_match(sha, a:spec.commit) elseif !s:hash_match(sha, a:spec.commit)
let err = join([printf('Invalid HEAD (expected: %s, actual: %s)', let err = join([printf('Invalid HEAD (expected: %s, actual: %s)',
@ -2208,8 +2315,9 @@ function! s:git_validate(spec, check_branch)
\ 'PlugUpdate required.'], "\n") \ 'PlugUpdate required.'], "\n")
endif endif
elseif a:check_branch elseif a:check_branch
let branch = result[0] let current_branch = result[0]
" Check tag " Check tag
let origin_branch = s:git_origin_branch(a:spec)
if has_key(a:spec, 'tag') if has_key(a:spec, 'tag')
let tag = s:system_chomp('git describe --exact-match --tags HEAD 2>&1', a:spec.dir) let tag = s:system_chomp('git describe --exact-match --tags HEAD 2>&1', a:spec.dir)
if a:spec.tag !=# tag && a:spec.tag !~ '\*' if a:spec.tag !=# tag && a:spec.tag !~ '\*'
@ -2217,14 +2325,14 @@ function! s:git_validate(spec, check_branch)
\ (empty(tag) ? 'N/A' : tag), a:spec.tag) \ (empty(tag) ? 'N/A' : tag), a:spec.tag)
endif endif
" Check branch " Check branch
elseif a:spec.branch !=# branch elseif origin_branch !=# current_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) \ current_branch, origin_branch)
endif endif
if empty(err) if empty(err)
let [ahead, behind] = split(s:lastline(s:system([ let [ahead, behind] = split(s:lastline(s:system([
\ 'git', 'rev-list', '--count', '--left-right', \ 'git', 'rev-list', '--count', '--left-right',
\ printf('HEAD...origin/%s', a:spec.branch) \ printf('HEAD...origin/%s', origin_branch)
\ ], a:spec.dir)), '\t') \ ], a:spec.dir)), '\t')
if !v:shell_error && ahead if !v:shell_error && ahead
if behind if behind
@ -2232,11 +2340,11 @@ function! s:git_validate(spec, check_branch)
" pushable (and probably not that messed up). " pushable (and probably not that messed up).
let err = printf( let err = printf(
\ "Diverged from origin/%s (%d commit(s) ahead and %d commit(s) behind!\n" \ "Diverged from origin/%s (%d commit(s) ahead and %d commit(s) behind!\n"
\ .'Backup local changes and run PlugClean and PlugUpdate to reinstall it.', a:spec.branch, ahead, behind) \ .'Backup local changes and run PlugClean and PlugUpdate to reinstall it.', origin_branch, ahead, behind)
else else
let err = printf("Ahead of origin/%s by %d commit(s).\n" let err = printf("Ahead of origin/%s by %d commit(s).\n"
\ .'Cannot update until local changes are pushed.', \ .'Cannot update until local changes are pushed.',
\ a:spec.branch, ahead) \ origin_branch, ahead)
endif endif
endif endif
endif endif
@ -2249,7 +2357,7 @@ 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 return s:system(s:is_win
\ ? 'rmdir /S /Q '.plug#shellescape(a:dir) \ ? 'rmdir /S /Q '.plug#shellescape(a:dir)
\ : ['rm', '-rf', a:dir]) \ : ['rm', '-rf', a:dir])
endif endif
@ -2333,6 +2441,7 @@ endfunction
function! s:delete(range, force) function! s:delete(range, force)
let [l1, l2] = a:range let [l1, l2] = a:range
let force = a:force let force = a:force
let err_count = 0
while l1 <= l2 while l1 <= l2
let line = getline(l1) let line = getline(l1)
if line =~ '^- ' && isdirectory(line[2:]) if line =~ '^- ' && isdirectory(line[2:])
@ -2341,11 +2450,22 @@ function! s:delete(range, force)
let answer = force ? 1 : s:ask('Delete '.line[2:].'?', 1) let answer = force ? 1 : s:ask('Delete '.line[2:].'?', 1)
let force = force || answer > 1 let force = force || answer > 1
if answer if answer
call s:rm_rf(line[2:]) let err = s:rm_rf(line[2:])
setlocal modifiable setlocal modifiable
call setline(l1, '~'.line[1:]) if empty(err)
let s:clean_count += 1 call setline(l1, '~'.line[1:])
call setline(4, printf('Removed %d directories.', s:clean_count)) let s:clean_count += 1
else
delete _
call append(l1 - 1, s:format_message('x', line[1:], err))
let l2 += len(s:lines(err))
let err_count += 1
endif
let msg = printf('Removed %d directories.', s:clean_count)
if err_count > 0
let msg .= printf(' Failed to remove %d directories.', err_count)
endif
call setline(4, msg)
setlocal nomodifiable setlocal nomodifiable
endif endif
endif endif
@ -2554,20 +2674,23 @@ function! s:diff()
endif 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 plugs for [k, v] in plugs
let range = origin ? '..origin/'.v.branch : 'HEAD@{1}..' let branch = s:git_origin_branch(v)
let cmd = ['git', 'log', '--graph', '--color=never'] if len(branch)
if s:git_version_requirement(2, 10, 0) let range = origin ? '..origin/'.branch : 'HEAD@{1}..'
call add(cmd, '--no-show-signature') let cmd = ['git', 'log', '--graph', '--color=never']
endif if s:git_version_requirement(2, 10, 0)
call extend(cmd, ['--pretty=format:%x01%h%x01%d%x01%s%x01%cr', range]) call add(cmd, '--no-show-signature')
if has_key(v, 'rtp') endif
call extend(cmd, ['--', v.rtp]) call extend(cmd, ['--pretty=format:%x01%h%x01%d%x01%s%x01%cr', range])
endif if has_key(v, 'rtp')
let diff = s:system_chomp(cmd, v.dir) call extend(cmd, ['--', v.rtp])
if !empty(diff) endif
let ref = has_key(v, 'tag') ? (' (tag: '.v.tag.')') : has_key(v, 'commit') ? (' '.v.commit) : '' let diff = s:system_chomp(cmd, v.dir)
call append(5, extend(['', '- '.k.':'.ref], map(s:lines(diff), 's:format_git_log(v:val)'))) if !empty(diff)
let cnts[origin] += 1 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)')))
let cnts[origin] += 1
endif
endif endif
let bar .= '=' let bar .= '='
call s:progress_bar(2, bar, len(total)) call s:progress_bar(2, bar, len(total))
@ -2629,7 +2752,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:git_revision(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

1
vimrc
View File

@ -135,6 +135,7 @@ call plug#end()
"{{{ Базовые настройки "{{{ Базовые настройки
" Включена подсветка синтаксиса " " Включена подсветка синтаксиса "
" Plug устанавливает свои значения, нужно явно переопределить после plug#end "
syntax on syntax on
filetype plugin indent on filetype plugin indent on