Skip to content

Instantly share code, notes, and snippets.

@ik5
Created November 29, 2016 17:00
Show Gist options
  • Save ik5/6096a11cad80b19d1f682977e2f08834 to your computer and use it in GitHub Desktop.
Save ik5/6096a11cad80b19d1f682977e2f08834 to your computer and use it in GitHub Desktop.
Work with native TAR files on Ruby
# based on https://gist.github.com/sinisterchipmunk/1335041
require 'rubygems/package'
require 'fileutils'
require 'zlib'
def create_tar(path, opts={})
tarfile = StringIO.new("")
Gem::Package::TarWriter.new(tarfile) do |tar|
Dir[File.join(path, "**/*")].each do |file|
mode = File.stat(file).mode
if opts[:relative_file]
relative_file = file.sub(/^#{Regexp::escape path}\/?/, '')
else
relative_file = file.sub %r|^/|, ''
end
if File.directory?(file)
tar.mkdir relative_file, mode
else
tar.add_file relative_file, mode do |tf|
File.open(file, "rb") { |f| tf.write f.read }
end
end
end
end
tarfile.rewind
tarfile
end
def gzip(tarfile)
gz = StringIO.new("")
z = Zlib::GzipWriter.new(gz)
z.write tarfile.string
z.close # this is necessary!
# z was closed to write the gzip footer, so
# now we need a new StringIO
StringIO.new gz.string
end
def ungzip(tarfile)
tarfile.rewind
z = Zlib::GzipReader.new(tarfile)
unzipped = StringIO.new(z.read)
z.close
unzipped
end
def untar(io, destination)
io.rewind
Gem::Package::TarReader.new io do |tar|
tar.each do |tarfile|
destination_file = File.join destination, tarfile.full_name
if tarfile.directory?
FileUtils.mkdir_p destination_file
else
destination_directory = File.dirname(destination_file)
FileUtils.mkdir_p destination_directory unless File.directory?(destination_directory)
File.open destination_file, "wb" do |f|
f.print tarfile.read
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment