blob: 7c1cefa63eaad72fcbd5c0ea34e1df3fd8145169 [file] [log] [blame]
Corpulent Robinb69cd522025-02-06 21:10:49 +01001" tar.vim: Handles browsing tarfiles - AUTOLOAD PORTION
Christian Brabandt8ac975d2025-03-01 17:13:40 +01002" Date: Mar 01, 2025
Christian Brabandt67abf152023-11-14 17:15:17 +01003" Version: 32b (with modifications from the Vim Project)
Christian Brabandtf9ca1392024-02-19 20:37:11 +01004" Maintainer: This runtime file is looking for a new maintainer.
5" Former Maintainer: Charles E Campbell
Bram Moolenaar29634562020-01-09 21:46:04 +01006" License: Vim License (see vim's :help license)
Jim Zhou56957ed2025-02-28 18:06:14 +01007" Last Change:
8" 2024 Jan 08 by Vim Project: fix a few problems (#138331, #12637, #8109)
9" 2024 Feb 19 by Vim Project: announce adoption
10" 2024 Nov 11 by Vim Project: support permissions (#7379)
11" 2025 Feb 06 by Vim Project: add support for lz4 (#16591)
12" 2025 Feb 28 by Vim Project: add support for bzip3 (#16755)
Christian Brabandt8ac975d2025-03-01 17:13:40 +010013" 2025 Mar 01 by Vim Project: fix syntax error in tar#Read()
Christian Brabandt334a13b2025-03-02 19:33:51 +010014" 2025 Mar 02 by Vim Project: escape the filename before using :read
Christian Brabandta2507382025-03-02 22:23:28 +010015" 2025 Mar 02 by Vim Project: determine the compression using readblob()
16" instead of shelling out to file(1)
Christian Brabandt470317f2025-04-16 17:13:28 +020017" 2025 Apr 16 by Vim Project: decouple from netrw by adding s:WinPath()
Michele Sorcinelli719ec0f2025-05-19 19:45:32 +020018" 2025 May 19 by Vim Project: restore working directory after read/write
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000019"
Bram Moolenaara5792f52005-11-23 21:25:05 +000020" Contains many ideas from Michael Toren's <tar.vim>
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000021"
Bram Moolenaar29634562020-01-09 21:46:04 +010022" Copyright: Copyright (C) 2005-2017 Charles E. Campbell {{{1
Bram Moolenaara5792f52005-11-23 21:25:05 +000023" Permission is hereby granted to use and distribute this code,
24" with or without modifications, provided that this copyright
25" notice is copied with it. Like anything else that's free,
Bram Moolenaar8c8de832008-06-24 22:58:06 +000026" tar.vim and tarPlugin.vim are provided *as is* and comes
27" with no warranty of any kind, either expressed or implied.
28" By using this plugin, you agree that in no event will the
29" copyright holder be liable for any damages resulting from
30" the use of this software.
Bram Moolenaarab194812005-09-14 21:40:12 +000031" ---------------------------------------------------------------------
Bram Moolenaarc81e5e72007-05-05 18:24:42 +000032" Load Once: {{{1
Bram Moolenaar5c736222010-01-06 20:54:52 +010033if &cp || exists("g:loaded_tar")
Bram Moolenaara5792f52005-11-23 21:25:05 +000034 finish
35endif
Lennart00129a8442024-11-11 22:39:30 +010036let g:loaded_tar= "v32b"
Bram Moolenaar5c736222010-01-06 20:54:52 +010037if v:version < 702
38 echohl WarningMsg
39 echo "***warning*** this version of tar needs vim 7.2"
40 echohl Normal
41 finish
Bram Moolenaar8c8de832008-06-24 22:58:06 +000042endif
Bram Moolenaar5c736222010-01-06 20:54:52 +010043let s:keepcpo= &cpo
44set cpo&vim
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000045
Bram Moolenaara5792f52005-11-23 21:25:05 +000046" ---------------------------------------------------------------------
47" Default Settings: {{{1
48if !exists("g:tar_browseoptions")
49 let g:tar_browseoptions= "Ptf"
50endif
51if !exists("g:tar_readoptions")
Lennart00129a8442024-11-11 22:39:30 +010052 let g:tar_readoptions= "pPxf"
Bram Moolenaara5792f52005-11-23 21:25:05 +000053endif
Bram Moolenaar910f66f2006-04-05 20:41:53 +000054if !exists("g:tar_cmd")
55 let g:tar_cmd= "tar"
56endif
Bram Moolenaara5792f52005-11-23 21:25:05 +000057if !exists("g:tar_writeoptions")
58 let g:tar_writeoptions= "uf"
59endif
Bram Moolenaar29634562020-01-09 21:46:04 +010060if !exists("g:tar_delfile")
61 let g:tar_delfile="--delete -f"
62endif
Bram Moolenaar251e1912011-06-19 05:09:16 +020063if !exists("g:netrw_cygwin")
64 if has("win32") || has("win95") || has("win64") || has("win16")
65 if &shell =~ '\%(\<bash\>\|\<zsh\>\)\%(\.exe\)\=$'
66 let g:netrw_cygwin= 1
67 else
68 let g:netrw_cygwin= 0
69 endif
70 else
71 let g:netrw_cygwin= 0
72 endif
73endif
Bram Moolenaar5c736222010-01-06 20:54:52 +010074if !exists("g:tar_copycmd")
75 if !exists("g:netrw_localcopycmd")
76 if has("win32") || has("win95") || has("win64") || has("win16")
77 if g:netrw_cygwin
78 let g:netrw_localcopycmd= "cp"
79 else
80 let g:netrw_localcopycmd= "copy"
81 endif
82 elseif has("unix") || has("macunix")
83 let g:netrw_localcopycmd= "cp"
84 else
85 let g:netrw_localcopycmd= ""
86 endif
87 endif
88 let g:tar_copycmd= g:netrw_localcopycmd
89endif
Bram Moolenaar5c736222010-01-06 20:54:52 +010090if !exists("g:tar_extractcmd")
Lennart00129a8442024-11-11 22:39:30 +010091 let g:tar_extractcmd= "tar -pxf"
Bram Moolenaar5c736222010-01-06 20:54:52 +010092endif
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000093
Bram Moolenaar8c8de832008-06-24 22:58:06 +000094" set up shell quoting character
95if !exists("g:tar_shq")
Bram Moolenaarff034192013-04-24 18:51:19 +020096 if exists("+shq") && exists("&shq") && &shq != ""
Bram Moolenaar8c8de832008-06-24 22:58:06 +000097 let g:tar_shq= &shq
98 elseif has("win32") || has("win95") || has("win64") || has("win16")
99 if exists("g:netrw_cygwin") && g:netrw_cygwin
100 let g:tar_shq= "'"
101 else
102 let g:tar_shq= '"'
103 endif
104 else
105 let g:tar_shq= "'"
106 endif
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000107endif
108
Bram Moolenaara5792f52005-11-23 21:25:05 +0000109" ----------------
110" Functions: {{{1
111" ----------------
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000112
Bram Moolenaara5792f52005-11-23 21:25:05 +0000113" ---------------------------------------------------------------------
114" tar#Browse: {{{2
115fun! tar#Browse(tarfile)
Bram Moolenaarbba577a2005-11-28 23:05:55 +0000116 let repkeep= &report
117 set report=10
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000118
Bram Moolenaara5792f52005-11-23 21:25:05 +0000119 " sanity checks
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000120 if !executable(g:tar_cmd)
Bram Moolenaarc81e5e72007-05-05 18:24:42 +0000121 redraw!
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000122 echohl Error | echo '***error*** (tar#Browse) "'.g:tar_cmd.'" not available on your system'
Bram Moolenaarbba577a2005-11-28 23:05:55 +0000123 let &report= repkeep
Bram Moolenaara5792f52005-11-23 21:25:05 +0000124 return
125 endif
126 if !filereadable(a:tarfile)
127 if a:tarfile !~# '^\a\+://'
Bram Moolenaar8024f932020-01-14 19:29:13 +0100128 " if it's an url, don't complain, let url-handlers such as vim do its thing
Bram Moolenaarc81e5e72007-05-05 18:24:42 +0000129 redraw!
Bram Moolenaara5792f52005-11-23 21:25:05 +0000130 echohl Error | echo "***error*** (tar#Browse) File not readable<".a:tarfile.">" | echohl None
Bram Moolenaara5792f52005-11-23 21:25:05 +0000131 endif
Bram Moolenaarbba577a2005-11-28 23:05:55 +0000132 let &report= repkeep
Bram Moolenaara5792f52005-11-23 21:25:05 +0000133 return
134 endif
135 if &ma != 1
136 set ma
137 endif
Bram Moolenaar7fc0c062010-08-10 21:43:35 +0200138 let b:tarfile= a:tarfile
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000139
Bram Moolenaara5792f52005-11-23 21:25:05 +0000140 setlocal noswapfile
141 setlocal buftype=nofile
142 setlocal bufhidden=hide
143 setlocal nobuflisted
144 setlocal nowrap
145 set ft=tar
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000146
Bram Moolenaara5792f52005-11-23 21:25:05 +0000147 " give header
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000148 let lastline= line("$")
149 call setline(lastline+1,'" tar.vim version '.g:loaded_tar)
150 call setline(lastline+2,'" Browsing tarfile '.a:tarfile)
Christian Brabandt470317f2025-04-16 17:13:28 +0200151 call setline(lastline+3,'" Select a file with cursor and press ENTER, "x" to extract a file')
Bram Moolenaar251e1912011-06-19 05:09:16 +0200152 keepj $put =''
Bram Moolenaar6be7f872012-01-20 21:08:56 +0100153 keepj sil! 0d
Bram Moolenaar251e1912011-06-19 05:09:16 +0200154 keepj $
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000155
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000156 let tarfile= a:tarfile
Bram Moolenaarff034192013-04-24 18:51:19 +0200157 if has("win32unix") && executable("cygpath")
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000158 " assuming cygwin
Bram Moolenaar5c736222010-01-06 20:54:52 +0100159 let tarfile=substitute(system("cygpath -u ".shellescape(tarfile,0)),'\n$','','e')
Bram Moolenaara5792f52005-11-23 21:25:05 +0000160 endif
Bram Moolenaard68071d2006-05-02 22:08:30 +0000161 let curlast= line("$")
Bram Moolenaar29634562020-01-09 21:46:04 +0100162
163 if tarfile =~# '\.\(gz\)$'
Bram Moolenaar29634562020-01-09 21:46:04 +0100164 exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
165
Corpulent Robinb69cd522025-02-06 21:10:49 +0100166 elseif tarfile =~# '\.\(tgz\)$' || tarfile =~# '\.\(tbz\)$' || tarfile =~# '\.\(txz\)$' ||
167 \ tarfile =~# '\.\(tzst\)$' || tarfile =~# '\.\(tlz4\)$'
Christian Brabandta2507382025-03-02 22:23:28 +0100168 let header= s:Header(tarfile)
Bram Moolenaar29634562020-01-09 21:46:04 +0100169
Christian Brabandta2507382025-03-02 22:23:28 +0100170 if header =~? 'bzip2'
Bram Moolenaar29634562020-01-09 21:46:04 +0100171 exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
Christian Brabandta2507382025-03-02 22:23:28 +0100172 elseif header =~? 'bzip3'
Jim Zhou56957ed2025-02-28 18:06:14 +0100173 exe "sil! r! bzip3 -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
Christian Brabandta2507382025-03-02 22:23:28 +0100174 elseif header =~? 'xz'
Bram Moolenaar29634562020-01-09 21:46:04 +0100175 exe "sil! r! xz -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
Christian Brabandta2507382025-03-02 22:23:28 +0100176 elseif header =~? 'zstd'
Bram Moolenaar23515b42020-11-29 14:36:24 +0100177 exe "sil! r! zstd --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
Christian Brabandta2507382025-03-02 22:23:28 +0100178 elseif header =~? 'lz4'
Corpulent Robinb69cd522025-02-06 21:10:49 +0100179 exe "sil! r! lz4 --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
Christian Brabandta2507382025-03-02 22:23:28 +0100180 elseif header =~? 'gzip'
Bram Moolenaar29634562020-01-09 21:46:04 +0100181 exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
182 endif
183
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000184 elseif tarfile =~# '\.lrp'
Bram Moolenaard4a1aab2018-09-08 15:10:34 +0200185 exe "sil! r! cat -- ".shellescape(tarfile,1)."|gzip -d -c -|".g:tar_cmd." -".g:tar_browseoptions." - "
Bram Moolenaar6be7f872012-01-20 21:08:56 +0100186 elseif tarfile =~# '\.\(bz2\|tbz\|tb2\)$'
Bram Moolenaar251e1912011-06-19 05:09:16 +0200187 exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
Jim Zhou56957ed2025-02-28 18:06:14 +0100188 elseif tarfile =~# '\.\(bz3\|tb3\)$'
189 exe "sil! r! bzip3 -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
Bram Moolenaar6be7f872012-01-20 21:08:56 +0100190 elseif tarfile =~# '\.\(lzma\|tlz\)$'
Bram Moolenaar251e1912011-06-19 05:09:16 +0200191 exe "sil! r! lzma -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
Bram Moolenaar477db062010-07-28 18:17:41 +0200192 elseif tarfile =~# '\.\(xz\|txz\)$'
Bram Moolenaar251e1912011-06-19 05:09:16 +0200193 exe "sil! r! xz --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
Christian Brabandt3a5b3df2024-01-08 20:02:14 +0100194 elseif tarfile =~# '\.\(zst\|tzst\)$'
Bram Moolenaar23515b42020-11-29 14:36:24 +0100195 exe "sil! r! zstd --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
Corpulent Robinb69cd522025-02-06 21:10:49 +0100196 elseif tarfile =~# '\.\(lz4\|tlz4\)$'
197 exe "sil! r! lz4 --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000198 else
Bram Moolenaared39e1d2008-08-09 17:55:22 +0000199 if tarfile =~ '^\s*-'
Bram Moolenaar5c736222010-01-06 20:54:52 +0100200 " A file name starting with a dash is taken as an option. Prepend ./ to avoid that.
Bram Moolenaared39e1d2008-08-09 17:55:22 +0000201 let tarfile = substitute(tarfile, '-', './-', '')
202 endif
Bram Moolenaar251e1912011-06-19 05:09:16 +0200203 exe "sil! r! ".g:tar_cmd." -".g:tar_browseoptions." ".shellescape(tarfile,1)
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000204 endif
205 if v:shell_error != 0
Bram Moolenaarc81e5e72007-05-05 18:24:42 +0000206 redraw!
Bram Moolenaard68071d2006-05-02 22:08:30 +0000207 echohl WarningMsg | echo "***warning*** (tar#Browse) please check your g:tar_browseoptions<".g:tar_browseoptions.">"
Bram Moolenaard68071d2006-05-02 22:08:30 +0000208 return
209 endif
Christian Brabandt3d372312023-11-05 17:44:05 +0100210 "
Christian Brabandt67abf152023-11-14 17:15:17 +0100211 " The following should not be neccessary, since in case of errors the
212 " previous if statement should have caught the problem (because tar exited
213 " with a non-zero exit code).
214 " if line("$") == curlast || ( line("$") == (curlast + 1) &&
215 " \ getline("$") =~# '\c\<\%(warning\|error\|inappropriate\|unrecognized\)\>' &&
216 " \ getline("$") =~ '\s' )
217 " redraw!
218 " echohl WarningMsg | echo "***warning*** (tar#Browse) ".a:tarfile." doesn't appear to be a tar file" | echohl None
219 " keepj sil! %d
220 " let eikeep= &ei
221 " set ei=BufReadCmd,FileReadCmd
222 " exe "r ".fnameescape(a:tarfile)
223 " let &ei= eikeep
224 " keepj sil! 1d
225 " call Dret("tar#Browse : a:tarfile<".a:tarfile.">")
226 " return
227 " endif
Bram Moolenaara5792f52005-11-23 21:25:05 +0000228
Bram Moolenaar29634562020-01-09 21:46:04 +0100229 " set up maps supported for tar
Bram Moolenaara5792f52005-11-23 21:25:05 +0000230 setlocal noma nomod ro
Bram Moolenaar29634562020-01-09 21:46:04 +0100231 noremap <silent> <buffer> <cr> :call <SID>TarBrowseSelect()<cr>
Christian Brabandt3a5b3df2024-01-08 20:02:14 +0100232 noremap <silent> <buffer> x :call tar#Extract()<cr>
Bram Moolenaar29634562020-01-09 21:46:04 +0100233 if &mouse != ""
234 noremap <silent> <buffer> <leftmouse> <leftmouse>:call <SID>TarBrowseSelect()<cr>
235 endif
Bram Moolenaara5792f52005-11-23 21:25:05 +0000236
Bram Moolenaarbba577a2005-11-28 23:05:55 +0000237 let &report= repkeep
Bram Moolenaarab194812005-09-14 21:40:12 +0000238endfun
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000239
Bram Moolenaarab194812005-09-14 21:40:12 +0000240" ---------------------------------------------------------------------
Bram Moolenaara5792f52005-11-23 21:25:05 +0000241" TarBrowseSelect: {{{2
242fun! s:TarBrowseSelect()
Bram Moolenaarbba577a2005-11-28 23:05:55 +0000243 let repkeep= &report
244 set report=10
Bram Moolenaara5792f52005-11-23 21:25:05 +0000245 let fname= getline(".")
Bram Moolenaara5792f52005-11-23 21:25:05 +0000246
Bram Moolenaared39e1d2008-08-09 17:55:22 +0000247 if !exists("g:tar_secure") && fname =~ '^\s*-\|\s\+-'
248 redraw!
Bram Moolenaar5c736222010-01-06 20:54:52 +0100249 echohl WarningMsg | echo '***warning*** (tar#BrowseSelect) rejecting tarfile member<'.fname.'> because of embedded "-"'
Bram Moolenaared39e1d2008-08-09 17:55:22 +0000250 return
251 endif
252
Bram Moolenaara5792f52005-11-23 21:25:05 +0000253 " sanity check
254 if fname =~ '^"'
Bram Moolenaarbba577a2005-11-28 23:05:55 +0000255 let &report= repkeep
Bram Moolenaara5792f52005-11-23 21:25:05 +0000256 return
257 endif
258
Bram Moolenaar7fc0c062010-08-10 21:43:35 +0200259 " about to make a new window, need to use b:tarfile
260 let tarfile= b:tarfile
Bram Moolenaara5792f52005-11-23 21:25:05 +0000261 let curfile= expand("%")
Bram Moolenaarff034192013-04-24 18:51:19 +0200262 if has("win32unix") && executable("cygpath")
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000263 " assuming cygwin
Bram Moolenaar5c736222010-01-06 20:54:52 +0100264 let tarfile=substitute(system("cygpath -u ".shellescape(tarfile,0)),'\n$','','e')
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000265 endif
Bram Moolenaara5792f52005-11-23 21:25:05 +0000266
Bram Moolenaar29634562020-01-09 21:46:04 +0100267 " open a new window (tar#Read will read a file into it)
268 noswapfile new
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000269 if !exists("g:tar_nomax") || g:tar_nomax == 0
270 wincmd _
271 endif
Bram Moolenaara5792f52005-11-23 21:25:05 +0000272 let s:tblfile_{winnr()}= curfile
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000273 call tar#Read("tarfile:".tarfile.'::'.fname,1)
Bram Moolenaara5792f52005-11-23 21:25:05 +0000274 filetype detect
Bram Moolenaarff034192013-04-24 18:51:19 +0200275 set nomod
276 exe 'com! -buffer -nargs=? -complete=file TarDiff :call tar#Diff(<q-args>,"'.fnameescape(fname).'")'
Bram Moolenaara5792f52005-11-23 21:25:05 +0000277
Bram Moolenaarbba577a2005-11-28 23:05:55 +0000278 let &report= repkeep
Bram Moolenaara5792f52005-11-23 21:25:05 +0000279endfun
280
281" ---------------------------------------------------------------------
282" tar#Read: {{{2
283fun! tar#Read(fname,mode)
Bram Moolenaarbba577a2005-11-28 23:05:55 +0000284 let repkeep= &report
285 set report=10
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000286 let tarfile = substitute(a:fname,'tarfile:\(.\{-}\)::.*$','\1','')
287 let fname = substitute(a:fname,'tarfile:.\{-}::\(.*\)$','\1','')
Christian Brabandt334a13b2025-03-02 19:33:51 +0100288 " be careful not to execute special crafted files
289 let escape_file = fname->fnameescape()
Lennart00129a8442024-11-11 22:39:30 +0100290
Corpulent Robinb69cd522025-02-06 21:10:49 +0100291 " changing the directory to the temporary earlier to allow tar to extract the file with permissions intact
Lennart00129a8442024-11-11 22:39:30 +0100292 if !exists("*mkdir")
293 redraw!
294 echohl Error | echo "***error*** (tar#Write) sorry, mkdir() doesn't work on your system" | echohl None
295 let &report= repkeep
296 return
297 endif
298
299 let curdir= getcwd()
300 let tmpdir= tempname()
301 let b:curdir= tmpdir
302 let b:tmpdir= curdir
303 if tmpdir =~ '\.'
304 let tmpdir= substitute(tmpdir,'\.[^.]*$','','e')
305 endif
306 call mkdir(tmpdir,"p")
307
308 " attempt to change to the indicated directory
309 try
Michele Sorcinelli719ec0f2025-05-19 19:45:32 +0200310 exe "lcd ".fnameescape(tmpdir)
Lennart00129a8442024-11-11 22:39:30 +0100311 catch /^Vim\%((\a\+)\)\=:E344/
312 redraw!
Michele Sorcinelli719ec0f2025-05-19 19:45:32 +0200313 echohl Error | echo "***error*** (tar#Write) cannot lcd to temporary directory" | Echohl None
Lennart00129a8442024-11-11 22:39:30 +0100314 let &report= repkeep
315 return
316 endtry
317
318 " place temporary files under .../_ZIPVIM_/
319 if isdirectory("_ZIPVIM_")
320 call s:Rmdir("_ZIPVIM_")
321 endif
322 call mkdir("_ZIPVIM_")
Michele Sorcinelli719ec0f2025-05-19 19:45:32 +0200323 lcd _ZIPVIM_
Lennart00129a8442024-11-11 22:39:30 +0100324
Bram Moolenaarff034192013-04-24 18:51:19 +0200325 if has("win32unix") && executable("cygpath")
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000326 " assuming cygwin
Bram Moolenaar5c736222010-01-06 20:54:52 +0100327 let tarfile=substitute(system("cygpath -u ".shellescape(tarfile,0)),'\n$','','e')
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000328 endif
Bram Moolenaara5792f52005-11-23 21:25:05 +0000329
Bram Moolenaar5c736222010-01-06 20:54:52 +0100330 if fname =~ '\.bz2$' && executable("bzcat")
331 let decmp= "|bzcat"
332 let doro = 1
Jim Zhou56957ed2025-02-28 18:06:14 +0100333 elseif fname =~ '\.bz3$' && executable("bz3cat")
334 let decmp= "|bz3cat"
335 let doro = 1
Bram Moolenaar29634562020-01-09 21:46:04 +0100336 elseif fname =~ '\.t\=gz$' && executable("zcat")
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000337 let decmp= "|zcat"
338 let doro = 1
Bram Moolenaar5c736222010-01-06 20:54:52 +0100339 elseif fname =~ '\.lzma$' && executable("lzcat")
340 let decmp= "|lzcat"
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000341 let doro = 1
Bram Moolenaar477db062010-07-28 18:17:41 +0200342 elseif fname =~ '\.xz$' && executable("xzcat")
343 let decmp= "|xzcat"
344 let doro = 1
Bram Moolenaar23515b42020-11-29 14:36:24 +0100345 elseif fname =~ '\.zst$' && executable("zstdcat")
346 let decmp= "|zstdcat"
347 let doro = 1
Corpulent Robinb69cd522025-02-06 21:10:49 +0100348 elseif fname =~ '\.lz4$' && executable("lz4cat")
349 let decmp= "|lz4cat"
350 let doro = 1
Bram Moolenaara5792f52005-11-23 21:25:05 +0000351 else
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000352 let decmp=""
353 let doro = 0
Jim Zhou56957ed2025-02-28 18:06:14 +0100354 if fname =~ '\.bz2$\|\.bz3$\|\.gz$\|\.lzma$\|\.xz$\|\.zip$\|\.Z$'
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000355 setlocal bin
356 endif
Bram Moolenaara5792f52005-11-23 21:25:05 +0000357 endif
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000358
Bram Moolenaared39e1d2008-08-09 17:55:22 +0000359 if exists("g:tar_secure")
360 let tar_secure= " -- "
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000361 else
Bram Moolenaared39e1d2008-08-09 17:55:22 +0000362 let tar_secure= " "
363 endif
Bram Moolenaar20aac6c2018-09-02 21:07:30 +0200364
Bram Moolenaar5c736222010-01-06 20:54:52 +0100365 if tarfile =~# '\.bz2$'
Bram Moolenaar251e1912011-06-19 05:09:16 +0200366 exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
Christian Brabandt334a13b2025-03-02 19:33:51 +0100367 exe "read ".escape_file
Christian Brabandt8ac975d2025-03-01 17:13:40 +0100368 elseif tarfile =~# '\.bz3$'
Jim Zhou56957ed2025-02-28 18:06:14 +0100369 exe "sil! r! bzip3 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
Christian Brabandt334a13b2025-03-02 19:33:51 +0100370 exe "read ".escape_file
Bram Moolenaar29634562020-01-09 21:46:04 +0100371 elseif tarfile =~# '\.\(gz\)$'
372 exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
Christian Brabandt334a13b2025-03-02 19:33:51 +0100373 exe "read ".escape_file
Bram Moolenaar29634562020-01-09 21:46:04 +0100374 elseif tarfile =~# '\(\.tgz\|\.tbz\|\.txz\)'
Christian Brabandta2507382025-03-02 22:23:28 +0100375 let filekind= s:Header(tarfile)
376 if filekind =~? "bzip2"
Bram Moolenaar29634562020-01-09 21:46:04 +0100377 exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
Christian Brabandt334a13b2025-03-02 19:33:51 +0100378 exe "read ".escape_file
Jim Zhou56957ed2025-02-28 18:06:14 +0100379 elseif filekind =~ "bzip3"
380 exe "sil! r! bzip3 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
Christian Brabandt334a13b2025-03-02 19:33:51 +0100381 exe "read ".escape_file
Christian Brabandta2507382025-03-02 22:23:28 +0100382 elseif filekind =~? "xz"
Bram Moolenaar29634562020-01-09 21:46:04 +0100383 exe "sil! r! xz -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
Christian Brabandt334a13b2025-03-02 19:33:51 +0100384 exe "read ".escape_file
Christian Brabandta2507382025-03-02 22:23:28 +0100385 elseif filekind =~? "zstd"
Bram Moolenaar23515b42020-11-29 14:36:24 +0100386 exe "sil! r! zstd --decompress --stdout -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
Christian Brabandt334a13b2025-03-02 19:33:51 +0100387 exe "read ".escape_file
Christian Brabandta2507382025-03-02 22:23:28 +0100388 elseif filekind =~? "gzip"
Bram Moolenaar29634562020-01-09 21:46:04 +0100389 exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
Christian Brabandt334a13b2025-03-02 19:33:51 +0100390 exe "read ".escape_file
Bram Moolenaar29634562020-01-09 21:46:04 +0100391 endif
392
Bram Moolenaared39e1d2008-08-09 17:55:22 +0000393 elseif tarfile =~# '\.lrp$'
Bram Moolenaard4a1aab2018-09-08 15:10:34 +0200394 exe "sil! r! cat -- ".shellescape(tarfile,1)." | gzip -d -c - | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
Christian Brabandt334a13b2025-03-02 19:33:51 +0100395 exe "read ".escape_file
Bram Moolenaar5c736222010-01-06 20:54:52 +0100396 elseif tarfile =~# '\.lzma$'
Bram Moolenaar251e1912011-06-19 05:09:16 +0200397 exe "sil! r! lzma -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
Christian Brabandt334a13b2025-03-02 19:33:51 +0100398 exe "read ".escape_file
Bram Moolenaar477db062010-07-28 18:17:41 +0200399 elseif tarfile =~# '\.\(xz\|txz\)$'
Bram Moolenaar251e1912011-06-19 05:09:16 +0200400 exe "sil! r! xz --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
Christian Brabandt334a13b2025-03-02 19:33:51 +0100401 exe "read ".escape_file
Corpulent Robinb69cd522025-02-06 21:10:49 +0100402 elseif tarfile =~# '\.\(lz4\|tlz4\)$'
403 exe "sil! r! lz4 --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
Christian Brabandt334a13b2025-03-02 19:33:51 +0100404 exe "read ".escape_file
Bram Moolenaared39e1d2008-08-09 17:55:22 +0000405 else
406 if tarfile =~ '^\s*-'
Bram Moolenaar5c736222010-01-06 20:54:52 +0100407 " A file name starting with a dash is taken as an option. Prepend ./ to avoid that.
Bram Moolenaared39e1d2008-08-09 17:55:22 +0000408 let tarfile = substitute(tarfile, '-', './-', '')
409 endif
Bram Moolenaar5c736222010-01-06 20:54:52 +0100410 exe "silent r! ".g:tar_cmd." -".g:tar_readoptions.shellescape(tarfile,1)." ".tar_secure.shellescape(fname,1).decmp
Christian Brabandt334a13b2025-03-02 19:33:51 +0100411 exe "read ".escape_file
Lennart00129a8442024-11-11 22:39:30 +0100412 endif
413
414 redraw!
415
416if v:shell_error != 0
Michele Sorcinelli719ec0f2025-05-19 19:45:32 +0200417 lcd ..
Lennart00129a8442024-11-11 22:39:30 +0100418 call s:Rmdir("_ZIPVIM_")
Michele Sorcinelli719ec0f2025-05-19 19:45:32 +0200419 exe "lcd ".fnameescape(curdir)
Lennart00129a8442024-11-11 22:39:30 +0100420 echohl Error | echo "***error*** (tar#Read) sorry, unable to open or extract ".tarfile." with ".fname | echohl None
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000421 endif
422
423 if doro
424 " because the reverse process of compressing changed files back into the tarball is not currently supported
425 setlocal ro
426 endif
427
Bram Moolenaar7fc0c062010-08-10 21:43:35 +0200428 let b:tarfile= a:fname
Bram Moolenaarc236c162008-07-13 17:41:49 +0000429 exe "file tarfile::".fnameescape(fname)
Bram Moolenaara5792f52005-11-23 21:25:05 +0000430
431 " cleanup
Bram Moolenaar251e1912011-06-19 05:09:16 +0200432 keepj sil! 0d
Bram Moolenaara5792f52005-11-23 21:25:05 +0000433 set nomod
434
Bram Moolenaarbba577a2005-11-28 23:05:55 +0000435 let &report= repkeep
Michele Sorcinelli719ec0f2025-05-19 19:45:32 +0200436 exe "lcd ".fnameescape(curdir)
437 silent exe "file tarfile::".escape_file
Bram Moolenaara5792f52005-11-23 21:25:05 +0000438endfun
439
440" ---------------------------------------------------------------------
441" tar#Write: {{{2
442fun! tar#Write(fname)
Michele Sorcinelli719ec0f2025-05-19 19:45:32 +0200443 let pwdkeep= getcwd()
Bram Moolenaarbba577a2005-11-28 23:05:55 +0000444 let repkeep= &report
445 set report=10
Lennart00129a8442024-11-11 22:39:30 +0100446 let curdir= b:curdir
447 let tmpdir= b:tmpdir
Bram Moolenaara5792f52005-11-23 21:25:05 +0000448
Bram Moolenaared39e1d2008-08-09 17:55:22 +0000449 if !exists("g:tar_secure") && a:fname =~ '^\s*-\|\s\+-'
450 redraw!
Bram Moolenaar5c736222010-01-06 20:54:52 +0100451 echohl WarningMsg | echo '***warning*** (tar#Write) rejecting tarfile member<'.a:fname.'> because of embedded "-"'
Bram Moolenaared39e1d2008-08-09 17:55:22 +0000452 return
453 endif
454
Bram Moolenaarab194812005-09-14 21:40:12 +0000455 " sanity checks
Bram Moolenaar910f66f2006-04-05 20:41:53 +0000456 if !executable(g:tar_cmd)
Bram Moolenaarc81e5e72007-05-05 18:24:42 +0000457 redraw!
Bram Moolenaarbba577a2005-11-28 23:05:55 +0000458 let &report= repkeep
Bram Moolenaarab194812005-09-14 21:40:12 +0000459 return
460 endif
Bram Moolenaarab194812005-09-14 21:40:12 +0000461
Bram Moolenaar7fc0c062010-08-10 21:43:35 +0200462 let tarfile = substitute(b:tarfile,'tarfile:\(.\{-}\)::.*$','\1','')
463 let fname = substitute(b:tarfile,'tarfile:.\{-}::\(.*\)$','\1','')
Bram Moolenaara5792f52005-11-23 21:25:05 +0000464
465 " handle compressed archives
Bram Moolenaar5c736222010-01-06 20:54:52 +0100466 if tarfile =~# '\.bz2'
467 call system("bzip2 -d -- ".shellescape(tarfile,0))
468 let tarfile = substitute(tarfile,'\.bz2','','e')
469 let compress= "bzip2 -- ".shellescape(tarfile,0)
Jim Zhou56957ed2025-02-28 18:06:14 +0100470 elseif tarfile =~# '\.bz3'
471 call system("bzip3 -d -- ".shellescape(tarfile,0))
472 let tarfile = substitute(tarfile,'\.bz3','','e')
473 let compress= "bzip3 -- ".shellescape(tarfile,0)
Bram Moolenaar5c736222010-01-06 20:54:52 +0100474 elseif tarfile =~# '\.gz'
Bram Moolenaar29634562020-01-09 21:46:04 +0100475 call system("gzip -d -- ".shellescape(tarfile,0))
Bram Moolenaara5792f52005-11-23 21:25:05 +0000476 let tarfile = substitute(tarfile,'\.gz','','e')
Bram Moolenaar5c736222010-01-06 20:54:52 +0100477 let compress= "gzip -- ".shellescape(tarfile,0)
Bram Moolenaara5792f52005-11-23 21:25:05 +0000478 elseif tarfile =~# '\.tgz'
Bram Moolenaar29634562020-01-09 21:46:04 +0100479 call system("gzip -d -- ".shellescape(tarfile,0))
Bram Moolenaara5792f52005-11-23 21:25:05 +0000480 let tarfile = substitute(tarfile,'\.tgz','.tar','e')
Bram Moolenaar5c736222010-01-06 20:54:52 +0100481 let compress= "gzip -- ".shellescape(tarfile,0)
Bram Moolenaara5792f52005-11-23 21:25:05 +0000482 let tgz = 1
Bram Moolenaar477db062010-07-28 18:17:41 +0200483 elseif tarfile =~# '\.xz'
484 call system("xz -d -- ".shellescape(tarfile,0))
485 let tarfile = substitute(tarfile,'\.xz','','e')
486 let compress= "xz -- ".shellescape(tarfile,0)
Bram Moolenaar23515b42020-11-29 14:36:24 +0100487 elseif tarfile =~# '\.zst'
Christian Brabandt3a5b3df2024-01-08 20:02:14 +0100488 call system("zstd --decompress --rm -- ".shellescape(tarfile,0))
Bram Moolenaar23515b42020-11-29 14:36:24 +0100489 let tarfile = substitute(tarfile,'\.zst','','e')
Christian Brabandt3a5b3df2024-01-08 20:02:14 +0100490 let compress= "zstd --rm -- ".shellescape(tarfile,0)
Corpulent Robinb69cd522025-02-06 21:10:49 +0100491 elseif tarfile =~# '\.lz4'
492 call system("lz4 --decompress --rm -- ".shellescape(tarfile,0))
493 let tarfile = substitute(tarfile,'\.lz4','','e')
494 let compress= "lz4 --rm -- ".shellescape(tarfile,0)
Bram Moolenaar477db062010-07-28 18:17:41 +0200495 elseif tarfile =~# '\.lzma'
496 call system("lzma -d -- ".shellescape(tarfile,0))
497 let tarfile = substitute(tarfile,'\.lzma','','e')
498 let compress= "lzma -- ".shellescape(tarfile,0)
Bram Moolenaarab194812005-09-14 21:40:12 +0000499 endif
Christian Brabandta2507382025-03-02 22:23:28 +0100500 " Note: no support for name.tar.tbz/.txz/.tgz/.tlz4/.tzst
Bram Moolenaarab194812005-09-14 21:40:12 +0000501
Bram Moolenaarab194812005-09-14 21:40:12 +0000502 if v:shell_error != 0
Bram Moolenaarc81e5e72007-05-05 18:24:42 +0000503 redraw!
Bram Moolenaara5792f52005-11-23 21:25:05 +0000504 echohl Error | echo "***error*** (tar#Write) sorry, unable to update ".tarfile." with ".fname | echohl None
Bram Moolenaarab194812005-09-14 21:40:12 +0000505 else
Bram Moolenaara5792f52005-11-23 21:25:05 +0000506
Bram Moolenaar1cbe5f72005-12-29 22:51:09 +0000507 if fname =~ '/'
508 let dirpath = substitute(fname,'/[^/]\+$','','e')
Bram Moolenaarff034192013-04-24 18:51:19 +0200509 if has("win32unix") && executable("cygpath")
Bram Moolenaar5c736222010-01-06 20:54:52 +0100510 let dirpath = substitute(system("cygpath ".shellescape(dirpath, 0)),'\n','','e')
Bram Moolenaar1cbe5f72005-12-29 22:51:09 +0000511 endif
512 call mkdir(dirpath,"p")
513 endif
Bram Moolenaara5792f52005-11-23 21:25:05 +0000514 if tarfile !~ '/'
515 let tarfile= curdir.'/'.tarfile
516 endif
Bram Moolenaared39e1d2008-08-09 17:55:22 +0000517 if tarfile =~ '^\s*-'
518 " A file name starting with a dash may be taken as an option. Prepend ./ to avoid that.
519 let tarfile = substitute(tarfile, '-', './-', '')
520 endif
Christian Brabandt3a5b3df2024-01-08 20:02:14 +0100521
Bram Moolenaared39e1d2008-08-09 17:55:22 +0000522 if exists("g:tar_secure")
523 let tar_secure= " -- "
524 else
525 let tar_secure= " "
526 endif
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000527 exe "w! ".fnameescape(fname)
Bram Moolenaarff034192013-04-24 18:51:19 +0200528 if has("win32unix") && executable("cygpath")
Bram Moolenaar5c736222010-01-06 20:54:52 +0100529 let tarfile = substitute(system("cygpath ".shellescape(tarfile,0)),'\n','','e')
Bram Moolenaara5792f52005-11-23 21:25:05 +0000530 endif
Christian Brabandt3a5b3df2024-01-08 20:02:14 +0100531
Bram Moolenaara5792f52005-11-23 21:25:05 +0000532 " delete old file from tarfile
Bram Moolenaar29634562020-01-09 21:46:04 +0100533 call system(g:tar_cmd." ".g:tar_delfile." ".shellescape(tarfile,0).tar_secure.shellescape(fname,0))
Bram Moolenaara5792f52005-11-23 21:25:05 +0000534 if v:shell_error != 0
Bram Moolenaarc81e5e72007-05-05 18:24:42 +0000535 redraw!
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000536 echohl Error | echo "***error*** (tar#Write) sorry, unable to update ".fnameescape(tarfile)." with ".fnameescape(fname) | echohl None
Bram Moolenaara5792f52005-11-23 21:25:05 +0000537 else
Christian Brabandt3a5b3df2024-01-08 20:02:14 +0100538
539 " update tarfile with new file
Bram Moolenaar5c736222010-01-06 20:54:52 +0100540 call system(g:tar_cmd." -".g:tar_writeoptions." ".shellescape(tarfile,0).tar_secure.shellescape(fname,0))
Bram Moolenaara5792f52005-11-23 21:25:05 +0000541 if v:shell_error != 0
Bram Moolenaarc81e5e72007-05-05 18:24:42 +0000542 redraw!
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000543 echohl Error | echo "***error*** (tar#Write) sorry, unable to update ".fnameescape(tarfile)." with ".fnameescape(fname) | echohl None
Bram Moolenaara5792f52005-11-23 21:25:05 +0000544 elseif exists("compress")
Bram Moolenaara5792f52005-11-23 21:25:05 +0000545 call system(compress)
546 if exists("tgz")
Bram Moolenaara5792f52005-11-23 21:25:05 +0000547 call rename(tarfile.".gz",substitute(tarfile,'\.tar$','.tgz','e'))
548 endif
549 endif
550 endif
551
552 " support writing tarfiles across a network
553 if s:tblfile_{winnr()} =~ '^\a\+://'
Bram Moolenaara5792f52005-11-23 21:25:05 +0000554 let tblfile= s:tblfile_{winnr()}
Bram Moolenaar29634562020-01-09 21:46:04 +0100555 1split|noswapfile enew
Bram Moolenaar5c736222010-01-06 20:54:52 +0100556 let binkeep= &l:binary
Bram Moolenaara5792f52005-11-23 21:25:05 +0000557 let eikeep = &ei
558 set binary ei=all
Bram Moolenaar29634562020-01-09 21:46:04 +0100559 exe "noswapfile e! ".fnameescape(tarfile)
Bram Moolenaara5792f52005-11-23 21:25:05 +0000560 call netrw#NetWrite(tblfile)
Bram Moolenaar5c736222010-01-06 20:54:52 +0100561 let &ei = eikeep
562 let &l:binary = binkeep
Bram Moolenaara5792f52005-11-23 21:25:05 +0000563 q!
564 unlet s:tblfile_{winnr()}
565 endif
Bram Moolenaarab194812005-09-14 21:40:12 +0000566 endif
Christian Brabandt3a5b3df2024-01-08 20:02:14 +0100567
Bram Moolenaarab194812005-09-14 21:40:12 +0000568 " cleanup and restore current directory
Michele Sorcinelli719ec0f2025-05-19 19:45:32 +0200569 lcd ..
Bram Moolenaara5792f52005-11-23 21:25:05 +0000570 call s:Rmdir("_ZIPVIM_")
Michele Sorcinelli719ec0f2025-05-19 19:45:32 +0200571 exe "lcd ".fnameescape(pwdkeep)
Bram Moolenaarab194812005-09-14 21:40:12 +0000572 setlocal nomod
573
Bram Moolenaarbba577a2005-11-28 23:05:55 +0000574 let &report= repkeep
Bram Moolenaarab194812005-09-14 21:40:12 +0000575endfun
576
577" ---------------------------------------------------------------------
Bram Moolenaarff034192013-04-24 18:51:19 +0200578" tar#Diff: {{{2
579fun! tar#Diff(userfname,fname)
Bram Moolenaarff034192013-04-24 18:51:19 +0200580 let fname= a:fname
581 if a:userfname != ""
582 let fname= a:userfname
583 endif
584 if filereadable(fname)
585 " sets current file (from tarball) for diff'ing
586 " splits window vertically
587 " opens original file, sets it for diff'ing
588 " sets up b:tardiff_otherbuf variables so each buffer knows about the other (for closing purposes)
589 diffthis
590 wincmd v
Bram Moolenaar29634562020-01-09 21:46:04 +0100591 exe "noswapfile e ".fnameescape(fname)
Bram Moolenaarff034192013-04-24 18:51:19 +0200592 diffthis
593 else
594 redraw!
595 echo "***warning*** unable to read file<".fname.">"
596 endif
Bram Moolenaarff034192013-04-24 18:51:19 +0200597endfun
598
599" ---------------------------------------------------------------------
Bram Moolenaar29634562020-01-09 21:46:04 +0100600" tar#Extract: extract a file from a (possibly compressed) tar archive {{{2
601fun! tar#Extract()
Bram Moolenaar29634562020-01-09 21:46:04 +0100602
603 let repkeep= &report
604 set report=10
605 let fname= getline(".")
Bram Moolenaar29634562020-01-09 21:46:04 +0100606
607 if !exists("g:tar_secure") && fname =~ '^\s*-\|\s\+-'
608 redraw!
609 echohl WarningMsg | echo '***warning*** (tar#BrowseSelect) rejecting tarfile member<'.fname.'> because of embedded "-"'
Bram Moolenaar29634562020-01-09 21:46:04 +0100610 return
611 endif
612
613 " sanity check
614 if fname =~ '^"'
615 let &report= repkeep
Bram Moolenaar29634562020-01-09 21:46:04 +0100616 return
617 endif
618
619 let tarball = expand("%")
Bram Moolenaar29634562020-01-09 21:46:04 +0100620 let tarbase = substitute(tarball,'\..*$','','')
Bram Moolenaar29634562020-01-09 21:46:04 +0100621
Christian Brabandt470317f2025-04-16 17:13:28 +0200622 let extractcmd= s:WinPath(g:tar_extractcmd)
Bram Moolenaar29634562020-01-09 21:46:04 +0100623 if filereadable(tarbase.".tar")
Bram Moolenaar29634562020-01-09 21:46:04 +0100624 call system(extractcmd." ".shellescape(tarbase).".tar ".shellescape(fname))
625 if v:shell_error != 0
626 echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tar ".fname.": failed!" | echohl NONE
Bram Moolenaar29634562020-01-09 21:46:04 +0100627 else
628 echo "***note*** successfully extracted ".fname
629 endif
630
631 elseif filereadable(tarbase.".tgz")
632 let extractcmd= substitute(extractcmd,"-","-z","")
Bram Moolenaar29634562020-01-09 21:46:04 +0100633 call system(extractcmd." ".shellescape(tarbase).".tgz ".shellescape(fname))
634 if v:shell_error != 0
635 echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tgz ".fname.": failed!" | echohl NONE
Bram Moolenaar29634562020-01-09 21:46:04 +0100636 else
637 echo "***note*** successfully extracted ".fname
638 endif
639
640 elseif filereadable(tarbase.".tar.gz")
641 let extractcmd= substitute(extractcmd,"-","-z","")
Bram Moolenaar29634562020-01-09 21:46:04 +0100642 call system(extractcmd." ".shellescape(tarbase).".tar.gz ".shellescape(fname))
643 if v:shell_error != 0
644 echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tar.gz ".fname.": failed!" | echohl NONE
Bram Moolenaar29634562020-01-09 21:46:04 +0100645 else
646 echo "***note*** successfully extracted ".fname
647 endif
648
649 elseif filereadable(tarbase.".tbz")
650 let extractcmd= substitute(extractcmd,"-","-j","")
Bram Moolenaar29634562020-01-09 21:46:04 +0100651 call system(extractcmd." ".shellescape(tarbase).".tbz ".shellescape(fname))
652 if v:shell_error != 0
653 echohl Error | echo "***error*** ".extractcmd."j ".tarbase.".tbz ".fname.": failed!" | echohl NONE
Bram Moolenaar29634562020-01-09 21:46:04 +0100654 else
655 echo "***note*** successfully extracted ".fname
656 endif
657
658 elseif filereadable(tarbase.".tar.bz2")
659 let extractcmd= substitute(extractcmd,"-","-j","")
Bram Moolenaar29634562020-01-09 21:46:04 +0100660 call system(extractcmd." ".shellescape(tarbase).".tar.bz2 ".shellescape(fname))
661 if v:shell_error != 0
662 echohl Error | echo "***error*** ".extractcmd."j ".tarbase.".tar.bz2 ".fname.": failed!" | echohl NONE
Bram Moolenaar29634562020-01-09 21:46:04 +0100663 else
664 echo "***note*** successfully extracted ".fname
665 endif
666
Jim Zhou56957ed2025-02-28 18:06:14 +0100667 elseif filereadable(tarbase.".tar.bz3")
668 let extractcmd= substitute(extractcmd,"-","-j","")
669 call system(extractcmd." ".shellescape(tarbase).".tar.bz3 ".shellescape(fname))
670 if v:shell_error != 0
671 echohl Error | echo "***error*** ".extractcmd."j ".tarbase.".tar.bz3 ".fname.": failed!" | echohl NONE
672 else
673 echo "***note*** successfully extracted ".fname
674 endif
675
Bram Moolenaar29634562020-01-09 21:46:04 +0100676 elseif filereadable(tarbase.".txz")
677 let extractcmd= substitute(extractcmd,"-","-J","")
Bram Moolenaar29634562020-01-09 21:46:04 +0100678 call system(extractcmd." ".shellescape(tarbase).".txz ".shellescape(fname))
679 if v:shell_error != 0
680 echohl Error | echo "***error*** ".extractcmd." ".tarbase.".txz ".fname.": failed!" | echohl NONE
Bram Moolenaar29634562020-01-09 21:46:04 +0100681 else
682 echo "***note*** successfully extracted ".fname
683 endif
684
685 elseif filereadable(tarbase.".tar.xz")
686 let extractcmd= substitute(extractcmd,"-","-J","")
Bram Moolenaar29634562020-01-09 21:46:04 +0100687 call system(extractcmd." ".shellescape(tarbase).".tar.xz ".shellescape(fname))
688 if v:shell_error != 0
689 echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tar.xz ".fname.": failed!" | echohl NONE
Bram Moolenaar29634562020-01-09 21:46:04 +0100690 else
691 echo "***note*** successfully extracted ".fname
692 endif
Bram Moolenaar23515b42020-11-29 14:36:24 +0100693
Christian Brabandt3a5b3df2024-01-08 20:02:14 +0100694 elseif filereadable(tarbase.".tzst")
Bram Moolenaar23515b42020-11-29 14:36:24 +0100695 let extractcmd= substitute(extractcmd,"-","--zstd","")
Christian Brabandt3a5b3df2024-01-08 20:02:14 +0100696 call system(extractcmd." ".shellescape(tarbase).".tzst ".shellescape(fname))
Bram Moolenaar23515b42020-11-29 14:36:24 +0100697 if v:shell_error != 0
Christian Brabandt3a5b3df2024-01-08 20:02:14 +0100698 echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tzst ".fname.": failed!" | echohl NONE
Bram Moolenaar23515b42020-11-29 14:36:24 +0100699 else
700 echo "***note*** successfully extracted ".fname
701 endif
702
703 elseif filereadable(tarbase.".tar.zst")
704 let extractcmd= substitute(extractcmd,"-","--zstd","")
Christian Brabandt3a5b3df2024-01-08 20:02:14 +0100705 call system(extractcmd." ".shellescape(tarbase).".tar.zst ".shellescape(fname))
Bram Moolenaar23515b42020-11-29 14:36:24 +0100706 if v:shell_error != 0
707 echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tar.zst ".fname.": failed!" | echohl NONE
Corpulent Robinb69cd522025-02-06 21:10:49 +0100708 else
709 echo "***note*** successfully extracted ".fname
710 endif
711
712 elseif filereadable(tarbase.".tlz4")
713 let extractcmd= substitute(extractcmd,"-","-I lz4","")
714 call system(extractcmd." ".shellescape(tarbase).".tlz4 ".shellescape(fname))
715 if v:shell_error != 0
716 echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tlz4 ".fname.": failed!" | echohl NONE
717 else
718 echo "***note*** successfully extracted ".fname
719 endif
720
721 elseif filereadable(tarbase.".tar.lz4")
722 let extractcmd= substitute(extractcmd,"-","-I lz4","")
723 call system(extractcmd." ".shellescape(tarbase).".tar.lz4".shellescape(fname))
724 if v:shell_error != 0
725 echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tar.lz4 ".fname.": failed!" | echohl NONE
Bram Moolenaar23515b42020-11-29 14:36:24 +0100726 else
727 echo "***note*** successfully extracted ".fname
728 endif
Bram Moolenaar29634562020-01-09 21:46:04 +0100729 endif
730
731 " restore option
732 let &report= repkeep
Bram Moolenaar29634562020-01-09 21:46:04 +0100733endfun
734
735" ---------------------------------------------------------------------
Bram Moolenaar5c736222010-01-06 20:54:52 +0100736" s:Rmdir: {{{2
Bram Moolenaarab194812005-09-14 21:40:12 +0000737fun! s:Rmdir(fname)
Bram Moolenaarab194812005-09-14 21:40:12 +0000738 if has("unix")
Bram Moolenaar5c736222010-01-06 20:54:52 +0100739 call system("/bin/rm -rf -- ".shellescape(a:fname,0))
Bram Moolenaarab194812005-09-14 21:40:12 +0000740 elseif has("win32") || has("win95") || has("win64") || has("win16")
741 if &shell =~? "sh$"
Bram Moolenaar5c736222010-01-06 20:54:52 +0100742 call system("/bin/rm -rf -- ".shellescape(a:fname,0))
Bram Moolenaarab194812005-09-14 21:40:12 +0000743 else
Bram Moolenaar5c736222010-01-06 20:54:52 +0100744 call system("del /S ".shellescape(a:fname,0))
Bram Moolenaarab194812005-09-14 21:40:12 +0000745 endif
746 endif
Bram Moolenaarab194812005-09-14 21:40:12 +0000747endfun
748
Christian Brabandta2507382025-03-02 22:23:28 +0100749" s:FileHeader: {{{2
750fun! s:Header(fname)
751 let header= readblob(a:fname, 0, 6)
752 if header[0:2] == str2blob(['BZh']) " bzip2 header
753 return "bzip2"
754 elseif header[0:2] == str2blob(['BZ3']) " bzip3 header
755 return "bzip3"
756 elseif header == str2blob(["\3757zXZ\n"]) " xz header
757 return "xz"
758 elseif header[0:3] == str2blob(["\x28\xB5\x2F\xFD"]) " zstd header
759 return "zstd"
760 elseif header[0:3] == str2blob(["\004\"M\030"]) " lz4 header
761 return "lz4"
762 elseif (header[0:1] == str2blob(["\037\235"]) ||
763 \ header[0:1] == str2blob(["\037\213"]) ||
764 \ header[0:1] == str2blob(["\037\236"]) ||
765 \ header[0:1] == str2blob(["\037\240"]) ||
766 \ header[0:1] == str2blob(["\037\036"]))
767 return "gzip"
768 endif
769 return "unknown"
770endfun
771
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000772" ---------------------------------------------------------------------
Christian Brabandt470317f2025-04-16 17:13:28 +0200773" s:WinPath: {{{2
774fun! s:WinPath(path)
775 if (!g:netrw_cygwin || &shell !~ '\%(\<bash\>\|\<zsh\>\)\%(\.exe\)\=$') && has("win32")
776 " remove cygdrive prefix, if present
777 let path = substitute(a:path, '/cygdrive/\(.\)', '\1:', '')
778 " remove trailing slash (Win95)
779 let path = substitute(path, '\(\\\|/\)$', '', 'g')
780 " remove escaped spaces
781 let path = substitute(path, '\ ', ' ', 'g')
782 " convert slashes to backslashes
783 let path = substitute(path, '/', '\', 'g')
784 else
785 let path = a:path
786 endif
787
788 return path
789endfun
790
791" ---------------------------------------------------------------------
Bram Moolenaar5c736222010-01-06 20:54:52 +0100792" tar#Vimuntar: installs a tarball in the user's .vim / vimfiles directory {{{2
793fun! tar#Vimuntar(...)
Bram Moolenaar5c736222010-01-06 20:54:52 +0100794 let tarball = expand("%")
Bram Moolenaar5c736222010-01-06 20:54:52 +0100795 let tarbase = substitute(tarball,'\..*$','','')
Bram Moolenaar5c736222010-01-06 20:54:52 +0100796 let tarhome = expand("%:p")
797 if has("win32") || has("win95") || has("win64") || has("win16")
798 let tarhome= substitute(tarhome,'\\','/','g')
799 endif
800 let tarhome= substitute(tarhome,'/[^/]*$','','')
Bram Moolenaar5c736222010-01-06 20:54:52 +0100801 let tartail = expand("%:t")
Bram Moolenaar5c736222010-01-06 20:54:52 +0100802 let curdir = getcwd()
Bram Moolenaar5c736222010-01-06 20:54:52 +0100803 " set up vimhome
804 if a:0 > 0 && a:1 != ""
805 let vimhome= a:1
806 else
807 let vimhome= vimball#VimballHome()
808 endif
Bram Moolenaar5c736222010-01-06 20:54:52 +0100809
Bram Moolenaar5c736222010-01-06 20:54:52 +0100810 if simplify(curdir) != simplify(vimhome)
811 " copy (possibly compressed) tarball to .vim/vimfiles
Christian Brabandt470317f2025-04-16 17:13:28 +0200812 call system(s:WinPath(g:tar_copycmd)." ".shellescape(tartail)." ".shellescape(vimhome))
Michele Sorcinelli719ec0f2025-05-19 19:45:32 +0200813 exe "lcd ".fnameescape(vimhome)
Bram Moolenaar5c736222010-01-06 20:54:52 +0100814 endif
Bram Moolenaar5c736222010-01-06 20:54:52 +0100815
816 " if necessary, decompress the tarball; then, extract it
817 if tartail =~ '\.tgz'
Bram Moolenaar29634562020-01-09 21:46:04 +0100818 if executable("gunzip")
Bram Moolenaar5c736222010-01-06 20:54:52 +0100819 silent exe "!gunzip ".shellescape(tartail)
820 elseif executable("gzip")
821 silent exe "!gzip -d ".shellescape(tartail)
Bram Moolenaarc236c162008-07-13 17:41:49 +0000822 else
Bram Moolenaar6c391a72021-09-09 21:55:11 +0200823 echoerr "unable to decompress<".tartail."> on this system"
Bram Moolenaar5c736222010-01-06 20:54:52 +0100824 if simplify(curdir) != simplify(tarhome)
825 " remove decompressed tarball, restore directory
Bram Moolenaar5c736222010-01-06 20:54:52 +0100826 call delete(tartail.".tar")
Michele Sorcinelli719ec0f2025-05-19 19:45:32 +0200827 exe "lcd ".fnameescape(curdir)
Bram Moolenaar5c736222010-01-06 20:54:52 +0100828 endif
Bram Moolenaar5c736222010-01-06 20:54:52 +0100829 return
Bram Moolenaarc236c162008-07-13 17:41:49 +0000830 endif
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000831 else
Bram Moolenaar5c736222010-01-06 20:54:52 +0100832 call vimball#Decompress(tartail,0)
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000833 endif
Christian Brabandt470317f2025-04-16 17:13:28 +0200834 let extractcmd= s:WinPath(g:tar_extractcmd)
Bram Moolenaar5c736222010-01-06 20:54:52 +0100835 call system(extractcmd." ".shellescape(tarbase.".tar"))
836
837 " set up help
838 if filereadable("doc/".tarbase.".txt")
Bram Moolenaar5c736222010-01-06 20:54:52 +0100839 exe "helptags ".getcwd()."/doc"
840 endif
841
842 if simplify(tarhome) != simplify(vimhome)
843 " remove decompressed tarball, restore directory
844 call delete(vimhome."/".tarbase.".tar")
Michele Sorcinelli719ec0f2025-05-19 19:45:32 +0200845 exe "lcd ".fnameescape(curdir)
Bram Moolenaar5c736222010-01-06 20:54:52 +0100846 endif
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000847endfun
848
Bram Moolenaar5c736222010-01-06 20:54:52 +0100849" =====================================================================
Bram Moolenaara5792f52005-11-23 21:25:05 +0000850" Modelines And Restoration: {{{1
851let &cpo= s:keepcpo
852unlet s:keepcpo
Bram Moolenaar8c8de832008-06-24 22:58:06 +0000853" vim:ts=8 fdm=marker