summaryrefslogtreecommitdiffstats
path: root/ruby-gem/tasks
diff options
context:
space:
mode:
Diffstat (limited to 'ruby-gem/tasks')
-rw-r--r--ruby-gem/tasks/ann.rake83
-rw-r--r--ruby-gem/tasks/constants.rb118
-rw-r--r--ruby-gem/tasks/gem.rake196
-rw-r--r--ruby-gem/tasks/git.rake38
-rw-r--r--ruby-gem/tasks/helpers.rb130
-rw-r--r--ruby-gem/tasks/notes.rake27
-rw-r--r--ruby-gem/tasks/post_load.rake35
-rw-r--r--ruby-gem/tasks/rdoc.rake46
-rw-r--r--ruby-gem/tasks/rubyforge.rake54
-rw-r--r--ruby-gem/tasks/setup.rb129
-rw-r--r--ruby-gem/tasks/spec.rake44
-rw-r--r--ruby-gem/tasks/svn.rake48
-rw-r--r--ruby-gem/tasks/test.rake41
13 files changed, 989 insertions, 0 deletions
diff --git a/ruby-gem/tasks/ann.rake b/ruby-gem/tasks/ann.rake
new file mode 100644
index 0000000..4515ccb
--- /dev/null
+++ b/ruby-gem/tasks/ann.rake
@@ -0,0 +1,83 @@
+# -*- coding: UTF-8 -*-
+#
+begin
+ require 'bones/smtp_tls'
+rescue LoadError
+ require 'net/smtp'
+end
+require 'time'
+
+namespace :ann do
+
+ # A prerequisites task that all other tasks depend upon
+ task :prereqs
+ file PROJ.ann.file do
+ ann = PROJ.ann
+ puts "Generating #{ann.file}"
+ File.open(ann.file,'w') do |fd|
+ fd.puts("#{PROJ.name} version #{PROJ.version}")
+ fd.puts(" by #{Array(PROJ.authors).first}") if PROJ.authors
+ fd.puts(" #{PROJ.url}") if PROJ.url.valid?
+ fd.puts(" (the \"#{PROJ.release_name}\" release)") if PROJ.release_name
+ fd.puts
+ fd.puts("== DESCRIPTION")
+ fd.puts
+ fd.puts(PROJ.description)
+ fd.puts
+ fd.puts(PROJ.changes.sub(%r/^.*$/, '== CHANGES'))
+ fd.puts
+ ann.paragraphs.each do |p|
+ fd.puts "== #{p.upcase}"
+ fd.puts
+ fd.puts paragraphs_of(PROJ.readme_file, p).join("\n\n")
+ fd.puts
+ end
+ fd.puts ann.text if ann.text
+ end
+ end
+
+ desc "Create an announcement file"
+ task :announcement => ['ann:prereqs', PROJ.ann.file]
+
+ desc "Send an email announcement"
+ task :email => ['ann:prereqs', PROJ.ann.file] do
+ ann = PROJ.ann
+ from = ann.email[:from] || Array(PROJ.authors).first || PROJ.email
+ to = Array(ann.email[:to])
+
+ ### build a mail header for RFC 822
+ rfc822msg = "From: #{from}\n"
+ rfc822msg << "To: #{to.join(',')}\n"
+ rfc822msg << "Subject: [ANN] #{PROJ.name} #{PROJ.version}"
+ rfc822msg << " (#{PROJ.release_name})" if PROJ.release_name
+ rfc822msg << "\n"
+ rfc822msg << "Date: #{Time.new.rfc822}\n"
+ rfc822msg << "Message-Id: "
+ rfc822msg << "<#{"%.8f" % Time.now.to_f}@#{ann.email[:domain]}>\n\n"
+ rfc822msg << File.read(ann.file)
+
+ params = [:server, :port, :domain, :acct, :passwd, :authtype].map do |key|
+ ann.email[key]
+ end
+
+ params[3] = (PROJ.ann.email[:from] || PROJ.email) if params[3].nil?
+
+# if ann.email[:tls] and params[4].nil?
+ if params[4].nil?
+ STDOUT.write "Please enter your e-mail password (#{params[3]}): "
+ params[4] = STDIN.gets.chomp
+ end
+# params = params.shift 2 if not ann.email[:tls]
+
+ ### send email
+ # TODO find a way to bypass /var/lib/gems/1.9/gems/bones-3.6.5/lib/bones/smtp_tls.rb which forces starttls usage
+ Net::SMTP.start(*params) {|smtp| smtp.sendmail(rfc822msg, from, to)}
+ end
+end # namespace :ann
+
+desc 'Alias to ann:announcement'
+task :ann => 'ann:announcement'
+
+CLOBBER << PROJ.ann.file
+
+# EOF
diff --git a/ruby-gem/tasks/constants.rb b/ruby-gem/tasks/constants.rb
new file mode 100644
index 0000000..78a7625
--- /dev/null
+++ b/ruby-gem/tasks/constants.rb
@@ -0,0 +1,118 @@
+# -*- coding: UTF-8 -*-
+#
+require 'rbconfig'
+
+# Setup some constants
+WIN32 = %r/djgpp|(cyg|ms|bcc)win|mingw/ =~ RUBY_PLATFORM unless defined? WIN32
+
+DEV_NULL = WIN32 ? 'NUL:' : '/dev/null'
+
+def quiet( &block )
+ io = [STDOUT.dup, STDERR.dup]
+ STDOUT.reopen DEV_NULL
+ STDERR.reopen DEV_NULL
+ block.call
+ensure
+ STDOUT.reopen io.first
+ STDERR.reopen io.last
+ $stdout, $stderr = STDOUT, STDERR
+end
+
+BUILD_DIR = "build"
+
+USE_RAKE_COMPILER = ( ( (RUBY_PLATFORM =~ /java/) ? false : true ) and test ?d, 'ext' )
+if USE_RAKE_COMPILER
+ gem 'rake-compiler', '>=0.6.0'
+ require 'rake/extensiontask'
+ ENV['RUBY_CC_VERSION'] = '1.8.7:1.9.2'
+end
+
+LIBEXT = case Config::CONFIG['host_os'].downcase
+ when /darwin/
+ "dylib"
+ when /mswin|mingw/
+ "dll"
+ else
+ Config::CONFIG['DLEXT']
+ end
+
+CPU = case Config::CONFIG['host_cpu'].downcase
+ when /i[3456]86/
+ # Darwin always reports i686, even when running in 64bit mode
+ if Config::CONFIG['host_os'] =~ /darwin/ && 0xfee1deadbeef.is_a?(Fixnum)
+ "x86_64"
+ else
+ "i386"
+ end
+ when /amd64|x86_64/
+ "x86_64"
+ when /ppc64|powerpc64/
+ "powerpc64"
+ when /ppc|powerpc/
+ "powerpc"
+ else
+ Config::CONFIG['host_cpu']
+ end
+
+OS = case Config::CONFIG['host_os'].downcase
+ when /linux/
+ "linux"
+ when /darwin/
+ "darwin"
+ when /freebsd/
+ "freebsd"
+ when /openbsd/
+ "openbsd"
+ when /sunos|solaris/
+ "solaris"
+ when /mswin|mingw/
+ "win32"
+ else
+ Config::CONFIG['host_os'].downcase
+ end
+
+CC=ENV['CC'] || Config::CONFIG['CC'] || "gcc"
+
+GMAKE = Config::CONFIG['host_os'].downcase =~ /bsd|solaris/ ? "gmake" : "make"
+
+
+DIFF = if WIN32 then 'diff.exe'
+ else
+ if quiet {system "gdiff", __FILE__, __FILE__} then 'gdiff'
+ else 'diff' end
+ end unless defined? DIFF
+
+SUDO = if WIN32 then ''
+ else
+ if quiet {system 'which sudo'} then 'sudo'
+ else '' end
+ end
+
+RCOV = WIN32 ? 'rcov.bat' : 'rcov'
+RDOC = WIN32 ? 'rdoc.bat' : 'rdoc'
+GEM = WIN32 ? 'gem.bat' : 'gem'
+
+%w(rcov spec/rake/spectask rubyforge bones facets/ansicode).each do |lib|
+ begin
+ require lib
+ Object.instance_eval {const_set "HAVE_#{lib.tr('/','_').upcase}", true}
+ rescue LoadError
+ Object.instance_eval {const_set "HAVE_#{lib.tr('/','_').upcase}", false}
+ end
+end
+
+HAVE_SVN = (Dir.entries(Dir.pwd).include?('.svn') and system("svn --version 2>&1 > #{DEV_NULL}"))
+HAVE_GIT = (Dir.entries(Dir.pwd).include?('.git') and system("git --version 2>&1 > #{DEV_NULL}"))
+
+# Add rake as a development dependency
+#
+PROJ.gem.development_dependencies << ['rake', '>=0.8.7']
+
+# Add bones as a development dependency
+#
+if HAVE_BONES
+ bones_version = defined?(Bones::VERSION) ? Bones::VERSION : Bones.version
+ PROJ.gem.development_dependencies << ['bones', ">= #{bones_version}"]
+end
+
+# EOF
diff --git a/ruby-gem/tasks/gem.rake b/ruby-gem/tasks/gem.rake
new file mode 100644
index 0000000..e5e5d13
--- /dev/null
+++ b/ruby-gem/tasks/gem.rake
@@ -0,0 +1,196 @@
+# -*- coding: UTF-8 -*-
+#
+require 'find'
+require 'rake/packagetask'
+require 'rubygems/user_interaction'
+require 'rubygems/builder'
+
+module Bones
+class GemPackageTask < Rake::PackageTask
+ # Ruby GEM spec containing the metadata for this package. The
+ # name, version and package_files are automatically determined
+ # from the GEM spec and don't need to be explicitly provided.
+ #
+ attr_accessor :gem_spec
+
+ # Tasks from the Bones gem directory
+ attr_reader :bones_files
+
+ # Create a GEM Package task library. Automatically define the gem
+ # if a block is given. If no block is supplied, then +define+
+ # needs to be called to define the task.
+ #
+ def initialize(gem_spec)
+ init(gem_spec)
+ yield self if block_given?
+ define if block_given?
+ end
+
+ # Initialization tasks without the "yield self" or define
+ # operations.
+ #
+ def init(gem)
+ super(gem.name, gem.version)
+ @gem_spec = gem
+ @package_files += gem_spec.files if gem_spec.files
+ @bones_files = []
+
+ local_setup = File.join(Dir.pwd, %w[tasks setup.rb])
+ if !test(?e, local_setup)
+ Dir.glob(::Bones.path(%w[lib bones tasks *])).each {|fn| bones_files << fn}
+ end
+ end
+
+ # Create the Rake tasks and actions specified by this
+ # GemPackageTask. (+define+ is automatically called if a block is
+ # given to +new+).
+ #
+ def define
+ super
+ task :prereqs
+ task :package => ['gem:prereqs', "#{package_dir_path}/#{gem_file}"]
+ file "#{package_dir_path}/#{gem_file}" => [package_dir_path] + package_files + bones_files do
+ when_writing("Creating GEM") {
+ chdir(package_dir_path) do
+ Gem::Builder.new(gem_spec).build
+ verbose(true) { mv gem_file, "../#{gem_file}" }
+ end
+ }
+ end
+
+ file package_dir_path => bones_files do
+ mkdir_p package_dir rescue nil
+
+ gem_spec.files = (gem_spec.files + bones_files.map {|fn| File.join('tasks', File.basename(fn))}).sort
+
+ bones_files.each do |fn|
+ base_fn = File.join('tasks', File.basename(fn))
+ f = File.join(package_dir_path, base_fn)
+ fdir = File.dirname(f)
+ mkdir_p(fdir) if !File.exist?(fdir)
+ if File.directory?(fn)
+ mkdir_p(f)
+ else
+ raise "file name conflict for '#{base_fn}' (conflicts with '#{fn}')" if test(?e, f)
+ safe_ln(fn, f)
+ end
+ end
+ end
+ end
+
+ def gem_file
+ if @gem_spec.platform == Gem::Platform::RUBY
+ "#{package_name}.gem"
+ else
+ "#{package_name}-#{@gem_spec.platform}.gem"
+ end
+ end
+end # class GemPackageTask
+end # module Bones
+
+namespace :gem do
+
+ PROJ.gem._spec = Gem::Specification.new do |s|
+ s.name = PROJ.name
+ s.version = PROJ.version
+ s.summary = PROJ.summary
+ s.authors = Array(PROJ.authors)
+ s.email = PROJ.email
+ s.homepage = Array(PROJ.url).first
+ s.rubyforge_project = PROJ.rubyforge.name
+
+ s.description = PROJ.description
+
+ PROJ.gem.dependencies.each do |dep|
+ s.add_dependency(*dep)
+ end
+
+ PROJ.gem.development_dependencies.each do |dep|
+ s.add_development_dependency(*dep)
+ end
+
+ s.files = PROJ.gem.files
+ s.executables = PROJ.gem.executables.map {|fn| File.basename(fn)}
+ s.extensions = PROJ.gem.files.grep %r/extconf\.rb$/
+
+ s.bindir = 'bin'
+ dirs = Dir["{#{PROJ.libs.join(',')}}"]
+ s.require_paths = dirs unless dirs.empty?
+
+ incl = Regexp.new(PROJ.rdoc.include.join('|'))
+ excl = PROJ.rdoc.exclude.dup.concat %w[\.rb$ ^(\.\/|\/)?ext]
+ excl = Regexp.new(excl.join('|'))
+ rdoc_files = PROJ.gem.files.find_all do |fn|
+ case fn
+ when excl; false
+ when incl; true
+ else false end
+ end
+ s.rdoc_options = PROJ.rdoc.opts + ['--main', PROJ.rdoc.main]
+ s.extra_rdoc_files = rdoc_files
+
+ if test ?f, PROJ.test.file
+ s.test_file = PROJ.test.file
+ else
+ s.test_files = PROJ.test.files.to_a
+ end
+
+ # Do any extra stuff the user wants
+ PROJ.gem.extras.each do |msg, val|
+ case val
+ when Proc
+ val.call(s.send(msg))
+ else
+ s.send "#{msg}=", val
+ end
+ end
+ end # Gem::Specification.new
+
+ Bones::GemPackageTask.new(PROJ.gem._spec) do |pkg|
+ pkg.need_tar = PROJ.gem.need_tar
+ pkg.need_zip = PROJ.gem.need_zip
+ end
+
+ desc 'Show information about the gem'
+ task :debug => 'gem:prereqs' do
+ puts PROJ.gem._spec.to_ruby
+ end
+
+ desc 'Write the gemspec '
+ task :spec => 'gem:prereqs' do
+ File.open("#{PROJ.name}.gemspec", 'w') do |f|
+ f.write PROJ.gem._spec.to_ruby
+ end
+ end
+
+ desc 'Install the gem'
+ task :install => [:clobber, 'gem:package'] do
+ sh "#{SUDO} #{GEM} install --local pkg/#{PROJ.gem._spec.full_name}"
+ # use this version of the command for rubygems > 1.0.0
+ #sh "#{SUDO} #{GEM} install --no-update-sources pkg/#{PROJ.gem._spec.full_name}"
+ end
+
+ desc 'Uninstall the gem'
+ task :uninstall do
+ installed_list = Gem.source_index.find_name(PROJ.name)
+ if installed_list and installed_list.collect { |s| s.version.to_s}.include?(PROJ.version) then
+ sh "#{SUDO} #{GEM} uninstall --version '#{PROJ.version}' --ignore-dependencies --executables #{PROJ.name}"
+ end
+ end
+
+ desc 'Reinstall the gem'
+ task :reinstall => [:uninstall, :install]
+
+ desc 'Cleanup the gem'
+ task :cleanup do
+ sh "#{SUDO} #{GEM} cleanup #{PROJ.gem._spec.name}"
+ end
+end # namespace :gem
+
+desc 'Alias to gem:package'
+task :gem => 'gem:package'
+
+task :clobber => 'gem:clobber_package'
+remove_desc_for_task 'gem:clobber_package'
+
+# EOF
diff --git a/ruby-gem/tasks/git.rake b/ruby-gem/tasks/git.rake
new file mode 100644
index 0000000..b219923
--- /dev/null
+++ b/ruby-gem/tasks/git.rake
@@ -0,0 +1,38 @@
+# -*- coding: UTF-8 -*-
+#
+if HAVE_GIT
+
+namespace :git do
+
+ # A prerequisites task that all other tasks depend upon
+ task :prereqs
+
+ desc 'Show tags from the Git repository'
+ task :show_tags => 'git:prereqs' do |t|
+ puts %x/git tag/
+ end
+
+ desc 'Create a new tag in the Git repository'
+ task :create_tag => 'git:prereqs' do |t|
+ v = ENV['VERSION'] or abort 'Must supply VERSION=x.y.z'
+ abort "Versions don't match #{v} vs #{PROJ.version}" if v != PROJ.version
+ tag = "%s" % [ PROJ.version ]
+ msg = "Creating tag for #{PROJ.name} version #{PROJ.version}"
+ puts "Creating Git tag '#{tag}'"
+ unless system "git tag -a -m '#{msg}' #{tag}"
+ abort "Tag creation failed"
+ end
+# if %x/git remote/ =~ %r/^origin\s*$/
+# unless system "git push origin #{tag}"
+# abort "Could not push tag to remote Git repository"
+# end
+# end
+ end
+
+end # namespace :git
+
+#task 'gem:release' => 'git:create_tag'
+
+end # if HAVE_GIT
+
+# EOF
diff --git a/ruby-gem/tasks/helpers.rb b/ruby-gem/tasks/helpers.rb
new file mode 100644
index 0000000..df5bd50
--- /dev/null
+++ b/ruby-gem/tasks/helpers.rb
@@ -0,0 +1,130 @@
+# -*- coding: UTF-8 -*-
+#
+require 'fileutils'
+require 'find'
+require 'date'
+#
+# Reads a file at +path+ and spits out an array of the +paragraphs+
+# specified.
+#
+# changes = paragraphs_of('History.txt', 0..1).join("\n\n")
+# summary, *description = paragraphs_of('README.txt', 3, 3..8)
+#
+def paragraphs_of( path, *paragraphs )
+ title = String === paragraphs.first ? paragraphs.shift : nil
+ ary = File.read(path).delete("\r").split(/\n\n+/)
+
+ result = if title
+ tmp, matching = [], false
+ rgxp = %r/^=+\s*#{Regexp.escape(title)}/i
+ paragraphs << (0..-1) if paragraphs.empty?
+
+ ary.each do |val|
+ if val =~ rgxp
+ break if matching
+ matching = true
+ rgxp = %r/^=+/i
+ elsif matching
+ tmp << val
+ end
+ end
+ tmp
+ else ary end
+
+ result.values_at(*paragraphs)
+end
+
+# Adds the given gem _name_ to the current project's dependency list. An
+# optional gem _version_ can be given. If omitted, the newest gem version
+# will be used.
+#
+def depend_on( name, version = nil )
+ spec = Gem::Specification.find_by_name(name)
+ version = spec.version.to_s if version.nil? and !spec.nil?
+
+ PROJ.gem.dependencies << case version
+ when nil; [name]
+ when %r/^\d/; [name, ">= #{version}"]
+ else [name, version] end
+end
+
+# Adds the given arguments to the include path if they are not already there
+#
+#def ensure_in_path( *args )
+# args.each do |path|
+# path = File.expand_path(path)
+# $:.unshift(path) if test(?d, path) and not $:.include?(path)
+# end
+#end
+
+# Find a rake task using the task name and remove any description text. This
+# will prevent the task from being displayed in the list of available tasks.
+#
+def remove_desc_for_task( names )
+ Array(names).each do |task_name|
+ task = Rake.application.tasks.find {|t| t.name == task_name}
+ next if task.nil?
+ task.instance_variable_set :@comment, nil
+ end
+end
+
+# Change working directories to _dir_, call the _block_ of code, and then
+# change back to the original working directory (the current directory when
+# this method was called).
+#
+#def in_directory( dir, &block )
+# curdir = pwd
+# begin
+# cd dir
+# return block.call
+# ensure
+# cd curdir
+# end
+#end
+
+# Scans the current working directory and creates a list of files that are
+# candidates to be in the manifest.
+#
+#def manifest
+# files = []
+# exclude = PROJ.exclude.dup
+# comment = %r/^\s*#/
+#
+# # process the ignore file and add the items there to the exclude list
+# if test(?f, PROJ.ignore_file)
+# ary = []
+# File.readlines(PROJ.ignore_file).each do |line|
+# next if line =~ comment
+# line.chomp!
+# line.strip!
+# next if line.nil? or line.empty?
+#
+# glob = line =~ %r/\*\./ ? File.join('**', line) : line
+# Dir.glob(glob).each {|fn| ary << "^#{Regexp.escape(fn)}"}
+# end
+# exclude.concat ary
+# end
+#
+# # generate a regular expression from the exclude list
+# exclude = Regexp.new(exclude.join('|'))
+#
+# Find.find '.' do |path|
+# path.sub! %r/^(\.\/|\/)/o, ''
+# next unless test ?f, path
+# next if path =~ exclude
+# files << path
+# end
+# files.sort!
+#end
+
+# We need a "valid" method that determines if a string is suitable for use
+# in the gem specification.
+#
+class Object
+ def valid?
+ return !(self.empty? or self == "\000") if self.respond_to?(:to_str)
+ return false
+ end
+end
+
+# EOF
diff --git a/ruby-gem/tasks/notes.rake b/ruby-gem/tasks/notes.rake
new file mode 100644
index 0000000..7f7ee79
--- /dev/null
+++ b/ruby-gem/tasks/notes.rake
@@ -0,0 +1,27 @@
+# -*- coding: UTF-8 -*-
+#
+if HAVE_BONES
+
+desc "Enumerate all annotations"
+task :notes do |t|
+ id = if t.application.top_level_tasks.length > 1
+ t.application.top_level_tasks.slice!(1..-1).join(' ')
+ end
+ Bones::AnnotationExtractor.enumerate(PROJ, PROJ.notes.tags.join('|'), id, :tag => true)
+end
+
+namespace :notes do
+ PROJ.notes.tags.each do |tag|
+ desc "Enumerate all #{tag} annotations"
+ task tag.downcase.to_sym do |t|
+ id = if t.application.top_level_tasks.length > 1
+ t.application.top_level_tasks.slice!(1..-1).join(' ')
+ end
+ Bones::AnnotationExtractor.enumerate(PROJ, tag, id)
+ end
+ end
+end
+
+end # if HAVE_BONES
+
+# EOF
diff --git a/ruby-gem/tasks/post_load.rake b/ruby-gem/tasks/post_load.rake
new file mode 100644
index 0000000..8ccdfc9
--- /dev/null
+++ b/ruby-gem/tasks/post_load.rake
@@ -0,0 +1,35 @@
+# -*- coding: UTF-8 -*-
+#
+# This file does not define any rake tasks. It is used to load some project
+# settings if they are not defined by the user.
+
+PROJ.exclude << ["^#{Regexp.escape(PROJ.ann.file)}$",
+ "^#{Regexp.escape(PROJ.ignore_file)}$",
+ "^#{Regexp.escape(PROJ.rdoc.dir)}/",
+ "^#{Regexp.escape(PROJ.rcov.dir)}/"]
+
+flatten_arrays = lambda do |this,os|
+ os.instance_variable_get(:@table).each do |key,val|
+ next if key == :dependencies \
+ or key == :development_dependencies
+ case val
+ when Array; val.flatten!
+ when OpenStruct; this.call(this,val)
+ end
+ end
+ end
+flatten_arrays.call(flatten_arrays,PROJ)
+
+PROJ.changes ||= paragraphs_of(PROJ.history_file, 0..1).join("\n\n")
+
+PROJ.description ||= paragraphs_of(PROJ.readme_file, 'description').join("\n\n")
+
+PROJ.summary ||= PROJ.description.split('.').first
+
+PROJ.gem.files ||= manifest
+
+PROJ.gem.executables ||= PROJ.gem.files.find_all {|fn| fn =~ %r/^bin/}
+
+PROJ.rdoc.main ||= PROJ.readme_file
+
+# EOF
diff --git a/ruby-gem/tasks/rdoc.rake b/ruby-gem/tasks/rdoc.rake
new file mode 100644
index 0000000..98ef3b8
--- /dev/null
+++ b/ruby-gem/tasks/rdoc.rake
@@ -0,0 +1,46 @@
+# -*- coding: UTF-8 -*-
+#
+require 'rdoc/task'
+
+namespace :doc do
+ desc 'Generate RDoc documentation'
+ Rake::RDocTask.new do |rd|
+ rdoc = PROJ.rdoc
+ rd.main = rdoc.main
+ rd.rdoc_dir = rdoc.dir
+
+ incl = Regexp.new(rdoc.include.join('|'))
+ excl = Regexp.new(rdoc.exclude.join('|'))
+ files = PROJ.gem.files.find_all do |fn|
+ case fn
+ when excl; false
+ when incl; true
+ else false end
+ end
+ rd.rdoc_files.push(*files)
+ title = "#{PROJ.name}-#{PROJ.version} Documentation"
+ rf_name = PROJ.rubyforge.name
+ title = "#{rf_name}'s " + title if rf_name.valid? and rf_name != title
+ rd.options << "-t #{title}"
+ rd.options.concat(rdoc.opts)
+ end
+
+ desc 'Generate ri locally for testing'
+ task :ri => :clobber_ri do
+ sh "#{RDOC} --ri -o ri ."
+ end
+
+ task :clobber_ri do
+ rm_r 'ri' rescue nil
+ end
+end # namespace :doc
+
+desc 'Alias to doc:rdoc'
+task :doc => 'doc:rdoc'
+
+desc 'Remove all build products'
+task :clobber => %w(doc:clobber_rdoc doc:clobber_ri)
+
+remove_desc_for_task %w(doc:clobber_rdoc)
+
+# EOF
diff --git a/ruby-gem/tasks/rubyforge.rake b/ruby-gem/tasks/rubyforge.rake
new file mode 100644
index 0000000..73be292
--- /dev/null
+++ b/ruby-gem/tasks/rubyforge.rake
@@ -0,0 +1,54 @@
+# -*- coding: UTF-8 -*-
+#
+if PROJ.rubyforge.name.valid? && HAVE_RUBYFORGE
+
+require 'rubyforge'
+require 'rake/contrib/sshpublisher'
+
+namespace :gem do
+ desc 'Package and upload to RubyForge'
+ task :release => [:clobber, 'gem'] do |t|
+ v = ENV['VERSION'] or abort 'Must supply VERSION=x.y.z'
+ abort "Versions don't match #{v} vs #{PROJ.version}" if v != PROJ.version
+ pkg = "pkg/#{PROJ.gem._spec.full_name}"
+
+ if $DEBUG then
+ puts "release_id = rf.add_release #{PROJ.rubyforge.name.inspect}, #{PROJ.name.inspect}, #{PROJ.version.inspect}, \"#{pkg}.tgz\""
+ puts "rf.add_file #{PROJ.rubyforge.name.inspect}, #{PROJ.name.inspect}, release_id, \"#{pkg}.gem\""
+ end
+
+ rf = RubyForge.new
+ rf.configure rescue nil
+ puts 'Logging in'
+ rf.login
+
+ c = rf.userconfig
+ c['release_notes'] = PROJ.description if PROJ.description
+ c['release_changes'] = PROJ.changes if PROJ.changes
+ c['preformatted'] = true
+
+ files = Dir.glob("#{pkg}*.*")
+
+ puts "Releasing #{PROJ.name} v. #{PROJ.version}"
+ rf.add_release PROJ.rubyforge.name, PROJ.name, PROJ.version, *files
+ end
+end # namespace :gem
+
+
+namespace :doc do
+ desc "Publish RDoc to RubyForge"
+ task :release => %w(doc:clobber_rdoc doc:rdoc) do
+ config = YAML.load(File.read(File.expand_path('~/.rubyforge/user-config.yml')))
+
+ host = "#{config['username']}@rubyforge.org"
+ remote_dir = "/var/www/gforge-projects/#{PROJ.rubyforge.name}/"
+ remote_dir << PROJ.rdoc.remote_dir if PROJ.rdoc.remote_dir
+ local_dir = PROJ.rdoc.dir
+
+ Rake::SshDirPublisher.new(host, remote_dir, local_dir).upload
+ end
+end # namespace :doc
+
+end # if HAVE_RUBYFORGE
+
+# EOF
diff --git a/ruby-gem/tasks/setup.rb b/ruby-gem/tasks/setup.rb
new file mode 100644
index 0000000..5e69d02
--- /dev/null
+++ b/ruby-gem/tasks/setup.rb
@@ -0,0 +1,129 @@
+# -*- coding: UTF-8 -*-
+#
+require 'rubygems'
+require 'rake'
+require 'rake/clean'
+require 'ostruct'
+
+class OpenStruct; undef :gem; end
+
+# TODO: make my own openstruct type object that includes descriptions
+# TODO: use the descriptions to output help on the available bones options
+
+PROJ = OpenStruct.new(
+ # Project Defaults
+ :name => nil,
+ :summary => nil,
+ :description => nil,
+ :changes => nil,
+ :authors => nil,
+ :email => nil,
+ :url => "\000",
+ :version => ENV['VERSION'] || '0.0.0',
+ :exclude => %w(tmp$ bak$ ~$ CVS \.svn/ \.git/ ^pkg/),
+ :release_name => ENV['RELEASE'],
+
+ # System Defaults
+ :ruby_opts => %w(-w),
+ :libs => [],
+ :history_file => 'Changelog',
+ :readme_file => 'README.rdoc',
+ :ignore_file => '.bnsignore',
+
+ # Announce
+ :ann => OpenStruct.new(
+ :file => 'announcement.txt',
+ :text => nil,
+ :paragraphs => [],
+ :email => {
+ :from => nil,
+ :to => %w(ruby-talk@ruby-lang.org),
+ :server => 'localhost',
+ :port => 25,
+ :domain => ENV['HOSTNAME'],
+ :acct => nil,
+ :passwd => nil,
+ :authtype => :plain,
+ :tls => true,
+ }
+ ),
+
+ # Gem Packaging
+ :gem => OpenStruct.new(
+ :dependencies => [],
+ :development_dependencies => [],
+ :executables => nil,
+ :extensions => FileList['ext/**/extconf.rb'],
+ :files => nil,
+ :need_tar => true,
+ :need_zip => false,
+ :extras => {}
+ ),
+
+ # File Annotations
+ :notes => OpenStruct.new(
+ :exclude => %w(^tasks/setup\.rb$),
+ :extensions => %w(.txt .rb .erb .rdoc) << '',
+ :tags => %w(FIXME OPTIMIZE TODO)
+ ),
+
+ # Rcov
+ :rcov => OpenStruct.new(
+ :dir => 'coverage',
+ :opts => %w[--sort coverage -T -x lib/rcov],
+ :threshold => 90.0,
+ :threshold_exact => false
+ ),
+
+ # Rdoc
+ :rdoc => OpenStruct.new(
+ :opts => [],
+ :include => %w(^lib/ ^bin/ ^ext/ \.txt$ \.rdoc$),
+ :exclude => %w(extconf\.rb$),
+ :main => nil,
+ :dir => 'doc',
+ :remote_dir => nil
+ ),
+
+ # Rubyforge
+ :rubyforge => OpenStruct.new(
+ :name => "\000"
+ ),
+
+ # Rspec
+ :spec => OpenStruct.new(
+ :files => FileList['spec/**/*_spec.rb'],
+ :opts => []
+ ),
+
+ # Subversion Repository
+ :svn => OpenStruct.new(
+ :root => nil,
+ :path => '',
+ :trunk => 'trunk',
+ :tags => 'tags',
+ :branches => 'branches'
+ ),
+
+ # Test::Unit
+ :test => OpenStruct.new(
+ :files => FileList['test/**/test_*.rb'],
+ :file => 'test/all.rb',
+ :opts => []
+ )
+)
+
+# Load the other rake files in the tasks folder
+tasks_dir = File.expand_path(File.dirname(__FILE__))
+post_load_fn = File.join(tasks_dir, 'post_load.rake')
+rakefiles = Dir.glob(File.join(tasks_dir, '*.rake')).sort
+rakefiles.unshift(rakefiles.delete(post_load_fn)).compact!
+import(*rakefiles)
+
+# Setup the project libraries
+%w(lib ext).each {|dir| PROJ.libs << dir if test ?d, dir}
+
+load './tasks/constants.rb'
+load './tasks/helpers.rb'
+
+# EOF
diff --git a/ruby-gem/tasks/spec.rake b/ruby-gem/tasks/spec.rake
new file mode 100644
index 0000000..7345f5c
--- /dev/null
+++ b/ruby-gem/tasks/spec.rake
@@ -0,0 +1,44 @@
+# -*- coding: UTF-8 -*-
+#
+#if HAVE_SPEC_RAKE_SPECTASK and not PROJ.spec.files.to_a.empty?
+require 'rspec/core/rake_task'
+#
+namespace :spec do
+
+ desc 'Run all specs with basic output'
+ RSpec::Core::RakeTask.new(:run) do |t,args|
+ t.ruby_opts = PROJ.ruby_opts
+ t.rspec_opts = PROJ.spec.opts
+ t.pattern = ENV['pattern'] if ENV['pattern']
+ end
+
+ desc 'Run all specs with text output'
+ RSpec::Core::RakeTask.new(:doc) do |t|
+ t.ruby_opts = PROJ.ruby_opts
+ t.rspec_opts = PROJ.spec.opts + ['-fs' ]
+ t.pattern = ENV['pattern'] if ENV['pattern']
+ end
+
+ desc 'Run all specs with html output'
+ RSpec::Core::RakeTask.new(:html) do |t|
+ t.ruby_opts = PROJ.ruby_opts
+ t.rspec_opts = PROJ.spec.opts + ['-fh' ]
+ t.pattern = ENV['pattern'] if ENV['pattern']
+ end
+
+ if HAVE_RCOV
+ desc 'Run all specs with RCov'
+ RSpec::Core::RakeTask.new(:rcov) do |t|
+ t.ruby_opts = PROJ.ruby_opts
+ t.rspec_opts = PROJ.spec.opts
+ t.rcov = true
+ t.rcov_opts = PROJ.rcov.opts + ['--exclude', 'spec']
+ end
+ end
+
+end # namespace :spec
+
+desc 'Alias to spec:run'
+task :spec => 'spec:run'
+
+# EOF
diff --git a/ruby-gem/tasks/svn.rake b/ruby-gem/tasks/svn.rake
new file mode 100644
index 0000000..ae9426e
--- /dev/null
+++ b/ruby-gem/tasks/svn.rake
@@ -0,0 +1,48 @@
+# -*- coding: UTF-8 -*-
+#
+if HAVE_SVN
+
+unless PROJ.svn.root
+ info = %x/svn info ./
+ m = %r/^Repository Root:\s+(.*)$/.match(info)
+ PROJ.svn.root = (m.nil? ? '' : m[1])
+end
+PROJ.svn.root = File.join(PROJ.svn.root, PROJ.svn.path) unless PROJ.svn.path.empty?
+
+namespace :svn do
+
+ # A prerequisites task that all other tasks depend upon
+ task :prereqs
+
+ desc 'Show tags from the SVN repository'
+ task :show_tags => 'svn:prereqs' do |t|
+ tags = %x/svn list #{File.join(PROJ.svn.root, PROJ.svn.tags)}/
+ tags.gsub!(%r/\/$/, '')
+ tags = tags.split("\n").sort {|a,b| b <=> a}
+ puts tags
+ end
+
+ desc 'Create a new tag in the SVN repository'
+ task :create_tag => 'svn:prereqs' do |t|
+ v = ENV['VERSION'] or abort 'Must supply VERSION=x.y.z'
+ abort "Versions don't match #{v} vs #{PROJ.version}" if v != PROJ.version
+
+ svn = PROJ.svn
+ trunk = File.join(svn.root, svn.trunk)
+ tag = "%s-%s" % [PROJ.name, PROJ.version]
+ tag = File.join(svn.root, svn.tags, tag)
+ msg = "Creating tag for #{PROJ.name} version #{PROJ.version}"
+
+ puts "Creating SVN tag '#{tag}'"
+ unless system "svn cp -m '#{msg}' #{trunk} #{tag}"
+ abort "Tag creation failed"
+ end
+ end
+
+end # namespace :svn
+
+task 'gem:release' => 'svn:create_tag'
+
+end # if PROJ.svn.path
+
+# EOF
diff --git a/ruby-gem/tasks/test.rake b/ruby-gem/tasks/test.rake
new file mode 100644
index 0000000..8257613
--- /dev/null
+++ b/ruby-gem/tasks/test.rake
@@ -0,0 +1,41 @@
+# -*- coding: UTF-8 -*-
+#
+if test(?e, PROJ.test.file) or not PROJ.test.files.to_a.empty?
+require 'rake/testtask'
+
+namespace :test do
+
+ Rake::TestTask.new(:run) do |t|
+ t.libs = PROJ.libs
+ t.test_files = if test(?f, PROJ.test.file) then [PROJ.test.file]
+ else PROJ.test.files end
+ t.ruby_opts += PROJ.ruby_opts
+ t.ruby_opts += PROJ.test.opts
+ end
+
+ if HAVE_RCOV
+ desc 'Run rcov on the unit tests'
+ task :rcov => :clobber_rcov do
+ opts = PROJ.rcov.opts.dup << '-o' << PROJ.rcov.dir
+ opts = opts.join(' ')
+ files = if test(?f, PROJ.test.file) then [PROJ.test.file]
+ else PROJ.test.files end
+ files = files.join(' ')
+ sh "#{RCOV} #{files} #{opts}"
+ end
+
+ task :clobber_rcov do
+ rm_r 'coverage' rescue nil
+ end
+ end
+
+end # namespace :test
+
+desc 'Alias to test:run'
+task :test => 'test:run'
+
+task :clobber => 'test:clobber_rcov' if HAVE_RCOV
+
+end
+
+# EOF