Class Echoe
In: lib/echoe/extensions.rb
lib/echoe.rb
lib/echoe/extensions.rb
lib/echoe.rb
Parent: Object

Echoe includes some optional accessors for more advanced gem configuration.

For example, a simple Rakefile might look like this:

  require 'echoe'

  Echoe.new("uncapitalizer") do |p|
    p.author = "Evan Weaver"
    p.summary = "A library that uncapitalizes strings. It's awesome."
    p.url = "http://www.uncapitalizer.com"
    p.docs_host = "uncapitalizer.com:~/www/files/doc/"
    p.runtime_dependencies = ["string_tools >=1.4.0"]
  end

See below for the full list.

Signing gems

Echoe supports signing gems. First, create yourself a public and private key:

  gem cert --build you@yourmail.com

Move them somewhere secret, and add the following environment variables in your .bash_profile or similar:

  export GEM_PRIVATE_KEY='/secret/path/to/gem-private_key.pem'
  export GEM_CERTIFICATE_CHAIN='/secret/path/to/gem-public_cert.pem'

Make sure your environment is up-to-date:

  source ~/.bash_profile

Upload your public_cert.pem file to your website or Rubyforge project, and tell your users to add that certificate to their system via:

  gem cert --add /path/to/public_cert.pem

Finally, package and release your project as normal. Now users can install your gem via:

  sudo gem install gemname -P HighSecurity

Note that you can also set the key and certificate locations in the Rakefile itself. Finally, you can add p.require_signed = true to your Rakefile so that you don‘t accidentally release an unsigned gem if your key is missing.

Metadependencies

Echoe does not force packages to depend on Echoe itself. Instead, it generates a gemspec from your Rakefile and includes that. Downstream repackagers can use the gemspec as-is to build new versions of your gem even without Echoe.

However, Echoe is added to the development_dependencies array so that users can automatically install it via gem install —development if they prefer. You can override this behavior by setting p.development_dependencies = [].

Cross-packaging

Echoe supports platform Rake targets to allow you to cross-package your gems. Just write the spec assuming RUBY_PLATFORM will be what you need it to be for each architecture, and then invoke Rake with the platform name when you‘re cross-packaging.

For example, on JRuby, rake package will build a generic -ruby type gem. But if you want to include a Java-specific extension, you can do one of two things. You can package from within JRuby by checking if RUBY_PLATFORM =~ /java/ and setting p.platform = jruby, or you can run rake java package, which will set RUBY_PLATFORM and p.platform for you.

This way you can run rake java package, rake aix install, or whatever task you need and Echoe will behave just like you‘re packaging from within the target platform.

Test environment setup and teardown

For some applications, you may need to setup and teardown environment state for the entire test suite. This is especially common for integration tests that may need to spawn an external daemon. To support this, you can add a file tests/setup.rb and it will be silently executed before the entire suite runs. Add a similar file tests/teardown.rb in your app to be executed at the end of the entire run.

Note; these files will only get executed if you run the tests via rake. Also, you can set the environment variable VERBOSE=1 to not hide the setup/teardown output.

Accessor options

Descriptive options:

  • author - Your name.
  • email - Your email address.
  • description - A more detailed description of the library.
  • summary - A shorter description of the library.
  • url - A url for the library.
  • install_message - A message to display after the gem is installed.

Versioning options:

  • version - A string for the version number. Parsed from CHANGELOG otherwise.
  • changes - A string describing the most recent changes. Parsed from CHANGELOG otherwise.

Common packaging options:

  • runtime_dependencies - An array of runtime dependencies for this gem. For example, [‘mongrel’, ‘activesupport >= 2.0.2’].
  • development_dependencies - An array of development dependencies for this gem. For example, [‘rake >=0.7.1’].
  • extension_pattern - A filename array, glob array, or regex for extension files that need to be run at install time. Defaults to "ext/**/extconf.rb".

Testing options:

  • clean_pattern - A filename array, glob array, or regex for files that should be removed when rake clean is run.
  • test_pattern - A filename array, glob array, or regex for test runners. Overridden by "test/test_all.rb", if it exists.
  • rcov_options - Any extra flags to pass to RCov when coverage reports are run.

Uncommon packaging options:

  • platform - What platform this gem is for.
  • manifest_name - The name of the manifest file. Defaults to Manifest.
  • need_gem - Whether to generate a gem package. Defaults to true.
  • need_tar_gz - Whether to generate a .tar.gz package. Defaults to true.
  • need_tgz - Whether to generate a .tgz package. Defaults to false.
  • need_zip - Whether to generate a .zip package. Defaults to false.
  • include_rakefile - Include the Rakefile directly within the package. Defaults to true.
  • include_gemspec - Include the generated gemspec file within the package. Defaults to true.
  • ruby_version - Version string for which Ruby to require (for example, ’>= 1.8.4‘.
  • eval - Accepts a proc to be evaluated in the context of the Gem::Specification object. This allows you to set more unusual gemspec options.
  • ignore_pattern - A filename array, glob array, or regex for pathnames that should be ignored when building the manifest.
  • executable_pattern - A filename array, glob array, or regex for files that should be installed as wrapped executables.

Security options:

  • private_key - The path to your gem private key. Defaults to ENV[‘GEM_PRIVATE_KEY’], if available. This accessor is not published in the resulting gemspec.
  • certificate_chain - An array representing your certificate authorization chain. If no one else has signed your certificate, just set it to your own cert. Defaults to ENV[‘GEM_CERTIFICATE_CHAIN’], if available. This accessor is not published in the resulting gemspec.
  • require_signed - Force Echoe to refuse to package your gem if it‘s not properly signed. Default false.

Publishing options:

  • project - The name of the Rubyforge project to upload to. Defaults to the name of the gem.
  • docs_host - A host and filesystem path to publish the documentation to. Defaults to the Rubyforge project.

Documentation options:

  • rdoc_pattern - A filename array, glob array, or regex for filenames that should be passed to RDoc.
  • rdoc_template - A path to an RDoc template. Defaults to the generic template.

Methods

Attributes

author  [RW]  user-configurable
author  [RW]  user-configurable
bin_files  [RW]  best left alone
bin_files  [RW]  best left alone
certificate_chain  [RW]  user-configurable
certificate_chain  [RW]  user-configurable
changelog  [RW]  user-configurable
changelog  [RW]  user-configurable
changelog_patterns  [RW]  best left alone
changelog_patterns  [RW]  best left alone
changes  [RW]  user-configurable
changes  [RW]  user-configurable
clean_pattern  [RW]  user-configurable
clean_pattern  [RW]  user-configurable
dependencies  [RW]  legacy
dependencies  [RW]  legacy
description  [RW]  user-configurable
description  [RW]  user-configurable
development_dependencies  [RW]  user-configurable
development_dependencies  [RW]  user-configurable
docs_host  [RW]  user-configurable
docs_host  [RW]  user-configurable
email  [RW]  user-configurable
email  [RW]  user-configurable
eval  [RW]  best left alone
eval  [RW]  best left alone
executable_pattern  [RW]  user-configurable
executable_pattern  [RW]  user-configurable
extension_pattern  [RW]  user-configurable
extension_pattern  [RW]  user-configurable
extensions  [RW]  legacy
extensions  [RW]  legacy
extra_deps  [RW]  legacy
extra_deps  [RW]  legacy
files  [RW]  best left alone
files  [RW]  best left alone
gemspec_format  [RW]  user-configurable
gemspec_format  [RW]  user-configurable
gemspec_name  [RW]  best left alone
gemspec_name  [RW]  best left alone
has_rdoc  [RW]  best left alone
has_rdoc  [RW]  best left alone
ignore_pattern  [RW]  user-configurable
ignore_pattern  [RW]  user-configurable
include_gemspec  [RW]  best left alone
include_gemspec  [RW]  best left alone
include_rakefile  [RW]  best left alone
include_rakefile  [RW]  best left alone
install_message  [RW]  user-configurable
install_message  [RW]  user-configurable
lib_files  [RW]  best left alone
lib_files  [RW]  best left alone
manifest_name  [RW]  user-configurable
manifest_name  [RW]  user-configurable
name  [RW]  best left alone
name  [RW]  best left alone
need_gem  [RW]  user-configurable
need_gem  [RW]  user-configurable
need_tar_gz  [RW]  user-configurable
need_tar_gz  [RW]  user-configurable
need_tgz  [RW]  user-configurable
need_tgz  [RW]  user-configurable
need_zip  [RW]  user-configurable
need_zip  [RW]  user-configurable
platform  [RW]  user-configurable
platform  [RW]  user-configurable
private_key  [RW]  user-configurable
private_key  [RW]  user-configurable
project  [RW]  user-configurable
project  [RW]  user-configurable
rakefile_name  [RW]  best left alone
rakefile_name  [RW]  best left alone
rcov_options  [RW]  user-configurable
rcov_options  [RW]  user-configurable
rdoc_files  [RW]  legacy
rdoc_files  [RW]  legacy
rdoc_options  [RW]  best left alone
rdoc_options  [RW]  best left alone
rdoc_pattern  [RW]  user-configurable
rdoc_pattern  [RW]  user-configurable
rdoc_template  [RW]  user-configurable
rdoc_template  [RW]  user-configurable
require_signed  [RW]  user-configurable
require_signed  [RW]  user-configurable
retain_gemspec  [RW]  best left alone
retain_gemspec  [RW]  best left alone
ruby_version  [RW]  user-configurable
ruby_version  [RW]  user-configurable
rubyforge_name  [RW]  best left alone
rubyforge_name  [RW]  best left alone
rubygems_version  [RW]  best left alone
rubygems_version  [RW]  best left alone
runtime_dependencies  [RW]  user-configurable
runtime_dependencies  [RW]  user-configurable
spec  [RW]  best left alone
spec  [RW]  best left alone
summary  [RW]  user-configurable
summary  [RW]  user-configurable
test_files  [RW]  best left alone
test_files  [RW]  best left alone
test_pattern  [RW]  user-configurable
test_pattern  [RW]  user-configurable
url  [RW]  user-configurable
url  [RW]  user-configurable
use_sudo  [RW]  best left alone
use_sudo  [RW]  best left alone
version  [RW]  user-configurable
version  [RW]  user-configurable

Public Class methods

[Source]

     # File lib/echoe.rb, line 159
159:   def initialize(name, _version = nil)
160:     # Defaults
161: 
162:     self.name = name
163:     self.project = name.downcase
164:     self.changelog = "CHANGELOG"
165:     self.url = ""
166:     self.author = ""
167:     self.email = ""
168:     self.clean_pattern = ["pkg", "doc", 'build/*', '**/coverage', '**/*.o', '**/*.so', '**/*.a', 'lib/*-*', '**/*.log', "{ext,lib}/*.{bundle,so,obj,pdb,lib,def,exp}", "ext/Makefile", "{ext,lib}/**/*.{bundle,so,obj,pdb,lib,def,exp}", "ext/**/Makefile", "pkg", "*.gem", ".config"]
169:     self.test_pattern = File.exist?("test/test_all.rb") ? "test/test_all.rb" : ['test/**/test_*.rb', 'test/**/*_test.rb']
170:     self.ignore_pattern = /^(pkg|doc)|\.svn|CVS|\.bzr|\.DS|\.git/
171: 
172:     self.changelog_patterns = {
173:         :version => [
174:             /^\s*v([\d\.]+)(\.|\s|$)/,
175:             /\s*\*\s*([\d\.]+)\s*\*\s*$/
176:           ],
177:         :changes => [
178:           /^\s*v([\d\.]+\. .*)/,
179:           /\*\s*[\d\.]+\s*\*\s*(.*)\*\s*[\d\.]+\s*\*$/m
180:         ]
181:       }
182: 
183:     self.description = ""
184:     self.summary = ""
185:     self.install_message = nil
186:     self.executable_pattern = /^bin\//
187:     self.has_rdoc = true
188:     self.use_sudo = RUBY_PLATFORM !~ /mswin32|cygwin/
189:     self.rcov_options = []
190:     self.rdoc_pattern = /^(lib|bin|tasks|ext)|^README|^CHANGELOG|^TODO|^LICENSE|^COPYING$/
191: 
192:     self.gemspec_format = :ruby
193: 
194:     title = (name.downcase == name ? name.capitalize : name)
195:     self.rdoc_options = ['--line-numbers', '--inline-source', '--title', title]
196: 
197:     readme = Dir['*'].detect { |filename| filename =~ /^readme/i }
198:     self.rdoc_options += ['--main', readme] if readme
199: 
200:     self.runtime_dependencies = []
201:     self.development_dependencies = ["echoe"]
202:     self.manifest_name = "Manifest"
203:     self.extension_pattern = ["ext/**/extconf.rb", "ext/extconf.rb"]
204:     self.private_key = ENV['GEM_PRIVATE_KEY']
205:     self.require_signed = false
206:     self.certificate_chain = ENV['GEM_CERTIFICATE_CHAIN'].to_s.split(/\,\s*/).compact
207: 
208:     self.need_gem = true
209:     self.need_tar_gz = true
210:     self.need_tgz = false
211:     self.need_zip = false
212:     self.platform = $platform
213: 
214:     self.include_rakefile = true
215:     self.include_gemspec = true
216:     self.gemspec_name = "#{name}.gemspec"
217:     self.retain_gemspec = false
218:     self.rakefile_name = "Rakefile"
219:     self.rubygems_version = ">= 1.2"
220: 
221:     yield self if block_given?
222: 
223:     # legacy compatibility
224:     self.runtime_dependencies = dependencies if dependencies and runtime_dependencies.empty?
225:     self.runtime_dependencies = extra_deps if extra_deps and runtime_dependencies.empty?
226:     self.project = rubyforge_name if rubyforge_name
227:     self.rdoc_pattern = rdoc_files if rdoc_files
228:     self.extension_pattern = extensions if extensions
229: 
230:     # read manifest
231:     begin
232:       self.files = File.read(manifest_name).split +
233:         [(gemspec_name if include_gemspec)] +
234:         [(rakefile_name if include_rakefile)]
235:       self.files = files.compact.uniq
236:     rescue Errno::ENOENT
237:       unless ARGV.include? "manifest"
238:         puts "Missing manifest. You can build one with 'rake manifest'."
239:         exit 1
240:       else
241:         self.files = []
242:       end
243:     end
244: 
245:     # snag version and changeset
246:     self.version ||= _version
247:     unless version
248:       if File.exist? changelog
249:         parsed = Array(changelog_patterns[:version]).map do |pattern|
250:           open(changelog) do |log|
251:             log.read[pattern, 1]
252:           end
253:         end.compact.first
254:         raise "Could not parse version from #{changelog}" unless parsed
255:         self.version = parsed.chomp(".").strip
256:       else
257:         raise "No #{changelog} found, and no version supplied in Rakefile."
258:       end
259:     end
260: 
261:     self.changes = if File.exist? changelog
262:       Array(changelog_patterns[:changes]).map do |pattern|
263:         open(changelog) do |log|
264:           log.read[pattern, 1]
265:         end
266:       end.compact.first or ""
267:     else
268:       ""
269:     end
270: 
271:     # set some post-defaults
272:     self.certificate_chain = Array(certificate_chain).map {|file| File.expand_path(file)}
273:     self.private_key = File.expand_path(private_key) if private_key
274:     self.description = summary if description.empty?
275:     self.summary = description if summary.empty?
276:     self.clean_pattern = apply_pattern(clean_pattern)
277:     self.extension_pattern = apply_pattern(extension_pattern, files)
278:     self.ignore_pattern = apply_pattern(ignore_pattern)
279:     self.rdoc_pattern = apply_pattern(rdoc_pattern, files) - [manifest_name]
280:     self.executable_pattern = apply_pattern(executable_pattern, files)
281:     self.test_pattern = apply_pattern(test_pattern)
282: 
283:     define_tasks
284:   end

[Source]

     # File lib/echoe.rb, line 159
159:   def initialize(name, _version = nil)
160:     # Defaults
161: 
162:     self.name = name
163:     self.project = name.downcase
164:     self.changelog = "CHANGELOG"
165:     self.url = ""
166:     self.author = ""
167:     self.email = ""
168:     self.clean_pattern = ["pkg", "doc", 'build/*', '**/coverage', '**/*.o', '**/*.so', '**/*.a', 'lib/*-*', '**/*.log', "{ext,lib}/*.{bundle,so,obj,pdb,lib,def,exp}", "ext/Makefile", "{ext,lib}/**/*.{bundle,so,obj,pdb,lib,def,exp}", "ext/**/Makefile", "pkg", "*.gem", ".config"]
169:     self.test_pattern = File.exist?("test/test_all.rb") ? "test/test_all.rb" : ['test/**/test_*.rb', 'test/**/*_test.rb']
170:     self.ignore_pattern = /^(pkg|doc)|\.svn|CVS|\.bzr|\.DS|\.git/
171: 
172:     self.changelog_patterns = {
173:         :version => [
174:             /^\s*v([\d\.]+)(\.|\s|$)/,
175:             /\s*\*\s*([\d\.]+)\s*\*\s*$/
176:           ],
177:         :changes => [
178:           /^\s*v([\d\.]+\. .*)/,
179:           /\*\s*[\d\.]+\s*\*\s*(.*)\*\s*[\d\.]+\s*\*$/m
180:         ]
181:       }
182: 
183:     self.description = ""
184:     self.summary = ""
185:     self.install_message = nil
186:     self.executable_pattern = /^bin\//
187:     self.has_rdoc = true
188:     self.use_sudo = RUBY_PLATFORM !~ /mswin32|cygwin/
189:     self.rcov_options = []
190:     self.rdoc_pattern = /^(lib|bin|tasks|ext)|^README|^CHANGELOG|^TODO|^LICENSE|^COPYING$/
191: 
192:     self.gemspec_format = :ruby
193: 
194:     title = (name.downcase == name ? name.capitalize : name)
195:     self.rdoc_options = ['--line-numbers', '--inline-source', '--title', title]
196: 
197:     readme = Dir['*'].detect { |filename| filename =~ /^readme/i }
198:     self.rdoc_options += ['--main', readme] if readme
199: 
200:     self.runtime_dependencies = []
201:     self.development_dependencies = ["echoe"]
202:     self.manifest_name = "Manifest"
203:     self.extension_pattern = ["ext/**/extconf.rb", "ext/extconf.rb"]
204:     self.private_key = ENV['GEM_PRIVATE_KEY']
205:     self.require_signed = false
206:     self.certificate_chain = ENV['GEM_CERTIFICATE_CHAIN'].to_s.split(/\,\s*/).compact
207: 
208:     self.need_gem = true
209:     self.need_tar_gz = true
210:     self.need_tgz = false
211:     self.need_zip = false
212:     self.platform = $platform
213: 
214:     self.include_rakefile = true
215:     self.include_gemspec = true
216:     self.gemspec_name = "#{name}.gemspec"
217:     self.retain_gemspec = false
218:     self.rakefile_name = "Rakefile"
219:     self.rubygems_version = ">= 1.2"
220: 
221:     yield self if block_given?
222: 
223:     # legacy compatibility
224:     self.runtime_dependencies = dependencies if dependencies and runtime_dependencies.empty?
225:     self.runtime_dependencies = extra_deps if extra_deps and runtime_dependencies.empty?
226:     self.project = rubyforge_name if rubyforge_name
227:     self.rdoc_pattern = rdoc_files if rdoc_files
228:     self.extension_pattern = extensions if extensions
229: 
230:     # read manifest
231:     begin
232:       self.files = File.read(manifest_name).split +
233:         [(gemspec_name if include_gemspec)] +
234:         [(rakefile_name if include_rakefile)]
235:       self.files = files.compact.uniq
236:     rescue Errno::ENOENT
237:       unless ARGV.include? "manifest"
238:         puts "Missing manifest. You can build one with 'rake manifest'."
239:         exit 1
240:       else
241:         self.files = []
242:       end
243:     end
244: 
245:     # snag version and changeset
246:     self.version ||= _version
247:     unless version
248:       if File.exist? changelog
249:         parsed = Array(changelog_patterns[:version]).map do |pattern|
250:           open(changelog) do |log|
251:             log.read[pattern, 1]
252:           end
253:         end.compact.first
254:         raise "Could not parse version from #{changelog}" unless parsed
255:         self.version = parsed.chomp(".").strip
256:       else
257:         raise "No #{changelog} found, and no version supplied in Rakefile."
258:       end
259:     end
260: 
261:     self.changes = if File.exist? changelog
262:       Array(changelog_patterns[:changes]).map do |pattern|
263:         open(changelog) do |log|
264:           log.read[pattern, 1]
265:         end
266:       end.compact.first or ""
267:     else
268:       ""
269:     end
270: 
271:     # set some post-defaults
272:     self.certificate_chain = Array(certificate_chain).map {|file| File.expand_path(file)}
273:     self.private_key = File.expand_path(private_key) if private_key
274:     self.description = summary if description.empty?
275:     self.summary = description if summary.empty?
276:     self.clean_pattern = apply_pattern(clean_pattern)
277:     self.extension_pattern = apply_pattern(extension_pattern, files)
278:     self.ignore_pattern = apply_pattern(ignore_pattern)
279:     self.rdoc_pattern = apply_pattern(rdoc_pattern, files) - [manifest_name]
280:     self.executable_pattern = apply_pattern(executable_pattern, files)
281:     self.test_pattern = apply_pattern(test_pattern)
282: 
283:     define_tasks
284:   end

[Source]

    # File lib/echoe/extensions.rb, line 14
14:   def self.silence
15:     if !ENV['VERBOSE']      
16:       stdout, stderr = $stdout.clone, $stderr.clone
17:       $stdout.reopen(File.new('/tmp/stdout.echoe', 'w'))
18:       $stderr.reopen(File.new('/tmp/stderr.echoe', 'w'))
19:       begin
20:         yield
21:       ensure
22:         $stdout.reopen(stdout)
23:         $stderr.reopen(stderr)
24:       end
25:     else
26:       yield
27:     end
28:   end

[Source]

    # File lib/echoe/extensions.rb, line 14
14:   def self.silence
15:     if !ENV['VERBOSE']      
16:       stdout, stderr = $stdout.clone, $stderr.clone
17:       $stdout.reopen(File.new('/tmp/stdout.echoe', 'w'))
18:       $stderr.reopen(File.new('/tmp/stderr.echoe', 'w'))
19:       begin
20:         yield
21:       ensure
22:         $stdout.reopen(stdout)
23:         $stderr.reopen(stderr)
24:       end
25:     else
26:       yield
27:     end
28:   end

Public Instance methods

[Source]

     # File lib/echoe.rb, line 286
286:   def apply_pattern(pattern, files = nil)
287:     files ||= Dir['**/**']
288:     case pattern
289:       when String, Array
290:         files & (Array(pattern).map do |p|
291:           Dir.glob(p)
292:         end.flatten)
293:       when Regexp
294:         files.select do |file|
295:           file =~ pattern
296:         end
297:       when FileList
298:         pattern.each do |ignorefile|
299:           ignorefiles = File.open(ignorefile).to_a.map(&:chomp)
300:           files = files.select do |file|
301:             ignorefiles.map { |i| File.fnmatch(i, file) }.include?(true)
302:           end
303:         end
304:         files
305:       else
306:         []
307:     end
308:   end

[Source]

     # File lib/echoe.rb, line 286
286:   def apply_pattern(pattern, files = nil)
287:     files ||= Dir['**/**']
288:     case pattern
289:       when String, Array
290:         files & (Array(pattern).map do |p|
291:           Dir.glob(p)
292:         end.flatten)
293:       when Regexp
294:         files.select do |file|
295:           file =~ pattern
296:         end
297:       when FileList
298:         pattern.each do |ignorefile|
299:           ignorefiles = File.open(ignorefile).to_a.map(&:chomp)
300:           files = files.select do |file|
301:             ignorefiles.map { |i| File.fnmatch(i, file) }.include?(true)
302:           end
303:         end
304:         files
305:       else
306:         []
307:     end
308:   end

[Source]

     # File lib/echoe.rb, line 310
310:   def define_tasks
311: 
312:     ### Packaging and Installing
313: 
314:     self.spec = Gem::Specification.new do |s|
315:       s.name = name
316:       s.version = version
317:       # s.specification_version = 3
318:       s.summary = summary
319:       s.author = Array(author).join(", ")
320:       s.email = email
321:       s.homepage = url
322:       s.rubyforge_project = project
323:       s.post_install_message = install_message if install_message
324:       s.description = description
325:       s.required_ruby_version = ruby_version
326:       s.required_rubygems_version = rubygems_version if rubygems_version
327:       s.platform = platform
328:       s.rdoc_options = rdoc_options
329:       s.extra_rdoc_files = rdoc_pattern
330: 
331:       if private_key and File.exist? private_key
332:         s.signing_key = private_key
333:         s.cert_chain = certificate_chain
334:       end
335: 
336:       runtime_dependencies.each do |dep|
337:         dep = dep.split(" ") if dep.is_a? String
338:         s.add_runtime_dependency(*dep)
339:       end
340: 
341:       development_dependencies.each do |dep|
342:         dep = dep.split(" ") if dep.is_a? String
343:         s.add_development_dependency(*dep)
344:       end
345: 
346:       s.files = files
347: 
348:       s.bindir = if executable_pattern.any?
349:         executable_pattern[0].split("/")[0]
350:       else
351:         "bin"
352:       end
353: 
354:       s.executables = executable_pattern.map do |file|
355:         file[(s.bindir.length + 1)..-1]
356:       end
357: 
358:       dirs = Dir['{lib,ext}']
359:       s.extensions = extension_pattern if extension_pattern.any?
360:       s.require_paths = dirs unless dirs.empty?
361:       s.has_rdoc = has_rdoc
362: 
363:       if File.exist? "test/test_all.rb"
364:         s.test_file = "test/test_all.rb"
365:       else
366:         s.test_files = test_pattern
367:       end
368: 
369:       if eval
370:         s.instance_eval &eval
371:       end
372: 
373:     end
374: 
375:     self.lib_files = spec.files.grep(/^lib/)
376:     self.bin_files = spec.files.grep(/^bin/)
377:     self.test_files = spec.files.grep(/^test/)
378: 
379:     Rake::GemPackageTask.new(spec) do |pkg|
380:       pkg.need_tar = @need_tgz
381:       pkg.need_tar_gz = @need_tar_gz
382:       pkg.need_zip = @need_zip
383:     end
384: 
385:     task :build_gemspec do
386:       # Construct the gemspec file, if needed.
387:       if include_gemspec
388:         File.open(gemspec_name, 'w') do |f|          
389:           case gemspec_format
390:           when :yaml
391:             spec.to_yaml.split("\n").each do |line|
392:               # Don't publish any information about the private key or certificate chain
393:               f.puts line unless line =~ /signing_key|cert_chain|\.pem/
394:             end          
395:           when :ruby
396:             f.puts spec.to_ruby
397:           else
398:             raise "Unknown gemspec format #{gemspec_format.inspect}. Supported formats: :ruby and :yaml"
399:           end
400:         end
401:       end
402:     end
403: 
404:     # Chain it to the gemspec task prerequisite
405:     task gemspec_name.to_sym => [:build_gemspec]
406: 
407:     task :package do
408:       # Chain some cleanup tasks to the default :package task.
409:       # Remove the gemfile if it wasn't actually requested.
410:       unless @need_gem
411:         puts "  Gem file not requested. Removed."
412:         system "rm pkg/*.gem"
413:       end
414:       # Remove the generated gemspec once the packaging is done, to discourage people from modifying it by hand.
415:       if include_gemspec and File.exist? gemspec_name and not retain_gemspec
416:         File.delete gemspec_name
417:       end
418: 
419:       # Test signing status
420:       if private_key and File.exist? private_key
421:         puts "Signing gem."
422:       else
423:         raise "Key required, but not found. Maybe you forget to set ENV['GEM_PRIVATE_KEY']?" if require_signed
424:         puts "Private key not found; gem will not be signed."
425:       end
426:       puts "Targeting \"#{platform}\" platform."
427:     end
428: 
429:     desc 'Install the gem'
430:     task :install => [:clean, :package, :uninstall] do
431:       system "#{'sudo' if use_sudo} gem install pkg/*.gem -P MediumSecurity --no-update-sources"
432:     end
433: 
434:     namespace :install do
435:       desc 'Install the gem including development dependencies'
436:       task :development => [:clean, :package, :uninstall] do
437:         system "#{'sudo' if use_sudo} gem install pkg/*.gem -P MediumSecurity --no-update-sources --development"
438:       end
439:     end
440: 
441:     desc 'Uninstall the gem'
442:     task :uninstall do
443:       system "#{'sudo' if use_sudo} gem uninstall #{name} -a -I -x"
444:     end
445: 
446:     desc 'Package and upload the release to Rubyforge'
447:     task :release => [:clean, :package] do |t|
448: 
449:       say "\n"
450:       if agree "Release #{name}-#{version} to Rubyforge? "
451:         pkg = "pkg/#{name}-#{version}"
452:         pkg_gem = pkg + ".gem"
453:         pkg_tar = pkg + ".tgz"
454:         pkg_tar_gz = pkg + ".tar.gz"
455:         pkg_zip = pkg + ".zip"
456: 
457:         rf = RubyForge.new.configure
458:         puts "Logging in"
459:         rf.login
460: 
461:         c = rf.userconfig
462:         c["release_notes"] = description if description
463:         c["release_changes"] = changes if changes
464:         c["preformatted"] = false
465: 
466:         files = [(@need_tgz ? pkg_tar : nil),
467:                   (@need_tar_gz ? pkg_tar_gz : nil),
468:                   (@need_zip ? pkg_zip : nil),
469:                   (@need_gem ? pkg_gem : nil)].compact
470: 
471:         puts "Releasing #{name} v. #{version}"
472:         self.version = self.version.ljust(3)
473: 
474:         rf.add_release project, name, version, *files
475:       end
476: 
477:     end
478: 
479:     ### Extension building
480: 
481:     task :lib do
482:       directory "lib"
483:     end
484: 
485:     if extension_pattern.any?
486: 
487:       desc "Compile the binary extension module"
488:       task :compile => [:lib] do
489:         extension_pattern.each do |extension|
490:           ext_dir = File.dirname(extension)
491:           lib_target = nil
492:           Dir.chdir(ext_dir) do
493:             ruby File.basename(extension)
494:             system(PLATFORM =~ /win32/ ? 'nmake' : 'make')
495:             lib_target = open('Makefile').readlines.grep(/target_prefix = /).first.split('=').last.chomp("\n").strip
496:           end
497:           Dir["#{ext_dir}/*.#{Config::CONFIG['DLEXT']}"].each do |file|
498:             dir = "lib/#{lib_target}/".gsub('//', '/')
499:             mkdir_p dir
500:             cp file, dir
501:           end
502:         end
503:       end
504: 
505:       task :test => [:compile]
506: 
507:     end
508: 
509:     ### Cross-platform targets
510: 
511:     Gem::Specification::PLATFORM_CROSS_TARGETS.each do |target|
512:       task target do
513:         reset_target target
514:       end
515:     end
516: 
517:     ### Documentation
518: 
519:     Rake::RDocTask.new(:docs) do |rd|
520:       # rd.main = Dir['*'].detect {|f| f =~ /^readme/i}
521:       rd.options += Array(rdoc_options)
522: 
523:       rd.rdoc_dir = 'doc'
524:       rd.rdoc_files.push(*rdoc_pattern)
525: 
526:       if rdoc_template
527:         rd.template = rdoc_template
528:       elsif ENV['RDOC_TEMPLATE']
529:         rd.template = ENV['RDOC_TEMPLATE']
530:       end
531:     end
532: 
533:     task :doc => [:redocs]
534: 
535:     desc "Publish documentation to #{docs_host ? "'#{docs_host}'" : "rubyforge"}"
536:     task :publish_docs => [:clean, :docs] do
537: 
538:       local_dir = 'doc'
539:       remote_dir_name = project
540:       remote_dir_name += "/#{name}" if project != name
541: 
542:       unless docs_host
543:         config = YAML.load(File.read(File.expand_path("~/.rubyforge/user-config.yml")))
544:         pub = Rake::SshDirPublisher.new "#{config["username"]}@rubyforge.org",
545:           "/var/www/gforge-projects/#{remote_dir_name}",
546:           local_dir
547:         if project != name then
548:           def pub.upload
549:             begin
550:               super
551:             rescue
552:               # project directory probably doesn't exist, transfer as a whole
553:               cmd = "scp -qr #{local_dir} #{host}:#{remote_dir}"
554:               puts "Uploading: #{cmd}"
555:               system(cmd)
556:             end
557:           end
558:         end
559:         pub.upload
560:       else
561:         # you may need ssh keys configured for this to work
562:         host, dir = docs_host.split(":")
563:         dir.chomp!("/")
564: 
565:         # XXX too dangerous?
566:         cmd = "ssh #{host} 'rm -rf #{dir}/#{remote_dir_name}'"
567:         puts "Deleting existing docs: #{cmd}"
568:         system(cmd)
569: 
570:         cmd = "scp -qr #{local_dir} #{host}:#{dir}/#{remote_dir_name}"
571:         puts "Uploading: #{cmd}"
572:         system(cmd)
573:       end
574:     end
575: 
576:     desc 'Generate a release announcement, edit it, and post it to Rubyforge.'
577:     task :announce do
578: 
579:       filename = "/tmp/#{name}_#{version}_announcement.txt"
580: 
581:       if !File.exist?(filename) or agree "Overwrite existing announcement file? "
582:         File.open(filename, 'w') do |f|
583:           f.write "Subject: #{name.capitalize} #{version}\n\n"
584:           f.write "#{name.capitalize} has been updated to #{version}. #{name.capitalize} is #{summary.uncapitalize}\n\n"
585:           f.write "Changes in this version: #{changes.sub(/^\s*[\w\d\.]+\s+/, '').uncapitalize}\n\n" unless changes.empty?
586:           f.write "More information is available at #{url} .\n\n" unless url.empty?
587:         end
588:       end
589: 
590:       begin
591:         editor = ENV['EDITOR'] || 'nano'
592:         system("#{editor} #{filename}") or raise "Editor '#{editor}' failed to start"
593:         puts File.open(filename).read
594:       end while !agree "Done editing? "
595: 
596:       if agree "Publish announcement to Rubyforge? "
597:         File.open(filename).readlines.detect { |line| line =~ /Subject: (.*)/ }
598:         subject = $1 or raise "Subject line seems to have disappeared"
599: 
600:         body = File.open(filename).readlines.reject { |line| line =~ /Subject: / }.join.gsub("\n\n\n", "\n\n")
601: 
602:         rf = RubyForge.new.configure
603:         rf.login
604:         rf.post_news(project, subject, body)
605:         puts "Published."
606:         File.delete filename
607:       end
608:     end
609: 
610:     ### Clean
611: 
612:     desc 'Clean up auto-generated files'
613:     task :clean do
614:       puts "Cleaning"
615:       clean_pattern.each do |file|
616:         if File.exist?(file)
617:           puts "- #{file}"
618:           rm_rf file
619:         end
620:       end
621:     end
622: 
623:     ### Manifest
624: 
625:     desc "Build a Manifest list"
626:     task :manifest => [:clean] do
627:       puts "Building Manifest"
628:       old_files = files
629:       files = []
630:       Dir['**/**'].each do |file|
631:         next unless file
632:         next if ignore_pattern.include?(file)
633:         next if File.directory?(file)
634:         next if !include_rakefile and file == rakefile_name
635:         files << file
636:       end
637: 
638:       files << rakefile_name if include_rakefile
639:       files << manifest_name
640:       files.uniq!
641: 
642:       File.open(manifest_name, 'w').puts(files)
643: 
644:       (files | old_files).sort.each do |file|
645:         next if file == gemspec_name
646:         sign = " "
647:         if old_files.include?(file) and !files.include?(file)
648:           sign = "-"
649:         elsif files.include?(file) and !old_files.include?(file)
650:           sign = "+"
651:         end
652:         puts "#{sign} #{file}"
653:       end
654:     end
655: 
656:     task :build_manifest => :manifest
657: 
658:     ### Testing
659: 
660:     if test_pattern.any?
661: 
662:       Rake::TestTask.new(:test_inner) do |t|
663:         t.libs = ['lib', 'ext', 'bin', 'test']
664:         t.test_files = test_pattern
665:         t.verbose = true
666:       end
667: 
668:       desc "Run the test suite"
669:       task :test do
670:         if File.exist? 'test/setup.rb'
671:           Echoe.silence do
672:             puts "Setting up test environment"
673:             system("ruby test/setup.rb")
674:           end
675:         end
676:         begin
677:           test = Rake::Task[:test_inner]
678:           if test.respond_to? :already_invoked=
679:             # Method provided by MultiRails
680:             test.already_invoked = false
681:           end
682:           test.invoke
683:         ensure
684:           if File.exist? 'test/teardown.rb'
685:             Echoe.silence do
686:               puts "Tearing down test environment"
687:               system("ruby test/teardown.rb")
688:             end
689:           end
690:         end
691:       end
692: 
693:     end
694: 
695:     task :default => :test
696: 
697:     if defined? Rcov
698:       Rcov::RcovTask.new(:coverage) do |t|
699:         t.test_files = test_pattern
700:         t.rcov_opts << rcov_options if rcov_options
701:         t.verbose = true
702:       end
703:       task :rcov => :coverage
704:     end
705: 
706:   end

[Source]

     # File lib/echoe.rb, line 310
310:   def define_tasks
311: 
312:     ### Packaging and Installing
313: 
314:     self.spec = Gem::Specification.new do |s|
315:       s.name = name
316:       s.version = version
317:       # s.specification_version = 3
318:       s.summary = summary
319:       s.author = Array(author).join(", ")
320:       s.email = email
321:       s.homepage = url
322:       s.rubyforge_project = project
323:       s.post_install_message = install_message if install_message
324:       s.description = description
325:       s.required_ruby_version = ruby_version
326:       s.required_rubygems_version = rubygems_version if rubygems_version
327:       s.platform = platform
328:       s.rdoc_options = rdoc_options
329:       s.extra_rdoc_files = rdoc_pattern
330: 
331:       if private_key and File.exist? private_key
332:         s.signing_key = private_key
333:         s.cert_chain = certificate_chain
334:       end
335: 
336:       runtime_dependencies.each do |dep|
337:         dep = dep.split(" ") if dep.is_a? String
338:         s.add_runtime_dependency(*dep)
339:       end
340: 
341:       development_dependencies.each do |dep|
342:         dep = dep.split(" ") if dep.is_a? String
343:         s.add_development_dependency(*dep)
344:       end
345: 
346:       s.files = files
347: 
348:       s.bindir = if executable_pattern.any?
349:         executable_pattern[0].split("/")[0]
350:       else
351:         "bin"
352:       end
353: 
354:       s.executables = executable_pattern.map do |file|
355:         file[(s.bindir.length + 1)..-1]
356:       end
357: 
358:       dirs = Dir['{lib,ext}']
359:       s.extensions = extension_pattern if extension_pattern.any?
360:       s.require_paths = dirs unless dirs.empty?
361:       s.has_rdoc = has_rdoc
362: 
363:       if File.exist? "test/test_all.rb"
364:         s.test_file = "test/test_all.rb"
365:       else
366:         s.test_files = test_pattern
367:       end
368: 
369:       if eval
370:         s.instance_eval &eval
371:       end
372: 
373:     end
374: 
375:     self.lib_files = spec.files.grep(/^lib/)
376:     self.bin_files = spec.files.grep(/^bin/)
377:     self.test_files = spec.files.grep(/^test/)
378: 
379:     Rake::GemPackageTask.new(spec) do |pkg|
380:       pkg.need_tar = @need_tgz
381:       pkg.need_tar_gz = @need_tar_gz
382:       pkg.need_zip = @need_zip
383:     end
384: 
385:     task :build_gemspec do
386:       # Construct the gemspec file, if needed.
387:       if include_gemspec
388:         File.open(gemspec_name, 'w') do |f|          
389:           case gemspec_format
390:           when :yaml
391:             spec.to_yaml.split("\n").each do |line|
392:               # Don't publish any information about the private key or certificate chain
393:               f.puts line unless line =~ /signing_key|cert_chain|\.pem/
394:             end          
395:           when :ruby
396:             f.puts spec.to_ruby
397:           else
398:             raise "Unknown gemspec format #{gemspec_format.inspect}. Supported formats: :ruby and :yaml"
399:           end
400:         end
401:       end
402:     end
403: 
404:     # Chain it to the gemspec task prerequisite
405:     task gemspec_name.to_sym => [:build_gemspec]
406: 
407:     task :package do
408:       # Chain some cleanup tasks to the default :package task.
409:       # Remove the gemfile if it wasn't actually requested.
410:       unless @need_gem
411:         puts "  Gem file not requested. Removed."
412:         system "rm pkg/*.gem"
413:       end
414:       # Remove the generated gemspec once the packaging is done, to discourage people from modifying it by hand.
415:       if include_gemspec and File.exist? gemspec_name and not retain_gemspec
416:         File.delete gemspec_name
417:       end
418: 
419:       # Test signing status
420:       if private_key and File.exist? private_key
421:         puts "Signing gem."
422:       else
423:         raise "Key required, but not found. Maybe you forget to set ENV['GEM_PRIVATE_KEY']?" if require_signed
424:         puts "Private key not found; gem will not be signed."
425:       end
426:       puts "Targeting \"#{platform}\" platform."
427:     end
428: 
429:     desc 'Install the gem'
430:     task :install => [:clean, :package, :uninstall] do
431:       system "#{'sudo' if use_sudo} gem install pkg/*.gem -P MediumSecurity --no-update-sources"
432:     end
433: 
434:     namespace :install do
435:       desc 'Install the gem including development dependencies'
436:       task :development => [:clean, :package, :uninstall] do
437:         system "#{'sudo' if use_sudo} gem install pkg/*.gem -P MediumSecurity --no-update-sources --development"
438:       end
439:     end
440: 
441:     desc 'Uninstall the gem'
442:     task :uninstall do
443:       system "#{'sudo' if use_sudo} gem uninstall #{name} -a -I -x"
444:     end
445: 
446:     desc 'Package and upload the release to Rubyforge'
447:     task :release => [:clean, :package] do |t|
448: 
449:       say "\n"
450:       if agree "Release #{name}-#{version} to Rubyforge? "
451:         pkg = "pkg/#{name}-#{version}"
452:         pkg_gem = pkg + ".gem"
453:         pkg_tar = pkg + ".tgz"
454:         pkg_tar_gz = pkg + ".tar.gz"
455:         pkg_zip = pkg + ".zip"
456: 
457:         rf = RubyForge.new.configure
458:         puts "Logging in"
459:         rf.login
460: 
461:         c = rf.userconfig
462:         c["release_notes"] = description if description
463:         c["release_changes"] = changes if changes
464:         c["preformatted"] = false
465: 
466:         files = [(@need_tgz ? pkg_tar : nil),
467:                   (@need_tar_gz ? pkg_tar_gz : nil),
468:                   (@need_zip ? pkg_zip : nil),
469:                   (@need_gem ? pkg_gem : nil)].compact
470: 
471:         puts "Releasing #{name} v. #{version}"
472:         self.version = self.version.ljust(3)
473: 
474:         rf.add_release project, name, version, *files
475:       end
476: 
477:     end
478: 
479:     ### Extension building
480: 
481:     task :lib do
482:       directory "lib"
483:     end
484: 
485:     if extension_pattern.any?
486: 
487:       desc "Compile the binary extension module"
488:       task :compile => [:lib] do
489:         extension_pattern.each do |extension|
490:           ext_dir = File.dirname(extension)
491:           lib_target = nil
492:           Dir.chdir(ext_dir) do
493:             ruby File.basename(extension)
494:             system(PLATFORM =~ /win32/ ? 'nmake' : 'make')
495:             lib_target = open('Makefile').readlines.grep(/target_prefix = /).first.split('=').last.chomp("\n").strip
496:           end
497:           Dir["#{ext_dir}/*.#{Config::CONFIG['DLEXT']}"].each do |file|
498:             dir = "lib/#{lib_target}/".gsub('//', '/')
499:             mkdir_p dir
500:             cp file, dir
501:           end
502:         end
503:       end
504: 
505:       task :test => [:compile]
506: 
507:     end
508: 
509:     ### Cross-platform targets
510: 
511:     Gem::Specification::PLATFORM_CROSS_TARGETS.each do |target|
512:       task target do
513:         reset_target target
514:       end
515:     end
516: 
517:     ### Documentation
518: 
519:     Rake::RDocTask.new(:docs) do |rd|
520:       # rd.main = Dir['*'].detect {|f| f =~ /^readme/i}
521:       rd.options += Array(rdoc_options)
522: 
523:       rd.rdoc_dir = 'doc'
524:       rd.rdoc_files.push(*rdoc_pattern)
525: 
526:       if rdoc_template
527:         rd.template = rdoc_template
528:       elsif ENV['RDOC_TEMPLATE']
529:         rd.template = ENV['RDOC_TEMPLATE']
530:       end
531:     end
532: 
533:     task :doc => [:redocs]
534: 
535:     desc "Publish documentation to #{docs_host ? "'#{docs_host}'" : "rubyforge"}"
536:     task :publish_docs => [:clean, :docs] do
537: 
538:       local_dir = 'doc'
539:       remote_dir_name = project
540:       remote_dir_name += "/#{name}" if project != name
541: 
542:       unless docs_host
543:         config = YAML.load(File.read(File.expand_path("~/.rubyforge/user-config.yml")))
544:         pub = Rake::SshDirPublisher.new "#{config["username"]}@rubyforge.org",
545:           "/var/www/gforge-projects/#{remote_dir_name}",
546:           local_dir
547:         if project != name then
548:           def pub.upload
549:             begin
550:               super
551:             rescue
552:               # project directory probably doesn't exist, transfer as a whole
553:               cmd = "scp -qr #{local_dir} #{host}:#{remote_dir}"
554:               puts "Uploading: #{cmd}"
555:               system(cmd)
556:             end
557:           end
558:         end
559:         pub.upload
560:       else
561:         # you may need ssh keys configured for this to work
562:         host, dir = docs_host.split(":")
563:         dir.chomp!("/")
564: 
565:         # XXX too dangerous?
566:         cmd = "ssh #{host} 'rm -rf #{dir}/#{remote_dir_name}'"
567:         puts "Deleting existing docs: #{cmd}"
568:         system(cmd)
569: 
570:         cmd = "scp -qr #{local_dir} #{host}:#{dir}/#{remote_dir_name}"
571:         puts "Uploading: #{cmd}"
572:         system(cmd)
573:       end
574:     end
575: 
576:     desc 'Generate a release announcement, edit it, and post it to Rubyforge.'
577:     task :announce do
578: 
579:       filename = "/tmp/#{name}_#{version}_announcement.txt"
580: 
581:       if !File.exist?(filename) or agree "Overwrite existing announcement file? "
582:         File.open(filename, 'w') do |f|
583:           f.write "Subject: #{name.capitalize} #{version}\n\n"
584:           f.write "#{name.capitalize} has been updated to #{version}. #{name.capitalize} is #{summary.uncapitalize}\n\n"
585:           f.write "Changes in this version: #{changes.sub(/^\s*[\w\d\.]+\s+/, '').uncapitalize}\n\n" unless changes.empty?
586:           f.write "More information is available at #{url} .\n\n" unless url.empty?
587:         end
588:       end
589: 
590:       begin
591:         editor = ENV['EDITOR'] || 'nano'
592:         system("#{editor} #{filename}") or raise "Editor '#{editor}' failed to start"
593:         puts File.open(filename).read
594:       end while !agree "Done editing? "
595: 
596:       if agree "Publish announcement to Rubyforge? "
597:         File.open(filename).readlines.detect { |line| line =~ /Subject: (.*)/ }
598:         subject = $1 or raise "Subject line seems to have disappeared"
599: 
600:         body = File.open(filename).readlines.reject { |line| line =~ /Subject: / }.join.gsub("\n\n\n", "\n\n")
601: 
602:         rf = RubyForge.new.configure
603:         rf.login
604:         rf.post_news(project, subject, body)
605:         puts "Published."
606:         File.delete filename
607:       end
608:     end
609: 
610:     ### Clean
611: 
612:     desc 'Clean up auto-generated files'
613:     task :clean do
614:       puts "Cleaning"
615:       clean_pattern.each do |file|
616:         if File.exist?(file)
617:           puts "- #{file}"
618:           rm_rf file
619:         end
620:       end
621:     end
622: 
623:     ### Manifest
624: 
625:     desc "Build a Manifest list"
626:     task :manifest => [:clean] do
627:       puts "Building Manifest"
628:       old_files = files
629:       files = []
630:       Dir['**/**'].each do |file|
631:         next unless file
632:         next if ignore_pattern.include?(file)
633:         next if File.directory?(file)
634:         next if !include_rakefile and file == rakefile_name
635:         files << file
636:       end
637: 
638:       files << rakefile_name if include_rakefile
639:       files << manifest_name
640:       files.uniq!
641: 
642:       File.open(manifest_name, 'w').puts(files)
643: 
644:       (files | old_files).sort.each do |file|
645:         next if file == gemspec_name
646:         sign = " "
647:         if old_files.include?(file) and !files.include?(file)
648:           sign = "-"
649:         elsif files.include?(file) and !old_files.include?(file)
650:           sign = "+"
651:         end
652:         puts "#{sign} #{file}"
653:       end
654:     end
655: 
656:     task :build_manifest => :manifest
657: 
658:     ### Testing
659: 
660:     if test_pattern.any?
661: 
662:       Rake::TestTask.new(:test_inner) do |t|
663:         t.libs = ['lib', 'ext', 'bin', 'test']
664:         t.test_files = test_pattern
665:         t.verbose = true
666:       end
667: 
668:       desc "Run the test suite"
669:       task :test do
670:         if File.exist? 'test/setup.rb'
671:           Echoe.silence do
672:             puts "Setting up test environment"
673:             system("ruby test/setup.rb")
674:           end
675:         end
676:         begin
677:           test = Rake::Task[:test_inner]
678:           if test.respond_to? :already_invoked=
679:             # Method provided by MultiRails
680:             test.already_invoked = false
681:           end
682:           test.invoke
683:         ensure
684:           if File.exist? 'test/teardown.rb'
685:             Echoe.silence do
686:               puts "Tearing down test environment"
687:               system("ruby test/teardown.rb")
688:             end
689:           end
690:         end
691:       end
692: 
693:     end
694: 
695:     task :default => :test
696: 
697:     if defined? Rcov
698:       Rcov::RcovTask.new(:coverage) do |t|
699:         t.test_files = test_pattern
700:         t.rcov_opts << rcov_options if rcov_options
701:         t.verbose = true
702:       end
703:       task :rcov => :coverage
704:     end
705: 
706:   end

[Validate]