You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@buildr.apache.org by as...@apache.org on 2009/03/13 20:55:01 UTC

svn commit: r753368 - in /buildr/trunk: ./ rakelib/

Author: assaf
Date: Fri Mar 13 19:54:58 2009
New Revision: 753368

URL: http://svn.apache.org/viewvc?rev=753368&view=rev
Log:
New and improved rakelib.

Added:
    buildr/trunk/rakelib/checks.rake
      - copied, changed from r753146, buildr/trunk/rakelib/package.rake
Removed:
    buildr/trunk/rakelib/apache.rake
    buildr/trunk/rakelib/changelog.rake
    buildr/trunk/rakelib/rubyforge.rake
    buildr/trunk/rakelib/scm.rake
Modified:
    buildr/trunk/Rakefile
    buildr/trunk/rakelib/doc.rake
    buildr/trunk/rakelib/jekylltask.rb
    buildr/trunk/rakelib/package.rake
    buildr/trunk/rakelib/release.rake
    buildr/trunk/rakelib/rspec.rake
    buildr/trunk/rakelib/setup.rake
    buildr/trunk/rakelib/stage.rake

Modified: buildr/trunk/Rakefile
URL: http://svn.apache.org/viewvc/buildr/trunk/Rakefile?rev=753368&r1=753367&r2=753368&view=diff
==============================================================================
--- buildr/trunk/Rakefile (original)
+++ buildr/trunk/Rakefile Fri Mar 13 19:54:58 2009
@@ -26,6 +26,7 @@
 end
 
 
+# Load the Gem specification for the current platform (Ruby or JRuby).
 def spec(platform = RUBY_PLATFORM[/java/] || 'ruby')
   @specs ||= ['ruby', 'java'].inject({}) { |hash, platform|
     $platform = platform
@@ -34,25 +35,11 @@
   @specs[platform]
 end
 
-
-
-
-ENV['staging'] = "people.apache.org:~/public_html/#{spec.name}/#{spec.version}"
-
-task('apache:license').enhance FileList[spec.files].exclude('.class', '.png', '.jar', '.tif', '.textile', '.icns',
-   'README', 'LICENSE', 'CHANGELOG', 'NOTICE', 'etc/KEYS', 'etc/git-svn-authors')
-
-task 'stage:check' do
-  print 'Checking that we have JRuby, Scala and Groovy available ... '
-  fail 'Full testing requires JRuby!' unless which('jruby')
-  fail 'Full testing requires Scala!' unless which('scala')
-  fail 'Full testing requires Groovy!' unless which('groovy')
-  puts 'OK'
+# Tell us if we need sudo for various commands.
+def sudo_needed?
+  Config::CONFIG['host_os'] !~ /windows|cygwin|bccwin|cygwin|djgpp|mingw|mswin|wince/i && !ENV['GEM_HOME']
 end
 
-task 'stage:check' do
-  # Dependency check for the other platform, i.e. if making a release with Ruby,
-  # run dependency checks with JRuby. (Also, good opportunity to upgrade other
-  # platform's dependencies)
-  sh RUBY_PLATFORM =~ /java/ ? 'ruby' : 'jruby -S rake setup dependency'
-end
+
+desc 'Clean up all temporary directories used for running tests, creating documentation, packaging, etc.'
+task :clobber

Copied: buildr/trunk/rakelib/checks.rake (from r753146, buildr/trunk/rakelib/package.rake)
URL: http://svn.apache.org/viewvc/buildr/trunk/rakelib/checks.rake?p2=buildr/trunk/rakelib/checks.rake&p1=buildr/trunk/rakelib/package.rake&r1=753146&r2=753368&rev=753368&view=diff
==============================================================================
--- buildr/trunk/rakelib/package.rake (original)
+++ buildr/trunk/rakelib/checks.rake Fri Mar 13 19:54:58 2009
@@ -14,47 +14,29 @@
 # the License.
 
 
-require 'rake/gempackagetask'
-
-
-desc 'Clean up all temporary directories used for running tests, creating documentation, packaging, etc.'
-task 'clobber'
-
-package = Rake::GemPackageTask.new(spec) do |pkg|
-  pkg.need_tar = true
-  pkg.need_zip = true
-end
-
-desc 'Install the package locally'
-task 'install'=>['setup', "#{package.package_dir}/#{package.gem_file}"] do |task|
-  print "Installing #{spec.name} ... "
-  args = [Config::CONFIG['ruby_install_name'], '-S', 'gem', 'install', "#{package.package_dir}/#{package.gem_file}"]
-  args.unshift('sudo') if sudo_needed?
-  sh *args
-  puts 'Done'
-end
-
-desc 'Uninstall previously installed packaged'
-task 'uninstall' do |task|
-  print "Uninstalling #{spec.name} ... "
-  args = [Config::CONFIG['ruby_install_name'], '-S', 'gem', 'uninstall', spec.name, '--version', spec.version.to_s]
-  args.unshift('sudo') if sudo_needed?
-  sh *args
-  puts 'Done'
+desc "Check that source files contain the Apache license"
+task :license=>FileList["**/*.{rb,rake,java,gemspec,buildfile}", 'Rakefile'] do |task|
+  puts "Checking that files contain the Apache license ... "
+  required = task.prerequisites.select { |fn| File.file?(fn) }
+  missing = required.reject { |fn| 
+    comments = File.read(fn).scan(/(\/\*(.*?)\*\/)|^#\s+(.*?)$|^-#\s+(.*?)$|<!--(.*?)-->/m).
+      map { |match| match.compact }.flatten.join("\n")
+    comments =~ /Licensed to the Apache Software Foundation/ && comments =~ /http:\/\/www.apache.org\/licenses\/LICENSE-2.0/
+  }
+  fail "#{missing.join(', ')} missing Apache License, please add it before making a release!" unless missing.empty?
+  puts "[x] Source files contain the Apache license"
 end
 
 
-desc 'Look for new dependencies, check transitive dependencies'
-task 'dependency' do
+desc "Look for new dependencies, check transitive dependencies"
+task :dependency do
   puts "Checking that all dependencies are up to date ..."
-=begin
   # Find if anything has a more recent dependency.  These are not errors, just reports.
-  for dep in spec.dependencies
-    current = Gem::SourceInfoCache.search(dep, true, true).last
-    latest = Gem::SourceInfoCache.search(Gem::Dependency.new(dep.name, '>0'), true, true).last
+  spec.dependencies.each do |dep|
+    current = Gem::SourceInfoCache.search(dep).last
+    latest = Gem::SourceInfoCache.search(Gem::Dependency.new(dep.name, '>0')).last
     puts "A new version of #{dep.name} is available, #{latest.version} replaces #{current.version}" if latest.version > current.version
   end
-=end
 
   # Returns orderd list of transitive dependencies for the given dependency.
   transitive = lambda { |depend|
@@ -65,31 +47,11 @@
   # as a Buildr dependency, and order is preserved.
   spec.dependencies.each_with_index do |dep, index|
     puts "checking #{dep.name}"
-    for trans in transitive[dep]
+    transitive[dep].each do |trans|
       matching = spec.dependencies.find { |existing| trans =~ existing }
       fail "#{trans} required by #{dep} and missing from spec" unless matching
       fail "#{trans} must come before #{dep} in dependency list" unless spec.dependencies.index(matching) < index
     end
   end
+  puts "[X] Checked all dependencies are up to date and transitive dependencies are correctly ordered"
 end
-
-task 'stage:check'=>'dependency'
-
-desc 'Compile Java libraries used by Buildr'
-task 'compile' do
-  puts 'Compiling Java libraries ...'
-  args = File.expand_path('_buildr'), '--buildfile=buildr.buildfile', 'compile'
-  args << '--trace' if Rake.application.options.trace
-  sh *args
-  puts 'OK'
-end
-file Rake::GemPackageTask.new(spec).package_dir=>'compile'
-file Rake::GemPackageTask.new(spec).package_dir_path=>'compile'
-
-# We also need the other package (JRuby if building on Ruby, and vice versa)
-Rake::GemPackageTask.new spec(RUBY_PLATFORM =~ /java/ ? 'ruby' : 'java') do |task|
-  # Block necessary otherwise doesn't do full job.
-end
-
-
-

Modified: buildr/trunk/rakelib/doc.rake
URL: http://svn.apache.org/viewvc/buildr/trunk/rakelib/doc.rake?rev=753368&r1=753367&r2=753368&view=diff
==============================================================================
--- buildr/trunk/rakelib/doc.rake (original)
+++ buildr/trunk/rakelib/doc.rake Fri Mar 13 19:54:58 2009
@@ -14,33 +14,47 @@
 # the License.
 
 
-require 'rakelib/jekylltask'
-
 begin # For the Web site, we use the mislav-hanna RDoc theme (http://github.com/mislav/hanna/)
   require 'hanna/rdoctask'
+
+  desc "Generate RDoc documentation in rdoc/"
+  Rake::RDocTask.new :rdoc do |rdoc|
+    rdoc.rdoc_dir = 'rdoc'
+    rdoc.title    = spec.name
+    rdoc.options  = spec.rdoc_options.clone
+    rdoc.rdoc_files.include('lib/**/*.rb')
+    rdoc.rdoc_files.include spec.extra_rdoc_files
+  end
+
 rescue LoadError
   puts "Buildr uses the mislav-hanna RDoc theme. You can install it by running rake setup"
-  task('setup') { install_gem 'mislav-hanna', :source=>'http://gems.github.com' }
-  require 'rake/rdoctask'
+  task(:setup) { install_gem 'mislav-hanna', :source=>'http://gems.github.com' }
 end
 
 
-desc "Generate RDoc documentation in rdoc/"
-Rake::RDocTask.new('rdoc') do |rdoc|
-  rdoc.rdoc_dir = 'rdoc'
-  rdoc.title    = spec.name
-  rdoc.options  = spec.rdoc_options.clone
-  rdoc.rdoc_files.include('lib/**/*.rb')
-  rdoc.rdoc_files.include spec.extra_rdoc_files
-end
+begin
+  require 'rakelib/jekylltask'
 
-desc "Generate Buildr documentation in _site/"
-JekyllTask.new 'jekyll' do |task|
-  task.source = 'doc'
-  task.target = '_site'
-  task.pygments = true
+  desc "Generate Buildr documentation in _site/"
+  JekyllTask.new :jekyll do |task|
+    task.source = 'doc'
+    task.target = '_site'
+    task.pygments = true
+  end
+
+rescue LoadError
+  puts "Buildr uses the mojombo-jekyll to generate the Web site. You can install it by running rake setup"
+  task :setup do
+    install_gem 'mojombo-jekyll', :source=>'http://gems.github.com', :version=>'0.4.1'
+    if `pygmentize -V`.empty?
+      args = %w{easy_install Pygments}
+      args.unshift 'sudo' unless Config::CONFIG['host_os'] =~ /windows/
+      sh *args
+    end
+  end
 end
 
+
 desc "Generate Buildr documentation as buildr.pdf"
 file 'buildr.pdf'=>'_site' do |task|
   pages = File.read('doc/preface.textile').scan(/^#.*":(\S*)$/).flatten.map { |f| "_site/#{f}" }
@@ -48,7 +62,7 @@
 end
 
 desc "Build a copy of the Web site in the ./_site"
-task 'site'=>['_site', 'rdoc', 'spec', 'coverage', 'buildr.pdf'] do
+task :site=>['_site', :rdoc, :spec, :coverage, 'buildr.pdf'] do
   cp_r 'rdoc', '_site'
   fail 'No RDocs in site directory' unless File.exist?('_site/rdoc/files/lib/buildr_rb.html')
   cp '_reports/specs.html', '_site'
@@ -61,15 +75,15 @@
 end
 
 # Publish prerequisites to Web site.
-task 'site_publish'=>'site' do
-  target = "people.apache.org:/www/#{spec.name}.apache.org"
+task :upload_site=>:site do
+  target = "people.apache.org:/www/#{spec.name}.apache.org/"
   puts "Uploading new site to #{target} ..."
-  sh "rsync --progress --recursive --delete _site/ #{target.inspect}/"
-  sh "ssh people.apache.org chmod -R g+w /www/#{spec.name}.apache.org/*"
+  sh 'rsync', '--progress', '--recursive', '--delete', '_site/', target
+  sh 'ssh', 'people.apache.org', 'chmod', '-R', 'g+w', "/www/#{spec.name}.apache.org/*"
   puts "Done"
 end
 
-task 'clobber' do
+task :clobber do
   rm_rf '_site'
   rm 'buildr.pdf'
   rm 'prince_errors.log'

Modified: buildr/trunk/rakelib/jekylltask.rb
URL: http://svn.apache.org/viewvc/buildr/trunk/rakelib/jekylltask.rb?rev=753368&r1=753367&r2=753368&view=diff
==============================================================================
--- buildr/trunk/rakelib/jekylltask.rb (original)
+++ buildr/trunk/rakelib/jekylltask.rb Fri Mar 13 19:54:58 2009
@@ -15,6 +15,8 @@
 
 
 require 'rake/tasklib'
+require 'jekyll'
+
 
 class JekyllTask < Rake::TaskLib
   def initialize(name=:jekyll)  # :yield: self
@@ -73,47 +75,36 @@
 end
 
 
-begin
-  require 'jekyll'
-
-  # TODO: Worked around bug in Jekyll 0.4.1. Removed when 0.4.2 is out.
-  # http://github.com/mojombo/jekyll/commit/c180bc47bf2f63db1bff9f6600cccbe5ad69077e#diff-0
-  class Albino
-    def execute(command)
-      output = ''
-      Open4.popen4(command) do |pid, stdin, stdout, stderr|
-        stdin.puts @target
-        stdin.close
-        output = stdout.read.strip
-        [stdout, stderr].each { |io| io.close }
-      end
-      output
-    end
-  end
-
-  class Jekyll::Page
-    def render(layouts, site_payload)
-      puts "... #{@name}"
-      payload = {"page" => self.data}.deep_merge(site_payload)
-      do_layout(payload, layouts)
+# TODO: Worked around bug in Jekyll 0.4.1. Removed when 0.4.2 is out.
+# http://github.com/mojombo/jekyll/commit/c180bc47bf2f63db1bff9f6600cccbe5ad69077e#diff-0
+class Albino
+  def execute(command)
+    output = ''
+    Open4.popen4(command) do |pid, stdin, stdout, stderr|
+      stdin.puts @target
+      stdin.close
+      output = stdout.read.strip
+      [stdout, stderr].each { |io| io.close }
     end
+    output
   end
+end
 
-  module TocFilter
-    def toc(input)
-      input.scan(/<(h2)(?:>|\s+(.*?)>)(.*?)<\/\1\s*>/mi).inject(%{<ol class="toc">}) { |toc, entry|
-        id = entry[1][/^id=(['"])(.*)\1$/, 2]
-        title = entry[2].gsub(/<(\w*).*?>(.*?)<\/\1\s*>/m, '\2').strip
-        toc << %{<li><a href="##{id}">#{title}</a></li>}
-      } << "</ol>"
-    end
+class Jekyll::Page
+  def render(layouts, site_payload)
+    puts "... #{@name}"
+    payload = {"page" => self.data}.deep_merge(site_payload)
+    do_layout(payload, layouts)
   end
-  Liquid::Template.register_filter(TocFilter)
+end
 
-rescue LoadError
-  puts "Buildr uses the mojombo-jekyll to generate the Web site. You can install it by running rake setup"
-  task 'setup' do
-    install_gem 'mojombo-jekyll', :source=>'http://gems.github.com', :version=>'0.4.1'
-    sh "#{sudo_needed? ? 'sudo ' : nil}easy_install Pygments"
+module TocFilter
+  def toc(input)
+    input.scan(/<(h2)(?:>|\s+(.*?)>)(.*?)<\/\1\s*>/mi).inject(%{<ol class="toc">}) { |toc, entry|
+      id = entry[1][/^id=(['"])(.*)\1$/, 2]
+      title = entry[2].gsub(/<(\w*).*?>(.*?)<\/\1\s*>/m, '\2').strip
+      toc << %{<li><a href="##{id}">#{title}</a></li>}
+    } << "</ol>"
   end
 end
+Liquid::Template.register_filter(TocFilter)

Modified: buildr/trunk/rakelib/package.rake
URL: http://svn.apache.org/viewvc/buildr/trunk/rakelib/package.rake?rev=753368&r1=753367&r2=753368&view=diff
==============================================================================
--- buildr/trunk/rakelib/package.rake (original)
+++ buildr/trunk/rakelib/package.rake Fri Mar 13 19:54:58 2009
@@ -17,79 +17,55 @@
 require 'rake/gempackagetask'
 
 
-desc 'Clean up all temporary directories used for running tests, creating documentation, packaging, etc.'
-task 'clobber'
-
 package = Rake::GemPackageTask.new(spec) do |pkg|
   pkg.need_tar = true
   pkg.need_zip = true
 end
 
-desc 'Install the package locally'
-task 'install'=>['setup', "#{package.package_dir}/#{package.gem_file}"] do |task|
+desc "Install Buildr from source"
+task :install=>[:setup, "#{package.package_dir}/#{package.gem_file}"] do |task|
   print "Installing #{spec.name} ... "
-  args = [Config::CONFIG['ruby_install_name'], '-S', 'gem', 'install', "#{package.package_dir}/#{package.gem_file}"]
+  args = Config::CONFIG['ruby_install_name'], '-S', 'gem', 'install', "#{package.package_dir}/#{package.gem_file}"
   args.unshift('sudo') if sudo_needed?
   sh *args
-  puts 'Done'
+  puts "[x] Installed Buildr #{spec.version}"
 end
 
-desc 'Uninstall previously installed packaged'
-task 'uninstall' do |task|
-  print "Uninstalling #{spec.name} ... "
-  args = [Config::CONFIG['ruby_install_name'], '-S', 'gem', 'uninstall', spec.name, '--version', spec.version.to_s]
+desc "Uninstall previous rake install"
+task :uninstall do |task|
+  puts "Uninstalling #{spec.name} ... "
+  args = Config::CONFIG['ruby_install_name'], '-S', 'gem', 'uninstall', spec.name, '--version', spec.version.to_s
   args.unshift('sudo') if sudo_needed?
   sh *args
-  puts 'Done'
-end
-
-
-desc 'Look for new dependencies, check transitive dependencies'
-task 'dependency' do
-  puts "Checking that all dependencies are up to date ..."
-=begin
-  # Find if anything has a more recent dependency.  These are not errors, just reports.
-  for dep in spec.dependencies
-    current = Gem::SourceInfoCache.search(dep, true, true).last
-    latest = Gem::SourceInfoCache.search(Gem::Dependency.new(dep.name, '>0'), true, true).last
-    puts "A new version of #{dep.name} is available, #{latest.version} replaces #{current.version}" if latest.version > current.version
-  end
-=end
-
-  # Returns orderd list of transitive dependencies for the given dependency.
-  transitive = lambda { |depend|
-    dep_spec = Gem::SourceIndex.from_installed_gems.search(depend).last
-    fail "No specification for dependency #{depend}" unless dep_spec
-    dep_spec.runtime_dependencies.map { |trans| transitive[trans].push(trans) }.flatten.uniq }
-  # For each dependency, make sure *all* its transitive dependencies are listed
-  # as a Buildr dependency, and order is preserved.
-  spec.dependencies.each_with_index do |dep, index|
-    puts "checking #{dep.name}"
-    for trans in transitive[dep]
-      matching = spec.dependencies.find { |existing| trans =~ existing }
-      fail "#{trans} required by #{dep} and missing from spec" unless matching
-      fail "#{trans} must come before #{dep} in dependency list" unless spec.dependencies.index(matching) < index
-    end
-  end
+  puts "[x] Uninstalled Buildr #{spec.version}"
 end
 
-task 'stage:check'=>'dependency'
 
-desc 'Compile Java libraries used by Buildr'
-task 'compile' do
-  puts 'Compiling Java libraries ...'
+desc "Compile Java libraries used by Buildr"
+task :compile do
+  puts "Compiling Java libraries ..."
   args = File.expand_path('_buildr'), '--buildfile=buildr.buildfile', 'compile'
   args << '--trace' if Rake.application.options.trace
   sh *args
-  puts 'OK'
 end
-file Rake::GemPackageTask.new(spec).package_dir=>'compile'
-file Rake::GemPackageTask.new(spec).package_dir_path=>'compile'
+file Rake::GemPackageTask.new(spec).package_dir=>:compile
+file Rake::GemPackageTask.new(spec).package_dir_path=>:compile
 
 # We also need the other package (JRuby if building on Ruby, and vice versa)
-Rake::GemPackageTask.new spec(RUBY_PLATFORM =~ /java/ ? 'ruby' : 'java') do |task|
-  # Block necessary otherwise doesn't do full job.
-end
-
+# Must call new with block, even if block does nothing, otherwise bad things happen.
+Rake::GemPackageTask.new(spec(RUBY_PLATFORM =~ /java/ ? 'ruby' : 'java')) { |task| }
 
 
+desc "Upload snapshot packages over to people.apache.org"
+task :snapshot=>[:package] do
+  rm_rf '_snapshot' # Always start with empty directory
+  puts "Copying existing gems from Apache"
+  sh 'rsync', '--progress', '--recursive', 'people.apache.org:public_html/buildr/snapshot/', '_snapshot/'
+  puts "Copying new gems over"
+  cp FileList['pkg/{*.gem,*.tgz,*.zip}'], '_snapshot/gems'
+  puts "Generating gem index ..."
+  sh 'gem', 'generate_index', '--directory', '_snapshot'
+  puts "Copying gem and index back to Apache" 
+  sh 'rsync', '--progress', '--recursive', '_snapshot/', 'people.apache.org:public_html/buildr/snapshot/'
+end
+task(:clobber) { rm_rf '_snapshot' }

Modified: buildr/trunk/rakelib/release.rake
URL: http://svn.apache.org/viewvc/buildr/trunk/rakelib/release.rake?rev=753368&r1=753367&r2=753368&view=diff
==============================================================================
--- buildr/trunk/rakelib/release.rake (original)
+++ buildr/trunk/rakelib/release.rake Fri Mar 13 19:54:58 2009
@@ -13,55 +13,108 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
-# Released files are placed in this directory first, and from there published to various servers.
-file 'published' do |task, args|
-  mkpath task.name
-  puts "Populating _release directory from #{args.staging}/dist ..."
-  sh 'rsync', '--progress', '--recursive', "#{args.staging}/dist", '_release'
-  puts "Populating _site directory from #{args.staging}/site ..."
-  sh 'rsync', '--progress', '--recursive', "#{args.staging}/site", '_site'
-  puts 'Done'
-end
-
-task 'clobber' do
-  rm_rf 'published'
-end
-
-namespace 'release' do
-  task 'prepare'=>['setup', 'clobber', 'published']
-
-  task 'publish'
-
-  task 'wrapup'
-end
 
-desc "Make a release using previously staged files"
-task 'release'=>['release:prepare', 'release:publish', 'release:wrapup']
+task :release do
+  # First, we need to get all the staged files from Apache to _release.
+  mkpath '_release'
+  lambda do
+    url = "people.apache.org:~/public_html/#{spec.name}/#{spec.version}"
+    puts "Populating _release directory from #{url} ..."
+    sh 'rsync', '--progress', '--recursive', url, '_release'
+    puts "[X] Staged files are now in _release"
+  end.call
+
+
+  # Upload binary and source packages and new Web site
+  lambda do
+    target = "people.apache.org:/www/www.apache.org/dist/#{spec.name}/#{spec.version}"
+    puts "Uploading packages to www.apache.org/dist ..."
+    host, remote_dir = target.split(':')
+    sh 'ssh', host, 'rm', '-rf', remote_dir rescue nil
+    sh 'ssh', host, 'mkdir', remote_dir
+    sh 'rsync', '--progress', '--recursive', '_release/dist/', target
+    puts "[X] Uploaded packages to www.apache.org/dist"
+
+    target = "people.apache.org:/www/#{spec.name}.apache.org/"
+    puts "Uploading new site to #{spec.name}.apache.org ..."
+    sh 'rsync', '--progress', '--recursive', '--delete', '_release/site/', target
+    sh 'ssh', 'people.apache.org', 'chmod', '-R', 'g+w', "/www/#{spec.name}.apache.org/*"
+    puts "[X] Uploaded new site to #{spec.name}.apache.org"
+  end.call
+
+
+  # Upload binary and source packages to RubyForge.
+  lambda do
+    changes = FileList['_release/CHANGES'].first
+    files = FileList['_release/dist/*.{gem,tgz,zip}']
+    puts "Uploading #{spec.version} to RubyForge ... "
+    rubyforge = RubyForge.new.configure
+    rubyforge.login 
+    rubyforge.userconfig.merge!('release_changes'=>changes,  'preformatted' => true) if changes
+    rubyforge.add_release spec.rubyforge_project.downcase, spec.name.downcase, spec.version.to_s, *files
+    puts "Posting news to RubyForge ... "
+    rubyforge.post_news spec.rubyforge_project.downcase, "Buildr #{spec.versions} released",
+      "New in Buildr #{spec.version}:\n\n#{changes}"
+    puts "[X] Uploaded gems and source files to #{spec.name}.rubyforge.org"
+  end.call
+
+
+  # Create an SVN tag for this release.
+  lambda do
+    info = `svn info` + `git svn info` # Using either svn or git-svn
+    if url = info[/^URL:/] && info.scan(/^URL: (.*)/)[0][0] 
+      new_url = url.sub(/(trunk$)|(branches\/\w*)$/, "tags/#{spec.version}")
+      unless url == new_url
+        sh 'svn', 'copy', url, new_url, '-m', "Release #{spec.version}" do |ok, res|
+          if ok
+            puts "[X] Tagged this release as tags/#{spec.version} ... "
+          else
+            puts "Could not create tag, please do it yourself!"
+            puts %{  svn copy #{url} #{new_url} -m "Release #{spec.version}"}
+          end
+        end
+      end
+    end
+  end.call
 
 
-task 'next_version' do
-  next_version = spec.version.to_s.split('.').map { |v| v.to_i }.
-    zip([0, 0, 1]).map { |a| a.inject(0) { |t,i| t + i } }.join('.')
-
-  ver_file = "lib/#{spec.name}.rb"
-  if File.exist?(ver_file)
-    print "Updating #{ver_file} to next version number (#{next_version}) ... "
-    modified = File.read(ver_file).sub(/(VERSION\s*=\s*)(['"])(.*)\2/) { |line| "#{$1}#{$2}#{next_version}#{$2}" } 
-    File.open ver_file, 'w' do |file|
+  # Update CHANGELOG to next release number.
+  lambda do 
+    next_version = spec.version.to_s.split('.').map { |v| v.to_i }.
+      zip([0, 0, 1]).map { |a| a.inject(0) { |t,i| t + i } }.join('.')
+    modified = "#{next_version} (Pending)\n\n" + File.read('CHANGELOG')
+    File.open 'CHANGELOG', 'w' do |file|
       file.write modified
     end
-    puts 'Done'
-  end
+    puts "[X] Updated CHANGELOG and added entry for next release"
+  end.call
+ 
+
+  # Update source files to next release number.
+  lambda do
+    next_version = spec.version.to_s.split('.').map { |v| v.to_i }.
+      zip([0, 0, 1]).map { |a| a.inject(0) { |t,i| t + i } }.join('.')
+
+    ver_file = "lib/#{spec.name}.rb"
+    if File.exist?(ver_file)
+      modified = File.read(ver_file).sub(/(VERSION\s*=\s*)(['"])(.*)\2/) { |line| "#{$1}#{$2}#{next_version}#{$2}" } 
+      File.open ver_file, 'w' do |file|
+        file.write modified
+      end
+      puts "[X] Updated #{ver_file} to next release"
+    end
 
-  spec_file = "#{spec.name}.gemspec"
-  if File.exist?(spec_file)
-    print "Updating #{spec_file} to next version number (#{next_version}) ... "
-    modified = File.read(spec_file).sub(/(s(?:pec)?\.version\s*=\s*)(['"])(.*)\2/) { |line| "#{$1}#{$2}#{next_version}#{$2}" } 
-    File.open spec_file, 'w' do |file|
-      file.write modified
+    spec_file = "#{spec.name}.gemspec"
+    if File.exist?(spec_file)
+      modified = File.read(spec_file).sub(/(s(?:pec)?\.version\s*=\s*)(['"])(.*)\2/) { |line| "#{$1}#{$2}#{next_version}#{$2}" } 
+      File.open spec_file, 'w' do |file|
+        file.write modified
+      end
+      puts "[X] Updated #{spec_file} to next release"
     end
-    puts 'Done'
-  end
+  end.call
+
 end
 
-task 'release:wrapup'=>'next_version'
+
+task(:clobber) { rm_rf '_release' }

Modified: buildr/trunk/rakelib/rspec.rake
URL: http://svn.apache.org/viewvc/buildr/trunk/rakelib/rspec.rake?rev=753368&r1=753367&r2=753368&view=diff
==============================================================================
--- buildr/trunk/rakelib/rspec.rake (original)
+++ buildr/trunk/rakelib/rspec.rake Fri Mar 13 19:54:58 2009
@@ -16,66 +16,54 @@
 
 begin
   require 'spec/rake/spectask'
-
   directory '_reports'
-  task 'clobber' do
-    rm_f 'failed'
-    rm_rf '_reports'
-  end
 
-  desc 'Run all specs'
-  Spec::Rake::SpecTask.new('spec'=>'_reports') do |task|
+  desc "Run all specs"
+  Spec::Rake::SpecTask.new :spec=>'_reports' do |task|
     task.spec_files = Dir['spec/**/*_spec.rb']
     task.spec_opts = %w{--format specdoc --format failing_examples:failed --format html:_reports/specs.html --loadby mtime --backtrace}    
     task.spec_opts << '--colour' if $stdout.isatty
   end
 
   desc 'Run all failed examples from previous run'
-  Spec::Rake::SpecTask.new('failed') do |task|
+  Spec::Rake::SpecTask.new :failed do |task|
     task.spec_files = Dir['spec/**/*_spec.rb']
     task.spec_opts = %w{--format specdoc --format failing_examples:failed --example failed --backtrace}    
     task.spec_opts << '--colour' if $stdout.isatty
   end
 
-  # TODO: Horribly broken!  Fix some other time.
   desc 'Run RSpec and generate Spec and coverage reports (slow)'
-  Spec::Rake::SpecTask.new('coverage'=>'_reports') do |task|
+  Spec::Rake::SpecTask.new :coverage=>'_reports' do |task|
     task.spec_files = Dir['spec/**/*_spec.rb']
     task.spec_opts = %W{--format progress --format failing_examples:failed --format html:_reports/specs.html --backtrace}    
     task.spec_opts << '--colour' if $stdout.isatty
     task.rcov = true
     task.rcov_dir = '_reports/coverage'
-    task.rcov_opts << '--exclude / --include-file ^lib --text-summary'
+    task.rcov_opts = '--exclude / --include-file ^lib --text-summary'
   end
 
   # Useful for testing with JRuby when using Ruby and vice versa.
-  namespace 'spec' do
-
-    desc 'Run all specs specifically with Ruby'
-    task 'ruby' do
-      puts 'Running test suite using Ruby ...'
+  namespace :spec do
+    desc "Run all specs specifically with Ruby"
+    task :ruby do
+      puts "Running test suite using Ruby ..."
       sh 'ruby -S rake spec'
     end
 
-    desc 'Run all specs specifically with JRuby'
-    task 'jruby' do
-      puts 'Running test suite using JRuby ...'
+    desc "Run all specs specifically with JRuby"
+    task :jruby do
+      puts "Running test suite using JRuby ..."
       sh 'jruby -S rake spec'
     end
-
   end
 
-  task 'setup' do
-    install_gem 'win32console' if windows? && !RUBY_PLATFORM[/java/] # Colors for RSpec, only on Windows platform.
+  task :clobber do
+    rm_f 'failed'
+    rm_rf '_reports'
   end
 
 rescue LoadError
-  puts 'Please run rake setup to install RSpec'
-  task 'stage:check' do
-    fail 'Please run rake setup to install RSpec'
-  end
+  puts "Buildr uses RSpec. You can install it by running rake setup"
+  task(:setup) { install_gem 'rcov', :version=>'~>0.8' }
+  task(:setup) { install_gem 'win32console' if RUBY_PLATFORM[/win32/] } # Colors for RSpec, only on Windows platform.
 end
-
-
-task 'stage:prepare'=>'spec'
-task 'stage:prepare'=>RUBY_PLATFORM =~ /java/ ? 'spec:ruby' : 'spec:jruby' # Test the *other* platform

Modified: buildr/trunk/rakelib/setup.rake
URL: http://svn.apache.org/viewvc/buildr/trunk/rakelib/setup.rake?rev=753368&r1=753367&r2=753368&view=diff
==============================================================================
--- buildr/trunk/rakelib/setup.rake (original)
+++ buildr/trunk/rakelib/setup.rake Fri Mar 13 19:54:58 2009
@@ -14,58 +14,35 @@
 # the License.
 
 
-require 'rubygems/source_info_cache'
-require 'stringio' # for Gem::RemoteFetcher
 require 'jruby' if RUBY_PLATFORM[/java/]
+require 'rubygems/source_info_cache'
 
-# True if running on the Windows operating sytem.  Different from Gem.win_platform?
-# which returns true if running on the Windows platform of MRI, false when using JRuby.
-def windows?
-  Config::CONFIG['host_os'] =~ /windows|cygwin|bccwin|cygwin|djgpp|mingw|mswin|wince/i
-end
-
-def sudo_needed?
-  !( windows? || ENV['GEM_HOME'] )
-end
-
-# Finds and returns path to executable.  Consults PATH environment variable.
-# Returns nil if executable not found.
-def which(name)
-  if windows?
-    path = ENV['PATH'].split(File::PATH_SEPARATOR).map { |path| path.gsub('\\', '/') }.map { |path| "#{path}/#{name}.{exe,bat,com}" }
-  else
-    path = ENV['PATH'].split(File::PATH_SEPARATOR).map { |path| "#{path}/#{name}" }
-  end
-  FileList[path].existing.first
-end
-
-# Execute a GemRunner command
-def gem_run(*args)
-  rb_bin = File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name'])
-  args.unshift rb_bin, '-S', 'gem'
-  args.unshift 'sudo', 'env', 'JAVA_HOME=' + ENV['JAVA_HOME'] if sudo_needed?
-  sh *args.map{ |a| a.inspect }.join(' ')
-end
 
-def install_gem(name, options = {}) # ver_requirement = ['> 0'])
+# Install the specified gem. Options include:
+# - :version -- Version requirement, e.g. '1.2' or '~> 1.2'
+# - :source  -- Gem repository, e.g. 'http://gems.github.com'
+def install_gem(name, options = {})
   dep = Gem::Dependency.new(name, options[:version] || '>0')
   if Gem::SourceIndex.from_installed_gems.search(dep).empty?
     puts "Installing #{name} ..."
-    args = 'install', name
-    args << '--version' << dep.version_requirements.to_s if options[:version]
+    rb_bin = File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name'])
+    args = []
+    args << 'sudo' << 'env' << "JAVA_HOME=#{ENV['JAVA_HOME']}" if sudo_needed?
+    args << rb_bin << '-S' << 'gem' << 'install' << name
+    args << '--version' << dep.version_requirements.to_s
     args << '--source' << options[:source] if options[:source]
     args << '--source' << 'http://gems.rubyforge.org'
     args << '--install-dir' << ENV['GEM_HOME'] if ENV['GEM_HOME']
-    gem_run *args
+    sh *args
   end
 end
 
-# Setup environment for running this Rakefile (RSpec, Docter, etc).
+
+# Setup environment for running this Rakefile (RSpec, Jekyll, etc).
 desc "If you're building from sources, run this task first to setup the necessary dependencies."
-missing = spec.dependencies.select { |dep| Gem::SourceIndex.from_installed_gems.search(dep).empty? }
-task 'setup' do
+task :setup do
+  missing = spec.dependencies.select { |dep| Gem::SourceIndex.from_installed_gems.search(dep).empty? }
   missing.each do |dep|
     install_gem dep.name, :version=>dep.version_requirements
   end
 end
-puts "Missing Gems #{missing.join(', ')}, please run rake setup first!" unless missing.empty?

Modified: buildr/trunk/rakelib/stage.rake
URL: http://svn.apache.org/viewvc/buildr/trunk/rakelib/stage.rake?rev=753368&r1=753367&r2=753368&view=diff
==============================================================================
--- buildr/trunk/rakelib/stage.rake (original)
+++ buildr/trunk/rakelib/stage.rake Fri Mar 13 19:54:58 2009
@@ -14,35 +14,188 @@
 # the License.
 
 
-# Staged files are copied to this directory first, and from there uploaded to the staging server.
-directory '_staged'
+require 'digest/md5'
+require 'digest/sha1'
 
-task 'clobber' do
-  rm_rf '_staged'
+
+task :prepare=>[:license, :dependency] do |task, args|
+  # Make sure we're doing a release from checked code.
+  lambda do
+    puts "Checking there are no local changes ... "
+    svn = `svn status`
+    fail "Cannot release unless all local changes are in SVN:\n#{svn}" unless svn.empty?
+    git = `git status`
+    fail "Cannot release unless all local changes are in Git:\n#{git}" if git[/^#\t/]
+    puts "[X] There are no local changes, everything is in source control"
+  end.call
+
+  # Make sure we have a valid CHANGELOG entry for this release.
+  lambda do
+    puts "Checking that CHANGELOG indicates most recent version and today's date ... "
+    expecting = "#{spec.version} (#{Time.now.strftime('%Y-%m-%d')})"
+    header = File.readlines('CHANGELOG').first.chomp
+    fail "Expecting CHANGELOG to start with #{expecting}, but found #{header} instead" unless expecting == header
+    puts "[x] CHANGELOG indicates most recent version and today's date"
+  end.call
+
+  task(:license).invoke
+  task(:dependency).invoke
+
+  # Need JRuby, Scala and Groovy installed to run all the specs.
+  lambda do
+    puts "Checking that we have JRuby, Scala and Groovy available ... "
+    sh 'jruby --version'
+    sh 'scala -version'
+    sh 'groovy -version'
+    puts "[X] We have JRuby, Scala and Groovy"
+  end.call
+
+  # Need GPG to sign the packages.
+  lambda do
+    args.gpg or fail "Please run with gpg=<argument for gpg --local-user>"
+    fail "No GPG user #{args.gpg}" if `gpg --list-keys #{args.gpg}`.empty?
+  end.call
+
+  # Need RubyForge to upload new release files.
+  lambda do
+    puts "[!] Make sure you have admin privileges to make a release on RubyForge"
+    rubyforge = RubyForge.new.configure
+    rubyforge.login 
+    rubyforge.scrape_project(spec.name)
+  end.call
+
+  # We will be speccing in one platform, so also spec the other one.
+  task(RUBY_PLATFORM =~ /java/ ? 'spec:ruby' : 'spec:jruby').invoke # Test the *other* platform
 end
 
-namespace 'stage' do
-  # stage:check verifies that we're able to stage a release: check for a changelog,
-  # local changes, run all the test cases, etc.  You can add more actions, e.g.
-  # checking license files, spell checking documentation.
-  task 'check'=>['setup', 'clobber']
-
-  # stage:prepare prepares all the files necessary for making a successful release:
-  # binary and source packages, documentation, Web site, change file, checksums, etc.
-  # This task depends on stage:check, and also performs its own verification of the
-  # produced artifacts.  Staged files are placed in the _staged directory.
-  task 'prepare'=>'_staged'
-
-  # stage:upload moves the stage directory to the staging server.
-  task 'upload' do |task, args|
-    puts "Uploading _staged directory to #{args.staging} ..."
-    sh 'rsync', '--progress', '--recursive', '_staged/', args.staging + '/dist'
-    puts 'Done'
-  end
+
+task :stage=>[:setup, :clobber, :check, :prepare] do |task, args|
+  mkpath '_staged'
+
+  # Start by figuring out what has changed.
+  lambda do
+    puts "Looking for changes between this release and previous one ..."
+    pattern = /(^(\d+\.\d+(?:\.\d+)?)\s+\(\d{4}-\d{2}-\d{2}\)\s*((:?^[^\n]+\n)*))/
+    changes = File.read('CHANGELOG').scan(pattern).inject({}) { |hash, set| hash[set[1]] = set[2] ; hash }
+    current = changes[spec.version.to_s]
+    fail "No changeset found for version #{spec.version}" unless current
+    File.open '_staged/CHANGES', 'w' do |file|
+      file.write "#{spec.version} (#{Time.now.strftime('%Y-%m-%d')})\n"
+      file.write current
+    end
+    puts "[X] Listed most recent changed in _staged/CHANGES"
+  end.call
+
+  # Create the packages (gem, tarball) and sign them. This requires user
+  # intervention so the earlier we do it the better.
+  lambda do
+    puts "Creating and signing release packages ..."
+    task(:package).invoke
+    mkpath '_staged/dist'
+    FileList['pkg/*.{gem,zip,tgz}'].each do |source|
+      pkg = source.pathmap('_staged/dist/%n%x') 
+      cp source, pkg
+      bytes = File.open(pkg, 'rb') { |file| file.read }
+      File.open(pkg + '.md5', 'w') { |file| file.write Digest::MD5.hexdigest(bytes) << ' ' << File.basename(pkg) }
+      File.open(pkg + '.sha1', 'w') { |file| file.write Digest::SHA1.hexdigest(bytes) << ' ' << File.basename(pkg) }
+      sh 'gpg', '--local-user', args.gpg, '--armor', '--output', pkg + '.asc', '--detach-sig', pkg, :verbose=>true
+    end
+    cp 'etc/KEYS', '_staged'
+    puts "[X] Created and signed release packages in _staged/dist"
+  end.call
+
+  # The download page should link to the new binaries/sources, and we
+  # want to do that before generating the site/documentation.
+  lambda do
+    puts "Updating download page with links to release packages ... "
+    url = "http://www.apache.org/dist/#{spec.name}/#{spec.version}"
+    rows = FileList['_staged/*.{gem,tgz,zip}'].map { |pkg|
+      name, md5 = File.basename(pkg), Digest::MD5.file(pkg).to_s
+      %{| "#{name}":#{url}/#{name} | "#{md5}":#{url}/#{name}.md5 | "Sig":#{url}/#{name}.asc |}
+    }
+    textile = <<-TEXTILE
+h3. #{spec.name} #{spec.version} (#{Time.now.strftime('%Y-%m-%d')})
+
+|_. Package |_. MD5 Checksum |_. PGP |
+#{rows.join("\n")}
+
+p>. ("Release signing keys":#{url}/KEYS)
+    TEXTILE
+    file_name = 'doc/download.textile'
+    print "Adding download links to #{file_name} ... "
+    modified = File.read(file_name).sub(/^h2\(#dist\).*$/) { |header| "#{header}\n\n#{textile}" }
+    File.open file_name, 'w' do |file|
+      file.write modified
+    end
+    puts "[X] Updated #{file_name}"
+  end.call
+
+
+  # Now we can create the Web site, this includes running specs, coverage report, etc.
+  # This will take a while, so we want to do it as last step before upload.
+  lambda do
+    puts "Creating new Web site"
+    task(:site).invoke
+    cp_r '_site', '_staged/site'
+    puts "[X] Created new Web site in _staged/site"
+  end.call
+
+
+  # Move everything over to people.apache.org so we can vote on it.
+  lambda do
+    url = "people.apache.org:~/public_html/#{spec.name}/#{spec.version}"
+    puts "Uploading _staged directory to #{url} ..."
+    sh 'rsync', '--progress', '--recursive', '_staged/', url
+    puts "[X] Uploaded _staged directory to #{url}"
+  end.call
   
-  # Put anything that happens post staging here, e.g. release vote email template.
-  task 'wrapup'
+
+  # Prepare a release vote email. In the distant future this will also send the
+  # email for you and vote on it.
+  lambda do
+    # Need to know who you are on Apache, local user may be different (see .ssh/config).
+    whoami = `ssh people.apache.org whoami`.strip
+    base_url = "http://people.apache.org/~#{whoami}/buildr/#{spec.version}"
+    # Need changes for this release only.
+    changelog = File.read('CHANGELOG').scan(/(^(\d+\.\d+(?:\.\d+)?)\s+\(\d{4}-\d{2}-\d{2}\)\s*((:?^[^\n]+\n)*))/)
+    changes = changelog[0][2]
+    previous_version = changelog[1][1]
+
+    email = <<-EMAIL
+To: dev@buildr.apache.org
+Subject: [VOTE] Buildr #{spec.version} release
+
+We're voting on the source distributions available here:
+#{base_url}/dist/
+
+Specifically:
+#{base_url}/dist/buildr-#{spec.version}.tgz
+#{base_url}/dist/buildr-#{spec.version}.zip
+
+The documentation generated for this release is available here:
+#{base_url}/site/
+#{base_url}/site/buildr.pdf
+
+The official specification against which this release was tested:
+#{base_url}/site/specs.html
+
+Test coverage report:
+#{base_url}/site/coverage/index.html
+
+
+The following changes were made since #{previous_version}:
+
+#{changes}
+    EMAIL
+    File.open 'vote-email.txt', 'w' do |file|
+      file.write email
+    end
+    puts "[X] Created release vote email template in 'vote-email.txt'"
+    puts email
+  end.call
+
 end
 
-desc 'Stage files for the release, upload them to staging server'
-task 'stage'=>['stage:check', 'stage:prepare', 'stage:upload', 'stage:wrapup']
+
+task(:clobber) { rm_rf '_staged' }
+task(:setup) { install_gem 'rubyforge' }