buildr-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From as...@apache.org
Subject svn commit: r631024 - in /incubator/buildr/trunk: DISCLAIMER Rakefile doc/pages/download.textile doc/web.toc.yaml lib/core/application.rb
Date Mon, 25 Feb 2008 22:47:22 GMT
Author: assaf
Date: Mon Feb 25 14:47:20 2008
New Revision: 631024

URL: http://svn.apache.org/viewvc?rev=631024&view=rev
Log:
Now with new and improved release task

Modified:
    incubator/buildr/trunk/DISCLAIMER
    incubator/buildr/trunk/Rakefile
    incubator/buildr/trunk/doc/pages/download.textile
    incubator/buildr/trunk/doc/web.toc.yaml
    incubator/buildr/trunk/lib/core/application.rb

Modified: incubator/buildr/trunk/DISCLAIMER
URL: http://svn.apache.org/viewvc/incubator/buildr/trunk/DISCLAIMER?rev=631024&r1=631023&r2=631024&view=diff
==============================================================================
--- incubator/buildr/trunk/DISCLAIMER (original)
+++ incubator/buildr/trunk/DISCLAIMER Mon Feb 25 14:47:20 2008
@@ -1 +1,7 @@
-Apache Buildr is an effort undergoing incubation at The Apache Software Foundation (ASF),
sponsored by the Apache Incubator. Incubation is required of all newly accepted projects until
a further review indicates that the infrastructure, communications, and decision making process
have stabilized in a manner consistent with other successful ASF projects. While incubation
status is not necessarily a reflection of the completeness or stability of the code, it does
indicate that the project has yet to be fully endorsed by the ASF.
+Apache Buildr is an effort undergoing incubation at The Apache Software
+Foundation (ASF), sponsored by the Apache Incubator. Incubation is required of
+all newly accepted projects until a further review indicates that the
+infrastructure, communications, and decision making process have stabilized in
+a manner consistent with other successful ASF projects. While incubation status
+is not necessarily a reflection of the completeness or stability of the code,
+it does indicate that the project has yet to be fully endorsed by the ASF.

Modified: incubator/buildr/trunk/Rakefile
URL: http://svn.apache.org/viewvc/incubator/buildr/trunk/Rakefile?rev=631024&r1=631023&r2=631024&view=diff
==============================================================================
--- incubator/buildr/trunk/Rakefile (original)
+++ incubator/buildr/trunk/Rakefile Mon Feb 25 14:47:20 2008
@@ -82,6 +82,8 @@
 
 # Testing is everything.
 #
+task('clobber') { rm 'failing' rescue nil }
+
 desc 'Run all specs'
 Spec::Rake::SpecTask.new('spec') do |task|
   task.spec_files = FileList['spec/**/*_spec.rb']
@@ -94,15 +96,18 @@
   task.spec_opts << '--options' << 'spec/spec.opts' << '--format' <<
'failing_examples:failing' << '--example' << 'failing'
 end
 
+
 namespace 'spec' do
 
-  desc 'Run all specs and generate test/coverage reports in html directory'
-  Spec::Rake::SpecTask.new('report') do |task|
-    mkpath 'html'
+  directory('reports')
+  Rake::Task['rake:clobber'].enhance { rm_rf 'reports' }
+
+  desc 'Run all specs and generate specification and test coverage reports in html directory'
+  Spec::Rake::SpecTask.new('full'=>'reports') do |task|
     task.spec_files = FileList['spec/**/*_spec.rb']
-    task.spec_opts << '--format' << 'html:html/report.html' << '--backtrace'
+    task.spec_opts << '--format' << 'html:reports/specs.html' << '--backtrace'
     task.rcov = true
-    task.rcov_dir = 'html/coverage'
+    task.rcov_dir = 'reports/coverage'
     task.rcov_opts = ['--exclude', 'spec,bin']
   end
 
@@ -119,7 +124,7 @@
 #
 desc 'Generate RDoc documentation'
 rdoc = Rake::RDocTask.new(:rdoc) do |rdoc|
-  rdoc.rdoc_dir = 'html/rdoc'
+  rdoc.rdoc_dir = 'rdoc'
   rdoc.title    = ruby_spec.name
   rdoc.options  = ruby_spec.rdoc_options + ['--promiscuous']
   rdoc.rdoc_files.include('lib/**/*.rb')
@@ -143,7 +148,7 @@
     :collection => Docter.collection('Buildr').using('doc/web.toc.yaml').
       include('doc/pages', 'LICENSE', 'CHANGELOG'),
     :template   => Docter.template('doc/web.haml').
-      include('doc/css', 'doc/images', 'doc/scripts', 'html/report.html', 'html/coverage',
'html/rdoc')
+      include('doc/css', 'doc/images', 'doc/scripts', 'reports/specs.html', 'reports/coverage',
'rdoc')
   }
   print_docs = {
     :collection => Docter.collection('Buildr').using('doc/print.toc.yaml').
@@ -157,6 +162,8 @@
 
   desc 'Generate HTML documentation'
   html = Docter::Rake.generate('html', web_docs[:collection], web_docs[:template])
+  html.enhance ['spec:full']
+
   desc 'Run Docter server'
   Docter::Rake.serve 'docter', web_docs[:collection], web_docs[:template], :port=>3000
   task('docs').enhance [html]
@@ -181,143 +188,202 @@
 end
 
 
-# Commit to SVN, upload and do the release cycle.
-#
-namespace :svn do
-  task :clean? do |task|
-    status = `svn status`.reject { |line| line =~ /\s(pkg|html)$/ }
+namespace 'release' do
+  require 'highline'
+  require 'highline/import'
+  Kernel.def_delegators :$terminal, :color
+
+  # This task does all prerequisites checks before starting the release, for example,
+  # that we have Groovy and Scala to run all the test cases, or that we have Allison
+  # and PrinceXML to generate the full documentation.
+  task 'check'
+  # This task does all the preparation work before making a release and also checks
+  # that we generate all the right material, for example, that we compiled Java sources,
+  # created the PDF, have coverage report.
+  task 'prepare'=>['clobber', 'check']
+
+  # Does CHANGELOG reflects current release?
+  task 'check' do
+    say 'Checking that CHANGELOG indicates most recent version and today\'s date ... '
+    expecting = "#{ruby_spec.version} (#{Time.now.strftime('%Y-%m-%d')})"
+    header = File.readlines('CHANGELOG').first
+    fail "Expecting CHANGELOG to start with #{expecting}, but found #{header} instead" unless
expecting == header
+    say 'OK'
+  end
+
+  # License requirement.
+  task 'check' do
+    say 'Checking that files contain the Apache license ... '
+    directories = 'lib', 'spec', 'docs', 'bin'
+    ignore = 'class', 'opts'
+    FileList['lib/**/*', 'spec/**/*', 'bin/**', 'doc/css/*', 'doc/scripts/*'].
+      exclude('doc/css/eiffel.css').reject { |file| File.directory?(file) || ignore.include?(file[/[^.]*$/])
}.each do |file|
+      comments = File.read(file).scan(/(\/\*(.*?)\*\/)|^#\s+(.*?)$|<!--(.*?)-->/m).
+        map { |match| match.reject(&:nil?) }.flatten.join("\n")
+      fail "File #{file} missing Apache License, please add it before making a release!"
unless
+        comments =~ /Licensed to the Apache Software Foundation/ && comments =~ /http:\/\/www.apache.org\/licenses\/LICENSE-2.0/
+    end
+    say 'OK'
+  end
+
+  # No local changes.
+  task 'check' do
+    status = `svn status`
     fail "Cannot release unless all local changes are in SVN:\n#{status}" unless status.empty?
   end
-  
-  task :tag do |task|
-    cur_url = `svn info`.scan(/URL: (.*)/)[0][0]
-    new_url = cur_url.sub(/(trunk$)|(branches\/\w*)$/, "tags/#{ruby_spec.version.to_s}")
-    system 'svn', 'copy', cur_url, new_url, '-m', "Release #{ruby_spec.version.to_s}"
+
+  # Compile Java libraries.
+  task 'prepare' do
+    say 'Compiling Java libraries ... '
+    FileList['lib/**/*.class'].each { |file| rm file }
+    `buildr compile`
+    FileList['lib/**/*.java'].each { |src| fail "Can't find .class file for #{src}!" unless
File.exist?(src.ext('class')) }
+    say 'OK'
   end
-end
 
-namespace :upload do
-  task :docs=>'rake:docs' do |task|
-    sh %{rsync -r --del --progress html/*  people.apache.org:/www/incubator.apache.org/#{ruby_spec.rubyforge_project.downcase}/}
+  # Tests, specs and coverage reports.
+  task 'check' do
+    say 'Checking that we have JRuby, Scala and Groovy available ... '
+    fail 'Full testing requires JRuby!' if `which jruby`.empty?
+    fail 'Full testing requires Scala!' if `which scalac`.empty? || ENV['SCALA_HOME'].to_s.empty?
+    fail 'Full testing requires Groovy!' if `which groovyc`.empty?
+    say 'OK'
+  end
+  task 'prepare' do
+    say 'Running test suite using JRuby ...'
+    task('spec:jruby').invoke
+    say 'Running test suite using Ruby ...'
+    task('spec:ruby').invoke
+    say 'Done'
   end
 
-  task :packages=>['rake:docs', 'rake:package'] do |task|
-    require 'rubyforge'
+  # Documentation (derived from above).
+  task 'check' do
+    say 'Checking that we can use Allison and PrinceXML ... '
+    fail 'Release requires the Allison RDoc template, please gem install allison!' unless
rdoc.template =~ /allison.rb/
+    fail 'Release requires PrinceXML to generate PDF documentation!' if `which prince`.empty?
+    say 'OK'
+  end
+  task 'prepare'=>'spec:full' do
+    say 'Generating RDocs and PDF ...'
+    task('docs').invoke
+    say 'Done'
 
-    # Read the changes for this release.
-    pattern = /(^(\d+\.\d+(?:\.\d+)?)\s+\(\d{4}-\d{2}-\d{2}\)\s*((:?^[^\n]+\n)*))/
-    changelog = File.read(__FILE__.pathmap('%d/CHANGELOG'))
-    changes = changelog.scan(pattern).inject({}) { |hash, set| hash[set[1]] = set[2] ; hash
}
-    current = changes[ruby_spec.version.to_s]
-    if !current && ruby_spec.version.to_s =~ /\.0$/
-      current = changes[ruby_spec.version.to_s.split('.')[0..-2].join('.')] 
+    say 'Checking that we have PDF, RDoc, specs and coverage report ... '
+    fail 'No RDocs if html/rdoc!' unless File.exist?('html/rdoc/files/lib/buildr_rb.html')
+    fail 'No PDF generated, you need to install PrinceXML!' unless File.exist?('html/buildr.pdf')
+    fail 'No specifications in html directory!' unless File.exist?('html/specs.html') 
+    fail 'No coverage reports in html/coverage directory!' unless File.exist?('html/coverage/index.html')
+    say 'OK'
+  end
+
+  task 'check' do
+    require 'rubyforge' rescue fail 'RubyForge required, please gem install rubyforge!'
+    fail 'GnuPG required to create signatures!' if `which gpg`.empty?
+    gpg_user = ENV['GPG_USER'] or fail 'Please set GPG_USER (--local-user) environment variable
so we know which key to use.'
+    sh('gpg', '--list-key', gpg_user) { |ok, res| ok or fail "No key matches for GPG_USER=#{gpg_user}"
}
+  end
+
+ 
+  # Cut the release: upload Gem to RubyForge before updating site (fail safe).
+  task 'cut'=>['upload:rubyforge', 'upload:site']
+
+
+  namespace 'upload' do
+    # Upload site (html directory) to Apache.
+    task 'site'=>'rake:docs' do
+      say 'Uploading Web site to people.apache.org ... '
+      args = Dir.glob('html/*') + ['people.apache.org:/www/incubator.apache.org/' + ruby_spec.rubyforge_project.downcase]
+      verbose(false) { sh 'rsync ', '-r', '--del', '--progress', *files }
+      say 'Done'
     end
-    fail "No changeset found for version #{ruby_spec.version}" unless current
 
-    puts "Uploading #{ruby_spec.name} #{ruby_spec.version}"
-    files = Dir.glob('pkg/*.{gem,tgz,zip}')
-    rubyforge = RubyForge.new
-    rubyforge.login    
-    File.open('.changes', 'w'){|f| f.write(current)}
-    rubyforge.userconfig.merge!('release_changes' => '.changes',  'preformatted' =>
true)
-    rubyforge.add_release ruby_spec.rubyforge_project.downcase, ruby_spec.name.downcase,
ruby_spec.version, *files
-    rm '.changes'
-    puts "Release #{ruby_spec.version} uploaded"
-  end
-end
+    # Upload Gems to RubyForge.
+    task 'rubyforge'=>['rake:docs', 'rake:package'] do
+      require 'rubyforge'
+
+      # Read the changes for this release.
+      say 'Looking for changes between this release and previous one ... '
+      pattern = /(^(\d+\.\d+(?:\.\d+)?)\s+\(\d{4}-\d{2}-\d{2}\)\s*((:?^[^\n]+\n)*))/
+      changelog = File.read(__FILE__.pathmap('%d/CHANGELOG'))
+      changes = changelog.scan(pattern).inject({}) { |hash, set| hash[set[1]] = set[2] ;
hash }
+      current = changes[ruby_spec.version.to_s]
+      current = changes[ruby_spec.version.to_s.split('.')[0..-2].join('.')] if !current &&
ruby_spec.version.to_s =~ /\.0$/
+      fail "No changeset found for version #{ruby_spec.version}" unless current
+      say 'OK'
+
+      say "Uploading #{ruby_spec.version} to RubyForge ... "
+      files = Dir.glob('pkg/*.{gem,tgz,zip}')
+      rubyforge = RubyForge.new
+      rubyforge.login    
+      File.open('.changes', 'w'){|f| f.write(current)}
+      rubyforge.userconfig.merge!('release_changes' => '.changes',  'preformatted' =>
true)
+      rubyforge.add_release ruby_spec.rubyforge_project.downcase, ruby_spec.name.downcase,
ruby_spec.version, *files
+      rm '.changes'
+      say 'Done'
+    end
 
-namespace :release do
+    task 'apache'=>['rake:package'] do
+      require 'md5'
+      require 'sha1'
+
+      gpg_user = ENV['GPG_USER'] or fail 'Please set GPG_USER (--local-user) environment
variable so we know which key to use.'
+      say 'Creating -incubating packages ... '
+      rm_rf 'incubating'
+      mkpath 'incubating'
+      packages = FileList['pkg/*.{gem,zip,tgz}'].map do |package|
+        package.pathmap('incubating/%n-incubating%x').tap do |incubating|
+          cp package, incubating
+        end
+      end
+      say 'Done'
 
-  # TODO:  Check that we're using allison.
-  # TODO:  Check that we can generate PDFs.
+      say 'Signing -incubating packages ... '
+      files = packages.each do |package|
+        binary = File.read(package)
+        File.open(package + '.md5', 'w') { |file| file.write MD5.hexdigest(binary) <<
' ' << package }
+        File.open(package + '.sha1', 'w') { |file| file.write SHA1.hexdigest(binary) <<
' ' << package }
+        sh 'gpg', '--local-user', gpg_user, '--armor', '--output', package + '.asc', '--detach-sig',
package, :verbose=>true
+        [package, package + '.md5', package + '.sha1', package + '.asc']
+      end
+      say 'Done'
+
+      say 'Uploading packages to Apache dist ... '
+      args = files.flatten << 'KEYS' << 'people.apache.org:/www.apache.org/dist/incubator/buildr/'
+      verbose(false) { sh 'rsync', '-progress', *args }
+      say 'Done'
+    end
+    Rake::Task['rake:clobber'].enhance { rm_rf 'incubating' }
+
+  end
 
-  task :ready? do
-    require 'highline'
-    require 'highline/import'
 
-    puts "This version: #{ruby_spec.version}"
-    puts
-    puts "Top 4 lines form CHANGELOG:'
-    puts File.readlines('CHANGELOG')[0..3].map { |l| "  #{l}" }
-    puts
-    ask('Top-entry in CHANGELOG file includes today\'s date?') =~ /yes/i or
-      fail 'Please update CHANGELOG to include the right date'
+  # Tag this release in SVN.
+  task 'tag' do
+    say "Tagging release as tags/#{ruby_spec.version} ... "
+    cur_url = `svn info`.scan(/URL: (.*)/)[0][0]
+    new_url = cur_url.sub(/(trunk$)|(branches\/\w*)$/, "tags/#{ruby_spec.version.to_s}")
+    sh 'svn', 'copy', cur_url, new_url, '-m', "Release #{ruby_spec.version.to_s}", :verbose=>false
+    say "OK"
   end
 
-  task :post do
+  # Update lib/buildr.rb to next vesion number, add new entry in CHANGELOG.
+  task 'next_version'=>'tag' do
     next_version = ruby_spec.version.to_ints.zip([0, 0, 1]).map { |a| a.inject(0) { |t,i|
t + i } }.join('.')
-    puts "Updating lib/buildr.rb to next version number: #{next_version}"
+    say "Updating lib/buildr.rb to next version number (#{next_version}) ... "
     buildr_rb = File.read(__FILE__.pathmap('%d/lib/buildr.rb')).
       sub(/(VERSION\s*=\s*)(['"])(.*)\2/) { |line| "#{$1}#{$2}#{next_version}#{$2}" } 
     File.open(__FILE__.pathmap('%d/lib/buildr.rb'), 'w') { |file| file.write buildr_rb }
-    puts 'Adding entry to CHANGELOG'
+    say "OK"
+
+    say 'Adding new entry to CHANGELOG ... '
     changelog = File.read(__FILE__.pathmap('%d/CHANGELOG'))
     File.open(__FILE__.pathmap('%d/CHANGELOG'), 'w') { |file| file.write "#{next_version}
(Pending)\n\n#{changelog}" }
+    say "OK"
   end
 
-  task :meat=>['clobber', 'svn:clean?', 'spec:jruby', 'spec:report', 'upload:packages',
'upload:docs', 'svn:tag']
-end
-
-desc 'Upload release to RubyForge including docs, tag SVN'
-task :release=>[ 'release:ready?', 'release:meat', 'release:post' ]
-
-
-# Handles Java libraries that are part of Buildr.
-#
-task 'compile' do
-  $LOAD_PATH.unshift File.expand_path('lib')
-  require 'buildr'
-  require 'buildr/jetty'
-
-  # RJB, JUnit and friends.
-  Dir.chdir 'lib/java' do
-    `javac -source 1.4 -target 1.4 -Xlint:all org/apache/buildr/*.java`
-  end
-
-  # Jetty server.
-  cp = artifacts(Buildr::Jetty::REQUIRES).each { |task| task.invoke }.map(&:name).join(File::PATH_SEPARATOR)
-  Dir.chdir 'lib/buildr' do
-    `javac -source 1.4 -target 1.4 -Xlint:all -cp #{cp} org/apache/buildr/*.java`
-  end
+  # Wrapup comes after cut, and does things like tagging in SVN, updating Buildr version
number, etc.
+  task 'wrapup'=>['tag', 'next_version']
 end
 
-
-# Apache release:
-# - Create MD5/SHA1/PGP signatures
-# - Upload to people.apache.org:/www/www.apache.org/dist/incubator/buildr
-#
-namespace 'release' do
-
-  task 'prepare'=>'clobber'
-
-  # Check that all source files have licenses.
-  task 'prepare' do
-    puts 'Checking that files contain the Apache license'
-    directories = 'lib', 'spec', 'docs', 'bin'
-    ignore = 'class', 'opts'
-    FileList['lib/**/*', 'spec/**/*', 'bin/**', 'doc/css/*', 'doc/scripts/*'].
-      exclude('doc/css/eiffel.css').reject { |file| File.directory?(file) || ignore.include?(file[/[^.]*$/])
}.each do |file|
-      comments = File.read(file).scan(/(\/\*(.*?)\*\/)|^#\s+(.*?)$|<!--(.*?)-->/m).
-        map { |match| match.reject(&:nil?) }.flatten.join("\n")
-      fail "File #{file} missing Apache License, please add it before making a release!"
unless
-        comments =~ /Licensed to the Apache Software Foundation/ && comments =~ /http:\/\/www.apache.org\/licenses\/LICENSE-2.0/
-    end
-  end
-
-  # Compile Java libraries.
-  task 'prepare'=>'compile' do
-    FileList['lib/**/*.java'].each { |src| fail "Can't find .class file for #{src}!" unless
File.exist?(src.ext('class')) }
-  end
-
-  # Make sure we have RDoc template, Docter and PDF genereation.
-  task 'prepare'=>[rdoc.template, pdf] do
-    fail 'Release requires the Allison RDoc template, please gem install allison!' unless
rdoc.template =~ /allison.rb/
-    fail 'No PDF generated, you need to install PrinceXML!' unless File.exist?('html/buildr.pdf')
-  end
-
-  # Run specs on Ruby and JRuby, make sure we generate test/coverage reports.
-  task 'prepare'=>['spec:jruby', 'spec:report'] do
-    fail 'No test reports in html directory!' unless File.exist?('html/report.html') 
-    fail 'No coverage reports in html directory!' unless File.exist?('html/coverage/index.html')
-  end
-end
+task 'release'=>['release:prepare', 'release:cut', 'release:wrapup']

Modified: incubator/buildr/trunk/doc/pages/download.textile
URL: http://svn.apache.org/viewvc/incubator/buildr/trunk/doc/pages/download.textile?rev=631024&r1=631023&r2=631024&view=diff
==============================================================================
--- incubator/buildr/trunk/doc/pages/download.textile (original)
+++ incubator/buildr/trunk/doc/pages/download.textile Mon Feb 25 14:47:20 2008
@@ -3,11 +3,12 @@
 
 h2.  Installing Buildr
 
-The easiest way to install Buildr is using the fabulous RubyGems package manager.  Of course,
-you will need either Ruby or JRuby, and we recommend a recent version of RubyGems and
-if this sounds foreign to you, don't worry.  We'll show you how to install Buildr on Linux,
-OS/X, Windows and JRuby in the "Getting Started guide":getting_started.html, we even provide
-automated installation scripts.
+The easiest way to install Buildr is using the fabulous RubyGems package
+manager.  Of course, you will need either Ruby or JRuby, and we recommend a
+recent version of RubyGems and if this sounds foreign to you, don't worry.
+We'll show you how to install Buildr on Linux, OS/X, Windows and JRuby in the
+"Getting Started guide":getting_started.html, we even provide automated
+installation scripts.
 
 
 h2.  Binaries and Source Code
@@ -15,3 +16,13 @@
 At the moment we do not make offical Apache binary and source distributions.
 Unofficial binary and source distributions are available form
 "RubyForge":http://rubyforge.org/projects/buildr.
+
+p(note). When downloading from a mirror please check the
+"md5sum":http://www.apache.org/dev/release-signing#md5 and verify the
+"OpenPGP":http://www.apache.org/dev/release-signing#openpgp compatible
+signature from the main Apache site. This
+"KEYS":http://www.apache.org/dist/incubator/buildr/KEYS file contains the
+public keys used for signing releases. It is recommended that (when possible) a
+web of trust is used to confirm the identity of these keys. For more
+information, please see the "Apache Release
+FAQ":http://www.apache.org/dev/release.html.

Modified: incubator/buildr/trunk/doc/web.toc.yaml
URL: http://svn.apache.org/viewvc/incubator/buildr/trunk/doc/web.toc.yaml?rev=631024&r1=631023&r2=631024&view=diff
==============================================================================
--- incubator/buildr/trunk/doc/web.toc.yaml (original)
+++ incubator/buildr/trunk/doc/web.toc.yaml Mon Feb 25 14:47:20 2008
@@ -26,5 +26,5 @@
 - Project Status:
   - License: license.html
   - Change Log: changelog.html
-  - Test Report: report.html
-  - Test Coverage: coverage
+  - Specs: specs.html
+  - Coverage: coverage

Modified: incubator/buildr/trunk/lib/core/application.rb
URL: http://svn.apache.org/viewvc/incubator/buildr/trunk/lib/core/application.rb?rev=631024&r1=631023&r2=631024&view=diff
==============================================================================
--- incubator/buildr/trunk/lib/core/application.rb (original)
+++ incubator/buildr/trunk/lib/core/application.rb Mon Feb 25 14:47:20 2008
@@ -13,6 +13,27 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+# Portion of this file derived from Rake.
+# Copyright (c) 2003, 2004 Jim Weirich
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
 
 require 'benchmark'
 



Mime
View raw message