Last active
December 20, 2015 17:09
-
-
Save glucero/6166501 to your computer and use it in GitHub Desktop.
self extracting ruby archiver
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
class RubyArchive | |
require 'rubygems/package' | |
require 'zlib' | |
attr_reader :path | |
class Archive | |
def initialize(path, object) | |
@path = path | |
@object = object | |
@data, @tar = StringIO.new, StringIO.new | |
end | |
def empty? | |
@object.size.zero? | |
end | |
def compressed_files | |
Gem::Package::TarReader.new(Zlib::GzipReader.new @object).tap(&:rewind) | |
end | |
def uncompressed_files | |
Dir.glob(File.join @path, '{,**/{*,.*}}').map &File.method(:open) | |
end | |
def make_dir(directory) | |
Dir.mkdir File.join(@path, directory.full_name), directory.header.mode | |
end | |
def make_file(file) | |
File.open(File.join(@path, file.full_name), 'wb') do |f| | |
f.write file.read | |
f.chmod file.header.mode | |
end | |
end | |
def add_dir(directory) | |
tar_writer.mkdir directory.path, directory.stat.mode | |
end | |
def add_file(file) | |
tar_writer.add_file(file.path, file.stat.mode) { |f| f.write file.read } | |
end | |
def finalize | |
@tar.seek 0 | |
gzip_writer.write @tar.read | |
@tar.close | |
gzip_writer.finish | |
@data.seek 0 | |
end | |
def write | |
File.open(filename, 'wb') do |file| | |
file.write File.read(__FILE__) | |
file.write @data.read | |
file.chmod 0o755 | |
end | |
end | |
def filename | |
@path.gsub(/\//, '') + '-archive.rb' | |
end | |
def gzip_writer | |
@gzip_writer ||= Zlib::GzipWriter.new(@data) | |
end | |
def tar_writer | |
@tar_writer ||= Gem::Package::TarWriter.new(@tar) | |
end | |
end | |
def initialize(path) | |
@path = path | |
@archive = Archive.new @path, StringIO.new(DATA.read) | |
yield self | |
end | |
def usage | |
@archive.empty? ? 'dir_or_file_to_compress' : 'dir_to_decompress_archive_to' | |
end | |
def run | |
@archive.empty? ? compress : decompress | |
end | |
def decompress | |
@archive.compressed_files.each do |object| | |
if object.directory? | |
@archive.make_dir object | |
else | |
@archive.make_file object | |
end | |
end | |
system "ls -la #@path" # change me to turn this into an installer | |
puts 'Extraction complete.' | |
end | |
def compress | |
@archive.uncompressed_files.each do |object| | |
if File.directory? object | |
@archive.add_dir object | |
else | |
@archive.add_file object | |
end | |
end | |
@archive.finalize | |
@archive.write | |
puts 'Compression complete.' | |
end | |
def self.start(path) | |
new(path) do |ruby_archive| | |
if ruby_archive.path | |
ruby_archive.run | |
else | |
puts %|usage: #{__FILE__} /path/to/#{ruby_archive.usage}| | |
end | |
end | |
end | |
end | |
RubyArchive.start ARGV.shift | |
__END__ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment