lib/hoe.rb in hoe-1.7.0 vs lib/hoe.rb in hoe-1.8.0

- old
+ new

@@ -36,31 +36,35 @@ # # # add other tasks here # # === Tasks Provided: # -# announce:: Create news email file and post to rubyforge. -# audit:: Run ZenTest against the package. -# check_manifest:: Verify the manifest. -# clean:: Clean up all the extras. -# config_hoe:: Create a fresh ~/.hoerc file. -# debug_gem:: Show information about the gem. -# default:: Run the default tasks. -# docs:: Build the docs HTML Files -# email:: Generate email announcement file. -# gem:: Build the gem file hoe-1.5.0.gem -# generate_key:: Generate a key for signing your gems. -# install_gem:: Install the package as a gem. -# multi:: Run the test suite using multiruby. -# package:: Build all the packages -# post_blog:: Post announcement to blog. -# post_news:: Post announcement to rubyforge. -# publish_docs:: Publish RDoc to RubyForge. -# release:: Package and upload the release to rubyforge. -# ridocs:: Generate ri locally for testing. -# test:: Run the test suite. -# test_deps:: Show which test files fail when run alone. +# announce:: Create news email file and post to rubyforge. +# audit:: Run ZenTest against the package. +# check_manifest:: Verify the manifest. +# clean:: Clean up all the extras. +# config_hoe:: Create a fresh ~/.hoerc file. +# debug_gem:: Show information about the gem. +# default:: Run the default tasks. +# deps:email:: Print a contact list for gems dependent on this gem +# deps:fetch:: Fetch all the dependent gems of this gem into tarballs +# deps:list:: List all the dependent gems of this gem +# docs:: Build the docs HTML Files +# email:: Generate email announcement file. +# gem:: Build the gem file hoe-1.8.0.gem +# generate_key:: Generate a key for signing your gems. +# install_gem:: Install the package as a gem. +# multi:: Run the test suite using multiruby. +# package:: Build all the packages +# post_blog:: Post announcement to blog. +# post_news:: Post announcement to rubyforge. +# publish_docs:: Publish RDoc to RubyForge. +# release:: Package and upload the release to rubyforge. +# ridocs:: Generate ri locally for testing. +# tasks:: Generate a list of tasks for doco. +# test:: Run the test suite. +# test_deps:: Show which test files fail when run alone. # # === Extra Configuration Options: # # Run +config_hoe+ to generate a new ~/.hoerc file. The file is a # YAML formatted config file with the following settings: @@ -118,11 +122,12 @@ # This will set the +Gem::Specification+ platform to the one indicated in # +FORCE_PLATFORM+ (instead of default Gem::Platform::CURRENT) # class Hoe - VERSION = '1.7.0' + VERSION = '1.8.0' + GEMURL = URI.parse 'http://gems.rubyforge.org' # for namespace :deps below ruby_prefix = Config::CONFIG['prefix'] sitelibdir = Config::CONFIG['sitelibdir'] ## @@ -302,19 +307,33 @@ # Optional: An array of test file patterns [default: test/**/test_*.rb] attr_accessor :test_globs ## + # Optional: What test library to require [default: test/unit] + + attr_accessor :testlib + + ## # Optional: The url(s) of the project. (can be array). Auto-populates. attr_accessor :url ## # *MANDATORY*: The version. Don't hardcode! use a constant in the project. attr_accessor :version + ## + # Add extra dirs to both $: and RUBY_FLAGS (for test runs) + + def self.add_include_dirs(*dirs) + dirs = dirs.flatten + $:.unshift(*dirs) + Hoe::RUBY_FLAGS.sub!(/-I/, "-I#{dirs.join(":")}:") + end + def normalize_deps deps Array(deps).map { |o| String === o ? [o] : o } end def missing name @@ -326,11 +345,11 @@ self.name = name self.version = version # Defaults self.author = [] - self.clean_globs = %w(diff diff.txt email.txt ri + self.clean_globs = %w(diff diff.txt email.txt ri deps .source_index *.gem *~ **/*~ *.rbc **/*.rbc) self.description_sections = %w(description) self.blog_categories = [name] self.email = [] self.extra_deps = [] @@ -343,10 +362,11 @@ self.rsync_args = '-av --delete' self.rubyforge_name = name.downcase self.spec_extras = {} self.summary_sentences = 1 self.test_globs = ['test/**/test_*.rb'] + self.testlib = 'test/unit' self.post_install_message = nil yield self if block_given? # Intuit values: @@ -634,10 +654,137 @@ Rake::Task['publish_docs'].invoke if config["publish_on_announce"] end end ############################################################ + # Dependencies: + + namespace :deps do + require 'zlib' # HACK for rubygems 1.3.0 + require 'rubygems/remote_fetcher' + + @@index = nil + + def self.get_source_index + return @@index if @@index + + dump = unless File.exist? '.source_index' then + url = GEMURL + "Marshal.#{Gem.marshal_version}.Z" + dump = Gem::RemoteFetcher.fetcher.fetch_path url + dump = Gem.inflate dump + open '.source_index', 'wb' do |io| io.write dump end + dump + else + open '.source_index', 'rb' do |io| io.read end + end + + @@index = Marshal.load dump + end + + def self.get_latest_gems + @@cache ||= get_source_index.latest_specs + end + + def self.get_gems_by_name + @@by_name ||= Hash[*get_latest_gems.map { |gem| + [gem.name, gem, gem.full_name, gem] + }.flatten] + end + + def self.dependent_upon name + get_latest_gems.find_all { |gem| + gem.dependencies.any? { |dep| dep.name == name } + } + end + + + desc "List all the dependent gems of this gem" + task :list do + gems = self.get_gems_by_name + gem = gems[self.name] + + abort "Couldn't find gem: #{self.name}" unless gem + + deps = self.dependent_upon self.name + max = deps.map { |s| s.full_name.size }.max + + puts " dependents:" + unless deps.empty? then + deps.sort_by { |spec| spec.full_name }.each do |spec| + vers = spec.dependencies.find {|s| s.name == name }.requirement_list + puts " %-*s - %s" % [max, spec.full_name, vers.join(", ")] + end + else + puts " none" + end + end + + desc "Print a contact list for gems dependent on this gem" + task :email do + gems = self.get_gems_by_name + gem = gems[self.name] + + abort "Couldn't find gem: #{self.name}" unless gem + + deps = self.dependent_upon self.name + + email = deps.map { |s| s.email }.flatten.sort.uniq + email = email.map { |s| s.split(/,\s*/) }.flatten.sort.uniq + + email.map! { |s| # don't you people realize how easy this is? + s.gsub(/ at | _at_ |\s*(atmark|@nospam@|-at?-|@at?@|<at?>|\[at?\]|\(at?\))\s*/i, '@').gsub(/\s*(dot|\[d(ot)?\]|\.dot\.)\s*/i, '.').gsub(/\s+com$/, '.com') + } + + bad, good = email.partition { |e| e !~ /^[\w.+-]+\@[\w.+-]+$/ } + + warn "Rejecting #{bad.size} email. I couldn't unmunge them." unless + bad.empty? + + puts good.join(", ") + end + + desc "Fetch all the dependent gems of this gem into tarballs" + task :fetch do + gems = self.get_gems_by_name + gem = gems[self.name] + deps = self.dependent_upon self.name + + mkdir "deps" unless File.directory? "deps" + Dir.chdir "deps" do + begin + deps.sort_by { |spec| spec.full_name }.each do |spec| + full_name = spec.full_name + tgz_name = "#{full_name}.tgz" + gem_name = "#{full_name}.gem" + + next if File.exist? tgz_name + FileUtils.rm_rf [full_name, gem_name] + + begin + warn "downloading #{full_name}" + Gem::RemoteFetcher.fetcher.download(spec, GEMURL, Dir.pwd) + FileUtils.mv "cache/#{gem_name}", '.' + rescue Gem::RemoteFetcher::FetchError + warn " failed" + next + end + + warn "converting #{gem_name} to tarball" + + system "gem unpack #{gem_name} 2> /dev/null" + system "gem spec -l #{gem_name} > #{full_name}/gemspec.rb" + system "tar zmcf #{tgz_name} #{full_name}" + FileUtils.rm_rf [full_name, gem_name, "cache"] + end + ensure + FileUtils.rm_rf "cache" + end + end + end + end + + ############################################################ # Misc/Maintenance: desc 'Run ZenTest against the package.' task :audit do libs = %w(lib test ext).join(File::PATH_SEPARATOR) @@ -823,11 +970,12 @@ def run_tests(multi=false) # :nodoc: msg = multi ? :sh : :ruby cmd = if test ?f, 'test/test_all.rb' then "#{RUBY_FLAGS} test/test_all.rb #{FILTER}" else - tests = ['test/unit'] + test_globs.map { |g| Dir.glob(g) }.flatten + tests = ["rubygems", self.testlib] + + test_globs.map { |g| Dir.glob(g) }.flatten tests.map! {|f| %Q(require "#{f}")} "#{RUBY_FLAGS} -e '#{tests.join("; ")}' #{FILTER}" end excludes = multiruby_skip.join(":") @@ -860,7 +1008,13 @@ end end if $0 == __FILE__ then out = `rake -T | egrep -v "redocs|repackage|clobber|trunk"` - puts out.gsub(/\#/, '-').gsub(/^rake /, '# * ') + if ARGV.empty? then + # # default:: Run the default tasks. + puts out.gsub(/(\s*)\#/, '::\1').gsub(/^rake /, '# ') + else + # * default - Run the default tasks. + puts out.gsub(/\#/, '-').gsub(/^rake /, '* ') + end end