require 'buildr' require 'archive/tar/minitar' module Buildr class TarTask < Rake::FileTask attr_reader :included def initialize(*args) super @included = {} enhance do $stdout << "Creating #{t.name}.\n" if verbose rm(name, :verbose=>false) rescue nil mkdir_p(File.dirname(name), :verbose=>false) begin out = File.new(name, "w+") out = Zlib::GzipWriter.new(out) if (/.tgz$/ =~ name) create_tar_internal(out) rescue rm(name, :verbose=>false) rescue nil raise end end end def with(options) options.each do |k,v| send "#{k}=", v end end def include(*args) options = (Hash === args.last) ? args.pop : {} args = args.flatten options[:path] ||= "/" check_add_path_internal options if options[:as] raise "Only use :as with one include file at a time" if args.length > 1 dest_file = File.join(options[:path], options[:as]) include_internal(dest_file, args.pop, options) else args.each do |f| dest_file = File.join(options[:path], File.basename(f.to_s)) include_internal(dest_file, f, options) end end end private def check_add_path_internal(opts) unless @included.has_key?(opts[:path]) include_internal(opts[:path], :mkdir_in_tar, opts) end end def include_internal(dst, src, opts) raise %Q("#{dst}" was already included in the archive with source path "#{@included[dst][:source_path]}".) if @included[dst] @included[dst] = opts.merge({:source_path => src}) enhance([src]) unless :mkdir_in_tar == src end def create_tar_internal(out) begin Archive::Tar::Minitar::Writer.open(out) do |tar| @included.keys.sort.each do |dst| opts = @included[dst] src = opts[:source_path] if :mkdir_in_tar == src $stdout << "adding directory #{dst}.\n" if verbose tar.mkdir(dst, {:mode=>"0755", :mtime=>Time.now}.merge(opts.reject{|k,v| not [:mode, :uid, :gid, :mtime].include?(k)})) else $stdout << "adding #{dst} from #{src}\n" if verbose is = File.new(src, "rb") opts[:size] = is.stat.size opts[:mode] ||= is.stat.mode opts[:mtime] ||= is.stat.mtime opts[:uid] ||= 80 opts[:gid] ||= 80 tar.add_file_simple(dst, opts.reject{|k,v| not [:size, :mode, :uid, :gid, :mtime].include?(k)}) do |os| while data = is.read(4096) os.write(data) $stdout << "." if verbose end end $stdout << "\n" if verbose end end end ensure out.close end end end class TarballTask < TarTask def initialize(*args) super end def include(*args) options = (Hash === args.last) ? args.pop : {} args = args.flatten options[:path] ||= "/" options[:path] = File.join(name.pathmap("%n"), options[:path]) super args, options end end end