def call(args, opts = {}, ioe = {})
argv = []
output = nil
dest = "."
files = []
while (arg = args.shift)
case arg
when '--uncompress', '-z'
opts[:uncompress] = true
when '--pipe'
opts[:output] = ioe[:error]
output = ioe[:output]
when '--output', '-o'
dest = args.shift
else
argv << arg
end
end
if argv.size < 1
ioe[:output] << "Not enough arguments.\n\n"
CommandPattern["help"][["extract"]]
return 255
end
input = argv.shift
if '-' == input
opts[:name] = "STDIN"
input = ioe[:input]
else
opts[:name] = input
input = File.open(input, "rb")
end
if opts[:name] =~ %r\.tar\.gz$|\.tgz$/ or opts[:uncompress]
input = Zlib::GzipReader.new(input)
end
files << argv.to_a
files.flatten!
if opts[:verbose]
watcher = lambda do |action, name, stats|
opts[:output] << "#{name}\n" if action == :dir or action == :file_done
end
finisher = lambda { opts[:output] << "\n" }
elsif opts[:progress]
progress = ProgressBar.new(opts[:name], 1)
watcher = lambda do |action, name, stats|
case action
when :file_start, :dir
progress.title = File.basename(name)
if action == :dir
progress.total += 1
progress.inc
else
progress.total += stats[:entry].size
end
when :file_progress
progress.inc(stats[:currinc])
end
end
finisher = lambda do
progress.title = opts[:name]
progress.finish
end
else
watcher = nil
finisher = lambda { }
end
if output.nil?
Archive::Tar::Minitar.unpack(input, dest, files, &watcher)
finisher.call
else
Archive::Tar::Minitar::Input.open(input) do |inp|
inp.each do |entry|
stats = {
:mode => entry.mode,
:mtime => entry.mtime,
:size => entry.size,
:gid => entry.gid,
:uid => entry.uid,
:current => 0,
:currinc => 0,
:entry => entry
}
if files.empty? or files.include?(entry.full_name)
if entry.directory?
puts "Directory: #{entry.full_name}"
watcher[:dir, dest, stats] unless watcher.nil?
else
puts "File: #{entry.full_name}"
watcher[:file_start, destfile, stats] unless watcher.nil?
loop do
data = entry.read(4096)
break unless data
stats[:currinc] = output.write(data)
stats[:current] += stats[:currinc]
watcher[:file_progress, name, stats] unless watcher.nil?
end
watcher[:file_done, name, stats] unless watcher.nil?
end
end
end
end
end
0
end