|
|
|
@ -1,3 +1,10 @@ |
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
" Try to clone all new bundles given (or all bundles in g:bundles by default) |
|
|
|
" to g:bundle_dir. If a:bang is 1 it will also update all plugins (git pull). |
|
|
|
" |
|
|
|
" bang -- 1 or 0 |
|
|
|
" ... -- any number of bundle specifications (separate arguments) |
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
func! vundle#installer#new(bang, ...) abort |
|
|
|
let bundles = (a:1 == '') ? |
|
|
|
\ g:bundles : |
|
|
|
@ -6,12 +13,23 @@ func! vundle#installer#new(bang, ...) abort |
|
|
|
let names = vundle#scripts#bundle_names(map(copy(bundles), 'v:val.name_spec')) |
|
|
|
call vundle#scripts#view('Installer',['" Installing plugins to '.expand(g:bundle_dir, 1)], names + ['Helptags']) |
|
|
|
|
|
|
|
" This calls 'add' as a normal mode command. This is a buffer local mapping |
|
|
|
" defined in vundle#scripts#view(). The mapping will call a buffer local |
|
|
|
" command InstallPlugin which in turn will call vundle#installer#run() with |
|
|
|
" vundle#installer#install(). |
|
|
|
call s:process(a:bang, (a:bang ? 'add!' : 'add')) |
|
|
|
|
|
|
|
call vundle#config#require(bundles) |
|
|
|
endf |
|
|
|
|
|
|
|
|
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
" Iterate over all lines in a Vundle window and execute the given command for |
|
|
|
" every line. Used by the installation and cleaning functions. |
|
|
|
" |
|
|
|
" bang -- not used (FIXME) |
|
|
|
" cmd -- the (normal mode) command to execute for every line as a string |
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
func! s:process(bang, cmd) |
|
|
|
let msg = '' |
|
|
|
|
|
|
|
@ -43,6 +61,16 @@ func! s:process(bang, cmd) |
|
|
|
echo 'Done! '.msg |
|
|
|
endf |
|
|
|
|
|
|
|
|
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
" Call another function in the different Vundle windows. |
|
|
|
" |
|
|
|
" func_name -- the function to call |
|
|
|
" name -- the bundle name to call func_name for (string) |
|
|
|
" ... -- the argument to be used when calling func_name (only the first |
|
|
|
" optional argument will be used) |
|
|
|
" return -- the status returned by the call to func_name |
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
func! vundle#installer#run(func_name, name, ...) abort |
|
|
|
let n = a:name |
|
|
|
|
|
|
|
@ -67,6 +95,8 @@ func! vundle#installer#run(func_name, name, ...) abort |
|
|
|
echo n.' deleted' |
|
|
|
elseif 'helptags' == status |
|
|
|
echo n.' regenerated' |
|
|
|
elseif 'pinned' == status |
|
|
|
echo n.' pinned' |
|
|
|
elseif 'error' == status |
|
|
|
echohl Error |
|
|
|
echo 'Error processing '.n |
|
|
|
@ -81,6 +111,13 @@ func! vundle#installer#run(func_name, name, ...) abort |
|
|
|
return status |
|
|
|
endf |
|
|
|
|
|
|
|
|
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
" Put a sign on the current line, indicating the status of the installation |
|
|
|
" step. |
|
|
|
" |
|
|
|
" status -- string describing the status |
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
func! s:sign(status) |
|
|
|
if (!has('signs')) |
|
|
|
return |
|
|
|
@ -89,6 +126,14 @@ func! s:sign(status) |
|
|
|
exe ":sign place ".line('.')." line=".line('.')." name=Vu_". a:status ." buffer=" . bufnr("%") |
|
|
|
endf |
|
|
|
|
|
|
|
|
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
" Install a plugin, then add it to the runtimepath and source it. |
|
|
|
" |
|
|
|
" bang -- 1 or 0, passed directly to vundle#installer#install() |
|
|
|
" name -- the name of a bundle (string) |
|
|
|
" return -- the return value from vundle#installer#install() |
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
func! vundle#installer#install_and_require(bang, name) abort |
|
|
|
let result = vundle#installer#install(a:bang, a:name) |
|
|
|
let b = vundle#config#bundle(a:name, {}) |
|
|
|
@ -97,6 +142,14 @@ func! vundle#installer#install_and_require(bang, name) abort |
|
|
|
return result |
|
|
|
endf |
|
|
|
|
|
|
|
|
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
" Install or update a bundle given by its name. |
|
|
|
" |
|
|
|
" bang -- 1 or 0, passed directly to s:sync() |
|
|
|
" name -- the name of a bundle (string) |
|
|
|
" return -- the return value from s:sync() |
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
func! vundle#installer#install(bang, name) abort |
|
|
|
if !isdirectory(g:bundle_dir) | call mkdir(g:bundle_dir, 'p') | endif |
|
|
|
|
|
|
|
@ -112,6 +165,12 @@ func! vundle#installer#install(bang, name) abort |
|
|
|
return s:sync(a:bang, b) |
|
|
|
endf |
|
|
|
|
|
|
|
|
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
" Call :helptags for all bundles in g:bundles. |
|
|
|
" |
|
|
|
" return -- 'error' if an error occurred, else return 'helptags' |
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
func! vundle#installer#docs() abort |
|
|
|
let error_count = vundle#installer#helptags(g:bundles) |
|
|
|
if error_count > 0 |
|
|
|
@ -120,6 +179,14 @@ func! vundle#installer#docs() abort |
|
|
|
return 'helptags' |
|
|
|
endf |
|
|
|
|
|
|
|
|
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
" Call :helptags for a list of bundles. |
|
|
|
" |
|
|
|
" bundles -- a list of bundle dictionaries for which :helptags should be |
|
|
|
" called. |
|
|
|
" return -- the number of directories where :helptags failed |
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
func! vundle#installer#helptags(bundles) abort |
|
|
|
let bundle_dirs = map(copy(a:bundles),'v:val.rtpath') |
|
|
|
let help_dirs = filter(bundle_dirs, 's:has_doc(v:val)') |
|
|
|
@ -135,6 +202,13 @@ func! vundle#installer#helptags(bundles) abort |
|
|
|
return len(errors) |
|
|
|
endf |
|
|
|
|
|
|
|
|
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
" List all installed plugins. |
|
|
|
" Corresponding documentation: vundle-plugins-list |
|
|
|
" |
|
|
|
" bang -- not used |
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
func! vundle#installer#list(bang) abort |
|
|
|
let bundles = vundle#scripts#bundle_names(map(copy(g:bundles), 'v:val.name_spec')) |
|
|
|
call vundle#scripts#view('list', ['" My Plugins'], bundles) |
|
|
|
@ -143,6 +217,13 @@ func! vundle#installer#list(bang) abort |
|
|
|
endf |
|
|
|
|
|
|
|
|
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
" List and remove all directories in the bundle directory which are not |
|
|
|
" activated (added to the bundle list). |
|
|
|
" |
|
|
|
" bang -- 0 if the user should be asked to confirm every deletion, 1 if they |
|
|
|
" should be removed unconditionally |
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
func! vundle#installer#clean(bang) abort |
|
|
|
let bundle_dirs = map(copy(g:bundles), 'v:val.path()') |
|
|
|
let all_dirs = (v:version > 702 || (v:version == 702 && has("patch51"))) |
|
|
|
@ -174,6 +255,14 @@ func! vundle#installer#clean(bang) abort |
|
|
|
endf |
|
|
|
|
|
|
|
|
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
" Delete to directory for a plugin. |
|
|
|
" |
|
|
|
" bang -- not used |
|
|
|
" dir_name -- the bundle directory to be deleted (as a string) |
|
|
|
" return -- 'error' if an error occurred, 'deleted' if the plugin folder was |
|
|
|
" successfully deleted |
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
func! vundle#installer#delete(bang, dir_name) abort |
|
|
|
|
|
|
|
let cmd = ((has('win32') || has('win64')) && empty(matchstr(&shell, 'sh'))) ? |
|
|
|
@ -187,8 +276,8 @@ func! vundle#installer#delete(bang, dir_name) abort |
|
|
|
|
|
|
|
call s:log('') |
|
|
|
call s:log('Plugin '.a:dir_name) |
|
|
|
call s:log('$ '.cmd) |
|
|
|
call s:log('> '.out) |
|
|
|
call s:log(cmd, '$ ') |
|
|
|
call s:log(out, '> ') |
|
|
|
|
|
|
|
if 0 != v:shell_error |
|
|
|
return 'error' |
|
|
|
@ -197,6 +286,13 @@ func! vundle#installer#delete(bang, dir_name) abort |
|
|
|
endif |
|
|
|
endf |
|
|
|
|
|
|
|
|
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
" Check if a bundled plugin has any documentation. |
|
|
|
" |
|
|
|
" rtp -- a path (string) where the plugin is installed |
|
|
|
" return -- 1 if some documentation was found, 0 otherwise |
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
func! s:has_doc(rtp) abort |
|
|
|
return isdirectory(a:rtp.'/doc') |
|
|
|
\ && (!filereadable(a:rtp.'/doc/tags') || filewritable(a:rtp.'/doc/tags')) |
|
|
|
@ -205,6 +301,13 @@ func! s:has_doc(rtp) abort |
|
|
|
\ : !(empty(glob(a:rtp.'/doc/*.txt')) && empty(glob(a:rtp.'/doc/*.??x'))) |
|
|
|
endf |
|
|
|
|
|
|
|
|
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
" Update the helptags for a plugin. |
|
|
|
" |
|
|
|
" rtp -- the path to the plugin's root directory (string) |
|
|
|
" return -- 1 if :helptags succeeded, 0 otherwise |
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
func! s:helptags(rtp) abort |
|
|
|
" it is important to keep trailing slash here |
|
|
|
let doc_path = resolve(a:rtp . '/doc/') |
|
|
|
@ -218,12 +321,69 @@ func! s:helptags(rtp) abort |
|
|
|
return 1 |
|
|
|
endf |
|
|
|
|
|
|
|
func! s:sync(bang, bundle) abort |
|
|
|
|
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
" Get the URL for the remote called 'origin' on the repository that |
|
|
|
" corresponds to a given bundle. |
|
|
|
" |
|
|
|
" bundle -- a bundle object to check the repository for |
|
|
|
" return -- the URL for the origin remote (string) |
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
func! s:get_current_origin_url(bundle) abort |
|
|
|
let cmd = 'cd '.vundle#installer#shellesc(a:bundle.path()).' && git config --get remote.origin.url' |
|
|
|
let cmd = g:shellesc_cd(cmd) |
|
|
|
let out = s:strip(s:system(cmd)) |
|
|
|
return out |
|
|
|
endf |
|
|
|
|
|
|
|
|
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
" Create the appropriate sync command to run according to the current state of |
|
|
|
" the local repository (clone, pull, reset, etc). |
|
|
|
" |
|
|
|
" In the case of a pull (update), also return the current sha, so that we can |
|
|
|
" later check that there has been an upgrade. |
|
|
|
" |
|
|
|
" bang -- 0 if only new plugins should be installed, 1 if existing plugins |
|
|
|
" should be updated |
|
|
|
" bundle -- a bundle object to create the sync command for |
|
|
|
" return -- A list containing the command to run and the sha for the current |
|
|
|
" HEAD |
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
func! s:make_sync_command(bang, bundle) abort |
|
|
|
let git_dir = expand(a:bundle.path().'/.git/', 1) |
|
|
|
if isdirectory(git_dir) || filereadable(expand(a:bundle.path().'/.git', 1)) |
|
|
|
if !(a:bang) | return 'todate' | endif |
|
|
|
let cmd = 'cd '.vundle#installer#shellesc(a:bundle.path()).' && git pull && git submodule update --init --recursive' |
|
|
|
|
|
|
|
let current_origin_url = s:get_current_origin_url(a:bundle) |
|
|
|
if current_origin_url != a:bundle.uri |
|
|
|
call s:log('Plugin URI change detected for Plugin ' . a:bundle.name) |
|
|
|
call s:log('> Plugin ' . a:bundle.name . ' old URI: ' . current_origin_url) |
|
|
|
call s:log('> Plugin ' . a:bundle.name . ' new URI: ' . a:bundle.uri) |
|
|
|
" Directory names match but the origin remotes are not the same |
|
|
|
let cmd_parts = [ |
|
|
|
\ 'cd '.vundle#installer#shellesc(a:bundle.path()) , |
|
|
|
\ 'git remote set-url origin ' . vundle#installer#shellesc(a:bundle.uri), |
|
|
|
\ 'git fetch', |
|
|
|
\ 'git reset --hard origin/HEAD', |
|
|
|
\ 'git submodule update --init --recursive', |
|
|
|
\ ] |
|
|
|
let cmd = join(cmd_parts, ' && ') |
|
|
|
let cmd = g:shellesc_cd(cmd) |
|
|
|
let initial_sha = '' |
|
|
|
return [cmd, initial_sha] |
|
|
|
endif |
|
|
|
|
|
|
|
if !(a:bang) |
|
|
|
" The repo exists, and no !, so leave as it is. |
|
|
|
return ['', ''] |
|
|
|
endif |
|
|
|
|
|
|
|
let cmd_parts = [ |
|
|
|
\ 'cd '.vundle#installer#shellesc(a:bundle.path()), |
|
|
|
\ 'git pull', |
|
|
|
\ 'git submodule update --init --recursive', |
|
|
|
\ ] |
|
|
|
let cmd = join(cmd_parts, ' && ') |
|
|
|
let cmd = g:shellesc_cd(cmd) |
|
|
|
|
|
|
|
let get_current_sha = 'cd '.vundle#installer#shellesc(a:bundle.path()).' && git rev-parse HEAD' |
|
|
|
@ -233,12 +393,39 @@ func! s:sync(bang, bundle) abort |
|
|
|
let cmd = 'git clone --recursive '.vundle#installer#shellesc(a:bundle.uri).' '.vundle#installer#shellesc(a:bundle.path()) |
|
|
|
let initial_sha = '' |
|
|
|
endif |
|
|
|
return [cmd, initial_sha] |
|
|
|
endf |
|
|
|
|
|
|
|
|
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
" Install or update a given bundle object with git. |
|
|
|
" |
|
|
|
" bang -- 0 if only new plugins should be installed, 1 if existing plugins |
|
|
|
" should be updated |
|
|
|
" bundle -- a bundle object (dictionary) |
|
|
|
" return -- a string indicating the status of the bundle installation: |
|
|
|
" - todate : Nothing was updated or the repository was up to date |
|
|
|
" - new : The plugin was newly installed |
|
|
|
" - updated : Some changes where pulled via git |
|
|
|
" - error : An error occurred in the shell command |
|
|
|
" - pinned : The bundle is marked as pinned |
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
func! s:sync(bang, bundle) abort |
|
|
|
" Do not sync if this bundle is pinned |
|
|
|
if a:bundle.is_pinned() |
|
|
|
return 'pinned' |
|
|
|
endif |
|
|
|
|
|
|
|
let [ cmd, initial_sha ] = s:make_sync_command(a:bang, a:bundle) |
|
|
|
if empty(cmd) |
|
|
|
return 'todate' |
|
|
|
endif |
|
|
|
|
|
|
|
let out = s:system(cmd) |
|
|
|
call s:log('') |
|
|
|
call s:log('Plugin '.a:bundle.name_spec) |
|
|
|
call s:log('$ '.cmd) |
|
|
|
call s:log('> '.out) |
|
|
|
call s:log(cmd, '$ ') |
|
|
|
call s:log(out, '> ') |
|
|
|
|
|
|
|
if 0 != v:shell_error |
|
|
|
return 'error' |
|
|
|
@ -258,6 +445,14 @@ func! s:sync(bang, bundle) abort |
|
|
|
return 'updated' |
|
|
|
endf |
|
|
|
|
|
|
|
|
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
" Escape special characters in a string to be able to use it as a shell |
|
|
|
" command with system(). |
|
|
|
" |
|
|
|
" cmd -- the string holding the shell command |
|
|
|
" return -- a string with the relevant characters escaped |
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
func! vundle#installer#shellesc(cmd) abort |
|
|
|
if ((has('win32') || has('win64')) && empty(matchstr(&shell, 'sh'))) |
|
|
|
return '"' . substitute(a:cmd, '"', '\\"', 'g') . '"' |
|
|
|
@ -265,6 +460,13 @@ func! vundle#installer#shellesc(cmd) abort |
|
|
|
return shellescape(a:cmd) |
|
|
|
endf |
|
|
|
|
|
|
|
|
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
" Fix a cd shell command to be used on Windows. |
|
|
|
" |
|
|
|
" cmd -- the command to be fixed (string) |
|
|
|
" return -- the fixed command (string) |
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
func! g:shellesc_cd(cmd) abort |
|
|
|
if ((has('win32') || has('win64')) && empty(matchstr(&shell, 'sh'))) |
|
|
|
let cmd = substitute(a:cmd, '^cd ','cd /d ','') " add /d switch to change drives |
|
|
|
@ -274,12 +476,45 @@ func! g:shellesc_cd(cmd) abort |
|
|
|
endif |
|
|
|
endf |
|
|
|
|
|
|
|
|
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
" Make a system call. This can be used to change the way system calls |
|
|
|
" are made during developing, without searching the whole code base for |
|
|
|
" actual system() calls. |
|
|
|
" |
|
|
|
" cmd -- the command passed to system() (string) |
|
|
|
" return -- the return value from system() |
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
func! s:system(cmd) abort |
|
|
|
return system(a:cmd) |
|
|
|
endf |
|
|
|
|
|
|
|
func! s:log(str) abort |
|
|
|
let fmt = '%y%m%d %H:%M:%S' |
|
|
|
call add(g:vundle_log, '['.strftime(fmt).'] '.a:str) |
|
|
|
|
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
" Add a log message to Vundle's internal logging variable. |
|
|
|
" |
|
|
|
" str -- the log message (string) |
|
|
|
" prefix -- optional prefix for multi-line entries (string) |
|
|
|
" return -- a:str |
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
func! s:log(str, ...) abort |
|
|
|
let prefix = a:0 > 0 ? a:1 : '' |
|
|
|
let fmt = '%Y-%m-%d %H:%M:%S' |
|
|
|
let lines = split(a:str, '\n', 1) |
|
|
|
let time = strftime(fmt) |
|
|
|
for line in lines |
|
|
|
call add(g:vundle_log, '['. time .'] '. prefix . line) |
|
|
|
endfor |
|
|
|
return a:str |
|
|
|
endf |
|
|
|
|
|
|
|
|
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
" Remove leading and trailing whitespace from a string |
|
|
|
" |
|
|
|
" str -- The string to rid of trailing and leading spaces |
|
|
|
" return -- A string stripped of side spaces |
|
|
|
" --------------------------------------------------------------------------- |
|
|
|
func! s:strip(str) |
|
|
|
return substitute(a:str, '\%^\_s*\(.\{-}\)\_s*\%$', '\1', '') |
|
|
|
endf |