module Reap class Manager # Remove gem package products. def gem_clobber(options=nil) store = "pkg" packages = glob(File.join(store, '*.gem')) packages.each do |path| File.directory?(path) ? rm_r(path) : rm(path) end end # Create a Gem package. # # TODO: Should this use staging too, like zip/tgz? def gem_package(options=nil) begin require 'rubygems/specification' Gem::manage_gems rescue LoadError #raise LoadError, "RubyGems is not installed?" end status "Creating .gem package" options = configure_options(options, 'package-gem', 'package') prepare(options) package = metadata.clone package.update(options) abort "No name" unless package.name abort "No version" unless package.version store = 'pkg' #package.package_directory fname = package.stage_name files = package.filelist stage = File.join(store, fname) pfile = stage + ".gem" unless out_of_date?(pfile, *files) or force? report_package_already_built(pfile) return end rm_r(stage) if File.exist?(stage) # remove old stage stage(stage, files) # make new stage package_manifest(stage) # generate manifest if dryrun? status "gem build #{stage}" else file = nil cd(stage) do #status "vi #{metadata.name}.gemspec" builder = ::Gem::Builder.new(gemspec(package)) status "gem build #{stage}" unless dryrun? file = builder.build file = File.expand_path(file) end end # transfer gem package to package store mkdir_p(store) destination = File.join(store, File.basename(file)) mv(file, store) unless File.expand_path(file) == File.expand_path(destination) end return destination end # Install gem package, creating the package if not already created. # # TODO: Endure that we even need a gem package using #out_of_date? def gem_install(options=nil) file = gem_package(options) sh "gem install #{file}" end # Uninstall gem package. # # TODO: Sepcify version? def gem_uninstall i = metadata.package_name.rindex('-') name, version = metadata.package_name[0...i], metadata.package_name[i+1..-1] sh "gem uninstall #{name} -v #{version}" end private # Create Gem::Specification. def gemspec(package) distribute = package.filelist #distribute = Dir.multiglob_with_default( '**/*', distribute ) # I don't quite get how Rubygems deals with authors. It turns a singel value into an array. Why? #author = [package.author, package.contact].flatten.compact.first if md = /(\w+).rubyforge.org/.match(package.homepage) rubyforge_project = md[1] else rubyforge_project = package.project # b/c it has to be something according to Eric Hodel. end ::Gem::Specification.new do |spec| spec.name = package.package spec.version = package.version spec.summary = package.brief spec.description = package.description spec.author = package.contact spec.email = package.email spec.rubyforge_project = rubyforge_project spec.homepage = package.homepage # Platform: ruby, mswin32, i586-linux, powerpc-darwin, current spec.platform = 'ruby' # TODO current support! spec.require_paths = [package.gem_path].flatten.reverse #if package.platform != 'ruby' # spec.require_paths.concat(spec.require_paths.collect{ |d| File.join(d, platform) }) #end spec.bindir = "bin" spec.executables = package.executables spec.requirements = package.requirements spec.has_rdoc = !(FalseClass===package.document) if package.dependencies package.dependencies.each do |d,v| spec.add_dependency(*[d,v].compact) end end spec.extensions = package.compile spec.files = distribute spec.test_files = distribute.select{ |f| f =~ /^test\// } # TODO make test_files configurable end end # Report that a package has been built. # FIXME def report_package_built(type, file) r = '' r << "\n Successfully built #{type}" r << "\n Name: #{package.name}" r << "\n Version: #{package.version}" r << "\n File: #{File.basename(file)}" say r end end end # # Build packages. # # TODO Move this to Manager ? # # def generate_packages # package_files = formats.collect do |format| # #format = clean_type(format) # say '' if format == 'gem' # FIXME This is here b/c Gems outputs on it's own. # file = create_package(format) # unless dryrun? or (format == 'gem') # report_package_built(format, file) if file # end # file # end # report_packaging_complete(package_files.size) # end # # # Create package. # # def create_package(type) # package.format = type # # builder_class = FormatBuilder.registry[type] # builder = builder_class.new(package, stage_directory, options) # file = builder.build # # transfer(file) unless dryrun? # # return file # end # # # Report that packaging is complete. # # def report_packaging_complete(size) # say "\nSuccessfully built #{size} packages at #{store}/." # end