lib/hoe.rb in hoe-1.2.2 vs lib/hoe.rb in hoe-1.3.0

- old
+ new

@@ -6,10 +6,11 @@ require 'rake/gempackagetask' require 'rake/rdoctask' require 'rake/testtask' require 'rbconfig' require 'rubyforge' +require 'yaml' ## # hoe - a tool to help rake # # Hoe is a simple rake/rubygems helper for project Rakefiles. It @@ -62,16 +63,43 @@ # YAML formatted config file with the following settings: # # exclude:: A regular expression of files to exclude from # +check_manifest+. # publish_on_announce:: Run +publish_docs+ when you run +release+. +# signing_key_file:: Signs your gems with this private key. +# signing_cert_file:: Signs your gem with this certificate. # blogs:: An array of hashes of blog settings. # # Run +config_hoe+ and see ~/.hoerc for examples. # +# === Signing Gems: +# +# Run the 'generate_key' task. This will: +# +# 1. Configure your ~/.hoerc. +# 2. Generate a signing key and certificate. +# 3. Install the private key and public certificate files into ~/.gem. +# 4. Upload the certificate to RubyForge. +# +# Hoe will now generate signed gems when the package task is run. If you have +# multiple machines you build gems on, be sure to install your key and +# certificate on each machine. +# +# Keep your private key secret! Keep your private key safe! +# +# To make sure your gems are signed run: +# +# rake package; tar tf pkg/yourproject-1.2.3.gem +# +# If your gem is signed you will see: +# +# data.tar.gz +# data.tar.gz.sig +# metadata.gz +# metadata.gz.sig class Hoe - VERSION = '1.2.2' + VERSION = '1.3.0' ruby_prefix = Config::CONFIG['prefix'] sitelibdir = Config::CONFIG['sitelibdir'] ## @@ -241,11 +269,11 @@ self.description = "The author was too lazy to write a description" self.email = "ryand-ruby@zenspider.com" self.extra_deps = [] self.need_tar = true self.need_zip = false - self.rdoc_pattern = /^(lib|bin)|txt$/ + self.rdoc_pattern = /^(lib|bin|ext)|txt$/ self.remote_rdoc_dir = name self.rsync_args = '-av --delete' self.rubyforge_name = name.downcase self.spec_extras = {} self.summary = "The author was too lazy to write a summary" @@ -257,13 +285,12 @@ hoe_deps = { 'rake' => ">= #{RAKEVERSION}", 'rubyforge' => ">= #{::RubyForge::VERSION}", } - self.extra_deps = Array(extra_deps) # just in case user used = instead of << - self.extra_deps = [extra_deps] unless - extra_deps.empty? or Array === extra_deps.first + self.extra_deps = Array(extra_deps).map { |o| String === o ? [o] : o } + if name == 'hoe' then hoe_deps.each do |pkg, version| extra_deps << [pkg, version] end else @@ -272,10 +299,17 @@ define_tasks end def define_tasks # :nodoc: + def with_config # :nodoc: + rc = File.expand_path("~/.hoerc") + exists = File.exist? rc + config = exists ? YAML.load_file(rc) : {} + yield(config, rc) + end + desc 'Run the default tasks' task :default => :test desc 'Run the test suite. Use FILTER to add to the command line.' task :test do @@ -299,10 +333,22 @@ end ############################################################ # Packaging and Installing + signing_key = nil + cert_chain = [] + + with_config do |config, path| + break unless config['signing_key_file'] and config['signing_cert_file'] + key_file = File.expand_path config['signing_key_file'].to_s + signing_key = key_file if File.exist? key_file + + cert_file = File.expand_path config['signing_cert_file'].to_s + cert_chain << cert_file if File.exist? cert_file + end + self.spec = Gem::Specification.new do |s| s.name = name s.version = version s.summary = summary case author @@ -336,10 +382,15 @@ s.test_file = "test/test_all.rb" else s.test_files = Dir[*test_globs] end + if signing_key and cert_chain then + s.signing_key = signing_key + s.cert_chain = cert_chain + end + # Do any extra stuff the user wants spec_extras.each do |msg, val| case val when Proc val.call(s.send(msg)) @@ -422,11 +473,11 @@ ############################################################ # Doco Rake::RDocTask.new(:docs) do |rd| rd.main = "README.txt" - rd.options << '-d' if RUBY_PLATFORM !~ /win32/ and `which dot` =~ /\/dot/ + rd.options << '-d' if RUBY_PLATFORM !~ /win32/ and `which dot` =~ /\/dot/ and not ENV['NODOT'] rd.rdoc_dir = 'doc' files = spec.files.grep(rdoc_pattern) files -= ['Manifest.txt'] rd.rdoc_files.push(*files) @@ -452,36 +503,18 @@ sh %{rsync #{rsync_args} #{local_dir}/ #{host}:#{remote_dir}} end # no doco for this one task :publish_on_announce do - with_config do |rc, path| - if rc["publish_on_announce"] then - Rake::Task['publish_docs'].invoke - end + with_config do |config, _| + Rake::Task['publish_docs'].invoke if config["publish_on_announce"] end end ############################################################ # Misc/Maintenance: - def with_config(create=false) # :nodoc: - require 'yaml' - rc = File.expand_path("~/.hoerc") - - unless create then - if test ?f, rc then - config = YAML.load_file(rc) - yield(config, rc) - end - else - unless test ?f, rc then - yield(rc) - end - end - end - desc 'Run ZenTest against the package' task :audit do libs = %w(lib test ext).join(File::PATH_SEPARATOR) sh "zentest -I=#{libs} #{spec.files.grep(/^(lib|test)/).join(' ')}" end @@ -494,32 +527,32 @@ end end desc 'Create a fresh ~/.hoerc file' task :config_hoe do - with_config(:create) do |rc, path| - blog = { + with_config do |config, path| + default_config = { "exclude" => /tmp$|CVS|\.svn/, "publish_on_announce" => false, + "signing_key_file" => "~/.gem/gem-private_key.pem", + "signing_cert_file" => "~/.gem/gem-public_cert.pem", "blogs" => [ { "user" => "user", "url" => "url", "extra_headers" => { "mt_convert_breaks" => "markdown" }, "blog_id" => "blog_id", "password"=>"password", } ], } - File.open(rc, "w") do |f| - YAML.dump(blog, f) + File.open(path, "w") do |f| + YAML.dump(default_config.merge(config), f) end - end - with_config do |rc, path| editor = ENV['EDITOR'] || 'vi' - system "#{editor} #{path}" + system "#{editor} #{path}" if ENV['SHOW_EDITOR'] != 'no' end end desc 'Generate email announcement file.' task :email do @@ -543,12 +576,13 @@ desc 'Post announcement to blog.' task :post_blog do require 'xmlrpc/client' with_config do |config, path| - subject, title, body, urls = announcement + break unless config['blogs'] + subject, title, body, urls = announcement body += "\n\n#{urls}" config['blogs'].each do |site| server = XMLRPC::Client.new2(site['url']) content = site['extra_headers'].merge(:title => title, @@ -591,9 +625,59 @@ end files = files.sort.join "\n" File.open f, 'w' do |fp| fp.puts files end system "#{DIFF} -du Manifest.txt #{f}" rm f + end + end + + desc 'Generate a key for signing your gems.' + task :generate_key do + email = spec.email + abort "No email in your gemspec" if email.nil? or email.empty? + + key_file = with_config { |config, _| config['signing_key_file'] } + cert_file = with_config { |config, _| config['signing_cert_file'] } + + if key_file.nil? or cert_file.nil? then + ENV['SHOW_EDITOR'] ||= 'no' + Rake::Task['config_hoe'].invoke + + key_file = with_config { |config, _| config['signing_key_file'] } + cert_file = with_config { |config, _| config['signing_cert_file'] } + end + + key_file = File.expand_path key_file + cert_file = File.expand_path cert_file + + unless File.exist? key_file or File.exist? cert_file then + sh "gem cert --build #{email}" + mv "gem-private_key.pem", key_file, :verbose => true + mv "gem-public_cert.pem", cert_file, :verbose => true + + puts "Installed key and certificate." + + rf = RubyForge.new + rf.login + + cert_package = "#{rubyforge_name}-certificates" + + begin + rf.lookup 'package', cert_package + rescue + rf.create_package rubyforge_name, cert_package + end + + begin + rf.lookup('release', cert_package)['certificates'] + rf.add_file rubyforge_name, cert_package, 'certificates', cert_file + rescue + rf.add_release rubyforge_name, cert_package, 'certificates', cert_file + end + + puts "Uploaded certificate to release \"certificates\" in package #{cert_package}" + else + puts "Keys already exist." end end end # end define