aboutsummaryrefslogtreecommitdiff
path: root/bundle/Vundle.vim/autoload/vundle/installer.vim
diff options
context:
space:
mode:
authorCody Hiar <chiar@hybridforge.com>2015-08-12 11:51:04 -0600
committerCody Hiar <chiar@hybridforge.com>2015-08-12 11:51:04 -0600
commit72d653e1e0cffe2e48bd7a393acf08c96d6db50a (patch)
tree6c870fd1fa4737103fe728b1438c27ac6863fc75 /bundle/Vundle.vim/autoload/vundle/installer.vim
Inidiat commit of working files
Diffstat (limited to 'bundle/Vundle.vim/autoload/vundle/installer.vim')
-rw-r--r--bundle/Vundle.vim/autoload/vundle/installer.vim547
1 files changed, 547 insertions, 0 deletions
diff --git a/bundle/Vundle.vim/autoload/vundle/installer.vim b/bundle/Vundle.vim/autoload/vundle/installer.vim
new file mode 100644
index 0000000..472271a
--- /dev/null
+++ b/bundle/Vundle.vim/autoload/vundle/installer.vim
@@ -0,0 +1,547 @@
+" ---------------------------------------------------------------------------
+" Try to clone all new bundles given (or all bundles in g:vundle#bundles by
+" default) to g:vundle#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
+ " No specific plugins are specified. Operate on all plugins.
+ if a:0 == 0
+ let bundles = g:vundle#bundles
+ " Specific plugins are specified for update. Update them.
+ elseif (a:bang)
+ let bundles = filter(copy(g:vundle#bundles), 'index(a:000, v:val.name) > -1')
+ " Specific plugins are specified for installation. Install them.
+ else
+ let bundles = map(copy(a:000), 'vundle#config#bundle(v:val, {})')
+ endif
+
+ if empty(bundles)
+ echoerr 'No bundles were selected for operation'
+ return
+ endif
+
+ let names = vundle#scripts#bundle_names(map(copy(bundles), 'v:val.name_spec'))
+ call vundle#scripts#view('Installer',['" Installing plugins to '.expand(g:vundle#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 = ''
+
+ redraw
+ sleep 1m
+
+ let lines = (getline('.','$')[0:-2])
+
+ for line in lines
+ redraw
+
+ exec ':norm '.a:cmd
+
+ if 'error' == s:last_status
+ let msg = 'With errors; press l to view log'
+ endif
+
+ if 'updated' == s:last_status && empty(msg)
+ let msg = 'Plugins updated; press u to view changelog'
+ endif
+
+ " goto next one
+ exec ':+1'
+
+ setl nomodified
+ endfor
+
+ redraw
+ 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
+
+ echo 'Processing '.n
+ call s:sign('active')
+
+ sleep 1m
+
+ let status = call(a:func_name, a:1)
+
+ call s:sign(status)
+
+ redraw
+
+ if 'new' == status
+ echo n.' installed'
+ elseif 'updated' == status
+ echo n.' updated'
+ elseif 'todate' == status
+ echo n.' already installed'
+ elseif 'deleted' == status
+ echo n.' deleted'
+ elseif 'helptags' == status
+ echo n.' regenerated'
+ elseif 'pinned' == status
+ echo n.' pinned'
+ elseif 'error' == status
+ echohl Error
+ echo 'Error processing '.n
+ echohl None
+ sleep 1
+ else
+ throw 'whoops, unknown status:'.status
+ endif
+
+ let s:last_status = status
+
+ 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
+ endif
+
+ 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, {})
+ call vundle#installer#helptags([b])
+ call vundle#config#require([b])
+ 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:vundle#bundle_dir) | call mkdir(g:vundle#bundle_dir, 'p') | endif
+
+ let n = substitute(a:name,"['".'"]\+','','g')
+ let matched = filter(copy(g:vundle#bundles), 'v:val.name_spec == n')
+
+ if len(matched) > 0
+ let b = matched[0]
+ else
+ let b = vundle#config#init_bundle(a:name, {})
+ endif
+
+ return s:sync(a:bang, b)
+endf
+
+
+" ---------------------------------------------------------------------------
+" Call :helptags for all bundles in g:vundle#bundles.
+"
+" return -- 'error' if an error occurred, else return 'helptags'
+" ---------------------------------------------------------------------------
+func! vundle#installer#docs() abort
+ let error_count = vundle#installer#helptags(g:vundle#bundles)
+ if error_count > 0
+ return 'error'
+ endif
+ 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)')
+
+ call s:log('')
+ call s:log('Helptags:')
+
+ let statuses = map(copy(help_dirs), 's:helptags(v:val)')
+ let errors = filter(statuses, 'v:val == 0')
+
+ call s:log('Helptags: '.len(help_dirs).' plugins processed')
+
+ 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:vundle#bundles), 'v:val.name_spec'))
+ call vundle#scripts#view('list', ['" My Plugins'], bundles)
+ redraw
+ echo len(g:vundle#bundles).' plugins configured'
+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:vundle#bundles), 'v:val.path()')
+ let all_dirs = (v:version > 702 || (v:version == 702 && has("patch51")))
+ \ ? split(globpath(g:vundle#bundle_dir, '*', 1), "\n")
+ \ : split(globpath(g:vundle#bundle_dir, '*'), "\n")
+ let x_dirs = filter(all_dirs, '0 > index(bundle_dirs, v:val)')
+
+ if empty(x_dirs)
+ let headers = ['" All clean!']
+ let names = []
+ else
+ let headers = ['" Removing Plugins:']
+ let names = vundle#scripts#bundle_names(map(copy(x_dirs), 'fnamemodify(v:val, ":t")'))
+ end
+
+ call vundle#scripts#view('clean', headers, names)
+ redraw
+
+ if (a:bang || empty(names))
+ call s:process(a:bang, 'D')
+ else
+ call inputsave()
+ let response = input('Continue? [Y/n]: ')
+ call inputrestore()
+ if (response =~? 'y' || response == '')
+ call s:process(a:bang, 'D')
+ endif
+ endif
+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'))) ?
+ \ 'rmdir /S /Q' :
+ \ 'rm -rf'
+
+ let bundle = vundle#config#init_bundle(a:dir_name, {})
+ let cmd .= ' '.vundle#installer#shellesc(bundle.path())
+
+ let out = s:system(cmd)
+
+ call s:log('')
+ call s:log('Plugin '.a:dir_name)
+ call s:log(cmd, '$ ')
+ call s:log(out, '> ')
+
+ if 0 != v:shell_error
+ return 'error'
+ else
+ return 'deleted'
+ 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'))
+ \ && (v:version > 702 || (v:version == 702 && has("patch51")))
+ \ ? !(empty(glob(a:rtp.'/doc/*.txt', 1)) && empty(glob(a:rtp.'/doc/*.??x', 1)))
+ \ : !(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/')
+ call s:log(':helptags '.doc_path)
+ try
+ execute 'helptags ' . doc_path
+ catch
+ call s:log("> Error running :helptags ".doc_path)
+ return 0
+ endtry
+ return 1
+endf
+
+
+" ---------------------------------------------------------------------------
+" 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 = vundle#installer#shellesc_cd(cmd)
+ let out = s:strip(s:system(cmd))
+ return out
+endf
+
+
+" ---------------------------------------------------------------------------
+" Get a short sha of the HEAD of the repository for a given bundle
+"
+" bundle -- a bundle object
+" return -- A 15 character log sha for the current HEAD
+" ---------------------------------------------------------------------------
+func! s:get_current_sha(bundle)
+ let cmd = 'cd '.vundle#installer#shellesc(a:bundle.path()).' && git rev-parse HEAD'
+ let cmd = vundle#installer#shellesc_cd(cmd)
+ let out = s:system(cmd)[0:15]
+ 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))
+
+ 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 = vundle#installer#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 = vundle#installer#shellesc_cd(cmd)
+
+ let initial_sha = s:get_current_sha(a:bundle)
+ else
+ 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, '> ')
+
+ if 0 != v:shell_error
+ return 'error'
+ end
+
+ if empty(initial_sha)
+ return 'new'
+ endif
+
+ let updated_sha = s:get_current_sha(a:bundle)
+
+ if initial_sha == updated_sha
+ return 'todate'
+ endif
+
+ call add(g:vundle#updated_bundles, [initial_sha, updated_sha, a:bundle])
+ 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') . '"'
+ endif
+ 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! vundle#installer#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
+ return cmd
+ else
+ return a:cmd
+ 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
+
+
+" ---------------------------------------------------------------------------
+" 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
+
+" vim: set expandtab sts=2 ts=2 sw=2 tw=78 norl: