" 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)
"
" Contains many ideas from Michael Toren's <tar.vim>
"
endif
elseif filereadable(tarbase.".tzst")
- let extractcmd= substitute(extractcmd,"-","--zstd","")
+ let extractcmd= substitute(extractcmd,"-","--zstd -","")
call system(extractcmd." ".shellescape(tarbase).".tzst ".shellescape(fname))
if v:shell_error != 0
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tzst {fname}: failed!")
endif
elseif filereadable(tarbase.".tar.zst")
- let extractcmd= substitute(extractcmd,"-","--zstd","")
+ let extractcmd= substitute(extractcmd,"-","--zstd -","")
call system(extractcmd." ".shellescape(tarbase).".tar.zst ".shellescape(fname))
if v:shell_error != 0
call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar.zst {fname}: failed!")
bw!
enddef
-def g:Test_tar_lz4_extract()
- CheckExecutable lz4
-
- delete('X.txt')
- delete('Xarchive.tar')
- delete('Xarchive.tar.lz4')
- call writefile(['hello'], 'X.txt')
- call system('tar -cf Xarchive.tar X.txt')
+def CreateTar(archivename: string, content: string, outputdir: string)
+ var tempdir = tempname()
+ mkdir(tempdir, 'R')
+ call writefile([content], tempdir .. '/X.txt')
+ assert_true(filereadable(tempdir .. '/X.txt'))
+ call system('tar -C ' .. tempdir .. ' -cf ' .. outputdir .. '/' .. archivename .. ' X.txt')
assert_equal(0, v:shell_error)
+enddef
- call system('lz4 -z Xarchive.tar Xarchive.tar.lz4')
+def CreateTgz(archivename: string, content: string, outputdir: string)
+ var tempdir = tempname()
+ mkdir(tempdir, 'R')
+ call writefile([content], tempdir .. '/X.txt')
+ assert_true(filereadable(tempdir .. '/X.txt'))
+ call system('tar -C ' .. tempdir .. ' -czf ' .. outputdir .. '/' .. archivename .. ' X.txt')
assert_equal(0, v:shell_error)
+enddef
- delete('X.txt')
- delete('Xarchive.tar')
- defer delete('Xarchive.tar.lz4')
-
- e Xarchive.tar.lz4
- assert_match('X.txt', getline(5))
- :5
- normal x
- assert_true(filereadable('X.txt'))
- assert_equal(['hello'], readfile('X.txt'))
- delete('X.txt')
- bw!
+def CreateTbz(archivename: string, content: string, outputdir: string)
+ var tempdir = tempname()
+ mkdir(tempdir, 'R')
+ call writefile([content], tempdir .. '/X.txt')
+ assert_true(filereadable(tempdir .. '/X.txt'))
+ call system('tar -C ' .. tempdir .. ' -cjf ' .. outputdir .. '/' .. archivename .. ' X.txt')
+ assert_equal(0, v:shell_error)
enddef
-def g:Test_tlz4_extract()
- CheckExecutable lz4
+def CreateTxz(archivename: string, content: string, outputdir: string)
+ var tempdir = tempname()
+ mkdir(tempdir, 'R')
+ call writefile([content], tempdir .. '/X.txt')
+ assert_true(filereadable(tempdir .. '/X.txt'))
+ call system('tar -C ' .. tempdir .. ' -cJf ' .. outputdir .. '/' .. archivename .. ' X.txt')
+ assert_equal(0, v:shell_error)
+enddef
- delete('X.txt')
- delete('Xarchive.tar')
- delete('Xarchive.tlz4')
- call writefile(['goodbye'], 'X.txt')
- call system('tar -cf Xarchive.tar X.txt')
+def CreateTzst(archivename: string, content: string, outputdir: string)
+ var tempdir = tempname()
+ mkdir(tempdir, 'R')
+ call writefile([content], tempdir .. '/X.txt')
+ assert_true(filereadable(tempdir .. '/X.txt'))
+ call system('tar --zstd -C ' .. tempdir .. ' -cf ' .. outputdir .. '/' .. archivename .. ' X.txt')
assert_equal(0, v:shell_error)
+enddef
- call system('lz4 -z Xarchive.tar Xarchive.tlz4')
+def CreateTlz4(archivename: string, content: string, outputdir: string)
+ var tempdir = tempname()
+ mkdir(tempdir, 'R')
+ call writefile([content], tempdir .. '/X.txt')
+ assert_true(filereadable(tempdir .. '/X.txt'))
+ call system('tar -C ' .. tempdir .. ' -cf ' .. tempdir .. '/Xarchive.tar X.txt')
+ assert_equal(0, v:shell_error)
+ assert_true(filereadable(tempdir .. '/Xarchive.tar'))
+ call system('lz4 -z ' .. tempdir .. '/Xarchive.tar ' .. outputdir .. '/' .. archivename)
assert_equal(0, v:shell_error)
+enddef
- delete('X.txt')
- delete('Xarchive.tar')
- defer delete('Xarchive.tlz4')
+# XXX: Add test for .tar.bz3
+def g:Test_extraction()
+ var control = [
+ {create: CreateTar,
+ archive: 'Xarchive.tar'},
+ {create: CreateTgz,
+ archive: 'Xarchive.tgz'},
+ {create: CreateTgz,
+ archive: 'Xarchive.tar.gz'},
+ {create: CreateTbz,
+ archive: 'Xarchive.tbz'},
+ {create: CreateTbz,
+ archive: 'Xarchive.tar.bz2'},
+ {create: CreateTxz,
+ archive: 'Xarchive.txz'},
+ {create: CreateTxz,
+ archive: 'Xarchive.tar.xz'},
+ ]
+
+ if executable('lz4') == 1
+ control->add({
+ create: CreateTlz4,
+ archive: 'Xarchive.tar.lz4'
+ })
+ control->add({
+ create: CreateTlz4,
+ archive: 'Xarchive.tlz4'
+ })
+ endif
+ if executable('zstd') == 1
+ control->add({
+ create: CreateTzst,
+ archive: 'Xarchive.tar.zst'
+ })
+ control->add({
+ create: CreateTzst,
+ archive: 'Xarchive.tzst'
+ })
+ endif
- e Xarchive.tlz4
- assert_match('X.txt', getline(5))
- :5
- normal x
- assert_true(filereadable('X.txt'))
- assert_equal(['goodbye'], readfile('X.txt'))
- delete('X.txt')
- bw!
+ for c in control
+ var dir = tempname()
+ mkdir(dir, 'R')
+ call(c.create, [c.archive, 'hello', dir])
+
+ delete('X.txt')
+ execute 'edit ' .. dir .. '/' .. c.archive
+ assert_match('X.txt', getline(5), 'line 5 wrong in archive: ' .. c.archive)
+ :5
+ normal x
+ assert_equal(0, v:shell_error, 'vshell error not 0')
+ assert_true(filereadable('X.txt'), 'X.txt not readable for archive: ' .. c.archive)
+ assert_equal(['hello'], readfile('X.txt'), 'X.txt wrong contents for archive: ' .. c.archive)
+ delete('X.txt')
+ delete(dir .. '/' .. c.archive)
+ bw!
+ endfor
enddef