.vim/autoload/plug.vim

changeset 888
44d34f2382f6
parent 878
ab714f06ef57
child 889
4400fb670a80
equal deleted inserted replaced
887:c3d421c18e39 888:44d34f2382f6
23 " 23 "
24 " " On-demand loading 24 " " On-demand loading
25 " Plug 'scrooloose/nerdtree', { 'on': 'NERDTreeToggle' } 25 " Plug 'scrooloose/nerdtree', { 'on': 'NERDTreeToggle' }
26 " Plug 'tpope/vim-fireplace', { 'for': 'clojure' } 26 " Plug 'tpope/vim-fireplace', { 'for': 'clojure' }
27 " 27 "
28 " " Using a non-master branch 28 " " Using a non-default branch
29 " Plug 'rdnetto/YCM-Generator', { 'branch': 'stable' } 29 " Plug 'rdnetto/YCM-Generator', { 'branch': 'stable' }
30 " 30 "
31 " " Using a tagged release; wildcard allowed (requires git 1.9.2 or above) 31 " " Using a tagged release; wildcard allowed (requires git 1.9.2 or above)
32 " Plug 'fatih/vim-go', { 'tag': '*' } 32 " Plug 'fatih/vim-go', { 'tag': '*' }
33 " 33 "
104 let s:me = resolve(expand('<sfile>:p')) 104 let s:me = resolve(expand('<sfile>:p'))
105 set shellslash 105 set shellslash
106 else 106 else
107 let s:me = resolve(expand('<sfile>:p')) 107 let s:me = resolve(expand('<sfile>:p'))
108 endif 108 endif
109 let s:base_spec = { 'branch': 'master', 'frozen': 0 } 109 let s:base_spec = { 'branch': '', 'frozen': 0 }
110 let s:TYPE = { 110 let s:TYPE = {
111 \ 'string': type(''), 111 \ 'string': type(''),
112 \ 'list': type([]), 112 \ 'list': type([]),
113 \ 'dict': type({}), 113 \ 'dict': type({}),
114 \ 'funcref': type(function('call')) 114 \ 'funcref': type(function('call'))
115 \ } 115 \ }
116 let s:loaded = get(s:, 'loaded', {}) 116 let s:loaded = get(s:, 'loaded', {})
117 let s:triggers = get(s:, 'triggers', {}) 117 let s:triggers = get(s:, 'triggers', {})
118
119 function! s:isabsolute(dir) abort
120 return a:dir =~# '^/' || (has('win32') && a:dir =~? '^\%(\\\|[A-Z]:\)')
121 endfunction
122
123 function! s:git_dir(dir) abort
124 let gitdir = s:trim(a:dir) . '/.git'
125 if isdirectory(gitdir)
126 return gitdir
127 endif
128 if !filereadable(gitdir)
129 return ''
130 endif
131 let gitdir = matchstr(get(readfile(gitdir), 0, ''), '^gitdir: \zs.*')
132 if len(gitdir) && !s:isabsolute(gitdir)
133 let gitdir = a:dir . '/' . gitdir
134 endif
135 return isdirectory(gitdir) ? gitdir : ''
136 endfunction
137
138 function! s:git_origin_url(dir) abort
139 let gitdir = s:git_dir(a:dir)
140 let config = gitdir . '/config'
141 if empty(gitdir) || !filereadable(config)
142 return ''
143 endif
144 return matchstr(join(readfile(config)), '\[remote "origin"\].\{-}url\s*=\s*\zs\S*\ze')
145 endfunction
146
147 function! s:git_revision(dir) abort
148 let gitdir = s:git_dir(a:dir)
149 let head = gitdir . '/HEAD'
150 if empty(gitdir) || !filereadable(head)
151 return ''
152 endif
153
154 let line = get(readfile(head), 0, '')
155 let ref = matchstr(line, '^ref: \zs.*')
156 if empty(ref)
157 return line
158 endif
159
160 if filereadable(gitdir . '/' . ref)
161 return get(readfile(gitdir . '/' . ref), 0, '')
162 endif
163
164 if filereadable(gitdir . '/packed-refs')
165 for line in readfile(gitdir . '/packed-refs')
166 if line =~# ' ' . ref
167 return matchstr(line, '^[0-9a-f]*')
168 endif
169 endfor
170 endif
171
172 return ''
173 endfunction
174
175 function! s:git_local_branch(dir) abort
176 let gitdir = s:git_dir(a:dir)
177 let head = gitdir . '/HEAD'
178 if empty(gitdir) || !filereadable(head)
179 return ''
180 endif
181 let branch = matchstr(get(readfile(head), 0, ''), '^ref: refs/heads/\zs.*')
182 return len(branch) ? branch : 'HEAD'
183 endfunction
184
185 function! s:git_origin_branch(spec)
186 if len(a:spec.branch)
187 return a:spec.branch
188 endif
189
190 " The file may not be present if this is a local repository
191 let gitdir = s:git_dir(a:spec.dir)
192 let origin_head = gitdir.'/refs/remotes/origin/HEAD'
193 if len(gitdir) && filereadable(origin_head)
194 return matchstr(get(readfile(origin_head), 0, ''),
195 \ '^ref: refs/remotes/origin/\zs.*')
196 endif
197
198 " The command may not return the name of a branch in detached HEAD state
199 let result = s:lines(s:system('git symbolic-ref --short HEAD', a:spec.dir))
200 return v:shell_error ? '' : result[-1]
201 endfunction
118 202
119 if s:is_win 203 if s:is_win
120 function! s:plug_call(fn, ...) 204 function! s:plug_call(fn, ...)
121 let shellslash = &shellslash 205 let shellslash = &shellslash
122 try 206 try
644 if empty(a:arg) 728 if empty(a:arg)
645 throw printf(opt_errfmt, 'tag', 'string') 729 throw printf(opt_errfmt, 'tag', 'string')
646 endif 730 endif
647 let opts.tag = a:arg 731 let opts.tag = a:arg
648 elseif type == s:TYPE.dict 732 elseif type == s:TYPE.dict
649 call extend(opts, a:arg)
650 for opt in ['branch', 'tag', 'commit', 'rtp', 'dir', 'as'] 733 for opt in ['branch', 'tag', 'commit', 'rtp', 'dir', 'as']
651 if has_key(opts, opt) 734 if has_key(a:arg, opt)
652 \ && (type(opts[opt]) != s:TYPE.string || empty(opts[opt])) 735 \ && (type(a:arg[opt]) != s:TYPE.string || empty(a:arg[opt]))
653 throw printf(opt_errfmt, opt, 'string') 736 throw printf(opt_errfmt, opt, 'string')
654 endif 737 endif
655 endfor 738 endfor
656 for opt in ['on', 'for'] 739 for opt in ['on', 'for']
657 if has_key(opts, opt) 740 if has_key(a:arg, opt)
658 \ && type(opts[opt]) != s:TYPE.list 741 \ && type(a:arg[opt]) != s:TYPE.list
659 \ && (type(opts[opt]) != s:TYPE.string || empty(opts[opt])) 742 \ && (type(a:arg[opt]) != s:TYPE.string || empty(a:arg[opt]))
660 throw printf(opt_errfmt, opt, 'string or list') 743 throw printf(opt_errfmt, opt, 'string or list')
661 endif 744 endif
662 endfor 745 endfor
663 if has_key(opts, 'do') 746 if has_key(a:arg, 'do')
664 \ && type(opts.do) != s:TYPE.funcref 747 \ && type(a:arg.do) != s:TYPE.funcref
665 \ && (type(opts.do) != s:TYPE.string || empty(opts.do)) 748 \ && (type(a:arg.do) != s:TYPE.string || empty(a:arg.do))
666 throw printf(opt_errfmt, 'do', 'string or funcref') 749 throw printf(opt_errfmt, 'do', 'string or funcref')
667 endif 750 endif
751 call extend(opts, a:arg)
668 if has_key(opts, 'dir') 752 if has_key(opts, 'dir')
669 let opts.dir = s:dirpath(s:plug_expand(opts.dir)) 753 let opts.dir = s:dirpath(s:plug_expand(opts.dir))
670 endif 754 endif
671 else 755 else
672 throw 'Invalid argument type (expected: string or dictionary)' 756 throw 'Invalid argument type (expected: string or dictionary)'
989 return stridx(a:a, a:b) == 0 || stridx(a:b, a:a) == 0 1073 return stridx(a:a, a:b) == 0 || stridx(a:b, a:a) == 0
990 endfunction 1074 endfunction
991 1075
992 function! s:checkout(spec) 1076 function! s:checkout(spec)
993 let sha = a:spec.commit 1077 let sha = a:spec.commit
994 let output = s:system(['git', 'rev-parse', 'HEAD'], a:spec.dir) 1078 let output = s:git_revision(a:spec.dir)
995 if !v:shell_error && !s:hash_match(sha, s:lines(output)[0]) 1079 if !empty(output) && !s:hash_match(sha, s:lines(output)[0])
996 let output = s:system( 1080 let output = s:system(
997 \ 'git fetch --depth 999999 && git checkout '.plug#shellescape(sha).' --', a:spec.dir) 1081 \ 'git fetch --depth 999999 && git checkout '.plug#shellescape(sha).' --', a:spec.dir)
998 endif 1082 endif
999 return output 1083 return output
1000 endfunction 1084 endfunction
1204 endif 1288 endif
1205 endif 1289 endif
1206 call s:log4(name, 'Checking out '.tag) 1290 call s:log4(name, 'Checking out '.tag)
1207 let out = s:system('git checkout -q '.plug#shellescape(tag).' -- 2>&1', spec.dir) 1291 let out = s:system('git checkout -q '.plug#shellescape(tag).' -- 2>&1', spec.dir)
1208 else 1292 else
1209 let branch = get(spec, 'branch', 'master') 1293 let branch = s:git_origin_branch(spec)
1210 call s:log4(name, 'Merging origin/'.s:esc(branch)) 1294 call s:log4(name, 'Merging origin/'.s:esc(branch))
1211 let out = s:system('git checkout -q '.plug#shellescape(branch).' -- 2>&1' 1295 let out = s:system('git checkout -q '.plug#shellescape(branch).' -- 2>&1'
1212 \. (has_key(s:update.new, name) ? '' : ('&& git merge --ff-only '.plug#shellescape('origin/'.branch).' 2>&1')), spec.dir) 1296 \. (has_key(s:update.new, name) ? '' : ('&& git merge --ff-only '.plug#shellescape('origin/'.branch).' 2>&1')), spec.dir)
1213 endif 1297 endif
1214 if !v:shell_error && filereadable(spec.dir.'/.gitmodules') && 1298 if !v:shell_error && filereadable(spec.dir.'/.gitmodules') &&
2209 endfunction 2293 endfunction
2210 2294
2211 function! s:git_validate(spec, check_branch) 2295 function! s:git_validate(spec, check_branch)
2212 let err = '' 2296 let err = ''
2213 if isdirectory(a:spec.dir) 2297 if isdirectory(a:spec.dir)
2214 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)) 2298 let result = [s:git_local_branch(a:spec.dir), s:git_origin_url(a:spec.dir)]
2215 let remote = result[-1] 2299 let remote = result[-1]
2216 if v:shell_error 2300 if empty(remote)
2217 let err = join([remote, 'PlugClean required.'], "\n") 2301 let err = join([remote, 'PlugClean required.'], "\n")
2218 elseif !s:compare_git_uri(remote, a:spec.uri) 2302 elseif !s:compare_git_uri(remote, a:spec.uri)
2219 let err = join(['Invalid URI: '.remote, 2303 let err = join(['Invalid URI: '.remote,
2220 \ 'Expected: '.a:spec.uri, 2304 \ 'Expected: '.a:spec.uri,
2221 \ 'PlugClean required.'], "\n") 2305 \ 'PlugClean required.'], "\n")
2222 elseif a:check_branch && has_key(a:spec, 'commit') 2306 elseif a:check_branch && has_key(a:spec, 'commit')
2223 let result = s:lines(s:system('git rev-parse HEAD 2>&1', a:spec.dir)) 2307 let sha = s:git_revision(a:spec.dir)
2224 let sha = result[-1] 2308 if empty(sha)
2225 if v:shell_error
2226 let err = join(add(result, 'PlugClean required.'), "\n") 2309 let err = join(add(result, 'PlugClean required.'), "\n")
2227 elseif !s:hash_match(sha, a:spec.commit) 2310 elseif !s:hash_match(sha, a:spec.commit)
2228 let err = join([printf('Invalid HEAD (expected: %s, actual: %s)', 2311 let err = join([printf('Invalid HEAD (expected: %s, actual: %s)',
2229 \ a:spec.commit[:6], sha[:6]), 2312 \ a:spec.commit[:6], sha[:6]),
2230 \ 'PlugUpdate required.'], "\n") 2313 \ 'PlugUpdate required.'], "\n")
2231 endif 2314 endif
2232 elseif a:check_branch 2315 elseif a:check_branch
2233 let branch = result[0] 2316 let current_branch = result[0]
2234 " Check tag 2317 " Check tag
2318 let origin_branch = s:git_origin_branch(a:spec)
2235 if has_key(a:spec, 'tag') 2319 if has_key(a:spec, 'tag')
2236 let tag = s:system_chomp('git describe --exact-match --tags HEAD 2>&1', a:spec.dir) 2320 let tag = s:system_chomp('git describe --exact-match --tags HEAD 2>&1', a:spec.dir)
2237 if a:spec.tag !=# tag && a:spec.tag !~ '\*' 2321 if a:spec.tag !=# tag && a:spec.tag !~ '\*'
2238 let err = printf('Invalid tag: %s (expected: %s). Try PlugUpdate.', 2322 let err = printf('Invalid tag: %s (expected: %s). Try PlugUpdate.',
2239 \ (empty(tag) ? 'N/A' : tag), a:spec.tag) 2323 \ (empty(tag) ? 'N/A' : tag), a:spec.tag)
2240 endif 2324 endif
2241 " Check branch 2325 " Check branch
2242 elseif a:spec.branch !=# branch 2326 elseif origin_branch !=# current_branch
2243 let err = printf('Invalid branch: %s (expected: %s). Try PlugUpdate.', 2327 let err = printf('Invalid branch: %s (expected: %s). Try PlugUpdate.',
2244 \ branch, a:spec.branch) 2328 \ current_branch, origin_branch)
2245 endif 2329 endif
2246 if empty(err) 2330 if empty(err)
2247 let [ahead, behind] = split(s:lastline(s:system([ 2331 let [ahead, behind] = split(s:lastline(s:system([
2248 \ 'git', 'rev-list', '--count', '--left-right', 2332 \ 'git', 'rev-list', '--count', '--left-right',
2249 \ printf('HEAD...origin/%s', a:spec.branch) 2333 \ printf('HEAD...origin/%s', origin_branch)
2250 \ ], a:spec.dir)), '\t') 2334 \ ], a:spec.dir)), '\t')
2251 if !v:shell_error && ahead 2335 if !v:shell_error && ahead
2252 if behind 2336 if behind
2253 " Only mention PlugClean if diverged, otherwise it's likely to be 2337 " Only mention PlugClean if diverged, otherwise it's likely to be
2254 " pushable (and probably not that messed up). 2338 " pushable (and probably not that messed up).
2255 let err = printf( 2339 let err = printf(
2256 \ "Diverged from origin/%s (%d commit(s) ahead and %d commit(s) behind!\n" 2340 \ "Diverged from origin/%s (%d commit(s) ahead and %d commit(s) behind!\n"
2257 \ .'Backup local changes and run PlugClean and PlugUpdate to reinstall it.', a:spec.branch, ahead, behind) 2341 \ .'Backup local changes and run PlugClean and PlugUpdate to reinstall it.', origin_branch, ahead, behind)
2258 else 2342 else
2259 let err = printf("Ahead of origin/%s by %d commit(s).\n" 2343 let err = printf("Ahead of origin/%s by %d commit(s).\n"
2260 \ .'Cannot update until local changes are pushed.', 2344 \ .'Cannot update until local changes are pushed.',
2261 \ a:spec.branch, ahead) 2345 \ origin_branch, ahead)
2262 endif 2346 endif
2263 endif 2347 endif
2264 endif 2348 endif
2265 endif 2349 endif
2266 else 2350 else
2586 if empty(plugs) 2670 if empty(plugs)
2587 continue 2671 continue
2588 endif 2672 endif
2589 call s:append_ul(2, origin ? 'Pending updates:' : 'Last update:') 2673 call s:append_ul(2, origin ? 'Pending updates:' : 'Last update:')
2590 for [k, v] in plugs 2674 for [k, v] in plugs
2591 let range = origin ? '..origin/'.v.branch : 'HEAD@{1}..' 2675 let branch = s:git_origin_branch(v)
2592 let cmd = ['git', 'log', '--graph', '--color=never'] 2676 if len(branch)
2593 if s:git_version_requirement(2, 10, 0) 2677 let range = origin ? '..origin/'.branch : 'HEAD@{1}..'
2594 call add(cmd, '--no-show-signature') 2678 let cmd = ['git', 'log', '--graph', '--color=never']
2595 endif 2679 if s:git_version_requirement(2, 10, 0)
2596 call extend(cmd, ['--pretty=format:%x01%h%x01%d%x01%s%x01%cr', range]) 2680 call add(cmd, '--no-show-signature')
2597 if has_key(v, 'rtp') 2681 endif
2598 call extend(cmd, ['--', v.rtp]) 2682 call extend(cmd, ['--pretty=format:%x01%h%x01%d%x01%s%x01%cr', range])
2599 endif 2683 if has_key(v, 'rtp')
2600 let diff = s:system_chomp(cmd, v.dir) 2684 call extend(cmd, ['--', v.rtp])
2601 if !empty(diff) 2685 endif
2602 let ref = has_key(v, 'tag') ? (' (tag: '.v.tag.')') : has_key(v, 'commit') ? (' '.v.commit) : '' 2686 let diff = s:system_chomp(cmd, v.dir)
2603 call append(5, extend(['', '- '.k.':'.ref], map(s:lines(diff), 's:format_git_log(v:val)'))) 2687 if !empty(diff)
2604 let cnts[origin] += 1 2688 let ref = has_key(v, 'tag') ? (' (tag: '.v.tag.')') : has_key(v, 'commit') ? (' '.v.commit) : ''
2689 call append(5, extend(['', '- '.k.':'.ref], map(s:lines(diff), 's:format_git_log(v:val)')))
2690 let cnts[origin] += 1
2691 endif
2605 endif 2692 endif
2606 let bar .= '=' 2693 let bar .= '='
2607 call s:progress_bar(2, bar, len(total)) 2694 call s:progress_bar(2, bar, len(total))
2608 normal! 2G 2695 normal! 2G
2609 redraw 2696 redraw
2661 1 2748 1
2662 let anchor = line('$') - 3 2749 let anchor = line('$') - 3
2663 let names = sort(keys(filter(copy(g:plugs), 2750 let names = sort(keys(filter(copy(g:plugs),
2664 \'has_key(v:val, "uri") && !has_key(v:val, "commit") && isdirectory(v:val.dir)'))) 2751 \'has_key(v:val, "uri") && !has_key(v:val, "commit") && isdirectory(v:val.dir)')))
2665 for name in reverse(names) 2752 for name in reverse(names)
2666 let sha = s:system_chomp(['git', 'rev-parse', '--short', 'HEAD'], g:plugs[name].dir) 2753 let sha = s:git_revision(g:plugs[name].dir)
2667 if !empty(sha) 2754 if !empty(sha)
2668 call append(anchor, printf("silent! let g:plugs['%s'].commit = '%s'", name, sha)) 2755 call append(anchor, printf("silent! let g:plugs['%s'].commit = '%s'", name, sha))
2669 redraw 2756 redraw
2670 endif 2757 endif
2671 endfor 2758 endfor

mercurial