metarake 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,20 @@
1
+ *~
2
+ *.gem
3
+ *.rbc
4
+ \#*
5
+ .#*
6
+ .bundle
7
+ .config
8
+ .yardoc
9
+ Gemfile.lock
10
+ InstalledFiles
11
+ _yardoc
12
+ coverage
13
+ doc/
14
+ lib/bundler/man
15
+ pkg
16
+ rdoc
17
+ spec/reports
18
+ test/tmp
19
+ test/version_tmp
20
+ tmp
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.2
5
+ - 1.9.3
6
+ - rbx-18mode
7
+ - rbx-19mode
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in metarake.gemspec
4
+ gemspec
5
+
6
+ group :development do
7
+ gem "pry"
8
+ gem "yard"
9
+ gem "redcarpet"
10
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Maciej Pasternacki
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,46 @@
1
+ # Metarake
2
+
3
+ Metarake is a Rake extension to build multiple separate projects,
4
+ which are published outside the repository.
5
+
6
+ Usually, Metarake's Rakefile lives in the directory that contains
7
+ subdirectories with separate projects, each with their own build
8
+ script (`Rakefile`, `Makefile`, `build.xml`, you name it). What
9
+ metarake does, is:
10
+
11
+ - Discover the projects,
12
+ - Discover their build targets,
13
+ - Verify whether those targets are already published,
14
+ - Build all unpublished targets and publish them.
15
+
16
+ Each of these steps can be customized. A sample custom class is
17
+ provided for building Debian packages and publishing them in an Apt
18
+ repository.
19
+
20
+ ## Installation
21
+
22
+ Add this line to your application's Gemfile:
23
+
24
+ gem 'metarake'
25
+
26
+ And then execute:
27
+
28
+ $ bundle
29
+
30
+ Or install it yourself as:
31
+
32
+ $ gem install metarake
33
+
34
+ ## Usage
35
+
36
+ Sample rakefiles are included in the `examples/` directory, and
37
+ detailed API documentation can be found at
38
+ http://rdoc.info/github/3ofcoins/metarake/.
39
+
40
+ ## Contributing
41
+
42
+ 1. Fork it
43
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
44
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
45
+ 4. Push to the branch (`git push origin my-new-feature`)
46
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require 'cucumber'
5
+ require 'cucumber/rake/task'
6
+
7
+ Cucumber::Rake::Task.new(:features) do |t|
8
+ t.cucumber_opts = "features --format pretty"
9
+ end
10
+
11
+ task :default => :features
@@ -0,0 +1,11 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'metarake'
4
+
5
+ class MetaTask < MetaRake::Task
6
+ include MetaRake::Builder::Rake
7
+ include MetaRake::Publisher::Directory
8
+ self.publish_path = "_published"
9
+ end
10
+
11
+ task :default => MetaTask.discover!
@@ -0,0 +1,67 @@
1
+ Feature: basic features
2
+
3
+ Background:
4
+ Given subdirectories "foo", "bar", "baz"
5
+ And following files:
6
+ | path | source |
7
+ | Rakefile | examples/Rakefile.basic |
8
+ | foo/Rakefile | features/files/Rakefile.one_two_three |
9
+ | bar/Rakefile | features/files/Rakefile.one_two_three |
10
+ | baz/Rakefile | features/files/Rakefile.one_two_three |
11
+
12
+ Scenario: a simple run
13
+ When I run "rake --trace"
14
+ Then the command succeeds
15
+ And following files exist:
16
+ | path | content |
17
+ | foo/one | ONE |
18
+ | foo/two | TWO |
19
+ | foo/three | THREE |
20
+ | bar/one | ONE |
21
+ | bar/two | TWO |
22
+ | bar/three | THREE |
23
+ | baz/one | ONE |
24
+ | baz/two | TWO |
25
+ | baz/three | THREE |
26
+ | _published/foo/one | ONE |
27
+ | _published/foo/two | TWO |
28
+ | _published/foo/three | THREE |
29
+ | _published/bar/one | ONE |
30
+ | _published/bar/two | TWO |
31
+ | _published/bar/three | THREE |
32
+ | _published/baz/one | ONE |
33
+ | _published/baz/two | TWO |
34
+ | _published/baz/three | THREE |
35
+
36
+ Scenario: one of the directories are published
37
+ Given subdirectory "_published"
38
+ And following files:
39
+ | path | content |
40
+ | _published/baz/one | JEDEN |
41
+ | _published/baz/two | DWA |
42
+ | _published/baz/three | TRZY |
43
+ When I run "rake"
44
+ Then the command succeeds
45
+ And following files exist:
46
+ | path | content |
47
+ | foo/one | ONE |
48
+ | foo/two | TWO |
49
+ | foo/three | THREE |
50
+ | bar/one | ONE |
51
+ | bar/two | TWO |
52
+ | bar/three | THREE |
53
+ | _published/foo/one | ONE |
54
+ | _published/foo/two | TWO |
55
+ | _published/foo/three | THREE |
56
+ | _published/bar/one | ONE |
57
+ | _published/bar/two | TWO |
58
+ | _published/bar/three | THREE |
59
+ | _published/baz/one | JEDEN |
60
+ | _published/baz/two | DWA |
61
+ | _published/baz/three | TRZY |
62
+ And following files do not exist:
63
+ | path |
64
+ | baz/one |
65
+ | baz/two |
66
+ | baz/three |
67
+
@@ -0,0 +1,8 @@
1
+ # -*- ruby -*-
2
+
3
+ %w(one two three).each do |tgt|
4
+ desc "Create file '#{tgt}'"
5
+ file tgt do |t|
6
+ File.open(t.to_s, 'w') { |f| f.puts(tgt.upcase) }
7
+ end
8
+ end
@@ -0,0 +1,42 @@
1
+ Given(/^subdirector(?:y|ies) ("[^"]*"(?:, "[^"]*")*)$/) do |subdirectories|
2
+ subdirectories.
3
+ split(/,\s*/).
4
+ map { |sd| sd.gsub(/^"|"$/, '') }.
5
+ each { |sd| FileUtils::mkdir_p(sd) }
6
+ end
7
+
8
+ Given /^following files:$/ do |table|
9
+ table.hashes.each do |ff|
10
+ FileUtils::mkdir_p(File.dirname(ff[:path]))
11
+ if ff[:source]
12
+ FileUtils::cp(File.join(@orig_wd, ff[:source]), ff[:path])
13
+ elsif ff[:content]
14
+ File.open(ff[:path], 'w') { |f| f.puts(ff[:content]) }
15
+ else
16
+ FileUtils::touch(ff[:path])
17
+ end
18
+ end
19
+ end
20
+
21
+ When /^I run "(.*?)"$/ do |command|
22
+ @shellout = Mixlib::ShellOut.new(command)
23
+ @shellout.run_command
24
+ end
25
+
26
+ Then /^the command succeeds$/ do
27
+ @shellout.error!
28
+ end
29
+
30
+ Then /^following files exist:$/ do |table|
31
+ table.hashes.each do |ff|
32
+ File.exist?(ff[:path]).should be true
33
+ File.read(ff[:path]).should include ff[:content] if ff[:content]
34
+ end
35
+ end
36
+
37
+ Then /^following files do not exist:$/ do |table|
38
+ table.hashes.each do |ff|
39
+ File.exist?(ff[:path]).should be false
40
+ end
41
+ end
42
+
@@ -0,0 +1,25 @@
1
+ require 'fileutils'
2
+ require 'tmpdir'
3
+
4
+ require 'rspec/expectations'
5
+ require 'mixlib/shellout'
6
+
7
+
8
+ # Run each test in a temporary directory, initialized as a git repository
9
+ FileUtils::mkdir_p 'tmp'
10
+
11
+ Before do
12
+ @orig_wd = Dir.getwd
13
+ @tmp_wd = Dir.mktmpdir(nil, 'tmp')
14
+ Dir.chdir(@tmp_wd)
15
+ end
16
+
17
+ After do
18
+ Dir::chdir(@orig_wd)
19
+ if ENV['DEBUG']
20
+ puts "Keeping working directory #{@tmp_wd} for debugging"
21
+ else
22
+ FileUtils::rm_rf(@tmp_wd)
23
+ end
24
+ @tmp_wd = nil
25
+ end
@@ -0,0 +1,78 @@
1
+ require 'mixlib/shellout'
2
+
3
+ module MetaRake::Builder::Rake
4
+ extend MetaRake::Magic
5
+
6
+ module ClassMethods
7
+ # Command that should be used to run Rake for projects (default: `'rake'`)
8
+ attr_accessor :rake_command
9
+
10
+ # Filter for discovered target names.
11
+ # @see Metarake::Builder::Rake#project_target?
12
+ attr_accessor :target_filter
13
+
14
+ # Projects are subdirectories that have a Rakefile.
15
+ def projects
16
+ Dir['*/Rakefile'].map { |rakefile| File.dirname(rakefile) }
17
+ end
18
+ end
19
+
20
+ # Create a sub-task for each of project targets.
21
+ def initialize(*args)
22
+ super
23
+
24
+ self.targets.each do |tgt|
25
+ tgt_f = application.define_task(Rake::FileTask, File.join(self.to_s, tgt))
26
+ tgt_f.comment = "Build #{tgt} in #{self}"
27
+ tgt_f.enhance([self])
28
+ end
29
+ end
30
+
31
+ # Decide, whether a target listed by `rake -T` is a project target.
32
+ #
33
+ # Default implementation decides based on
34
+ # {MetaRake::Builder::Rake.target_filter}, based on its
35
+ # type. When target_filter is a:
36
+ #
37
+ # [nil] All targets returned by `rake -T` are project targets (default)
38
+ # [Regex] Targets whose names match the regular expression are
39
+ # project targets
40
+ # [String] Targets whose names include the string are project targets
41
+ # [Proc] It is called with a target name as an argument; if it returns
42
+ # true, the target is a project target.
43
+ def project_target?(target_name)
44
+ case self.class.target_filter
45
+ when nil ; true
46
+ when Regexp ; dir_targets_filter =~ target
47
+ when Proc ; dir_targets_filter.call(target)
48
+ when String ; target.include?(dir_targets_filter)
49
+ end
50
+ end
51
+
52
+ # @return [Array] Project target names, as returned by `rake -T`
53
+ # and filtered by {#project_target?}
54
+ def targets
55
+ @targets ||=
56
+ begin
57
+ cmd = Mixlib::ShellOut.new(rake_command+['-T'], :cwd => self.to_s)
58
+ cmd.run_command.error!
59
+ cmd.stdout.lines.
60
+ map { |ln| tgt=ln.split[1] ; tgt if self.project_target?(tgt) }.
61
+ compact
62
+ end
63
+ end
64
+
65
+ def build
66
+ Dir.chdir(self.to_s) do
67
+ print "[#{self}/] "
68
+ sh *(rake_command+targets)
69
+ end
70
+ end
71
+
72
+ private
73
+ def rake_command
74
+ cmd = self.class.rake_command || 'rake'
75
+ cmd = cmd.split if cmd.respond_to?(:split)
76
+ cmd
77
+ end
78
+ end # MetaRake::Builder::Rake
@@ -0,0 +1,31 @@
1
+ require 'rake/file_utils'
2
+
3
+ module MetaRake::Publisher::Directory
4
+ extend MetaRake::Magic
5
+ include FileUtils
6
+
7
+ module ClassMethods
8
+ # Path, in which the targets are published.
9
+ attr_accessor :publish_path
10
+ end
11
+
12
+ # @return class attribute @publish_path
13
+ # @raises @ValueError if `publish_path` is unset
14
+ def publish_path
15
+ self.class.publish_path or raise ValueError, "#{self.class}.publish_path is not set"
16
+ end
17
+
18
+ # True if all project targets are copied to the publish path
19
+ def published?
20
+ self.targets.map { |tgt| File.exist?(File.join(
21
+ self.publish_path, self.to_s, tgt)) }.all?
22
+ end
23
+
24
+ # Copy all the project targets to the publish path
25
+ def publish!
26
+ mkdir_p File.join(self.publish_path, self.to_s)
27
+ self.targets.each do |tgt|
28
+ install File.join(self.to_s, tgt), File.join(self.publish_path, self.to_s, tgt)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,53 @@
1
+ require 'mixlib/shellout'
2
+
3
+ # Metarake publisher that pushes `.deb` Debian packages to a Freight
4
+ # apt repository (https://github.com/rcrowley/freight).
5
+ module MetaRake::Publisher::Directory
6
+ extend MetaRake::Magic
7
+
8
+ module ClassMethods
9
+ # Path of Freight configuration file
10
+ attr_accessor :freight_conf_path
11
+
12
+ # Distribution to use when publishing to / searching in the Freight repository
13
+ attr_accessor :freight_distro
14
+
15
+ # Command to run Freight (default: "freight")
16
+ attr_accessor :freight_command
17
+
18
+ # @return [Hash] freight config, plus some random shell environment.
19
+ def freight_conf
20
+ @freight_conf ||=
21
+ begin
22
+ raise ValueError, "#{self}.freight_conf_path is not set" unless freight_conf_path
23
+ conf = Mixlib::ShellOut.new('env', '-i', '/bin/sh', '-c', ". #{freight_conf_path} ; set")
24
+ conf.run_command.error!
25
+ Hash[ conf.stdout.lines.map { |ln| ln.strip.split('=', 2) } ]
26
+ end
27
+ end
28
+ end
29
+
30
+ # True if all project targets are added to the repository
31
+ def published?
32
+ raise ValueError, "#{self.class}.freight_distro is not set" unless self.class.freight_distro
33
+ self.targets.map { |tgt| File.exist?(File.join(
34
+ self.class.freight_conf['VARLIB'], self.class.freight_distro, tgt)) }.all?
35
+ end
36
+
37
+ # Add files to the freight repo and publish them
38
+ def publish!
39
+ self.targets.each do |tgt|
40
+ sh *(self.freight_command('add') + [
41
+ File.join(self.to_s, tgt),
42
+ "apt/#{self.class.freight_distro}" ])
43
+ end
44
+ sh *(self.freight_command('cache'))
45
+ end
46
+
47
+ private
48
+ def freight_command(cmd)
49
+ cmd = self.class.freight_command || 'freight'
50
+ cmd = cmd.split if cmd.respond_to?(:split)
51
+ cmd + [ cmd, '-c' self.class.freight_conf_path ]
52
+ end
53
+ end
@@ -0,0 +1,72 @@
1
+ require 'rake/task'
2
+ require 'rake/file_utils'
3
+
4
+ module MetaRake
5
+ # An abstract Rake task that builds a project if it is not
6
+ # published. The individual methods need to be implemented in
7
+ # a subclass. Concrete implementation are provided in
8
+ # {MetaRake::Builder} and {MetaRake::Publisher} modules. Complete
9
+ # sample Rakefiles are included in the {file:examples examples
10
+ # directory}.
11
+ class Task < Rake::Task
12
+ include FileUtils
13
+
14
+ class << self
15
+ # @abstract Discover projects to build.
16
+ # @return [Enumerable] discovered project names
17
+ def projects
18
+ raise NotImplementedError
19
+ end
20
+
21
+ # Discover projects and build tasks for them.
22
+ #
23
+ # @return [Enumerable] tasks defined for each of projects returned by {#projects}
24
+ # @see #projects
25
+ def discover!
26
+ projects.map do |prj|
27
+ t = Rake.application.define_task(self, prj)
28
+ t.comment = "Build #{prj}"
29
+ t
30
+ end
31
+ end
32
+ end
33
+
34
+ # @abstract Check whether the project has been published
35
+ # @return [TrueClass, FalseClass] True if project is already published and doesn't need to be rebuilt.
36
+ def published?
37
+ raise NotImplementedError
38
+ end
39
+
40
+ # @abstract Publishes the project
41
+ # Runs after the project has been built in order to publish the build artifacts.
42
+ def publish!
43
+ raise NotImplementedError
44
+ end
45
+
46
+ # @abstract Array of project's targets
47
+ def targets
48
+ raise NotImplementedError
49
+ end
50
+
51
+ # Automatically add action calling the {#build} method if it's dtefined.
52
+ def initialize(*args)
53
+ super
54
+ @actions << lambda { |t| t.build } if self.respond_to?(:build)
55
+ end
56
+
57
+ # Project is "needed" only if it's not published.
58
+ def needed?
59
+ !self.published?
60
+ end
61
+
62
+ # Publish the project after executing the task.
63
+ def execute(*args)
64
+ super
65
+ if application.options.dryrun
66
+ $stderr.puts "** Publish (dry run) #{name}"
67
+ else
68
+ self.publish!
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,3 @@
1
+ module MetaRake
2
+ VERSION = "0.1.0"
3
+ end
data/lib/metarake.rb ADDED
@@ -0,0 +1,23 @@
1
+ require "metarake/version"
2
+
3
+ # A Rake extension to build multiple separate projects, which are
4
+ # published outside the repository.
5
+ module MetaRake
6
+ # Builder mixin modules for {MetaRake::Task}
7
+ module Builder ; end
8
+
9
+ # Publisher mixin modules for {MetaRake::Task}
10
+ module Publisher ; end
11
+
12
+ # Magic glue to be included in Publisher and Builder classes via extend.
13
+ module Magic
14
+ # Add modules' ClassMethods submodule to the class it's being included in.
15
+ def included(base)
16
+ base.extend(self::ClassMethods) if defined?(self::ClassMethods)
17
+ end
18
+ end
19
+ end
20
+
21
+ require 'metarake/task'
22
+ require 'metarake/builder/rake'
23
+ require 'metarake/publisher/directory'
data/metarake.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/metarake/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Maciej Pasternacki"]
6
+ gem.email = ["maciej@pasternacki.net"]
7
+ gem.description = "A Rake extension to build multiple separate projects, published outside the repository"
8
+ gem.summary = "Rake extension to manage multiple builds"
9
+ gem.homepage = "https://github.com/3ofcoins/metarake/"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "metarake"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = MetaRake::VERSION
17
+
18
+ gem.add_dependency "rake", ">= 0.9.2"
19
+ gem.add_dependency "mixlib-shellout"
20
+
21
+ gem.add_development_dependency "cucumber"
22
+ gem.add_development_dependency 'rspec-expectations'
23
+ end
metadata ADDED
@@ -0,0 +1,139 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: metarake
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Maciej Pasternacki
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-09-23 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 0.9.2
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 0.9.2
30
+ - !ruby/object:Gem::Dependency
31
+ name: mixlib-shellout
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: cucumber
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rspec-expectations
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ description: A Rake extension to build multiple separate projects, published outside
79
+ the repository
80
+ email:
81
+ - maciej@pasternacki.net
82
+ executables: []
83
+ extensions: []
84
+ extra_rdoc_files: []
85
+ files:
86
+ - .gitignore
87
+ - .travis.yml
88
+ - Gemfile
89
+ - LICENSE
90
+ - README.md
91
+ - Rakefile
92
+ - examples/Rakefile.basic
93
+ - features/basic.feature
94
+ - features/files/Rakefile.one_two_three
95
+ - features/step_definitions/basic.rb
96
+ - features/support/env.rb
97
+ - lib/metarake.rb
98
+ - lib/metarake/builder/rake.rb
99
+ - lib/metarake/publisher/directory.rb
100
+ - lib/metarake/publisher/freight.rb
101
+ - lib/metarake/task.rb
102
+ - lib/metarake/version.rb
103
+ - metarake.gemspec
104
+ homepage: https://github.com/3ofcoins/metarake/
105
+ licenses: []
106
+ post_install_message:
107
+ rdoc_options: []
108
+ require_paths:
109
+ - lib
110
+ required_ruby_version: !ruby/object:Gem::Requirement
111
+ none: false
112
+ requirements:
113
+ - - ! '>='
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ segments:
117
+ - 0
118
+ hash: 2320268432724083561
119
+ required_rubygems_version: !ruby/object:Gem::Requirement
120
+ none: false
121
+ requirements:
122
+ - - ! '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ segments:
126
+ - 0
127
+ hash: 2320268432724083561
128
+ requirements: []
129
+ rubyforge_project:
130
+ rubygems_version: 1.8.24
131
+ signing_key:
132
+ specification_version: 3
133
+ summary: Rake extension to manage multiple builds
134
+ test_files:
135
+ - features/basic.feature
136
+ - features/files/Rakefile.one_two_three
137
+ - features/step_definitions/basic.rb
138
+ - features/support/env.rb
139
+ has_rdoc: