浏览代码

Post-update hook (`do` option)

Junegunn Choi 11 年之前
父节点
当前提交
f98c8456fa
共有 3 个文件被更改,包括 152 次插入17 次删除
  1. 1 0
      README.md
  2. 61 16
      plug.vim
  3. 90 1
      test/workflow.vader

+ 1 - 0
README.md

@@ -76,6 +76,7 @@ Reload .vimrc and `:PlugInstall` to install plugins.
 | -------------- | -------------------------------------------------------------------- |
 | `branch`/`tag` | Branch or tag of the repository to use                               |
 | `rtp`          | Subdirectory that contains Vim plugin                                |
+| `do`           | Post-update hook (string of funcref)                                 |
 | `on`           | On-demand loading: Commands or <Plug>-mappings                       |
 | `for`          | On-demand loading: File types                                        |
 | `frozen`       | Do not install/update plugin unless explicitly given as the argument |

+ 61 - 16
plug.vim

@@ -9,14 +9,24 @@
 "
 " Edit your .vimrc
 "
-"   call plug#begin()
+"   call plug#begin('~/.vim/plugged')
 "
+"   " Make sure you use single quotes
 "   Plug 'junegunn/seoul256.vim'
 "   Plug 'junegunn/vim-easy-align'
-"   Plug 'junegunn/goyo.vim', { 'on': 'Goyo' }
-"   " Plug 'user/repo1', 'branch_or_tag'
-"   " Plug 'user/repo2', { 'rtp': 'vim/plugin/dir', 'branch': 'branch_or_tag' }
-"   " ...
+"
+"   " On-demand loading
+"   Plug 'scrooloose/nerdtree', { 'on':  'NERDTreeToggle' }
+"   Plug 'tpope/vim-fireplace', { 'for': 'clojure' }
+"
+"   " Using git URL
+"   Plug 'https://github.com/junegunn/vim-github-dashboard.git'
+"
+"   " Plugin options
+"   Plug 'nsf/gocode', { 'tag': 'go.weekly.2012-03-13', 'rtp': 'vim' }
+"
+"   " Locally-managed plugin
+"   Plug '~/.fzf'
 "
 "   call plug#end()
 "
@@ -354,7 +364,8 @@ function! s:syntax()
   syn match plugDash /^-/
   syn match plugPlus /^+/
   syn match plugStar /^*/
-  syn match plugName /\(^- \)\@<=[^:]*/
+  syn match plugMessage /\(^- \)\@<=.*/
+  syn match plugName /\(^- \)\@<=[^ ]*:/
   syn match plugInstall /\(^+ \)\@<=[^:]*/
   syn match plugUpdate /\(^* \)\@<=[^:]*/
   syn match plugCommit /^  [0-9a-z]\{7} .*/ contains=plugRelDate,plugSha
@@ -372,6 +383,7 @@ function! s:syntax()
   hi def link plugPlus    Constant
   hi def link plugStar    Boolean
 
+  hi def link plugMessage Function
   hi def link plugName    Label
   hi def link plugInstall Function
   hi def link plugUpdate  Type
@@ -430,6 +442,32 @@ function! s:assign_name()
   silent! execute "f ".fnameescape(name)
 endfunction
 
+function! s:do(pull, todo)
+  for [name, spec] in items(a:todo)
+    execute 'cd '.s:esc(spec.dir)
+    if has_key(s:prev_update.new, name) || (a:pull &&
+      \ !empty(s:system_chomp('git log --pretty=format:"%h" "HEAD...HEAD@{1}"')))
+      call append(3, '- Post-update hook for '. name .' ... ')
+      let type = type(spec.do)
+      if type == 1 " String
+        call system(spec.do)
+        let result = v:shell_error ? ('Exit status: '.v:shell_error) : 'Done!'
+      elseif type == 2 " Funcref
+        try
+          call spec.do()
+          let result = 'Done!'
+        catch
+          let result = 'Error: ' . v:exception
+        endtry
+      else
+        let result = 'Error: Invalid type!'
+      endif
+      call setline(4, getline(4) . result)
+    endif
+    cd -
+  endfor
+endfunction
+
 function! s:finish(pull)
   call append(3, '- Finishing ... ')
   redraw
@@ -486,8 +524,11 @@ function! s:update_impl(pull, args) abort
   normal! 2G
   redraw
 
+  if !isdirectory(g:plug_home)
+    call mkdir(g:plug_home, 'p')
+  endif
   let len = len(g:plugs)
-  let s:prev_update = { 'errors': [], 'pull': a:pull, 'threads': threads }
+  let s:prev_update = { 'errors': [], 'pull': a:pull, 'new': {}, 'threads': threads }
   if has('ruby') && threads > 1
     try
       let imd = &imd
@@ -517,6 +558,7 @@ function! s:update_impl(pull, args) abort
   else
     call s:update_serial(a:pull, todo)
   endif
+  call s:do(a:pull, filter(copy(todo), 'has_key(v:val, "do")'))
   if len(g:plugs) > len
     call plug#end()
   endif
@@ -562,20 +604,21 @@ function! s:update_serial(pull, todo)
         execute 'cd '.s:esc(spec.dir)
         let [valid, msg] = s:git_valid(spec, 0, 0)
         if valid
-          let result = a:pull ?
+          if a:pull
+            let result =
             \ s:system(
             \ printf('git checkout -q %s 2>&1 && git pull origin %s 2>&1 && git submodule update --init --recursive 2>&1',
-            \   s:shellesc(spec.branch), s:shellesc(spec.branch))) : 'Already installed'
-          let error = a:pull ? v:shell_error != 0 : 0
+            \   s:shellesc(spec.branch), s:shellesc(spec.branch)))
+            let [result, error] = [result, v:shell_error != 0]
+          else
+            let [result, error] = ['Already installed', 0]
+          endif
         else
           let result = msg
           let error = 1
         endif
         cd -
       else
-        if !isdirectory(base)
-          call mkdir(base, 'p')
-        endif
         let result = s:system(
               \ printf('git clone --recursive %s -b %s %s 2>&1 && cd %s && git submodule update --init --recursive 2>&1',
               \ s:shellesc(spec.uri),
@@ -583,6 +626,7 @@ function! s:update_serial(pull, todo)
               \ s:shellesc(substitute(spec.dir, '[\/]\+$', '', '')),
               \ s:shellesc(spec.dir)))
         let error = v:shell_error != 0
+        if !error | let s:prev_update.new[name] = 1 | endif
       endif
       let bar .= error ? 'x' : '='
       if error
@@ -773,8 +817,9 @@ function! s:update_parallel(pull, todo, threads)
             dir, uri, branch = pair.last.values_at *%w[dir uri branch]
             branch = esc branch
             subm = "git submodule update --init --recursive 2>&1"
+            exists = File.directory? dir
             ok, result =
-              if File.directory? dir
+              if exists
                 dir = esc dir
                 ret, data = bt.call "#{cd} #{dir} && git rev-parse --abbrev-ref HEAD 2>&1 && git config remote.origin.url", nil, nil
                 current_uri = data.lines.to_a.last
@@ -797,11 +842,11 @@ function! s:update_parallel(pull, todo, threads)
                   end
                 end
               else
-                FileUtils.mkdir_p(base)
                 d = esc dir.sub(%r{[\\/]+$}, '')
                 log.call name, 'Installing ...', :install
                 bt.call "(git clone #{progress} --recursive #{uri} -b #{branch} #{d} 2>&1 && cd #{esc dir} && #{subm})", name, :install
               end
+            mtx.synchronize { VIM::command("let s:prev_update.new['#{name}'] = 1") } if !exists && ok
             log.call name, result, ok
           end
         } if running
@@ -1082,7 +1127,7 @@ function! s:diff()
     endif
 
     execute 'cd '.s:esc(v.dir)
-    let diff = system('git log --pretty=format:"%h %s (%cr)" "HEAD@{0}...HEAD@{1}"')
+    let diff = system('git log --pretty=format:"%h %s (%cr)" "HEAD...HEAD@{1}"')
     if !v:shell_error && !empty(diff)
       call append(1, '')
       call append(2, '- '.k.':')

+ 90 - 1
test/workflow.vader

@@ -396,7 +396,7 @@ Expect (Aligned code):
   a  = 1
   aa = 2
 
-Given (nothing):
+Given:
 Execute (Partial PlugUpdate):
   PlugUpdate vim-redis
   q
@@ -576,6 +576,94 @@ Execute (Retry failed tasks):
   AssertExpect! '[xxx]', 1
   q
 
+**********************************************************************
+~ Post-update hook (`do` option)
+**********************************************************************
+
+Execute (Cleanup):
+  call plug#begin()
+  call plug#end()
+  PlugClean!
+
+Execute (On install):
+  call plug#begin()
+  Plug 'junegunn/vim-easy-align', { 'do': 'touch installed' }
+  Plug 'junegunn/vim-pseudocl'
+  call plug#end()
+
+  PlugInstall
+  q
+
+  Assert filereadable(g:plugs['vim-easy-align'].dir.'/installed'),
+    \ 'vim-easy-align/installed should exist'
+  Assert !filereadable(g:plugs['vim-pseudocl'].dir.'/installed'),
+    \ 'vim-pseudocl/installed should not exist'
+
+Execute (On update):
+  call plug#begin()
+  Plug 'junegunn/vim-easy-align', { 'do': 'touch updated' }
+  Plug 'junegunn/vim-pseudocl', { 'do': 'touch updated' }
+  call plug#end()
+
+  " Reset for updates
+  call system('cd '.g:plugs['vim-pseudocl'].dir.' && git reset --hard HEAD^')
+
+  PlugUpdate
+  Log getline(1, '$')
+  q
+
+  Assert !filereadable(g:plugs['vim-easy-align'].dir.'/updated'),
+    \ 'vim-easy-align/updated should not exist'
+  Assert filereadable(g:plugs['vim-pseudocl'].dir.'/updated'),
+    \ 'vim-pseudocl/updated should exist'
+
+Execute (When already installed):
+  call plug#begin()
+  Plug 'junegunn/vim-easy-align', { 'do': 'touch installed2' }
+  Plug 'junegunn/vim-pseudocl', { 'do': 'touch installed2' }
+  call plug#end()
+
+  PlugInstall
+  q
+  Assert !filereadable(g:plugs['vim-easy-align'].dir.'/installed2'),
+    \ 'vim-easy-align/installed2 should not exist'
+  Assert !filereadable(g:plugs['vim-pseudocl'].dir.'/installed2'),
+    \ 'vim-pseudocl/installed2 should exist'
+
+Execute (When already updated):
+  call plug#begin()
+  Plug 'junegunn/vim-easy-align', { 'do': 'touch updated2' }
+  Plug 'junegunn/vim-pseudocl', { 'do': 'touch updated2' }
+  call plug#end()
+
+  PlugUpdate
+  q
+  Assert !filereadable(g:plugs['vim-easy-align'].dir.'/updated2'),
+    \ 'vim-easy-align/updated2 should not exist'
+  Assert !filereadable(g:plugs['vim-pseudocl'].dir.'/updated2'),
+    \ 'vim-pseudocl/updated2 should exist'
+
+Execute (Using Funcref):
+  function! PlugUpdated()
+    call system('touch me')
+  endfunction
+
+  call plug#begin()
+  Plug 'junegunn/vim-easy-align', { 'do': function('PlugUpdated') }
+  Plug 'junegunn/vim-pseudocl',   { 'do': function('PlugUpdated') }
+  call plug#end()
+
+  call system('cd '.g:plugs['vim-easy-align'].dir.' && git reset --hard HEAD^')
+  call system('rm -rf '.g:plugs['vim-pseudocl'].dir)
+
+  PlugUpdate
+  Log getline(1, '$')
+  q
+  Assert filereadable(g:plugs['vim-easy-align'].dir.'/me'),
+    \ 'vim-easy-align/me should exist'
+  Assert filereadable(g:plugs['vim-pseudocl'].dir.'/me'),
+    \ 'vim-pseudocl/me should exist'
+
 Execute (Cleanup):
   call system('rm -rf '.temp_plugged)
   call rename('fzf', 'fzf-staged')
@@ -586,6 +674,7 @@ Execute (Cleanup):
   unlet temp_plugged vader plug basertp save_rtp repo lnum fzf
   delf PlugStatusSorted
   delf AssertExpect
+  delf PlugUpdated
   delc AssertExpect
 
   Restore