gem.rake

tasks/gem.rake (view online)
Last Update: Mon Apr 27 20:51:54 +0000 2009

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
        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