# Available options: # # rake test - Runs all test cases. # rake package - Runs test cases and builds packages for distribution. # rake rdoc - Builds API documentation in doc dir. # rake build_tz_modules - Builds Timezone modules and the Country index. # Expects to find source data in ../data. # rake build_tz_module zone=Zone/Name - Builds a single Timezone module. # Expects to find source data in ../data. # rake build_countries - Builds the Country index. # Expects to find source data in ../data. require 'rake' require 'rake/testtask' require 'rake/rdoctask' require 'rake/gempackagetask' require 'fileutils' Rake::TaskManager.class_eval do def remove_task(task_name) @tasks.delete(task_name.to_s) end end def remove_task(task_name) Rake.application.remove_task(task_name) end self.class.class_eval { alias_method :orig_sh, :sh } private :orig_sh def sh(*cmd, &block) if cmd.first =~ /\A__tar_with_owner__ -?([zjcvf]+)(.*)\z/ opts = $1 args = $2 cmd[0] = "tar c --owner 0 --group 0 -#{opts.gsub('c', '')}#{args}" end orig_sh(*cmd, &block) end BUILD_TZ_CLASSES_DIR = 'lib/tzinfo.build_tz_classes' SPEC = eval(File.read('tzinfo.gemspec')) package_task = Rake::GemPackageTask.new(SPEC) do |pkg| pkg.need_zip = true pkg.need_tar_gz = true pkg.tar_command = '__tar_with_owner__' end # Replace the Rake::PackageTask task that prepares the files to package with # a version that ensures the permissions are correct for the package. # Also just copy rather than link the files so that old versions are maintained. remove_task package_task.package_dir_path file package_task.package_dir_path => [package_task.package_dir] + package_task.package_files do mkdir_p package_task.package_dir_path rescue nil chmod(0755, package_task.package_dir_path) package_task.package_files.each do |fn| f = File.join(package_task.package_dir_path, fn) fdir = File.dirname(f) mkdir_p(fdir) if !File.exist?(fdir) if File.directory?(fn) mkdir_p(f) chmod(0755, f) else rm_f f cp(fn, f) chmod(0644, f) end end end # Replace the Rake::GemPackageTask task that builds the gem with a version that # changes to the copied package directory first. This allows the gem builder # to pick up the correct file permissions. remove_task "#{package_task.package_dir}/#{package_task.gem_file}" file "#{package_task.package_dir}/#{package_task.gem_file}" => [package_task.package_dir] + package_task.gem_spec.files do when_writing("Creating GEM") do chdir(package_task.package_dir_path) do Gem::Builder.new(package_task.gem_spec).build end verbose(true) do mv File.join(package_task.package_dir_path, package_task.gem_file), "#{package_task.package_dir}/#{package_task.gem_file}" end end end Rake::TestTask.new('test') do |t| # Force a particular timezone to be local (helps find issues when local # timezone isn't GMT). This won't work on Windows. ENV['TZ'] = 'America/Los_Angeles' t.libs << '.' t.pattern = 'test/tc_*.rb' t.verbose = true end Rake::RDocTask.new do |rdoc| rdoc.rdoc_dir = 'doc' rdoc.title = "TZInfo" rdoc.options << '--inline-source' rdoc.options.concat SPEC.rdoc_options rdoc.rdoc_files.include(*SPEC.extra_rdoc_files) rdoc.rdoc_files.include('lib') end task :build_tz_modules do require 'lib/tzinfo/tzdataparser' FileUtils.mkdir_p(BUILD_TZ_CLASSES_DIR) begin p = TZInfo::TZDataParser.new('data', BUILD_TZ_CLASSES_DIR) p.execute scm = Scm.create(File.dirname(__FILE__)) ['indexes', 'definitions'].each do |dir| scm.sync("#{BUILD_TZ_CLASSES_DIR}/#{dir}", "lib/tzinfo/#{dir}") end ensure FileUtils.rm_rf(BUILD_TZ_CLASSES_DIR) end end class Scm def self.create(dir) if File.directory?(File.join(dir, '.git')) GitScm.new(dir) elsif File.directory?(File.join(dir, '.svn')) SvnScm.new(dir) else NullScm.new(dir) end end def initialize(dir) end def sync(source_dir, target_dir) puts "Sync from #{source_dir} to #{target_dir}#{command ? " using #{command}" : ''}" sync_dirs(source_dir, target_dir) end protected def exec_scm(params) puts "#{command} #{params}" `#{command} #{params}` raise "#{command} exited with status #$?" if $? != 0 end private def sync_dirs(source_dir, target_dir) # Assumes a directory will never turn into a file and vice-versa # (files will all end in .rb, directories won't). source_entries, target_entries = [source_dir, target_dir].collect do |dir| Dir.entries(dir).delete_if {|entry| entry =~ /\A\./}.sort end until source_entries.empty? || target_entries.empty? last_source = source_entries.last last_target = target_entries.last if last_source == last_target source_file = File.join(source_dir, last_source) target_file = File.join(target_dir, last_target) if File.directory?(source_file) sync_dirs(source_file, target_file) else FileUtils.cp(source_file, target_file) end source_entries.pop target_entries.pop elsif source_entries.last < target_entries.last sync_only_in_target(target_dir, target_entries) else sync_only_in_source(source_dir, target_dir, source_entries) end end until target_entries.empty? sync_only_in_target(target_dir, target_entries) end until source_entries.empty? sync_only_in_source(source_dir, target_dir, source_entries) end end def sync_only_in_target(target_dir, target_entries) target_file = File.join(target_dir, target_entries.last) delete(target_file) target_entries.pop end def sync_only_in_source(source_dir, target_dir, source_entries) source_file = File.join(source_dir, source_entries.last) target_file = File.join(target_dir, source_entries.last) if File.directory?(source_file) Dir.mkdir(target_file) add(target_file) sync_dirs(source_file, target_file) else FileUtils.cp(source_file, target_file) add(target_file) end source_entries.pop end end class NullScm < Scm def command nil end def add(file) end def delete(file) puts "rm -rf \"#{file}\"" FileUtils.rm_rf(file) end end class GitScm < Scm def command 'git' end def add(file) unless File.directory?(file) exec_scm "add \"#{file}\"" end end def delete(file) exec_scm "rm -rf \"#{file}\"" end end class SvnScm < Scm def command 'svn' end def add(file) exec_scm "add \"#{file}\"" end def delete(file) exec_scm "delete --force \"#{file}\"" end end task :build_tz_module do require 'lib/tzinfo/tzdataparser' p = TZInfo::TZDataParser.new('data', 'lib/tzinfo') p.generate_countries = false p.only_zones = [ENV['zone']] p.execute end task :build_countries do require 'lib/tzinfo/tzdataparser' p = TZInfo::TZDataParser.new('data', 'lib/tzinfo') p.generate_countries = true p.generate_zones = false p.execute end