348 endfunction |
348 endfunction |
349 |
349 |
350 function! s:is_local_plug(repo) |
350 function! s:is_local_plug(repo) |
351 return a:repo =~? '^[a-z]:\|^[%~]' |
351 return a:repo =~? '^[a-z]:\|^[%~]' |
352 endfunction |
352 endfunction |
|
353 |
|
354 " Copied from fzf |
|
355 function! s:wrap_cmds(cmds) |
|
356 return map(['@echo off','setlocal enabledelayedexpansion','for /f "delims=: tokens=2" %%a in (''chcp'') do set origchcp=%%a','set origchcp=!origchcp: =!','chcp 65001 > nul'] + |
|
357 \ (type(a:cmds) == type([]) ? a:cmds : [a:cmds]) + |
|
358 \ ['chcp !origchcp! > nul','setlocal disabledelayedexpansion'],'v:val."\r"') |
|
359 endfunction |
|
360 |
|
361 function! s:batchfile(cmd) |
|
362 let batchfile = tempname().'.bat' |
|
363 call writefile(s:wrap_cmds(a:cmd), batchfile) |
|
364 let cmd = plug#shellescape(batchfile, {'shell': &shell, 'script': 1}) |
|
365 if &shell =~# 'powershell\.exe$' |
|
366 let cmd = '& ' . cmd |
|
367 endif |
|
368 return [batchfile, cmd] |
|
369 endfunction |
353 else |
370 else |
354 function! s:rtp(spec) |
371 function! s:rtp(spec) |
355 return s:dirpath(a:spec.dir . get(a:spec, 'rtp', '')) |
372 return s:dirpath(a:spec.dir . get(a:spec, 'rtp', '')) |
356 endfunction |
373 endfunction |
357 |
374 |
805 let [sh, shellcmdflag, shrd] = s:chsh(a:0) |
822 let [sh, shellcmdflag, shrd] = s:chsh(a:0) |
806 " FIXME: Escaping is incomplete. We could use shellescape with eval, |
823 " FIXME: Escaping is incomplete. We could use shellescape with eval, |
807 " but it won't work on Windows. |
824 " but it won't work on Windows. |
808 let cmd = a:0 ? s:with_cd(a:cmd, a:1) : a:cmd |
825 let cmd = a:0 ? s:with_cd(a:cmd, a:1) : a:cmd |
809 if s:is_win |
826 if s:is_win |
810 let batchfile = tempname().'.bat' |
827 let [batchfile, cmd] = s:batchfile(cmd) |
811 call writefile(["@echo off\r", cmd . "\r"], batchfile) |
|
812 let cmd = s:shellesc(expand(batchfile)) |
|
813 endif |
828 endif |
814 let g:_plug_bang = (s:is_win && has('gui_running') ? 'silent ' : '').'!'.escape(cmd, '#!%') |
829 let g:_plug_bang = (s:is_win && has('gui_running') ? 'silent ' : '').'!'.escape(cmd, '#!%') |
815 execute "normal! :execute g:_plug_bang\<cr>\<cr>" |
830 execute "normal! :execute g:_plug_bang\<cr>\<cr>" |
816 finally |
831 finally |
817 unlet g:_plug_bang |
832 unlet g:_plug_bang |
1090 call s:log4(name, 'Checking out '.spec.commit) |
1105 call s:log4(name, 'Checking out '.spec.commit) |
1091 let out = s:checkout(spec) |
1106 let out = s:checkout(spec) |
1092 elseif has_key(spec, 'tag') |
1107 elseif has_key(spec, 'tag') |
1093 let tag = spec.tag |
1108 let tag = spec.tag |
1094 if tag =~ '\*' |
1109 if tag =~ '\*' |
1095 let tags = s:lines(s:system('git tag --list '.s:shellesc(tag).' --sort -version:refname 2>&1', spec.dir)) |
1110 let tags = s:lines(s:system('git tag --list '.plug#shellescape(tag).' --sort -version:refname 2>&1', spec.dir)) |
1096 if !v:shell_error && !empty(tags) |
1111 if !v:shell_error && !empty(tags) |
1097 let tag = tags[0] |
1112 let tag = tags[0] |
1098 call s:log4(name, printf('Latest tag for %s -> %s', spec.tag, tag)) |
1113 call s:log4(name, printf('Latest tag for %s -> %s', spec.tag, tag)) |
1099 call append(3, '') |
1114 call append(3, '') |
1100 endif |
1115 endif |
1200 \ s:job_cb('s:job_exit_cb', self, 0, a:data) |
1215 \ s:job_cb('s:job_exit_cb', self, 0, a:data) |
1201 endfunction |
1216 endfunction |
1202 |
1217 |
1203 function! s:spawn(name, cmd, opts) |
1218 function! s:spawn(name, cmd, opts) |
1204 let job = { 'name': a:name, 'running': 1, 'error': 0, 'lines': [''], |
1219 let job = { 'name': a:name, 'running': 1, 'error': 0, 'lines': [''], |
1205 \ 'batchfile': (s:is_win && (s:nvim || s:vim8)) ? tempname().'.bat' : '', |
|
1206 \ 'new': get(a:opts, 'new', 0) } |
1220 \ 'new': get(a:opts, 'new', 0) } |
1207 let s:jobs[a:name] = job |
1221 let s:jobs[a:name] = job |
1208 let cmd = has_key(a:opts, 'dir') ? s:with_cd(a:cmd, a:opts.dir) : a:cmd |
1222 let cmd = has_key(a:opts, 'dir') ? s:with_cd(a:cmd, a:opts.dir, 0) : a:cmd |
1209 if !empty(job.batchfile) |
1223 let argv = s:is_win ? ['cmd', '/s', '/c', '"'.cmd.'"'] : ['sh', '-c', cmd] |
1210 call writefile(["@echo off\r", cmd . "\r"], job.batchfile) |
|
1211 let cmd = s:shellesc(expand(job.batchfile)) |
|
1212 endif |
|
1213 let argv = add(s:is_win ? ['cmd', '/c'] : ['sh', '-c'], cmd) |
|
1214 |
1224 |
1215 if s:nvim |
1225 if s:nvim |
1216 call extend(job, { |
1226 call extend(job, { |
1217 \ 'on_stdout': function('s:nvim_cb'), |
1227 \ 'on_stdout': function('s:nvim_cb'), |
1218 \ 'on_exit': function('s:nvim_cb'), |
1228 \ 'on_exit': function('s:nvim_cb'), |
1258 let bullet = job.error ? 'x' : '-' |
1268 let bullet = job.error ? 'x' : '-' |
1259 let result = job.error ? join(job.lines, "\n") : s:last_non_empty_line(job.lines) |
1269 let result = job.error ? join(job.lines, "\n") : s:last_non_empty_line(job.lines) |
1260 call s:log(bullet, a:name, empty(result) ? 'OK' : result) |
1270 call s:log(bullet, a:name, empty(result) ? 'OK' : result) |
1261 call s:bar() |
1271 call s:bar() |
1262 |
1272 |
1263 if has_key(job, 'batchfile') && !empty(job.batchfile) |
|
1264 call delete(job.batchfile) |
|
1265 endif |
|
1266 call remove(s:jobs, a:name) |
1273 call remove(s:jobs, a:name) |
1267 endfunction |
1274 endfunction |
1268 |
1275 |
1269 function! s:bar() |
1276 function! s:bar() |
1270 if s:switch_in() |
1277 if s:switch_in() |
1350 else |
1357 else |
1351 call s:spawn(name, |
1358 call s:spawn(name, |
1352 \ printf('git clone %s %s %s %s 2>&1', |
1359 \ printf('git clone %s %s %s %s 2>&1', |
1353 \ has_tag ? '' : s:clone_opt, |
1360 \ has_tag ? '' : s:clone_opt, |
1354 \ prog, |
1361 \ prog, |
1355 \ s:shellesc(spec.uri), |
1362 \ plug#shellescape(spec.uri, {'script': 0}), |
1356 \ s:shellesc(s:trim(spec.dir))), { 'new': 1 }) |
1363 \ plug#shellescape(s:trim(spec.dir), {'script': 0})), { 'new': 1 }) |
1357 endif |
1364 endif |
1358 |
1365 |
1359 if !s:jobs[name].running |
1366 if !s:jobs[name].running |
1360 call s:reap(name) |
1367 call s:reap(name) |
1361 endif |
1368 endif |
1978 refresh.kill if refresh |
1985 refresh.kill if refresh |
1979 watcher.kill |
1986 watcher.kill |
1980 EOF |
1987 EOF |
1981 endfunction |
1988 endfunction |
1982 |
1989 |
1983 function! s:shellesc_cmd(arg) |
1990 function! s:shellesc_cmd(arg, script) |
1984 let escaped = substitute(a:arg, '[&|<>()@^]', '^&', 'g') |
1991 let escaped = substitute('"'.a:arg.'"', '[&|<>()@^!"]', '^&', 'g') |
1985 let escaped = substitute(escaped, '%', '%%', 'g') |
1992 return substitute(escaped, '%', (a:script ? '%' : '^') . '&', 'g') |
1986 let escaped = substitute(escaped, '"', '\\^&', 'g') |
1993 endfunction |
1987 let escaped = substitute(escaped, '\(\\\+\)\(\\^\)', '\1\1\2', 'g') |
1994 |
1988 return '^"'.substitute(escaped, '\(\\\+\)$', '\1\1', '').'^"' |
1995 function! s:shellesc_ps1(arg) |
1989 endfunction |
1996 return "'".substitute(escape(a:arg, '\"'), "'", "''", 'g')."'" |
1990 |
1997 endfunction |
1991 function! s:shellesc(arg) |
1998 |
1992 if &shell =~# 'cmd.exe$' |
1999 function! plug#shellescape(arg, ...) |
1993 return s:shellesc_cmd(a:arg) |
2000 let opts = a:0 > 0 && type(a:1) == s:TYPE.dict ? a:1 : {} |
|
2001 let shell = get(opts, 'shell', s:is_win ? 'cmd.exe' : 'sh') |
|
2002 let script = get(opts, 'script', 1) |
|
2003 if shell =~# 'cmd\.exe$' |
|
2004 return s:shellesc_cmd(a:arg, script) |
|
2005 elseif shell =~# 'powershell\.exe$' || shell =~# 'pwsh$' |
|
2006 return s:shellesc_ps1(a:arg) |
1994 endif |
2007 endif |
1995 return shellescape(a:arg) |
2008 return shellescape(a:arg) |
1996 endfunction |
2009 endfunction |
1997 |
2010 |
1998 function! s:glob_dir(path) |
2011 function! s:glob_dir(path) |
2022 let lines = map(s:lines(a:message), '" ".v:val') |
2035 let lines = map(s:lines(a:message), '" ".v:val') |
2023 return extend([printf('x %s:', a:name)], lines) |
2036 return extend([printf('x %s:', a:name)], lines) |
2024 endif |
2037 endif |
2025 endfunction |
2038 endfunction |
2026 |
2039 |
2027 function! s:with_cd(cmd, dir) |
2040 function! s:with_cd(cmd, dir, ...) |
2028 return printf('cd%s %s && %s', s:is_win ? ' /d' : '', s:shellesc(a:dir), a:cmd) |
2041 let script = a:0 > 0 ? a:1 : 1 |
|
2042 return printf('cd%s %s && %s', s:is_win ? ' /d' : '', plug#shellescape(a:dir, {'script': script}), a:cmd) |
2029 endfunction |
2043 endfunction |
2030 |
2044 |
2031 function! s:system(cmd, ...) |
2045 function! s:system(cmd, ...) |
2032 try |
2046 try |
2033 let [sh, shellcmdflag, shrd] = s:chsh(1) |
2047 let [sh, shellcmdflag, shrd] = s:chsh(1) |
2034 let cmd = a:0 > 0 ? s:with_cd(a:cmd, a:1) : a:cmd |
2048 let cmd = a:0 > 0 ? s:with_cd(a:cmd, a:1) : a:cmd |
2035 if s:is_win |
2049 if s:is_win |
2036 let batchfile = tempname().'.bat' |
2050 let [batchfile, cmd] = s:batchfile(cmd) |
2037 call writefile(["@echo off\r", cmd . "\r"], batchfile) |
|
2038 let cmd = s:shellesc(expand(batchfile)) |
|
2039 endif |
2051 endif |
2040 return system(cmd) |
2052 return system(cmd) |
2041 finally |
2053 finally |
2042 let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd] |
2054 let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd] |
2043 if s:is_win |
2055 if s:is_win |
2111 return [err, err =~# 'PlugClean'] |
2123 return [err, err =~# 'PlugClean'] |
2112 endfunction |
2124 endfunction |
2113 |
2125 |
2114 function! s:rm_rf(dir) |
2126 function! s:rm_rf(dir) |
2115 if isdirectory(a:dir) |
2127 if isdirectory(a:dir) |
2116 call s:system((s:is_win ? 'rmdir /S /Q ' : 'rm -rf ') . s:shellesc(a:dir)) |
2128 call s:system((s:is_win ? 'rmdir /S /Q ' : 'rm -rf ') . plug#shellescape(a:dir)) |
2117 endif |
2129 endif |
2118 endfunction |
2130 endfunction |
2119 |
2131 |
2120 function! s:clean(force) |
2132 function! s:clean(force) |
2121 call s:prepare() |
2133 call s:prepare() |
2220 redraw |
2232 redraw |
2221 let tmp = tempname() |
2233 let tmp = tempname() |
2222 let new = tmp . '/plug.vim' |
2234 let new = tmp . '/plug.vim' |
2223 |
2235 |
2224 try |
2236 try |
2225 let out = s:system(printf('git clone --depth 1 %s %s', s:shellesc(s:plug_src), s:shellesc(tmp))) |
2237 let out = s:system(printf('git clone --depth 1 %s %s', plug#shellescape(s:plug_src), plug#shellescape(tmp))) |
2226 if v:shell_error |
2238 if v:shell_error |
2227 return s:err('Error upgrading vim-plug: '. out) |
2239 return s:err('Error upgrading vim-plug: '. out) |
2228 endif |
2240 endif |
2229 |
2241 |
2230 if readfile(s:me) ==# readfile(new) |
2242 if readfile(s:me) ==# readfile(new) |
2363 wincmd P |
2375 wincmd P |
2364 endif |
2376 endif |
2365 setlocal previewwindow filetype=git buftype=nofile nobuflisted modifiable |
2377 setlocal previewwindow filetype=git buftype=nofile nobuflisted modifiable |
2366 try |
2378 try |
2367 let [sh, shellcmdflag, shrd] = s:chsh(1) |
2379 let [sh, shellcmdflag, shrd] = s:chsh(1) |
2368 let cmd = 'cd '.s:shellesc(g:plugs[name].dir).' && git show --no-color --pretty=medium '.sha |
2380 let cmd = 'cd '.plug#shellescape(g:plugs[name].dir).' && git show --no-color --pretty=medium '.sha |
2369 if s:is_win |
2381 if s:is_win |
2370 let batchfile = tempname().'.bat' |
2382 let [batchfile, cmd] = s:batchfile(cmd) |
2371 call writefile(["@echo off\r", cmd . "\r"], batchfile) |
|
2372 let cmd = expand(batchfile) |
|
2373 endif |
2383 endif |
2374 execute 'silent %!' cmd |
2384 execute 'silent %!' cmd |
2375 finally |
2385 finally |
2376 let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd] |
2386 let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd] |
2377 if s:is_win |
2387 if s:is_win |
2416 continue |
2426 continue |
2417 endif |
2427 endif |
2418 call s:append_ul(2, origin ? 'Pending updates:' : 'Last update:') |
2428 call s:append_ul(2, origin ? 'Pending updates:' : 'Last update:') |
2419 for [k, v] in plugs |
2429 for [k, v] in plugs |
2420 let range = origin ? '..origin/'.v.branch : 'HEAD@{1}..' |
2430 let range = origin ? '..origin/'.v.branch : 'HEAD@{1}..' |
2421 let cmd = 'git log --graph --color=never '.join(map(['--pretty=format:%x01%h%x01%d%x01%s%x01%cr', range], 's:shellesc(v:val)')) |
2431 let cmd = 'git log --graph --color=never '.join(map(['--pretty=format:%x01%h%x01%d%x01%s%x01%cr', range], 'plug#shellescape(v:val)')) |
2422 if has_key(v, 'rtp') |
2432 if has_key(v, 'rtp') |
2423 let cmd .= ' -- '.s:shellesc(v.rtp) |
2433 let cmd .= ' -- '.plug#shellescape(v.rtp) |
2424 endif |
2434 endif |
2425 let diff = s:system_chomp(cmd, v.dir) |
2435 let diff = s:system_chomp(cmd, v.dir) |
2426 if !empty(diff) |
2436 if !empty(diff) |
2427 let ref = has_key(v, 'tag') ? (' (tag: '.v.tag.')') : has_key(v, 'commit') ? (' '.v.commit) : '' |
2437 let ref = has_key(v, 'tag') ? (' (tag: '.v.tag.')') : has_key(v, 'commit') ? (' '.v.commit) : '' |
2428 call append(5, extend(['', '- '.k.':'.ref], map(s:lines(diff), 's:format_git_log(v:val)'))) |
2438 call append(5, extend(['', '- '.k.':'.ref], map(s:lines(diff), 's:format_git_log(v:val)'))) |