require 'find' require 'rake/packagetask' require 'rubygems/user_interaction' require 'rubygems/builder' module Bones class GemPackageTask < Rake::PackageTask # Ruby GEM spec containing the metadata for this package. The # name, version and package_files are automatically determined # from the GEM spec and don't need to be explicitly provided. # attr_accessor :gem_spec # Tasks from the Bones gem directory attr_reader :bones_files # Create a GEM Package task library. Automatically define the gem # if a block is given. If no block is supplied, then +define+ # needs to be called to define the task. # def initialize(gem_spec) init(gem_spec) yield self if block_given? define if block_given? end # Initialization tasks without the "yield self" or define # operations. # def init(gem) super(gem.name, gem.version) @gem_spec = gem @package_files += gem_spec.files if gem_spec.files @bones_files = [] local_setup = File.join(Dir.pwd, %w[tasks setup.rb]) if !test(?e, local_setup) Dir.glob(::Bones.path(%w[lib bones tasks *])).each {|fn| bones_files << fn} end end # Create the Rake tasks and actions specified by this # GemPackageTask. (+define+ is automatically called if a block is # given to +new+). # def define super task :prereqs task :package => ['gem:prereqs', "#{package_dir_path}/#{gem_file}"] file "#{package_dir_path}/#{gem_file}" => [package_dir_path] + package_files + bones_files do when_writing("Creating GEM") { chdir(package_dir_path) do puts gem_spec.inspect Gem::Builder.new(gem_spec).build verbose(true) { mv gem_file, "../#{gem_file}" } end } end file package_dir_path => bones_files do mkdir_p package_dir rescue nil gem_spec.files = (gem_spec.files + bones_files.map {|fn| File.join('tasks', File.basename(fn))}).sort bones_files.each do |fn| base_fn = File.join('tasks', File.basename(fn)) f = File.join(package_dir_path, base_fn) fdir = File.dirname(f) mkdir_p(fdir) if !File.exist?(fdir) if File.directory?(fn) mkdir_p(f) else raise "file name conflict for '#{base_fn}' (conflicts with '#{fn}')" if test(?e, f) safe_ln(fn, f) end end end end def gem_file if @gem_spec.platform == Gem::Platform::RUBY "#{package_name}.gem" else "#{package_name}-#{@gem_spec.platform}.gem" end end end # class GemPackageTask end # module Bones namespace :gem do PROJ.gem._spec = Gem::Specification.new do |s| s.name = PROJ.name s.version = PROJ.version s.summary = PROJ.summary s.authors = Array(PROJ.authors) s.email = PROJ.email s.homepage = Array(PROJ.url).first s.rubyforge_project = PROJ.rubyforge.name s.description = PROJ.description PROJ.gem.dependencies.each do |dep| s.add_dependency(*dep) end PROJ.gem.development_dependencies.each do |dep| s.add_development_dependency(*dep) end s.files = PROJ.gem.files s.executables = PROJ.gem.executables.map {|fn| File.basename(fn)} s.extensions = PROJ.gem.files.grep %r/extconf\.rb$/ s.bindir = 'bin' dirs = Dir["{#{PROJ.libs.join(',')}}"] s.require_paths = dirs unless dirs.empty? incl = Regexp.new(PROJ.rdoc.include.join('|')) excl = PROJ.rdoc.exclude.dup.concat %w[\.rb$ ^(\.\/|\/)?ext] excl = Regexp.new(excl.join('|')) rdoc_files = PROJ.gem.files.find_all do |fn| case fn when excl; false when incl; true else false end end s.rdoc_options = PROJ.rdoc.opts + ['--main', PROJ.rdoc.main] s.extra_rdoc_files = rdoc_files s.has_rdoc = true if test ?f, PROJ.test.file s.test_file = PROJ.test.file else s.test_files = PROJ.test.files.to_a end # Do any extra stuff the user wants PROJ.gem.extras.each do |msg, val| case val when Proc val.call(s.send(msg)) else s.send "#{msg}=", val end end end # Gem::Specification.new Bones::GemPackageTask.new(PROJ.gem._spec) do |pkg| pkg.need_tar = PROJ.gem.need_tar pkg.need_zip = PROJ.gem.need_zip end desc 'Show information about the gem' task :debug => 'gem:prereqs' do puts PROJ.gem._spec.to_ruby end desc 'Write the gemspec ' task :spec => 'gem:prereqs' do File.open("#{PROJ.name}.gemspec", 'w') do |f| f.write PROJ.gem._spec.to_ruby end end desc 'Install the gem' task :install => [:clobber, 'gem:package'] do sh "#{SUDO} #{GEM} install --local pkg/#{PROJ.gem._spec.full_name}" # use this version of the command for rubygems > 1.0.0 #sh "#{SUDO} #{GEM} install --no-update-sources pkg/#{PROJ.gem._spec.full_name}" end desc 'Uninstall the gem' task :uninstall do installed_list = Gem.source_index.find_name(PROJ.name) if installed_list and installed_list.collect { |s| s.version.to_s}.include?(PROJ.version) then sh "#{SUDO} #{GEM} uninstall --version '#{PROJ.version}' --ignore-dependencies --executables #{PROJ.name}" end end desc 'Reinstall the gem' task :reinstall => [:uninstall, :install] desc 'Cleanup the gem' task :cleanup do sh "#{SUDO} #{GEM} cleanup #{PROJ.gem._spec.name}" end end # namespace :gem desc 'Alias to gem:package' task :gem => 'gem:package' task :clobber => 'gem:clobber_package' remove_desc_for_task 'gem:clobber_package' # EOF