require "albacore/albacoretask" require "albacore/config/zipdirectoryconfig" require "zip" class ZipDirectory TaskName = :zip include Albacore::Task include Configuration::Zip attr_reader :flatten attr_accessor :output_path attr_array :dirs, :files, :exclusions def initialize @dirs = [] @files = [] @exclusions = [] super() update_attributes(zip.to_hash) end def execute() unless @output_path fail_with_message("zip requires #output_path") return end FileUtils.rm_rf(@output_path) exclusions = Exclusions.new(@dirs) @exclusions.each { |ex| exclusions.expand!(ex) } archive = Archive.new(output_path, exclusions, flatten) @dirs.each { |path| archive.dir(path) } @files.each { |path| archive.file(path) } archive.close() end def flatten @flatten = true end end class Archive def initialize(archive_path, exclusions, flatten) @archive = Zip::File.open(archive_path, Zip::File::CREATE) @exclusions = exclusions @flatten = flatten end def dir(dir) pattern = File.join(dir, "**/*") Dir[pattern].each do |file| next if @exclusions.exclude?(file) name = @flatten ? file.sub(File.join(dir, "/"), "") : file @archive.add(name, file) end end def file(file) return if @exclusions.exclude?(file) name = @flatten ? file.split("/").last : file @archive.add(name, file) end def close() @archive.close() end end class Exclusions def initialize(dirs) @dirs = dirs @exclusions = [] end def expand!(ex) if ex.is_a?(Regexp) @exclusions << ex return end @dirs.each do |dir| Dir.chdir(dir) do matches = Dir.glob(ex) matches = matches.map { |path| File.join(dir, path) } unless matches[0] == ex @exclusions += (matches.empty? ? [ex] : matches) end end end def exclude?(path) @exclusions.any? do |ex| return path =~ ex if ex.is_a?(Regexp) return path == ex end end end