Skip to content

Commit 83de0e0

Browse files
Merge pull request #68 from JuliaIO/sk/list-without-mark
Tar.list: refactor to avoid using mark/unmark/reset
2 parents 678e790 + 4f18ad9 commit 83de0e0

File tree

4 files changed

+73
-37
lines changed

4 files changed

+73
-37
lines changed

src/Tar.jl

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -131,12 +131,8 @@ function list(
131131
)
132132
raw && strict &&
133133
error("`raw=true` and `strict=true` options are incompatible")
134-
read_hdr = raw ? read_standard_header :
135-
let globals = Dict{String,String}()
136-
(tar; buf) -> read_header(tar, globals, buf=buf)
137-
end
138134
arg_read(tarball) do tar
139-
iterate_headers(callback, tar, read_hdr, strict=strict)
135+
iterate_headers(callback, tar, raw=raw, strict=strict)
140136
end
141137
end
142138

src/create.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ function recreate_tarball(
2626
check_skeleton_header(skeleton, buf=buf)
2727
globals = Dict{String,String}()
2828
while !eof(skeleton)
29-
hdr = read_header(skeleton, globals, buf=buf, tee=tar)
29+
hdr = read_header(skeleton, globals=globals, buf=buf, tee=tar)
3030
hdr === nothing && break
3131
check_header(hdr)
3232
sys_path = joinpath(root, hdr.path)

src/extract.jl

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,34 @@ end
88

99
function iterate_headers(
1010
callback::Function,
11-
tar::IO,
12-
read_hdr::Function;
13-
strict::Bool = true,
11+
tar::IO;
12+
raw::Bool = false,
13+
strict::Bool = !raw,
1414
buf::Vector{UInt8} = Vector{UInt8}(undef, DEFAULT_BUFFER_SIZE),
1515
)
16-
if !eof(tar)
17-
mark(tar)
18-
hdr = read_standard_header(tar, buf=buf)
19-
if hdr.type == :g && hdr.path == SKELETON_MAGIC
20-
skip_data(tar, hdr.size)
21-
skeleton = true
22-
unmark(tar)
23-
else
24-
skeleton = false
25-
reset(tar)
16+
eof(tar) && return
17+
hdr = read_standard_header(tar, buf=buf)
18+
hdr == nothing && return
19+
if !raw
20+
globals = Dict{String,String}()
21+
end
22+
if hdr.type == :g && hdr.path == SKELETON_MAGIC
23+
skip_data(tar, hdr.size)
24+
skeleton = true
25+
else
26+
if !raw
27+
hdr = read_header(tar, hdr, globals=globals, buf=buf)
2628
end
29+
skeleton = false
30+
@goto loop
2731
end
2832
while !eof(tar)
29-
hdr = read_hdr(tar, buf=buf)
33+
hdr = if raw
34+
read_standard_header(tar, buf=buf)
35+
else
36+
read_header(tar, globals=globals, buf=buf)
37+
end
38+
@label loop
3039
hdr === nothing && break
3140
strict && check_header(hdr)
3241
callback(hdr)
@@ -298,7 +307,7 @@ function read_tarball(
298307
paths = Dict{String,Union{Symbol,String}}()
299308
globals = Dict{String,String}()
300309
while !eof(tar)
301-
hdr = read_header(tar, globals, buf=buf, tee=skeleton)
310+
hdr = read_header(tar, globals=globals, buf=buf, tee=skeleton)
302311
hdr === nothing && break
303312
# check if we should extract or skip
304313
if !predicate(hdr)
@@ -332,13 +341,23 @@ function read_tarball(
332341
end
333342

334343
function read_header(
335-
io::IO,
336-
globals::Dict{String,String} = Dict{String,String}();
344+
io::IO;
345+
globals::Dict{String,String} = Dict{String,String}(),
337346
buf::Vector{UInt8} = Vector{UInt8}(undef, DEFAULT_BUFFER_SIZE),
338347
tee::IO = devnull,
339348
)
340349
hdr = read_standard_header(io, buf=buf, tee=tee)
341350
hdr === nothing && return nothing
351+
read_header(io, hdr, globals=globals, buf=buf, tee=tee)
352+
end
353+
354+
function read_header(
355+
io::IO,
356+
hdr::Header; # initial header
357+
globals::Dict{String,String} = Dict{String,String}(),
358+
buf::Vector{UInt8} = Vector{UInt8}(undef, DEFAULT_BUFFER_SIZE),
359+
tee::IO = devnull,
360+
)
342361
# process zero or more extended headers
343362
metadata = copy(globals)
344363
while true

test/runtests.jl

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,42 @@ include("setup.jl")
3939
end
4040

4141
@testset "empty tarball" begin
42-
dir = mktempdir()
43-
tarball = Tar.create(dir)
44-
rm(dir, recursive=true)
45-
@test Tar.list(tarball) == [Tar.Header(".", :directory, 0o755, 0, "")]
46-
test_empty_hashes(tarball)
47-
dir = Tar.extract(tarball)
48-
@test isempty(readdir(dir))
49-
rm(dir, recursive=true)
50-
open(tarball, append=true) do io
51-
write(io, zeros(UInt8, 512))
42+
@testset "empty file as tarball" begin
43+
tarball = devnull
44+
@test Tar.list(tarball) == Tar.Header[]
45+
skel = tempname()
46+
dir = Tar.extract(tarball, skeleton=skel)
47+
@test isempty(readdir(dir))
48+
rm(dir, recursive=true)
49+
@test isfile(skel)
50+
@test Tar.list(skel) == Tar.Header[]
51+
@test Tar.list(skel, raw=true) == Tar.Header[]
52+
rm(skel)
53+
end
54+
55+
@testset "create an empty tarball" begin
56+
dir = mktempdir()
57+
tarball = Tar.create(dir)
58+
rm(dir, recursive=true)
59+
@test Tar.list(tarball) == [Tar.Header(".", :directory, 0o755, 0, "")]
60+
@test Tar.list(tarball, raw=true) == [Tar.Header(".", :directory, 0o755, 0, "")]
61+
test_empty_hashes(tarball)
62+
skel = tempname()
63+
dir = Tar.extract(tarball, skeleton=skel)
64+
@test isempty(readdir(dir))
65+
rm(dir, recursive=true)
66+
@test isfile(skel)
67+
@test Tar.list(skel) == [Tar.Header(".", :directory, 0o755, 0, "")]
68+
@test Tar.list(skel, raw=true) == [Tar.Header(".", :directory, 0o755, 0, "")]
69+
rm(skel)
70+
open(tarball, append=true) do io
71+
write(io, zeros(UInt8, 512))
72+
end
73+
test_empty_hashes(tarball)
74+
dir = Tar.extract(tarball)
75+
@test isempty(readdir(dir))
76+
rm(dir, recursive=true)
5277
end
53-
test_empty_hashes(tarball)
54-
dir = Tar.extract(tarball)
55-
@test isempty(readdir(dir))
56-
rm(dir, recursive=true)
5778
end
5879

5980
@testset "test tarball" begin

0 commit comments

Comments
 (0)