Class: Echoe

Class | Echoe
In: | lib/echoe/extensions.rb lib/echoe/platform.rb lib/echoe.rb lib/echoe/extensions.rb lib/echoe/platform.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."
        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.

## 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.
- `spec_pattern` - A filename array, glob array, or regex for test runners.
- `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

apply_pattern apply_pattern define_tasks define_tasks new new silence silence

### Classes and Modules

Module Echoe::Platform

### 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
gem_bin | [RW] | best left alone
gem_bin | [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
spec_pattern | [RW] | user-configurable
spec_pattern | [RW] | user-configurable
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

new(name, _version = nil) {|self if block_given?| ...}

[Source]

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

new(name, _version = nil) {|self if block_given?| ...}

[Source]

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

silence() {|| ...}

[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

silence() {|| ...}

[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

apply_pattern(pattern, files = nil)

[Source]

         # File lib/echoe.rb, line 295
    295:   def apply_pattern(pattern, files = nil)
    296:     files ||= Dir['**/**']
    297:     case pattern
    298:       when String, Array
    299:         files & (Array(pattern).map do |p|
    300:           Dir.glob(p)
    301:         end.flatten)
    302:       when Regexp
    303:         files.select do |file|
    304:           file =~ pattern
    305:         end
    306:       when FileList
    307:         pattern.each do |ignorefile|
    308:           ignorefiles = File.open(ignorefile).to_a.map(&:chomp)
    309:           files = files.select do |file|
    310:             ignorefiles.map { |i| File.fnmatch(i, file) }.include?(true)
    311:           end
    312:         end
    313:         files
    314:       else
    315:         []
    316:     end
    317:   end

apply_pattern(pattern, files = nil)

[Source]

         # File lib/echoe.rb, line 295
    295:   def apply_pattern(pattern, files = nil)
    296:     files ||= Dir['**/**']
    297:     case pattern
    298:       when String, Array
    299:         files & (Array(pattern).map do |p|
    300:           Dir.glob(p)
    301:         end.flatten)
    302:       when Regexp
    303:         files.select do |file|
    304:           file =~ pattern
    305:         end
    306:       when FileList
    307:         pattern.each do |ignorefile|
    308:           ignorefiles = File.open(ignorefile).to_a.map(&:chomp)
    309:           files = files.select do |file|
    310:             ignorefiles.map { |i| File.fnmatch(i, file) }.include?(true)
    311:           end
    312:         end
    313:         files
    314:       else
    315:         []
    316:     end
    317:   end

define_tasks()

[Source]

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

define_tasks()

[Source]

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

[Validate]