From e6f40479eec26fa2cf7551d1287dd2ee7097477e Mon Sep 17 00:00:00 2001 From: Junegunn Choi Date: Tue, 22 Dec 2015 23:12:02 +0900 Subject: [PATCH] PlugDiff to show pending updates as well Related: #348 --- README.md | 2 +- plug.vim | 77 ++++++++++++++++++++++++++++++--------------- test/run | 18 ++++++----- test/workflow.vader | 71 +++++++++++++++++++++++++++++++++++++---- 4 files changed, 129 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index 38d3d86..7f760b9 100644 --- a/README.md +++ b/README.md @@ -104,7 +104,7 @@ Reload .vimrc and `:PlugInstall` to install plugins. | `PlugClean[!]` | Remove unused directories (bang version will clean without prompt) | | `PlugUpgrade` | Upgrade vim-plug itself | | `PlugStatus` | Check the status of plugins | -| `PlugDiff` | See the updated changes from the previous PlugUpdate | +| `PlugDiff` | Examine changes from the previous update and the pending changes | | `PlugSnapshot[!] [output path]` | Generate script for restoring the current snapshot of the plugins | ### `Plug` options diff --git a/plug.vim b/plug.vim index c01acc2..c8f755c 100644 --- a/plug.vim +++ b/plug.vim @@ -531,16 +531,20 @@ function! s:syntax() syn match plugStar /^*/ syn match plugMessage /\(^- \)\@<=.*/ syn match plugName /\(^- \)\@<=[^ ]*:/ + syn match plugSha /\%(: \)\@<=[0-9a-z]\{4,}$/ + syn match plugTag /(tag: [^)]\+)/ syn match plugInstall /\(^+ \)\@<=[^:]*/ syn match plugUpdate /\(^* \)\@<=[^:]*/ - syn match plugCommit /^ [0-9a-z]\{7} .*/ contains=plugRelDate,plugSha + syn match plugCommit /^ [0-9a-z]\{7} .*/ contains=plugRelDate,plugSha,plugTag syn match plugSha /\(^ \)\@<=[0-9a-z]\{7}/ contained syn match plugRelDate /([^)]*)$/ contained syn match plugNotLoaded /(not loaded)$/ syn match plugError /^x.*/ + syn match plugH2 /^.*:\n-\+$/ syn keyword Function PlugInstall PlugStatus PlugUpdate PlugClean hi def link plug1 Title hi def link plug2 Repeat + hi def link plugH2 Type hi def link plugX Exception hi def link plugBracket Structure hi def link plugNumber Number @@ -557,6 +561,7 @@ function! s:syntax() hi def link plugError Error hi def link plugRelDate Comment hi def link plugSha Identifier + hi def link plugTag Constant hi def link plugNotLoaded Comment endfunction @@ -1993,41 +1998,63 @@ function! s:section(flags) call search('\(^[x-] \)\@<=[^:]\+:', a:flags) endfunction +function! s:format_git_log(line) + let [sha, refs, subject, date] = split(a:line, nr2char(1)) + let tag = matchstr(refs, 'tag: [^,)]\+') + let tag = empty(tag) ? ' ' : ' ('.tag.') ' + return printf(' %s%s%s (%s)', sha, tag, subject, date) +endfunction + +function! s:append_ul(lnum, text) + call append(a:lnum, ['', a:text, repeat('-', len(a:text))]) +endfunction + function! s:diff() call s:prepare() - call append(0, 'Collecting updated changes ...') - normal! gg - redraw - - let cnt = 0 - for [k, v] in filter(items(g:plugs), '!has_key(v:val[1], "commit")') - if !isdirectory(v.dir) || !s:is_managed(k) - continue - endif - - let diff = s:system_chomp('git log --left-only --pretty=format:"%h %s (%cr)" "HEAD...HEAD@{1}"', v.dir) - if !empty(diff) - call append(1, '') - call append(2, '- '.k.':') - call append(3, map(s:lines(diff), '" ". v:val')) - let cnt += 1 - normal! gg + call append(0, ['Collecting changes ...', '']) + let cnts = [0, 0] + let bar = '' + let total = filter(copy(g:plugs), 's:is_managed(v:key) && isdirectory(v:val.dir)') + call s:progress_bar(2, bar, len(total)) + for origin in [1, 0] + 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"))')))) + 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) + if !empty(diff) + 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 + let bar .= '=' + call s:progress_bar(2, bar, len(total)) + normal! 2G redraw + endfor + if !cnts[origin] + call append(5, ['', 'N/A']) endif endfor + call setline(1, printf('%d plugin(s) updated.', cnts[0]) + \ . (cnts[1] ? printf(' %d plugin(s) have pending updates.', cnts[1]) : '')) - call setline(1, cnt == 0 ? 'No updates.' : 'Last update:') - nnoremap :silent! call preview_commit() - nnoremap o :silent! call preview_commit() - nnoremap X :call revert() - normal! gg - setlocal nomodifiable - if cnt > 0 + if cnts[0] || cnts[1] + nnoremap :silent! call preview_commit() + nnoremap o :silent! call preview_commit() + endif + if cnts[0] + nnoremap X :call revert() echo "Press 'X' on each block to revert the update" endif + normal! gg + setlocal nomodifiable endfunction function! s:revert() + if search('^Pending updates', 'bnW') + return + endif + let name = s:find_name(line('.')) if empty(name) || !has_key(g:plugs, name) || \ input(printf('Revert the update of %s? (y/N) ', name)) !~? '^y' diff --git a/test/run b/test/run index 8efde6a..f97bcaf 100755 --- a/test/run +++ b/test/run @@ -18,7 +18,7 @@ clone() { fi } -clone_repos() { +clone_repos() ( cd /tmp mkdir -p junegunn vim-scripts jg for repo in vader.vim goyo.vim rust.vim seoul256.vim vim-easy-align vim-fnr \ @@ -31,11 +31,9 @@ clone_repos() { clone junegunn/vim-emoji jg/vim-emoji cd junegunn/seoul256.vim && git checkout no-t_co && git checkout master +) - cd "$BASE" -} - -make_dirs() { +make_dirs() ( rm -rf "$PLUG_FIXTURES/$1" mkdir -p "$PLUG_FIXTURES/$1" cd "$PLUG_FIXTURES/$1" @@ -51,9 +49,13 @@ make_dirs() { call add(g:total_order, s:name) EOF done +) - cd "$BASE" -} +gitinit() ( + cd "$PLUG_FIXTURES/$1" + git init + git commit -m 'commit' --allow-empty +) prepare() { make_dirs xxx/ xxx @@ -62,9 +64,11 @@ prepare() { cat > "$PLUG_FIXTURES/xxx/doc/xxx.txt" << DOC hello *xxx* DOC + gitinit xxx make_dirs yyy/ yyy make_dirs yyy/after yyy + gitinit yyy make_dirs z1/ z1 make_dirs z2/ z2 diff --git a/test/workflow.vader b/test/workflow.vader index 7973019..50bf6bc 100644 --- a/test/workflow.vader +++ b/test/workflow.vader @@ -262,12 +262,16 @@ Execute (PlugUpdate only to find out plugins are up-to-date, D key to check): PlugUpdate AssertExpect 'Already up-to-date', 2 normal D - AssertEqual 'No updates.', getline(1) + AssertEqual '0 plugin(s) updated.', getline(1) q Execute (PlugDiff - 'No updates.'): PlugDiff - AssertEqual 'No updates.', getline(1) + Log getline(1, '$') + AssertEqual '0 plugin(s) updated.', getline(1) + Assert empty(mapcheck('o')) + Assert empty(mapcheck('X')) + Assert empty(mapcheck("\")) q Execute (New commits on remote, PlugUpdate, then PlugDiff): @@ -281,7 +285,7 @@ Execute (New commits on remote, PlugUpdate, then PlugDiff): " Now we have updates normal D - AssertEqual 'Last update:', getline(1) + AssertEqual '2 plugin(s) updated.', getline(1) " Preview commit silent! wincmd P @@ -367,7 +371,58 @@ Execute (contd. PlugDiff should not show inverted history): " PlugDiff should not report the changes i.e. git log --left-only PlugDiff Log getline(1, '$') - AssertEqual 'No updates.', getline(1) + AssertEqual '0 plugin(s) updated.', getline(1) + q + +********************************************************************** +~ PlugDiff to see the pending changes +********************************************************************** + +Execute (PlugDiff): + call plug#begin() + call plug#end() + PlugClean! + + call plug#begin() + Plug 'file://'.expand('$PLUG_FIXTURES').'/xxx' + Plug 'file://'.expand('$PLUG_FIXTURES').'/yyy' + call plug#end() + PlugInstall + Log getline(1, '$') + + call system('cd "$PLUG_FIXTURES/xxx" && git commit --allow-empty -m update-xxx && git tag -f xxx') + call system('cd "$PLUG_FIXTURES/yyy" && git tag -f yyy && git commit --allow-empty -m update-yyy && git tag -f zzz') + + let g:plugs.yyy.tag = 'yyy' + PlugUpdate + Log getline(1, '$') + + PlugDiff + " 1 plugin(s) updated. 1 plugin(s) have pending updates. + " [==] + " + " Last update: + " ------------ + " + " - xxx: + " 166cfff (tag: xxx) update-xxx (1 second ago) + " + " Pending updates: + " ---------------- + " + " - yyy: (tag: yyy) + " c0a064b (tag: zzz) update-yyy (1 second ago) + " + Log getline(1, '$') + AssertEqual 15, line('$') + AssertEqual '1 plugin(s) updated. 1 plugin(s) have pending updates.', getline(1) + AssertEqual '[==]', getline(2) + AssertEqual '- yyy: (tag: yyy)', getline(13) + Assert getline(8) =~ '(tag: xxx)' + Assert getline(14) =~ '(tag: zzz)' + Assert !empty(mapcheck('o')) + Assert !empty(mapcheck('X')) + Assert !empty(mapcheck("\")) q ********************************************************************** @@ -1258,9 +1313,13 @@ Execute (Commit hash support): AssertEqual [' PlugUpdate required.', \'- vim-emoji: OK'], getline(6, '$') - " Plugins with commit option should not appear in PlugDiff output + " PlugDiff should show pending updates for vim-emoji PlugDiff - AssertEqual 'No updates.', getline(1) + Log getline(1, '$') + AssertEqual '0 plugin(s) updated. 1 plugin(s) have pending updates.', getline(1) + Assert !empty(mapcheck('o')) + Assert empty(mapcheck('X')) + Assert !empty(mapcheck("\")) " Nor in PlugSnapshot output PlugSnapshot