Switching to new build system

This commit is contained in:
Michael Granger 2008-09-05 23:39:39 +00:00
parent 4e9e23789b
commit 26c9e33395
7 changed files with 0 additions and 999 deletions

View file

@ -1,353 +0,0 @@
#####################################################################
### G L O B A L H E L P E R F U N C T I O N S
#####################################################################
require 'pathname'
require 'readline'
require 'open3'
# Set some ANSI escape code constants (Shamelessly stolen from Perl's
# Term::ANSIColor by Russ Allbery <rra@stanford.edu> and Zenin <zenin@best.com>
ANSI_ATTRIBUTES = {
'clear' => 0,
'reset' => 0,
'bold' => 1,
'dark' => 2,
'underline' => 4,
'underscore' => 4,
'blink' => 5,
'reverse' => 7,
'concealed' => 8,
'black' => 30, 'on_black' => 40,
'red' => 31, 'on_red' => 41,
'green' => 32, 'on_green' => 42,
'yellow' => 33, 'on_yellow' => 43,
'blue' => 34, 'on_blue' => 44,
'magenta' => 35, 'on_magenta' => 45,
'cyan' => 36, 'on_cyan' => 46,
'white' => 37, 'on_white' => 47
}
CLEAR_TO_EOL = "\e[K"
CLEAR_CURRENT_LINE = "\e[2K"
### Output a logging message
def log( *msg )
output = colorize( msg.flatten.join(' '), 'cyan' )
$deferr.puts( output )
end
### Output a logging message if tracing is on
def trace( *msg )
return unless $trace
output = colorize( msg.flatten.join(' '), 'yellow' )
$deferr.puts( output )
end
### Run the specified command +cmd+ with system(), failing if the execution
### fails.
def run( *cmd )
cmd.flatten!
log( cmd.collect {|part| part =~ /\s/ ? part.inspect : part} )
if $dryrun
$deferr.puts "(dry run mode)"
else
system( *cmd )
unless $?.success?
fail "Command failed: [%s]" % [cmd.join(' ')]
end
end
end
### Open a pipe to a process running the given +cmd+ and call the given block with it.
def pipeto( *cmd )
$DEBUG = true
cmd.flatten!
log( "Opening a pipe to: ", cmd.collect {|part| part =~ /\s/ ? part.inspect : part} )
if $dryrun
$deferr.puts "(dry run mode)"
else
open( '|-', 'w+' ) do |io|
# Parent
if io
yield( io )
# Child
else
exec( *cmd )
fail "Command failed: [%s]" % [cmd.join(' ')]
end
end
end
end
### Download the file at +sourceuri+ via HTTP and write it to +targetfile+.
def download( sourceuri, targetfile )
oldsync = $defout.sync
$defout.sync = true
require 'net/http'
require 'uri'
targetpath = Pathname.new( targetfile )
log "Downloading %s to %s" % [sourceuri, targetfile]
targetpath.open( File::WRONLY|File::TRUNC|File::CREAT, 0644 ) do |ofh|
url = URI.parse( sourceuri )
downloaded = false
limit = 5
until downloaded or limit.zero?
Net::HTTP.start( url.host, url.port ) do |http|
req = Net::HTTP::Get.new( url.path )
http.request( req ) do |res|
if res.is_a?( Net::HTTPSuccess )
log "Downloading..."
res.read_body do |buf|
ofh.print( buf )
end
downloaded = true
puts "done."
elsif res.is_a?( Net::HTTPRedirection )
url = URI.parse( res['location'] )
log "...following redirection to: %s" % [ url ]
limit -= 1
sleep 0.2
next
else
res.error!
end
end
end
end
end
return targetpath
ensure
$defout.sync = oldsync
end
### Return the fully-qualified path to the specified +program+ in the PATH.
def which( program )
ENV['PATH'].split(/:/).
collect {|dir| Pathname.new(dir) + program }.
find {|path| path.exist? && path.executable? }
end
### Create a string that contains the ANSI codes specified and return it
def ansi_code( *attributes )
attributes.flatten!
attributes.collect! {|at| at.to_s }
# $deferr.puts "Returning ansicode for TERM = %p: %p" %
# [ ENV['TERM'], attributes ]
return '' unless /(?:vt10[03]|xterm(?:-color)?|linux|screen)/i =~ ENV['TERM']
attributes = ANSI_ATTRIBUTES.values_at( *attributes ).compact.join(';')
# $deferr.puts " attr is: %p" % [attributes]
if attributes.empty?
return ''
else
return "\e[%sm" % attributes
end
end
### Colorize the given +string+ with the specified +attributes+ and return it, handling
### line-endings, color reset, etc.
def colorize( *args )
string = ''
if block_given?
string = yield
else
string = args.shift
end
ending = string[/(\s)$/] || ''
string = string.rstrip
return ansi_code( args.flatten ) + string + ansi_code( 'reset' ) + ending
end
### Output the specified <tt>msg</tt> as an ANSI-colored error message
### (white on red).
def error_message( msg, details='' )
$deferr.puts colorize( 'bold', 'white', 'on_red' ) { msg } + details
end
alias :error :error_message
### Highlight and embed a prompt control character in the given +string+ and return it.
def make_prompt_string( string )
return CLEAR_CURRENT_LINE + colorize( 'bold', 'green' ) { string + ' ' }
end
### Output the specified <tt>prompt_string</tt> as a prompt (in green) and
### return the user's input with leading and trailing spaces removed. If a
### test is provided, the prompt will repeat until the test returns true.
### An optional failure message can also be passed in.
def prompt( prompt_string, failure_msg="Try again." ) # :yields: response
prompt_string.chomp!
prompt_string << ":" unless /\W$/.match( prompt_string )
response = nil
begin
prompt = make_prompt_string( prompt_string )
response = Readline.readline( prompt ) || ''
response.strip!
if block_given? && ! yield( response )
error_message( failure_msg + "\n\n" )
response = nil
end
end while response.nil?
return response
end
### Prompt the user with the given <tt>prompt_string</tt> via #prompt,
### substituting the given <tt>default</tt> if the user doesn't input
### anything. If a test is provided, the prompt will repeat until the test
### returns true. An optional failure message can also be passed in.
def prompt_with_default( prompt_string, default, failure_msg="Try again." )
response = nil
begin
response = prompt( "%s [%s]" % [ prompt_string, default ] )
response = default if response.empty?
if block_given? && ! yield( response )
error_message( failure_msg + "\n\n" )
response = nil
end
end while response.nil?
return response
end
### Display a description of a potentially-dangerous task, and prompt
### for confirmation. If the user answers with anything that begins
### with 'y', yield to the block, else raise with an error.
def ask_for_confirmation( description )
puts description
answer = prompt_with_default( "Continue?", 'n' ) do |input|
input =~ /^[yn]/i
end
case answer
when /^y/i
yield
else
error "Aborted."
fail
end
end
### Search line-by-line in the specified +file+ for the given +regexp+, returning the
### first match, or nil if no match was found. If the +regexp+ has any capture groups,
### those will be returned in an Array, else the whole matching line is returned.
def find_pattern_in_file( regexp, file )
rval = nil
File.open( file, 'r' ).each do |line|
if (( match = regexp.match(line) ))
rval = match.captures.empty? ? match[0] : match.captures
break
end
end
return rval
end
### Search line-by-line in the output of the specified +cmd+ for the given +regexp+,
### returning the first match, or nil if no match was found. If the +regexp+ has any
### capture groups, those will be returned in an Array, else the whole matching line
### is returned.
def find_pattern_in_pipe( regexp, *cmd )
output = []
Open3.popen3( *cmd ) do |stdin, stdout, stderr|
stdin.close
output << stdout.gets until stdout.eof?
output << stderr.gets until stderr.eof?
end
result = output.find { |line| regexp.match(line) }
return $1 || result
end
### Extract all the non Rake-target arguments from ARGV and return them.
def get_target_args
args = ARGV.reject {|arg| Rake::Task.task_defined?(arg) }
return args
end
require 'rubygems/dependency_installer'
require 'rubygems/source_index'
require 'rubygems/requirement'
require 'rubygems/doc_manager'
### Install the specified +gems+ if they aren't already installed.
def install_gems( *gems )
gems.flatten!
defaults = Gem::DependencyInstaller::DEFAULT_OPTIONS.merge({
:generate_rdoc => true,
:generate_ri => true,
:install_dir => Gem.dir,
:format_executable => false,
:test => false,
:version => Gem::Requirement.default,
})
# Check for root
if Process.euid != 0
$stderr.puts "This probably won't work, as you aren't root, but I'll try anyway"
end
gemindex = Gem::SourceIndex.from_installed_gems
gems.each do |gemname|
if (( specs = gemindex.search(gemname) )) && ! specs.empty?
log "Version %s of %s is already installed; skipping..." %
[ specs.first.version, specs.first.name ]
next
end
log "Trying to install #{gemname.inspect}..."
installer = Gem::DependencyInstaller.new
installer.install( gemname )
installer.installed_gems.each do |spec|
log "Installed: %s" % [ spec.full_name ]
end
end
end

View file

@ -1,32 +0,0 @@
#
# Packaging Rake Tasks
#
#
require 'rake/packagetask'
require 'rake/gempackagetask'
Rake::GemPackageTask.new( GEMSPEC ) do |task|
task.gem_spec = GEMSPEC
task.need_tar = false
task.need_tar_gz = true
task.need_tar_bz2 = true
task.need_zip = true
end
### Task: install
task :install_gem => [:package] do
$stderr.puts
installer = Gem::Installer.new( %{pkg/#{PKG_FILE_NAME}.gem} )
installer.install
end
### Task: uninstall
task :uninstall_gem => [:clean] do
uninstaller = Gem::Uninstaller.new( PKG_FILE_NAME )
uninstaller.uninstall
end

View file

@ -1,36 +0,0 @@
#
# RDoc Rake tasks
# $Id$
#
BEGIN {
require 'pathname'
basedir = Pathname.new( __FILE__ ).dirname.parent
docsdir = basedir + 'docs'
$LOAD_PATH << docsdir.to_s
}
require 'rake/rdoctask'
gem 'darkfish-rdoc', '>= 1.1.0'
require 'darkfish-rdoc'
### Task: rdoc
Rake::RDocTask.new do |rdoc|
rdoc.rdoc_dir = 'docs/api'
rdoc.title = "%s -- %s" % [ GEMSPEC.name, GEMSPEC.summary ]
rdoc.options += [
'-w', '4',
'-SHN',
'-i', BASEDIR.to_s,
'-f', 'darkfish',
'-m', 'README',
'-W', 'http://opensource.laika.com/browser/ruby-ezmlm/trunk/'
]
rdoc.rdoc_files.include 'README'
rdoc.rdoc_files.include LIB_FILES.collect {|f| f.relative_path_from(BASEDIR).to_s }
end

View file

@ -1,59 +0,0 @@
#
# Style Fixup Rake Tasks
#
#
#
### Coding style checks and fixes
namespace :style do
BLANK_LINE = /^\s*$/
GOOD_INDENT = /^(\t\s*)?\S/
# A list of the files that have legitimate leading whitespace, etc.
PROBLEM_FILES = [ SPECDIR + 'config_spec.rb' ]
desc "Check source files for inconsistent indent and fix them"
task :fix_indent do
files = LIB_FILES + SPEC_FILES
badfiles = Hash.new {|h,k| h[k] = [] }
trace "Checking files for indentation"
files.each do |file|
if PROBLEM_FILES.include?( file )
trace " skipping problem file #{file}..."
next
end
trace " #{file}"
linecount = 0
file.each_line do |line|
linecount += 1
# Skip blank lines
next if line =~ BLANK_LINE
# If there's a line with incorrect indent, note it and skip to the
# next file
if line !~ GOOD_INDENT
trace " Bad line %d: %p" % [ linecount, line ]
badfiles[file] << [ linecount, line ]
end
end
end
if badfiles.empty?
log "No indentation problems found."
else
log "Found incorrect indent in #{badfiles.length} files:\n "
badfiles.each do |file, badlines|
log " #{file}:\n" +
" " + badlines.collect {|badline| "%5d: %p" % badline }.join( "\n " )
end
end
end
end

View file

@ -1,328 +0,0 @@
#####################################################################
### S U B V E R S I O N T A S K S A N D H E L P E R S
#####################################################################
require 'pp'
require 'yaml'
require 'English'
# Strftime format for tags/releases
TAG_TIMESTAMP_FORMAT = '%Y%m%d-%H%M%S'
TAG_TIMESTAMP_PATTERN = /\d{4}\d{2}\d{2}-\d{6}/
RELEASE_VERSION_PATTERN = /\d+\.\d+\.\d+/
DEFAULT_EDITOR = 'vi'
DEFAULT_KEYWORDS = %w[Date Rev Author URL Id]
KEYWORDED_FILEDIRS = %w[applets bin etc lib misc]
KEYWORDED_FILEPATTERN = /^(?:Rakefile|.*\.(?:rb|js|html|template))$/i
COMMIT_MSG_FILE = 'commit-msg.txt'
###
### Subversion-specific Helpers
###
### Return a new tag for the given time
def make_new_tag( time=Time.now )
return time.strftime( TAG_TIMESTAMP_FORMAT )
end
### Get the subversion information for the current working directory as
### a hash.
def get_svn_info( dir='.' )
info = IO.read( '|-' ) or exec 'svn', 'info', dir
return YAML.load( info ) # 'svn info' outputs valid YAML! Yay!
end
### Get a list of the objects registered with subversion under the specified directory and
### return them as an Array of Pathame objects.
def get_svn_filelist( dir='.' )
list = IO.read( '|-' ) or exec 'svn', 'st', '-v', '--ignore-externals', dir
# Split into lines, filter out the unknowns, and grab the filenames as Pathnames
# :FIXME: This will break if we ever put in a file with spaces in its name. This
# will likely be the least of our worries if we do so, however, so it's not worth
# the additional complexity to make it handle that case. If we do need that, there's
# always the --xml output for 'svn st'...
return list.split( $/ ).
reject {|line| line =~ /^\?/ }.
collect {|fn| Pathname(fn[/\S+$/]) }
end
### Return the URL to the repository root for the specified +dir+.
def get_svn_repo_root( dir='.' )
info = get_svn_info( dir )
return info['URL'].sub( %r{/trunk$}, '' )
end
### Return the Subversion URL to the given +dir+.
def get_svn_url( dir='.' )
info = get_svn_info( dir )
return info['URL']
end
### Return the path of the specified +dir+ under the svn root of the
### checkout.
def get_svn_path( dir='.' )
root = get_svn_repo_root( dir )
url = get_svn_url( dir )
return url.sub( root + '/', '' )
end
### Return the keywords for the specified array of +files+ as a Hash keyed by filename.
def get_svn_keyword_map( files )
cmd = ['svn', 'pg', 'svn:keywords', *files]
# trace "Executing: svn pg svn:keywords " + files.join(' ')
output = IO.read( '|-' ) or exec( 'svn', 'pg', 'svn:keywords', *files )
kwmap = {}
output.split( "\n" ).each do |line|
next if line !~ /\s+-\s+/
path, keywords = line.split( /\s+-\s+/, 2 )
kwmap[ path ] = keywords.split
end
return kwmap
end
### Return the latest revision number of the specified +dir+ as an Integer.
def get_svn_rev( dir='.' )
info = get_svn_info( dir )
return info['Revision']
end
### Return a list of the entries at the specified Subversion url. If
### no +url+ is specified, it will default to the list in the URL
### corresponding to the current working directory.
def svn_ls( url=nil )
url ||= get_svn_url()
list = IO.read( '|-' ) or exec 'svn', 'ls', url
trace 'svn ls of %s: %p' % [url, list] if $trace
return [] if list.nil? || list.empty?
return list.split( $INPUT_RECORD_SEPARATOR )
end
### Return the URL of the latest timestamp in the tags directory.
def get_latest_svn_timestamp_tag
rooturl = get_svn_repo_root()
tagsurl = rooturl + '/tags'
tags = svn_ls( tagsurl ).grep( TAG_TIMESTAMP_PATTERN ).sort
return nil if tags.nil? || tags.empty?
return tagsurl + '/' + tags.last
end
### Get a subversion diff of the specified targets and return it. If no targets are
### specified, the current directory will be diffed instead.
def get_svn_diff( *targets )
targets << BASEDIR if targets.empty?
trace "Getting svn diff for targets: %p" % [targets]
log = IO.read( '|-' ) or exec 'svn', 'diff', *(targets.flatten)
return log
end
### Return the URL of the latest timestamp in the tags directory.
def get_latest_release_tag
rooturl = get_svn_repo_root()
releaseurl = rooturl + '/releases'
tags = svn_ls( releaseurl ).grep( RELEASE_VERSION_PATTERN ).sort_by do |tag|
tag.split('.').collect {|i| Integer(i) }
end
return nil if tags.empty?
return releaseurl + '/' + tags.last
end
### Extract a diff from the specified subversion working +dir+, rewrite its
### file lines as Trac links, and return it.
def make_svn_commit_log( dir='.' )
editor_prog = ENV['EDITOR'] || ENV['VISUAL'] || DEFAULT_EDITOR
diff = IO.read( '|-' ) or exec 'svn', 'diff'
fail "No differences." if diff.empty?
return diff
end
###
### Tasks
###
desc "Subversion tasks"
namespace :svn do
desc "Copy the HEAD revision of the current trunk/ to tags/ with a " +
"current timestamp."
task :tag do
svninfo = get_svn_info()
tag = make_new_tag()
svntrunk = svninfo['URL']
svntagdir = svninfo['URL'].sub( %r{trunk$}, 'tags' )
svntag = svntagdir + '/' + tag
desc = "Tagging trunk as #{svntag}"
ask_for_confirmation( desc ) do
msg = prompt_with_default( "Commit log: ", "Tagging for code push" )
run 'svn', 'cp', '-m', msg, svntrunk, svntag
end
end
desc "Copy the most recent tag to releases/#{PKG_VERSION}"
task :release do
last_tag = get_latest_svn_timestamp_tag()
svninfo = get_svn_info()
release = PKG_VERSION
svnrel = svninfo['URL'] + '/releases'
svnrelease = svnrel + '/' + release
if last_tag.nil?
error "There are no tags in the repository"
fail
end
releases = svn_ls( svnrel )
trace "Releases: %p" % [releases]
if releases.include?( release )
error "Version #{release} already has a branch (#{svnrelease}). Did you mean" +
"to increment the version in #{PKG_VERSION_FROM}?"
fail
else
trace "No #{svnrel} version currently exists"
end
desc = "Release tag\n #{last_tag}\nto\n #{svnrelease}"
ask_for_confirmation( desc ) do
msg = prompt_with_default( "Commit log: ", "Branching for release" )
run 'svn', 'cp', '-m', msg, last_tag, svnrelease
end
end
### Task for debugging the #get_target_args helper
task :show_targets do
$stdout.puts "Targets from ARGV (%p): %p" % [ARGV, get_target_args()]
end
desc "Generate a commit log"
task :commitlog => [COMMIT_MSG_FILE]
desc "Show the (pre-edited) commit log for the current directory"
task :show_commitlog => [COMMIT_MSG_FILE] do
ask_for_confirmation( "Confirm? " ) do
args = get_target_args()
puts get_svn_diff( *args )
end
end
file COMMIT_MSG_FILE do
args = get_target_args()
diff = get_svn_diff( *args )
File.open( COMMIT_MSG_FILE, File::WRONLY|File::EXCL|File::CREAT ) do |fh|
fh.print( diff )
end
editor = ENV['EDITOR'] || ENV['VISUAL'] || DEFAULT_EDITOR
system editor, COMMIT_MSG_FILE
unless $?.success?
fail "Editor exited uncleanly."
end
end
desc "Update from Subversion"
task :update do
run 'svn', 'up', '--ignore-externals'
end
desc "Check in all the changes in your current working copy"
task :checkin => ['svn:update', 'coverage:verify', 'svn:fix_keywords', COMMIT_MSG_FILE] do
targets = get_target_args()
$deferr.puts '---', File.read( COMMIT_MSG_FILE ), '---'
ask_for_confirmation( "Continue with checkin?" ) do
run 'svn', 'ci', '-F', COMMIT_MSG_FILE, targets
rm_f COMMIT_MSG_FILE
end
end
task :commit => :checkin
task :ci => :checkin
task :clean do
rm_f COMMIT_MSG_FILE
end
desc "Check and fix any missing keywords for any files in the project which need them"
task :fix_keywords do
log "Checking subversion keywords..."
paths = get_svn_filelist( BASEDIR ).
select {|path| path.file? && path.to_s =~ KEYWORDED_FILEPATTERN }
trace "Looking at %d paths for keywords:\n %p" % [paths.length, paths]
kwmap = get_svn_keyword_map( paths )
buf = ''
PP.pp( kwmap, buf, 132 )
trace "keyword map is: %s" % [buf]
files_needing_fixups = paths.find_all do |path|
(kwmap[path.to_s] & DEFAULT_KEYWORDS) != DEFAULT_KEYWORDS
end
unless files_needing_fixups.empty?
$deferr.puts "Files needing keyword fixes: ",
files_needing_fixups.collect {|f|
" %s: %s" % [f, kwmap[f] ? kwmap[f].join(' ') : "(no keywords)"]
}
ask_for_confirmation( "Will add default keywords to these files." ) do
run 'svn', 'ps', 'svn:keywords', DEFAULT_KEYWORDS.join(' '), *files_needing_fixups
end
else
log "Keywords are all up to date."
end
end
task :debug_helpers do
methods = [
:make_new_tag,
:get_svn_info,
:get_svn_repo_root,
:get_svn_url,
:get_svn_path,
:svn_ls,
:get_latest_svn_timestamp_tag,
]
maxlen = methods.collect {|sym| sym.to_s.length }.max
methods.each do |meth|
res = send( meth )
puts "%*s => %p" % [ maxlen, colorize(meth.to_s, :cyan), res ]
end
end
end

View file

@ -1,127 +0,0 @@
#
# Testing Rake Tasks
# $Id$
#
#
# Keep these tasks optional by handling LoadErrors with stub task
# replacements.
begin
gem 'rspec', '>= 1.1.1'
require 'spec/rake/spectask'
COMMON_SPEC_OPTS = ['-c', '-f', 's']
### Task: spec
Spec::Rake::SpecTask.new( :spec ) do |task|
task.spec_files = SPEC_FILES
task.libs += [LIBDIR]
task.spec_opts = COMMON_SPEC_OPTS
end
task :test => [:spec]
namespace :spec do
desc "Generate HTML output for a spec run"
Spec::Rake::SpecTask.new( :html ) do |task|
task.spec_files = SPEC_FILES
task.spec_opts = ['-f','h', '-D']
end
desc "Generate plain-text output for a CruiseControl.rb build"
Spec::Rake::SpecTask.new( :text ) do |task|
task.spec_files = SPEC_FILES
task.spec_opts = ['-f','p']
end
end
rescue LoadError => err
task :no_rspec do
$stderr.puts "Testing tasks not defined: RSpec rake tasklib not available: %s" %
[ err.message ]
end
task :spec => :no_rspec
namespace :spec do
task :autotest => :no_rspec
task :html => :no_rspec
task :text => :no_rspec
end
end
### RCov (via RSpec) tasks
begin
gem 'rcov'
gem 'rspec', '>= 1.1.1'
COVERAGE_TARGETDIR = STATICWWWDIR + 'coverage'
RCOV_OPTS = ['--exclude', SPEC_EXCLUDES, '--xrefs', '--save']
### Task: coverage (via RCov)
### Task: spec
desc "Build test coverage reports"
Spec::Rake::SpecTask.new( :coverage ) do |task|
task.spec_files = SPEC_FILES
task.libs += [LIBDIR]
task.spec_opts = ['-f', 'p', '-b']
task.rcov_opts = RCOV_OPTS
task.rcov = true
end
task :rcov => [:coverage] do; end
### Other coverage tasks
namespace :coverage do
desc "Generate a detailed text coverage report"
Spec::Rake::SpecTask.new( :text ) do |task|
task.spec_files = SPEC_FILES
task.rcov_opts = RCOV_OPTS + ['--text-report']
task.rcov = true
end
desc "Show differences in coverage from last run"
Spec::Rake::SpecTask.new( :diff ) do |task|
task.spec_files = SPEC_FILES
task.rcov_opts = ['--text-coverage-diff']
task.rcov = true
end
### Task: verify coverage
desc "Build coverage statistics"
VerifyTask.new( :verify => :rcov ) do |task|
task.threshold = 85.0
end
desc "Run RCov in 'spec-only' mode to check coverage from specs"
Spec::Rake::SpecTask.new( :speconly ) do |task|
task.spec_files = SPEC_FILES
task.rcov_opts = ['--exclude', SPEC_EXCLUDES, '--text-report', '--save']
task.rcov = true
end
end
task :clobber_coverage do
rmtree( COVERAGE_TARGETDIR )
end
rescue LoadError => err
task :no_rcov do
$stderr.puts "Coverage tasks not defined: RSpec+RCov tasklib not available: %s" %
[ err.message ]
end
task :coverage => :no_rcov
task :clobber_coverage
task :rcov => :no_rcov
namespace :coverage do
task :text => :no_rcov
task :diff => :no_rcov
end
task :verify => :no_rcov
end

View file

@ -1,64 +0,0 @@
#####################################################################
### S U B V E R S I O N T A S K S A N D H E L P E R S
#####################################################################
require 'rake/tasklib'
#
# Work around the inexplicable behaviour of the original RDoc::VerifyTask, which
# errors if your coverage isn't *exactly* the threshold.
#
# A task that can verify that the RCov coverage doesn't
# drop below a certain threshold. It should be run after
# running Spec::Rake::SpecTask.
class VerifyTask < Rake::TaskLib
COVERAGE_PERCENTAGE_PATTERN =
%r{<tt class='coverage_code'>(\d+\.\d+)%</tt>}
# Name of the task. Defaults to :verify_rcov
attr_accessor :name
# Path to the index.html file generated by RCov, which
# is the file containing the total coverage.
# Defaults to 'coverage/index.html'
attr_accessor :index_html
# Whether or not to output details. Defaults to true.
attr_accessor :verbose
# The threshold value (in percent) for coverage. If the
# actual coverage is not equal to this value, the task will raise an
# exception.
attr_accessor :threshold
def initialize( name=:verify )
@name = name
@index_html = 'coverage/index.html'
@verbose = true
yield self if block_given?
raise "Threshold must be set" if @threshold.nil?
define
end
def define
desc "Verify that rcov coverage is at least #{threshold}%"
task @name do
total_coverage = nil
if match = File.read( index_html ).match( COVERAGE_PERCENTAGE_PATTERN )
total_coverage = Float( match[1] )
else
raise "Couldn't find the coverage percentage in #{index_html}"
end
puts "Coverage: #{total_coverage}% (threshold: #{threshold}%)" if verbose
if total_coverage < threshold
raise "Coverage must be at least #{threshold}% but was #{total_coverage}%"
end
end
end
end
# vim: set nosta noet ts=4 sw=4: