Class: Hoe
- Inherits:
-
Object
- Object
- Hoe
- Defined in:
- lib/hoe-patched.rb
Overview
hoe - a tool to help rake
Hoe is a simple rake/rubygems helper for project Rakefiles. It generates all the usual tasks for projects including rdoc generation, testing, packaging, and deployment.
Using Hoe
Basics
Use this as a minimal starting point:
require 'hoe'
Hoe.new("project_name", '1.0.0') do |p|
p.rubyforge_name = "rf_project"
# add other details here
end
# 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.
- 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
-
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:
- exclude
-
A regular expression of files to exclude from
check_manifest
. - publish_on_announce
-
Run
publish_docs
when you runrelease
. - 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:
-
Configure your ~/.hoerc.
-
Generate a signing key and certificate.
-
Install the private key and public certificate files into ~/.gem.
-
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
.gz
.gz.sig
Platform awareness
Hoe allows bundling of pre-compiled extensions in the package
task.
To create a package for your current platform:
rake package INLINE=1
This will force Hoe analize your Inline
already compiled extensions and include them in your gem.
If somehow you need to force a specific platform:
rake package INLINE=1 FORCE_PLATFORM=mswin32
This will set the Gem::Specification
platform to the one indicated in FORCE_PLATFORM
(instead of default Gem::Platform::CURRENT)
Constant Summary collapse
- VERSION =
'1.8.0'
- GEMURL =
for namespace :deps below
URI.parse 'http://gems.rubyforge.org'
- PREFIX =
Used to specify a custom install location (for rake install).
ENV['PREFIX'] || ruby_prefix
- RUBY_DEBUG =
Used to add extra flags to RUBY_FLAGS.
ENV['RUBY_DEBUG']
- RUBY_FLAGS =
Used to specify flags to ruby [has smart default].
ENV['RUBY_FLAGS'] || default_ruby_flags
- FILTER =
Used to add flags to test_unit (e.g., -n test_borked).
ENV['FILTER']
- RUBYLIB =
:stopdoc:
if PREFIX == ruby_prefix then sitelibdir else File.join(PREFIX, sitelibdir[ruby_prefix.size..-1]) end
- DLEXT =
Config::CONFIG['DLEXT']
- WINDOZE =
/djgpp|(cyg|ms|bcc)win|mingw/ =~ RUBY_PLATFORM
- DIFF =
if WINDOZE 'diff.exe' else if system("gdiff", __FILE__, __FILE__) 'gdiff' # solaris and kin suck else 'diff' end end
Instance Attribute Summary collapse
-
#author ⇒ Object
Recommended: The author(s) of the package.
-
#bin_files ⇒ Object
Populated automatically from the manifest.
-
#blog_categories ⇒ Object
Optional: An array of the project’s blog categories.
-
#changes ⇒ Object
Optional: A description of the release’s latest changes.
-
#clean_globs ⇒ Object
Optional: An array of file patterns to delete on clean.
-
#description ⇒ Object
Optional: A description of the project.
-
#description_sections ⇒ Object
Optional: What sections from the readme to use for auto-description.
-
#email ⇒ Object
Recommended: The author’s email address(es).
-
#extra_deps ⇒ Object
Optional: An array of rubygem dependencies.
-
#extra_dev_deps ⇒ Object
Optional: An array of rubygem developer dependencies.
-
#lib_files ⇒ Object
Populated automatically from the manifest.
-
#multiruby_skip ⇒ Object
Optional: Array of incompatible versions for multiruby filtering.
-
#name ⇒ Object
MANDATORY: The name of the release.
-
#need_tar ⇒ Object
Optional: Should package create a tarball? [default: true].
-
#need_zip ⇒ Object
Optional: Should package create a zipfile? [default: false].
-
#post_install_message ⇒ Object
Optional: A post-install message to be displayed when gem is installed.
-
#rdoc_pattern ⇒ Object
Optional: A regexp to match documentation files against the manifest.
-
#remote_rdoc_dir ⇒ Object
Optional: Name of RDoc destination directory on Rubyforge.
-
#rsync_args ⇒ Object
Optional: Flags for RDoc rsync.
-
#rubyforge_name ⇒ Object
Optional: The name of the rubyforge project.
-
#spec ⇒ Object
The Gem::Specification.
-
#spec_extras ⇒ Object
Optional: A hash of extra values to set in the gemspec.
-
#summary ⇒ Object
Optional: A short summary of the project.
-
#summary_sentences ⇒ Object
Optional: Number of sentences from description for summary.
-
#test_files ⇒ Object
Populated automatically from the manifest.
-
#test_globs ⇒ Object
Optional: An array of test file patterns [default: test/*/test_.rb].
-
#testlib ⇒ Object
Optional: What test library to require [default: test/unit].
-
#url ⇒ Object
Optional: The url(s) of the project.
-
#version ⇒ Object
MANDATORY: The version.
Class Method Summary collapse
-
.add_include_dirs(*dirs) ⇒ Object
Add extra dirs to both $: and RUBY_FLAGS (for test runs).
Instance Method Summary collapse
-
#announcement ⇒ Object
end define.
-
#define_tasks ⇒ Object
:nodoc:.
- #developer(name, email) ⇒ Object
-
#initialize(name, version) {|_self| ... } ⇒ Hoe
constructor
:nodoc:.
- #missing(name) ⇒ Object
- #normalize_deps(deps) ⇒ Object
-
#paragraphs_of(path, *paragraphs) ⇒ Object
Reads a file at
path
and spits out an array of theparagraphs
specified. - #readme_name ⇒ Object
-
#run_tests(multi = false) ⇒ Object
:nodoc:.
-
#with_config {|config, rc| ... } ⇒ Object
:nodoc:.
Constructor Details
#initialize(name, version) {|_self| ... } ⇒ Hoe
:nodoc:
353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 |
# File 'lib/hoe-patched.rb', line 353 def initialize(name, version) # :nodoc: self.name = name self.version = version # Defaults self. = [] 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 = [] self.extra_dev_deps = [] self.multiruby_skip = [] self.need_tar = true self.need_zip = false self.rdoc_pattern = /^(lib|bin|ext)|txt|rdoc$/ self.remote_rdoc_dir = name 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. = nil yield self if block_given? # Intuit values: readme = File.read(readme_name).split(/^(=+ .*)$/)[1..-1] rescue '' unless readme.empty? then sections = readme.map { |s| s =~ /^=/ ? s.strip.downcase.chomp(':').split.last : s.strip } sections = Hash[*sections] desc = sections.values_at(*description_sections).join("\n\n") summ = desc.split(/\.\s+/).first(summary_sentences).join(". ") self.description ||= desc self.summary ||= summ self.url ||= readme[1].gsub(/^\* /, '').split(/\n/).grep(/\S+/) else missing readme_name end self.changes ||= begin h = File.read("History.txt") h.split(/^(===.*)/)[1..2].join.strip rescue missing 'History.txt' '' end %w(email author).each do |field| value = self.send(field) if value.nil? or value.empty? then if Time.now < Time.local(2008, 4, 1) then warn "Hoe #{field} value not set - Fix by 2008-04-01!" self.send "#{field}=", "doofus" else abort "Hoe #{field} value not set. aborting" end end end hoe_deps = { 'rake' => ">= #{RAKEVERSION}", 'rubyforge' => ">= #{::RubyForge::VERSION}", } self.extra_deps = normalize_deps extra_deps self.extra_dev_deps = normalize_deps extra_dev_deps if name == 'hoe' then hoe_deps.each do |pkg, vers| extra_deps << [pkg, vers] end else extra_dev_deps << ['hoe', ">= #{VERSION}"] unless hoe_deps.has_key? name end define_tasks end |
Instance Attribute Details
#author ⇒ Object
Recommended: The author(s) of the package. (can be array) Really. Set this or we’ll tease you.
189 190 191 |
# File 'lib/hoe-patched.rb', line 189 def @author end |
#bin_files ⇒ Object
Populated automatically from the manifest. List of executables.
194 195 196 |
# File 'lib/hoe-patched.rb', line 194 def bin_files @bin_files end |
#blog_categories ⇒ Object
Optional: An array of the project’s blog categories. Defaults to project name.
199 200 201 |
# File 'lib/hoe-patched.rb', line 199 def blog_categories @blog_categories end |
#changes ⇒ Object
Optional: A description of the release’s latest changes. Auto-populates.
204 205 206 |
# File 'lib/hoe-patched.rb', line 204 def changes @changes end |
#clean_globs ⇒ Object
Optional: An array of file patterns to delete on clean.
209 210 211 |
# File 'lib/hoe-patched.rb', line 209 def clean_globs @clean_globs end |
#description ⇒ Object
Optional: A description of the project. Auto-populates.
214 215 216 |
# File 'lib/hoe-patched.rb', line 214 def description @description end |
#description_sections ⇒ Object
Optional: What sections from the readme to use for auto-description. Defaults to %w(description).
219 220 221 |
# File 'lib/hoe-patched.rb', line 219 def description_sections @description_sections end |
#email ⇒ Object
Recommended: The author’s email address(es). (can be array)
224 225 226 |
# File 'lib/hoe-patched.rb', line 224 def email @email end |
#extra_deps ⇒ Object
Optional: An array of rubygem dependencies.
229 230 231 |
# File 'lib/hoe-patched.rb', line 229 def extra_deps @extra_deps end |
#extra_dev_deps ⇒ Object
Optional: An array of rubygem developer dependencies.
234 235 236 |
# File 'lib/hoe-patched.rb', line 234 def extra_dev_deps @extra_dev_deps end |
#lib_files ⇒ Object
Populated automatically from the manifest. List of library files.
239 240 241 |
# File 'lib/hoe-patched.rb', line 239 def lib_files @lib_files end |
#multiruby_skip ⇒ Object
Optional: Array of incompatible versions for multiruby filtering. Used as a regex.
244 245 246 |
# File 'lib/hoe-patched.rb', line 244 def multiruby_skip @multiruby_skip end |
#name ⇒ Object
MANDATORY: The name of the release.
249 250 251 |
# File 'lib/hoe-patched.rb', line 249 def name @name end |
#need_tar ⇒ Object
Optional: Should package create a tarball? [default: true]
254 255 256 |
# File 'lib/hoe-patched.rb', line 254 def need_tar @need_tar end |
#need_zip ⇒ Object
Optional: Should package create a zipfile? [default: false]
259 260 261 |
# File 'lib/hoe-patched.rb', line 259 def need_zip @need_zip end |
#post_install_message ⇒ Object
Optional: A post-install message to be displayed when gem is installed.
264 265 266 |
# File 'lib/hoe-patched.rb', line 264 def @post_install_message end |
#rdoc_pattern ⇒ Object
Optional: A regexp to match documentation files against the manifest.
269 270 271 |
# File 'lib/hoe-patched.rb', line 269 def rdoc_pattern @rdoc_pattern end |
#remote_rdoc_dir ⇒ Object
Optional: Name of RDoc destination directory on Rubyforge. [default: name
]
274 275 276 |
# File 'lib/hoe-patched.rb', line 274 def remote_rdoc_dir @remote_rdoc_dir end |
#rsync_args ⇒ Object
Optional: Flags for RDoc rsync. [default: “-av –delete”]
279 280 281 |
# File 'lib/hoe-patched.rb', line 279 def rsync_args @rsync_args end |
#rubyforge_name ⇒ Object
Optional: The name of the rubyforge project. [default: name.downcase]
284 285 286 |
# File 'lib/hoe-patched.rb', line 284 def rubyforge_name @rubyforge_name end |
#spec ⇒ Object
The Gem::Specification.
289 290 291 |
# File 'lib/hoe-patched.rb', line 289 def spec @spec end |
#spec_extras ⇒ Object
Optional: A hash of extra values to set in the gemspec. Value may be a proc.
294 295 296 |
# File 'lib/hoe-patched.rb', line 294 def spec_extras @spec_extras end |
#summary ⇒ Object
Optional: A short summary of the project. Auto-populates.
299 300 301 |
# File 'lib/hoe-patched.rb', line 299 def summary @summary end |
#summary_sentences ⇒ Object
Optional: Number of sentences from description for summary. Defaults to 1.
304 305 306 |
# File 'lib/hoe-patched.rb', line 304 def summary_sentences @summary_sentences end |
#test_files ⇒ Object
Populated automatically from the manifest. List of tests.
309 310 311 |
# File 'lib/hoe-patched.rb', line 309 def test_files @test_files end |
#test_globs ⇒ Object
Optional: An array of test file patterns [default: test/*/test_.rb]
314 315 316 |
# File 'lib/hoe-patched.rb', line 314 def test_globs @test_globs end |
#testlib ⇒ Object
Optional: What test library to require [default: test/unit]
319 320 321 |
# File 'lib/hoe-patched.rb', line 319 def testlib @testlib end |
#url ⇒ Object
Optional: The url(s) of the project. (can be array). Auto-populates.
324 325 326 |
# File 'lib/hoe-patched.rb', line 324 def url @url end |
#version ⇒ Object
MANDATORY: The version. Don’t hardcode! use a constant in the project.
329 330 331 |
# File 'lib/hoe-patched.rb', line 329 def version @version end |
Class Method Details
.add_include_dirs(*dirs) ⇒ Object
Add extra dirs to both $: and RUBY_FLAGS (for test runs)
334 335 336 337 338 |
# File 'lib/hoe-patched.rb', line 334 def self.add_include_dirs(*dirs) dirs = dirs.flatten $:.unshift(*dirs) Hoe::RUBY_FLAGS.sub!(/-I/, "-I#{dirs.join(":")}:") end |
Instance Method Details
#announcement ⇒ Object
end define
969 970 971 972 973 974 975 976 977 |
# File 'lib/hoe-patched.rb', line 969 def announcement # :nodoc: changes = self.changes.rdoc_to_markdown subject = "#{name} #{version} Released" title = "#{name} version #{version} has been released!" body = "#{description}\n\nChanges:\n\n#{changes}".rdoc_to_markdown urls = Array(url).map { |s| "* <#{s.strip.rdoc_to_markdown}>" }.join("\n") return subject, title, body, urls end |
#define_tasks ⇒ Object
:nodoc:
450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 |
# File 'lib/hoe-patched.rb', line 450 def define_tasks # :nodoc: desc 'Run the default tasks.' task :default => :test desc 'Run the test suite. Use FILTER to add to the command line.' task :test do run_tests end desc 'Show which test files fail when run alone.' task :test_deps do tests = Dir["test/**/test_*.rb"] + Dir["test/**/*_test.rb"] tests.each do |test| if not system "ruby -Ibin:lib:test #{test} &> /dev/null" then puts "Dependency Issues: #{test}" end end end desc 'Run the test suite using multiruby.' task :multi do run_tests :multi 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. config['signing_key_file'].to_s signing_key = key_file if File.exist? key_file cert_file = File. 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 when Array s. = else s. = end s.email = email s.homepage = Array(url).first s.rubyforge_project = rubyforge_name s.description = description extra_deps.each do |dep| s.add_dependency(*dep) end extra_dev_deps.each do |dep| s.add_development_dependency(*dep) end s.files = File.read("Manifest.txt").delete("\r").split(/\n/) s.executables = s.files.grep(/^bin/) { |f| File.basename(f) } s.bindir = "bin" dirs = Dir['{lib,ext}'] s.require_paths = dirs unless dirs.empty? s. = ['--main', readme_name] s.extra_rdoc_files = s.files.grep(/(txt|rdoc)$/) s.has_rdoc = true s. = if test ?f, "test/test_all.rb" then 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 ############################################################ # Allow automatic inclusion of compiled extensions if ENV['INLINE'] then s.platform = ENV['FORCE_PLATFORM'] || Gem::Platform::CURRENT # name of the extension is CamelCase alternate_name = if name =~ /[A-Z]/ then name.gsub(/([A-Z])/, '_\1').downcase.sub(/^_/, '') elsif name =~ /_/ then name.capitalize.gsub(/_([a-z])/) { $1.upcase } end # Try collecting Inline extensions for +name+ if defined?(Inline) then directory 'lib/inline' extensions = Dir.chdir(Inline::directory) { Dir["Inline_{#{name},#{alternate_name}}_*.#{DLEXT}"] } extensions.each do |ext| # add the inlined extension to the spec files s.files += ["lib/inline/#{ext}"] # include the file in the tasks file "lib/inline/#{ext}" => ["lib/inline"] do cp File.join(Inline::directory, ext), "lib/inline" end end end end # Do any extra stuff the user wants spec_extras.each do |msg, val| case val when Proc val.call(s.send(msg)) else s.send "#{msg}=", val end end end desc 'Show information about the gem.' task :debug_gem do puts spec.to_ruby end self.lib_files = spec.files.grep(/^(lib|ext)/) self.bin_files = spec.files.grep(/^bin/) self.test_files = spec.files.grep(/^test/) Rake::GemPackageTask.new spec do |pkg| pkg.need_tar = @need_tar pkg.need_zip = @need_zip end desc 'Install the package as a gem.' task :install_gem => [:clean, :package] do gem = Dir['pkg/*.gem'].first sh "#{'sudo ' unless WINDOZE}gem install --local #{gem}" end desc 'Package and upload the release to rubyforge.' task :release => [:clean, :package] do |t| v = ENV["VERSION"] or abort "Must supply VERSION=x.y.z" abort "Versions don't match #{v} vs #{version}" if v != version pkg = "pkg/#{name}-#{version}" if $DEBUG then puts "release_id = rf.add_release #{rubyforge_name.inspect}, #{name.inspect}, #{version.inspect}, \"#{pkg}.tgz\"" puts "rf.add_file #{rubyforge_name.inspect}, #{name.inspect}, release_id, \"#{pkg}.gem\"" end rf = RubyForge.new.configure puts "Logging in" rf.login c = rf.userconfig c["release_notes"] = description if description c["release_changes"] = changes if changes c["preformatted"] = true files = [(@need_tar ? "#{pkg}.tgz" : nil), (@need_zip ? "#{pkg}.zip" : nil), "#{pkg}.gem"].compact puts "Releasing #{name} v. #{version}" rf.add_release rubyforge_name, name, version, *files end ############################################################ # Doco Rake::RDocTask.new(:docs) do |rd| rd.main = readme_name rd. << '-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) title = "#{name}-#{version} Documentation" title = "#{rubyforge_name}'s " + title if rubyforge_name != name rd. << "-t #{title}" end desc 'Generate ri locally for testing.' task :ridocs => :clean do sh %q{ rdoc --ri -o ri . } end desc 'Publish RDoc to RubyForge.' task :publish_docs => [:clean, :docs] do config = YAML.load(File.read(File.("~/.rubyforge/user-config.yml"))) host = "#{config["username"]}@rubyforge.org" remote_dir = "/var/www/gforge-projects/#{rubyforge_name}/#{remote_rdoc_dir}" local_dir = 'doc' sh %{rsync #{rsync_args} #{local_dir}/ #{host}:#{remote_dir}} end # no doco for this one task :publish_on_announce do with_config do |config, _| 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) sh "zentest -I=#{libs} #{spec.files.grep(/^(lib|test)/).join(' ')}" end desc 'Clean up all the extras.' task :clean => [ :clobber_docs, :clobber_package ] do clean_globs.each do |pattern| files = Dir[pattern] rm_rf files, :verbose => true unless files.empty? end end desc 'Create a fresh ~/.hoerc file.' task :config_hoe do 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(path, "w") do |f| YAML.dump(default_config.merge(config), f) end editor = ENV['EDITOR'] || 'vi' system "#{editor} #{path}" if ENV['SHOW_EDITOR'] != 'no' end end desc 'Generate email announcement file.' task :email do require 'rubyforge' subject, title, body, urls = announcement File.open("email.txt", "w") do |mail| mail.puts "Subject: [ANN] #{subject}" mail.puts mail.puts title mail.puts mail.puts urls mail.puts mail.puts body mail.puts mail.puts urls end puts "Created email.txt" end desc 'Post announcement to blog.' task :post_blog do require 'xmlrpc/client' with_config do |config, path| 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, :description => body, :categories => blog_categories) result = server.call('metaWeblog.newPost', site['blog_id'], site['user'], site['password'], content, true) end end end desc 'Post announcement to rubyforge.' task :post_news do require 'rubyforge' subject, title, body, urls = announcement rf = RubyForge.new.configure rf.login rf.post_news(rubyforge_name, subject, "#{title}\n\n#{body}") puts "Posted to rubyforge" end desc 'Create news email file and post to rubyforge.' task :announce => [:email, :post_news, :post_blog, :publish_on_announce ] desc 'Verify the manifest.' task :check_manifest => :clean do f = "Manifest.tmp" require 'find' files = [] with_config do |config, _| exclusions = config["exclude"] abort "exclude entry missing from .hoerc. Aborting." if exclusions.nil? Find.find '.' do |path| next unless File.file? path next if path =~ exclusions files << path[2..-1] 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. key_file cert_file = File. 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.configure 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 |
#developer(name, email) ⇒ Object
438 439 440 441 |
# File 'lib/hoe-patched.rb', line 438 def developer name, email self. << name self.email << email end |
#missing(name) ⇒ Object
344 345 346 347 |
# File 'lib/hoe-patched.rb', line 344 def missing name warn "** #{name} is missing or in the wrong format for auto-intuiting." warn " run `sow blah` and look at its text files" end |
#normalize_deps(deps) ⇒ Object
340 341 342 |
# File 'lib/hoe-patched.rb', line 340 def normalize_deps deps Array(deps).map { |o| String === o ? [o] : o } end |
#paragraphs_of(path, *paragraphs) ⇒ Object
Reads a file at path
and spits out an array of the paragraphs
specified.
changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
summary, *description = p.paragraphs_of('README.txt', 3, 3..8)
1003 1004 1005 |
# File 'lib/hoe-patched.rb', line 1003 def paragraphs_of(path, *paragraphs) File.read(path).delete("\r").split(/\n\n+/).values_at(*paragraphs) end |
#readme_name ⇒ Object
349 350 351 |
# File 'lib/hoe-patched.rb', line 349 def readme_name Dir['README*'].first || 'README.txt' end |
#run_tests(multi = false) ⇒ Object
:nodoc:
979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 |
# File 'lib/hoe-patched.rb', line 979 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 = ["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(":") ENV['EXCLUDED_VERSIONS'] = excludes cmd = "multiruby #{cmd}" if multi send msg, cmd end |
#with_config {|config, rc| ... } ⇒ Object
:nodoc:
443 444 445 446 447 448 |
# File 'lib/hoe-patched.rb', line 443 def with_config # :nodoc: rc = File.("~/.hoerc") exists = File.exist? rc config = exists ? YAML.load_file(rc) : {} yield(config, rc) end |