mirror of
https://github.com/neovim/neovim.git
synced 2026-06-06 12:04:15 +00:00
Merge pull request #38924 from zeertzjq/vim-9.2.0325
vim-patch:9.2.{0325,0326}: tar plugin fixes
This commit is contained in:
@@ -20,6 +20,8 @@
|
||||
" 2026 Feb 06 by Vim Project: consider 'nowrapscan' (#19333)
|
||||
" 2026 Feb 07 by Vim Project: make the path traversal detection more robust (#19341)
|
||||
" 2026 Apr 06 by Vim Project: fix bugs with lz4 support (#19925)
|
||||
" 2026 Apr 09 by Vim Project: fix bugs with zstd support (#19930)
|
||||
" 2026 Apr 09 by Vim Project: fix bug with dotted filename (#19930)
|
||||
"
|
||||
" Contains many ideas from Michael Toren's <tar.vim>
|
||||
"
|
||||
@@ -610,117 +612,120 @@ fun! tar#Extract()
|
||||
return
|
||||
endif
|
||||
|
||||
let tarball = expand("%")
|
||||
let tarbase = substitute(tarball,'\..*$','','')
|
||||
|
||||
let extractcmd= s:WinPath(g:tar_extractcmd)
|
||||
if filereadable(tarbase.".tar")
|
||||
call system(extractcmd." ".shellescape(tarbase).".tar ".shellescape(fname))
|
||||
let tarball = expand("%")
|
||||
if !filereadable(tarball)
|
||||
let &report= repkeep
|
||||
return
|
||||
endif
|
||||
|
||||
if tarball =~# "\.tar$"
|
||||
call system(extractcmd." ".shellescape(tarball)." ".shellescape(fname))
|
||||
if v:shell_error != 0
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar {fname}: failed!")
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarball} {fname}: failed!")
|
||||
else
|
||||
echo "***note*** successfully extracted ". fname
|
||||
endif
|
||||
|
||||
elseif filereadable(tarbase.".tgz")
|
||||
elseif tarball =~# "\.tgz$"
|
||||
let extractcmd= substitute(extractcmd,"-","-z","")
|
||||
call system(extractcmd." ".shellescape(tarbase).".tgz ".shellescape(fname))
|
||||
call system(extractcmd." ".shellescape(tarball)." ".shellescape(fname))
|
||||
if v:shell_error != 0
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tgz {fname}: failed!")
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarball} {fname}: failed!")
|
||||
else
|
||||
echo "***note*** successfully extracted ".fname
|
||||
endif
|
||||
|
||||
elseif filereadable(tarbase.".tar.gz")
|
||||
elseif tarball =~# "\.tar\.gz$"
|
||||
let extractcmd= substitute(extractcmd,"-","-z","")
|
||||
call system(extractcmd." ".shellescape(tarbase).".tar.gz ".shellescape(fname))
|
||||
call system(extractcmd." ".shellescape(tarball)." ".shellescape(fname))
|
||||
if v:shell_error != 0
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar.gz {fname}: failed!")
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarball} {fname}: failed!")
|
||||
else
|
||||
echo "***note*** successfully extracted ".fname
|
||||
endif
|
||||
|
||||
elseif filereadable(tarbase.".tbz")
|
||||
elseif tarball =~# "\.tbz$"
|
||||
let extractcmd= substitute(extractcmd,"-","-j","")
|
||||
call system(extractcmd." ".shellescape(tarbase).".tbz ".shellescape(fname))
|
||||
call system(extractcmd." ".shellescape(tarball)." ".shellescape(fname))
|
||||
if v:shell_error != 0
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tbz {fname}: failed!")
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarball} {fname}: failed!")
|
||||
else
|
||||
echo "***note*** successfully extracted ".fname
|
||||
endif
|
||||
|
||||
elseif filereadable(tarbase.".tar.bz2")
|
||||
elseif tarball =~# "\.tar\.bz2$"
|
||||
let extractcmd= substitute(extractcmd,"-","-j","")
|
||||
call system(extractcmd." ".shellescape(tarbase).".tar.bz2 ".shellescape(fname))
|
||||
call system(extractcmd." ".shellescape(tarball)." ".shellescape(fname))
|
||||
if v:shell_error != 0
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar.bz2 {fname}: failed!")
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarball} {fname}: failed!")
|
||||
else
|
||||
echo "***note*** successfully extracted ".fname
|
||||
endif
|
||||
|
||||
elseif filereadable(tarbase.".tar.bz3")
|
||||
elseif tarball =~# "\.tar\.bz3$"
|
||||
let extractcmd= substitute(extractcmd,"-","-j","")
|
||||
call system(extractcmd." ".shellescape(tarbase).".tar.bz3 ".shellescape(fname))
|
||||
call system(extractcmd." ".shellescape(tarball)." ".shellescape(fname))
|
||||
if v:shell_error != 0
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar.bz3 {fname}: failed!")
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarball} {fname}: failed!")
|
||||
else
|
||||
echo "***note*** successfully extracted ".fname
|
||||
endif
|
||||
|
||||
elseif filereadable(tarbase.".txz")
|
||||
elseif tarball =~# "\.txz$"
|
||||
let extractcmd= substitute(extractcmd,"-","-J","")
|
||||
call system(extractcmd." ".shellescape(tarbase).".txz ".shellescape(fname))
|
||||
call system(extractcmd." ".shellescape(tarball)." ".shellescape(fname))
|
||||
if v:shell_error != 0
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.txz {fname}: failed!")
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarball} {fname}: failed!")
|
||||
else
|
||||
echo "***note*** successfully extracted ".fname
|
||||
endif
|
||||
|
||||
elseif filereadable(tarbase.".tar.xz")
|
||||
elseif tarball =~# "\.tar\.xz$"
|
||||
let extractcmd= substitute(extractcmd,"-","-J","")
|
||||
call system(extractcmd." ".shellescape(tarbase).".tar.xz ".shellescape(fname))
|
||||
call system(extractcmd." ".shellescape(tarball)." ".shellescape(fname))
|
||||
if v:shell_error != 0
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar.xz {fname}: failed!")
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarball} {fname}: failed!")
|
||||
else
|
||||
echo "***note*** successfully extracted ".fname
|
||||
endif
|
||||
|
||||
elseif filereadable(tarbase.".tzst")
|
||||
let extractcmd= substitute(extractcmd,"-","--zstd","")
|
||||
call system(extractcmd." ".shellescape(tarbase).".tzst ".shellescape(fname))
|
||||
elseif tarball =~# "\.tzst$"
|
||||
let extractcmd= substitute(extractcmd,"-","--zstd -","")
|
||||
call system(extractcmd." ".shellescape(tarball)." ".shellescape(fname))
|
||||
if v:shell_error != 0
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tzst {fname}: failed!")
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarball} {fname}: failed!")
|
||||
else
|
||||
echo "***note*** successfully extracted ".fname
|
||||
endif
|
||||
|
||||
elseif filereadable(tarbase.".tar.zst")
|
||||
let extractcmd= substitute(extractcmd,"-","--zstd","")
|
||||
call system(extractcmd." ".shellescape(tarbase).".tar.zst ".shellescape(fname))
|
||||
elseif tarball =~# "\.tar\.zst$"
|
||||
let extractcmd= substitute(extractcmd,"-","--zstd -","")
|
||||
call system(extractcmd." ".shellescape(tarball)." ".shellescape(fname))
|
||||
if v:shell_error != 0
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar.zst {fname}: failed!")
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarball} {fname}: failed!")
|
||||
else
|
||||
echo "***note*** successfully extracted ".fname
|
||||
endif
|
||||
|
||||
elseif filereadable(tarbase.".tlz4")
|
||||
elseif tarball =~# "\.tlz4$"
|
||||
if has("linux")
|
||||
let extractcmd= substitute(extractcmd,"-","-I lz4 -","")
|
||||
endif
|
||||
call system(extractcmd." ".shellescape(tarbase).".tlz4 ".shellescape(fname))
|
||||
call system(extractcmd." ".shellescape(tarball)." ".shellescape(fname))
|
||||
if v:shell_error != 0
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tlz4 {fname}: failed!")
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarball} {fname}: failed!")
|
||||
else
|
||||
echo "***note*** successfully extracted ".fname
|
||||
endif
|
||||
|
||||
elseif filereadable(tarbase.".tar.lz4")
|
||||
elseif tarball =~# "\.tar\.lz4$"
|
||||
if has("linux")
|
||||
let extractcmd= substitute(extractcmd,"-","-I lz4 -","")
|
||||
endif
|
||||
call system(extractcmd." ".shellescape(tarbase).".tar.lz4 ".shellescape(fname))
|
||||
call system(extractcmd." ".shellescape(tarball)." ".shellescape(fname))
|
||||
if v:shell_error != 0
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar.lz4 {fname}: failed!")
|
||||
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarball} {fname}: failed!")
|
||||
else
|
||||
echo "***note*** successfully extracted ".fname
|
||||
endif
|
||||
|
||||
@@ -151,56 +151,168 @@ func Test_tar_path_traversal_with_nowrapscan()
|
||||
bw!
|
||||
endfunc
|
||||
|
||||
func Test_tar_lz4_extract()
|
||||
CheckExecutable lz4
|
||||
|
||||
call delete('X.txt')
|
||||
call delete('Xarchive.tar')
|
||||
call delete('Xarchive.tar.lz4')
|
||||
call writefile(['hello'], 'X.txt')
|
||||
call system('tar -cf Xarchive.tar X.txt')
|
||||
func s:CreateTar(archivename, content, outputdir)
|
||||
let tempdir = tempname()
|
||||
call mkdir(tempdir, 'R')
|
||||
call writefile([a:content], tempdir .. '/X.txt')
|
||||
call assert_true(filereadable(tempdir .. '/X.txt'))
|
||||
call system('tar -C ' .. tempdir .. ' -cf ' .. a:outputdir .. '/' .. a:archivename .. ' X.txt')
|
||||
call assert_equal(0, v:shell_error)
|
||||
endfunc
|
||||
|
||||
call system('lz4 -z Xarchive.tar Xarchive.tar.lz4')
|
||||
func s:CreateTgz(archivename, content, outputdir)
|
||||
let tempdir = tempname()
|
||||
call mkdir(tempdir, 'R')
|
||||
call writefile([a:content], tempdir .. '/X.txt')
|
||||
call assert_true(filereadable(tempdir .. '/X.txt'))
|
||||
call system('tar -C ' .. tempdir .. ' -czf ' .. a:outputdir .. '/' .. a:archivename .. ' X.txt')
|
||||
call assert_equal(0, v:shell_error)
|
||||
endfunc
|
||||
|
||||
func s:CreateTbz(archivename, content, outputdir)
|
||||
let tempdir = tempname()
|
||||
call mkdir(tempdir, 'R')
|
||||
call writefile([a:content], tempdir .. '/X.txt')
|
||||
call assert_true(filereadable(tempdir .. '/X.txt'))
|
||||
call system('tar -C ' .. tempdir .. ' -cjf ' .. a:outputdir .. '/' .. a:archivename .. ' X.txt')
|
||||
call assert_equal(0, v:shell_error)
|
||||
endfunc
|
||||
|
||||
func s:CreateTxz(archivename, content, outputdir)
|
||||
let tempdir = tempname()
|
||||
call mkdir(tempdir, 'R')
|
||||
call writefile([a:content], tempdir .. '/X.txt')
|
||||
call assert_true(filereadable(tempdir .. '/X.txt'))
|
||||
call system('tar -C ' .. tempdir .. ' -cJf ' .. a:outputdir .. '/' .. a:archivename .. ' X.txt')
|
||||
call assert_equal(0, v:shell_error)
|
||||
endfunc
|
||||
|
||||
func s:CreateTzst(archivename, content, outputdir)
|
||||
let tempdir = tempname()
|
||||
call mkdir(tempdir, 'R')
|
||||
call writefile([a:content], tempdir .. '/X.txt')
|
||||
call assert_true(filereadable(tempdir .. '/X.txt'))
|
||||
call system('tar --zstd -C ' .. tempdir .. ' -cf ' .. a:outputdir .. '/' .. a:archivename .. ' X.txt')
|
||||
call assert_equal(0, v:shell_error)
|
||||
endfunc
|
||||
|
||||
func s:CreateTlz4(archivename, content, outputdir)
|
||||
let tempdir = tempname()
|
||||
call mkdir(tempdir, 'R')
|
||||
call writefile([a:content], tempdir .. '/X.txt')
|
||||
call assert_true(filereadable(tempdir .. '/X.txt'))
|
||||
call system('tar -C ' .. tempdir .. ' -cf ' .. tempdir .. '/Xarchive.tar X.txt')
|
||||
call assert_equal(0, v:shell_error)
|
||||
call assert_true(filereadable(tempdir .. '/Xarchive.tar'))
|
||||
call system('lz4 -z ' .. tempdir .. '/Xarchive.tar ' .. a:outputdir .. '/' .. a:archivename)
|
||||
call assert_equal(0, v:shell_error)
|
||||
endfunc
|
||||
|
||||
" XXX: Add test for .tar.bz3
|
||||
func Test_extraction()
|
||||
let control = [
|
||||
\ #{create: function('s:CreateTar'),
|
||||
\ archive: 'Xarchive.tar'},
|
||||
\ #{create: function('s:CreateTgz'),
|
||||
\ archive: 'Xarchive.tgz'},
|
||||
\ #{create: function('s:CreateTgz'),
|
||||
\ archive: 'Xarchive.tar.gz'},
|
||||
\ #{create: function('s:CreateTbz'),
|
||||
\ archive: 'Xarchive.tbz'},
|
||||
\ #{create: function('s:CreateTbz'),
|
||||
\ archive: 'Xarchive.tar.bz2'},
|
||||
\ #{create: function('s:CreateTxz'),
|
||||
\ archive: 'Xarchive.txz'},
|
||||
\ #{create: function('s:CreateTxz'),
|
||||
\ archive: 'Xarchive.tar.xz'},
|
||||
\ ]
|
||||
|
||||
if executable('lz4') == 1
|
||||
eval control->add(#{
|
||||
\ create: function('s:CreateTlz4'),
|
||||
\ archive: 'Xarchive.tar.lz4'
|
||||
\ })
|
||||
eval control->add(#{
|
||||
\ create: function('s:CreateTlz4'),
|
||||
\ archive: 'Xarchive.tlz4'
|
||||
\ })
|
||||
endif
|
||||
if executable('zstd') == 1
|
||||
eval control->add(#{
|
||||
\ create: function('s:CreateTzst'),
|
||||
\ archive: 'Xarchive.tar.zst'
|
||||
\ })
|
||||
eval control->add(#{
|
||||
\ create: function('s:CreateTzst'),
|
||||
\ archive: 'Xarchive.tzst'
|
||||
\ })
|
||||
endif
|
||||
|
||||
for c in control
|
||||
let dir = tempname()
|
||||
call mkdir(dir, 'R')
|
||||
call call(c.create, [c.archive, 'hello', dir])
|
||||
|
||||
call delete('X.txt')
|
||||
execute 'edit ' .. dir .. '/' .. c.archive
|
||||
call assert_match('X.txt', getline(5), 'line 5 wrong in archive: ' .. c.archive)
|
||||
:5
|
||||
normal x
|
||||
call assert_equal(0, v:shell_error, 'vshell error not 0')
|
||||
call assert_true(filereadable('X.txt'), 'X.txt not readable for archive: ' .. c.archive)
|
||||
call assert_equal(['hello'], readfile('X.txt'), 'X.txt wrong contents for archive: ' .. c.archive)
|
||||
call delete('X.txt')
|
||||
call delete(dir .. '/' .. c.archive)
|
||||
bw!
|
||||
endfor
|
||||
endfunc
|
||||
|
||||
func Test_extract_with_dotted_dir()
|
||||
call delete('X.txt')
|
||||
call writefile(['when they kiss they spit white noise'], 'X.txt')
|
||||
|
||||
let dirname = tempname()
|
||||
call mkdir(dirname, 'R')
|
||||
let dirname = dirname .. '/foo.bar'
|
||||
call mkdir(dirname, 'R')
|
||||
let tarpath = dirname .. '/Xarchive.tar.gz'
|
||||
call system('tar -czf ' .. tarpath .. ' X.txt')
|
||||
call assert_true(filereadable(tarpath))
|
||||
call assert_equal(0, v:shell_error)
|
||||
|
||||
call delete('X.txt')
|
||||
call delete('Xarchive.tar')
|
||||
defer delete('Xarchive.tar.lz4')
|
||||
defer delete(tarpath)
|
||||
|
||||
e Xarchive.tar.lz4
|
||||
execute 'e ' .. tarpath
|
||||
call assert_match('X.txt', getline(5))
|
||||
:5
|
||||
normal x
|
||||
call assert_true(filereadable('X.txt'))
|
||||
call assert_equal(['hello'], readfile('X.txt'))
|
||||
call assert_equal(['when they kiss they spit white noise'], readfile('X.txt'))
|
||||
call delete('X.txt')
|
||||
bw!
|
||||
endfunc
|
||||
|
||||
func Test_tlz4_extract()
|
||||
CheckExecutable lz4
|
||||
|
||||
func Test_extract_with_dotted_filename()
|
||||
call delete('X.txt')
|
||||
call delete('Xarchive.tar')
|
||||
call delete('Xarchive.tlz4')
|
||||
call writefile(['goodbye'], 'X.txt')
|
||||
call system('tar -cf Xarchive.tar X.txt')
|
||||
call assert_equal(0, v:shell_error)
|
||||
call writefile(['holiday inn'], 'X.txt')
|
||||
|
||||
call system('lz4 -z Xarchive.tar Xarchive.tlz4')
|
||||
let dirname = tempname()
|
||||
call mkdir(dirname, 'R')
|
||||
let tarpath = dirname .. '/Xarchive.foo.tar.gz'
|
||||
call system('tar -czf ' .. tarpath .. ' X.txt')
|
||||
call assert_true(filereadable(tarpath))
|
||||
call assert_equal(0, v:shell_error)
|
||||
|
||||
call delete('X.txt')
|
||||
call delete('Xarchive.tar')
|
||||
defer delete('Xarchive.tlz4')
|
||||
defer delete(tarpath)
|
||||
|
||||
e Xarchive.tlz4
|
||||
execute 'e ' .. tarpath
|
||||
call assert_match('X.txt', getline(5))
|
||||
:5
|
||||
normal x
|
||||
call assert_true(filereadable('X.txt'))
|
||||
call assert_equal(['goodbye'], readfile('X.txt'))
|
||||
call assert_equal(['holiday inn'], readfile('X.txt'))
|
||||
call delete('X.txt')
|
||||
bw!
|
||||
endfunc
|
||||
|
||||
Reference in New Issue
Block a user