parallel_tests 0.8.14 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +5 -6
- data/Gemfile.lock +15 -13
- data/Rakefile +1 -17
- data/Readme.md +5 -1
- data/lib/parallel_tests/cli.rb +15 -5
- data/lib/parallel_tests/grouper.rb +8 -21
- data/lib/parallel_tests/tasks.rb +9 -2
- data/lib/parallel_tests/test/runner.rb +9 -7
- data/lib/parallel_tests/version.rb +1 -1
- data/spec/parallel_tests/grouper_spec.rb +0 -10
- data/spec/parallel_tests/rspec/summary_logger_spec.rb +2 -2
- data/spec/parallel_tests/tasks_spec.rb +2 -2
- data/spec/parallel_tests/test/runner_spec.rb +25 -4
- data/spec/spec_helper.rb +2 -2
- metadata +12 -12
data/Gemfile
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
source :rubygems
|
2
2
|
gemspec
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
end
|
4
|
+
gem 'bump'
|
5
|
+
gem 'test-unit', :platform => :ruby_19
|
6
|
+
gem 'rspec', '>=2.4'
|
7
|
+
gem 'cucumber'
|
8
|
+
gem 'rake'
|
data/Gemfile.lock
CHANGED
@@ -1,33 +1,34 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
parallel_tests (0.
|
4
|
+
parallel_tests (0.9.0)
|
5
5
|
parallel
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: http://rubygems.org/
|
9
9
|
specs:
|
10
10
|
builder (3.0.0)
|
11
|
+
bump (0.3.8)
|
11
12
|
cucumber (1.1.4)
|
12
13
|
builder (>= 2.1.2)
|
13
14
|
diff-lcs (>= 1.1.2)
|
14
15
|
gherkin (~> 2.7.1)
|
15
16
|
json (>= 1.4.6)
|
16
17
|
term-ansicolor (>= 1.0.6)
|
17
|
-
diff-lcs (1.1.
|
18
|
+
diff-lcs (1.1.3)
|
18
19
|
gherkin (2.7.6)
|
19
20
|
json (>= 1.4.6)
|
20
|
-
json (1.
|
21
|
-
parallel (0.
|
22
|
-
rake (0.
|
23
|
-
rspec (2.
|
24
|
-
rspec-core (~> 2.
|
25
|
-
rspec-expectations (~> 2.
|
26
|
-
rspec-mocks (~> 2.
|
27
|
-
rspec-core (2.
|
28
|
-
rspec-expectations (2.
|
29
|
-
diff-lcs (~> 1.1.
|
30
|
-
rspec-mocks (2.
|
21
|
+
json (1.7.5)
|
22
|
+
parallel (0.6.1)
|
23
|
+
rake (10.0.3)
|
24
|
+
rspec (2.12.0)
|
25
|
+
rspec-core (~> 2.12.0)
|
26
|
+
rspec-expectations (~> 2.12.0)
|
27
|
+
rspec-mocks (~> 2.12.0)
|
28
|
+
rspec-core (2.12.2)
|
29
|
+
rspec-expectations (2.12.1)
|
30
|
+
diff-lcs (~> 1.1.3)
|
31
|
+
rspec-mocks (2.12.1)
|
31
32
|
term-ansicolor (1.0.7)
|
32
33
|
test-unit (2.4.4)
|
33
34
|
|
@@ -35,6 +36,7 @@ PLATFORMS
|
|
35
36
|
ruby
|
36
37
|
|
37
38
|
DEPENDENCIES
|
39
|
+
bump
|
38
40
|
cucumber
|
39
41
|
parallel_tests!
|
40
42
|
rake
|
data/Rakefile
CHANGED
@@ -1,22 +1,6 @@
|
|
1
|
+
require 'bump/tasks'
|
1
2
|
require 'bundler/gem_tasks'
|
2
3
|
|
3
4
|
task :default do
|
4
5
|
sh "rspec spec/"
|
5
6
|
end
|
6
|
-
|
7
|
-
# extracted from https://github.com/grosser/project_template
|
8
|
-
rule /^version:bump:.*/ do |t|
|
9
|
-
sh "git status | grep 'nothing to commit'" # ensure we are not dirty
|
10
|
-
index = ['major', 'minor','patch'].index(t.name.split(':').last)
|
11
|
-
file = 'lib/parallel_tests/version.rb'
|
12
|
-
|
13
|
-
version_file = File.read(file)
|
14
|
-
old_version, *version_parts = version_file.match(/(\d+)\.(\d+)\.(\d+)/).to_a
|
15
|
-
version_parts[index] = version_parts[index].to_i + 1
|
16
|
-
version_parts[2] = 0 if index < 2 # remove patch for minor
|
17
|
-
version_parts[1] = 0 if index < 1 # remove minor for major
|
18
|
-
new_version = version_parts * '.'
|
19
|
-
File.open(file,'w'){|f| f.write(version_file.sub(old_version, new_version)) }
|
20
|
-
|
21
|
-
sh "bundle && git add #{file} Gemfile.lock && git commit -m 'bump version to #{new_version}'"
|
22
|
-
end
|
data/Readme.md
CHANGED
@@ -132,7 +132,8 @@ Options are:
|
|
132
132
|
steps - number of cucumber steps
|
133
133
|
default - runtime or filesize
|
134
134
|
-m, --multiply-processes [FLOAT] use given number as a multiplier of processes to run
|
135
|
-
-s, --single [PATTERN] Run all matching files in
|
135
|
+
-s, --single [PATTERN] Run all matching files in the same process
|
136
|
+
-i, --isolate Do not run any other tests in the group used by --single(-s)
|
136
137
|
-e, --exec [COMMAND] execute this code parallel and with ENV['TEST_ENV_NUM']
|
137
138
|
-o, --test-options '[OPTIONS]' execute test commands with those options
|
138
139
|
-t, --type [TYPE] test(default) / rspec / cucumber
|
@@ -176,6 +177,7 @@ TIPS
|
|
176
177
|
|
177
178
|
TODO
|
178
179
|
====
|
180
|
+
- fix tests vs cucumber >= 1.2 `unknown option --format`
|
179
181
|
- add tests for the rake tasks, maybe generate a rails project ...
|
180
182
|
- add unit tests for cucumber runtime formatter
|
181
183
|
- make jRuby compatible [basics](http://yehudakatz.com/2009/07/01/new-rails-isolation-testing/)
|
@@ -222,6 +224,8 @@ inspired by [pivotal labs](http://pivotallabs.com/users/miked/blog/articles/849-
|
|
222
224
|
- [Ulrich Berkmüller](https://github.com/ulrich-berkmueller)
|
223
225
|
- [Grzegorz Derebecki](https://github.com/madmax)
|
224
226
|
- [Florian Motlik](https://github.com/flomotlik)
|
227
|
+
- [Artem Kuzko](https://github.com/akuzko)
|
228
|
+
- [Zeke Fast](https://github.com/zekefast)
|
225
229
|
|
226
230
|
[Michael Grosser](http://grosser.it)<br/>
|
227
231
|
michael@grosser.it<br/>
|
data/lib/parallel_tests/cli.rb
CHANGED
@@ -25,13 +25,13 @@ module ParallelTest
|
|
25
25
|
|
26
26
|
report_time_taken do
|
27
27
|
groups = runner.tests_in_groups(options[:files], num_processes, options)
|
28
|
-
report_number_of_tests
|
28
|
+
report_number_of_tests(runner, groups)
|
29
29
|
|
30
30
|
test_results = Parallel.map(groups, :in_processes => groups.size) do |group|
|
31
31
|
run_tests(runner, group, groups.index(group), options)
|
32
32
|
end
|
33
33
|
|
34
|
-
report_results
|
34
|
+
report_results(runner, test_results)
|
35
35
|
end
|
36
36
|
|
37
37
|
abort final_fail_message(lib) if any_test_failed?(test_results)
|
@@ -89,10 +89,20 @@ group tests by:
|
|
89
89
|
TEXT
|
90
90
|
) { |type| options[:group_by] = type.to_sym }
|
91
91
|
opts.on("-m [FLOAT]", "--multiply-processes [FLOAT]", Float, "use given number as a multiplier of processes to run") { |multiply| options[:multiply] = multiply }
|
92
|
-
|
92
|
+
|
93
|
+
opts.on("-s [PATTERN]", "--single [PATTERN]",
|
94
|
+
"Run all matching files in the same process") do |pattern|
|
95
|
+
|
93
96
|
options[:single_process] ||= []
|
94
97
|
options[:single_process] << /#{pattern}/
|
95
98
|
end
|
99
|
+
|
100
|
+
opts.on("-i", "--isolate",
|
101
|
+
"Do not run any other tests in the group used by --single(-s)") do |pattern|
|
102
|
+
|
103
|
+
options[:isolate] = true
|
104
|
+
end
|
105
|
+
|
96
106
|
opts.on("-e", "--exec [COMMAND]", "execute this code parallel and with ENV['TEST_ENV_NUM']") { |path| options[:execute] = path }
|
97
107
|
opts.on("-o", "--test-options '[OPTIONS]'", "execute test commands with those options") { |arg| options[:test_options] = arg }
|
98
108
|
opts.on("-t", "--type [TYPE]", "test(default) / rspec / cucumber") { |type| options[:type] = type }
|
@@ -131,13 +141,13 @@ TEXT
|
|
131
141
|
def self.report_time_taken
|
132
142
|
start = Time.now
|
133
143
|
yield
|
134
|
-
puts ""
|
135
|
-
puts "Took #{Time.now - start} seconds"
|
144
|
+
puts "\nTook #{Time.now - start} seconds"
|
136
145
|
end
|
137
146
|
|
138
147
|
def self.final_fail_message(lib)
|
139
148
|
fail_message = "#{lib.capitalize}s Failed"
|
140
149
|
fail_message = "\e[31m#{fail_message}\e[0m" if use_colors?
|
150
|
+
|
141
151
|
fail_message
|
142
152
|
end
|
143
153
|
|
@@ -1,32 +1,19 @@
|
|
1
1
|
module ParallelTests
|
2
2
|
class Grouper
|
3
|
-
def self.
|
4
|
-
groups = Array.new(num_groups){ [] }
|
5
|
-
|
6
|
-
until items.empty?
|
7
|
-
num_groups.times do |group_number|
|
8
|
-
if item = items.shift
|
9
|
-
groups[group_number] << item
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
groups.map!(&:sort!)
|
15
|
-
end
|
16
|
-
|
17
|
-
def self.in_even_groups_by_size(items_with_sizes, num_groups, options={})
|
18
|
-
groups = Array.new(num_groups){{:items => [], :size => 0}}
|
3
|
+
def self.in_even_groups_by_size(items_with_sizes, num_groups, options = {})
|
4
|
+
groups = Array.new(num_groups) { {:items => [], :size => 0} }
|
19
5
|
|
20
6
|
# add all files that should run in a single process to one group
|
21
|
-
(options[:single_process]||[]).each do |pattern|
|
22
|
-
matched, items_with_sizes = items_with_sizes.partition{|item, size| item =~ pattern }
|
23
|
-
|
24
|
-
matched.each{|item,size| add_to_group(smallest, item, size) }
|
7
|
+
(options[:single_process] || []).each do |pattern|
|
8
|
+
matched, items_with_sizes = items_with_sizes.partition { |item, size| item =~ pattern }
|
9
|
+
matched.each { |item, size| add_to_group(groups.first, item, size) }
|
25
10
|
end
|
26
11
|
|
12
|
+
groups_to_fill = (options[:isolate] ? groups[1..-1] : groups)
|
13
|
+
|
27
14
|
# add all other files
|
28
15
|
largest_first(items_with_sizes).each do |item, size|
|
29
|
-
smallest = smallest_group(
|
16
|
+
smallest = smallest_group(groups_to_fill)
|
30
17
|
add_to_group(smallest, item, size)
|
31
18
|
end
|
32
19
|
|
data/lib/parallel_tests/tasks.rb
CHANGED
@@ -108,18 +108,25 @@ namespace :parallel do
|
|
108
108
|
|
109
109
|
['test', 'spec', 'features'].each do |type|
|
110
110
|
desc "run #{type} in parallel with parallel:#{type}[num_cpus]"
|
111
|
-
task type, [:count, :pattern, :options] do |t,args|
|
111
|
+
task type, [:count, :pattern, :options] do |t, args|
|
112
112
|
ParallelTests::Tasks.check_for_pending_migrations
|
113
|
+
|
113
114
|
$LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
114
115
|
require "parallel_tests"
|
116
|
+
|
115
117
|
count, pattern, options = ParallelTests::Tasks.parse_args(args)
|
116
118
|
test_framework = {
|
117
119
|
'spec' => 'rspec',
|
118
120
|
'test' => 'test',
|
119
121
|
'features' => 'cucumber'
|
120
122
|
}[type]
|
123
|
+
|
121
124
|
executable = File.join(File.dirname(__FILE__), '..', '..', 'bin', 'parallel_test')
|
122
|
-
command = "#{executable} #{type} --type #{test_framework}
|
125
|
+
command = "#{executable} #{type} --type #{test_framework} " \
|
126
|
+
"-n #{count} " \
|
127
|
+
"--pattern '#{pattern}' " \
|
128
|
+
"--test-options '#{options}'"
|
129
|
+
|
123
130
|
abort unless system(command) # allow to chain tasks e.g. rake parallel:spec parallel:features
|
124
131
|
end
|
125
132
|
end
|
@@ -31,12 +31,12 @@ module ParallelTests
|
|
31
31
|
def self.tests_in_groups(tests, num_groups, options={})
|
32
32
|
tests = find_tests(tests, options)
|
33
33
|
|
34
|
-
if options[:group_by] == :found
|
35
|
-
|
34
|
+
tests = if options[:group_by] == :found
|
35
|
+
tests.map { |t| [t, 1] }
|
36
36
|
else
|
37
|
-
|
38
|
-
Grouper.in_even_groups_by_size(tests, num_groups, options)
|
37
|
+
with_runtime_info(tests)
|
39
38
|
end
|
39
|
+
Grouper.in_even_groups_by_size(tests, num_groups, options)
|
40
40
|
end
|
41
41
|
|
42
42
|
def self.execute_command(cmd, process_number, options)
|
@@ -73,10 +73,11 @@ module ParallelTests
|
|
73
73
|
sum[word] += number.to_i
|
74
74
|
sum
|
75
75
|
end
|
76
|
+
|
76
77
|
sums
|
77
78
|
end
|
78
79
|
|
79
|
-
# read output of the process and print
|
80
|
+
# read output of the process and print it in chunks
|
80
81
|
def self.fetch_output(process)
|
81
82
|
all = ''
|
82
83
|
while buffer = process.readpartial(1000000)
|
@@ -84,6 +85,7 @@ module ParallelTests
|
|
84
85
|
$stdout.print buffer
|
85
86
|
$stdout.flush
|
86
87
|
end rescue EOFError
|
88
|
+
|
87
89
|
all
|
88
90
|
end
|
89
91
|
|
@@ -105,8 +107,8 @@ module ParallelTests
|
|
105
107
|
end
|
106
108
|
end
|
107
109
|
|
108
|
-
def self.find_tests(tests, options={})
|
109
|
-
(tests||[]).map do |file_or_folder|
|
110
|
+
def self.find_tests(tests, options = {})
|
111
|
+
(tests || []).map do |file_or_folder|
|
110
112
|
if File.directory?(file_or_folder)
|
111
113
|
files = files_in_folder(file_or_folder, options)
|
112
114
|
files.grep(/#{Regexp.escape test_suffix}$/).grep(options[:pattern]||//)
|
@@ -49,14 +49,4 @@ describe ParallelTests::Grouper do
|
|
49
49
|
call(6).should == [["5"], ["4"], ["3"], ["2"], ["1"], []]
|
50
50
|
end
|
51
51
|
end
|
52
|
-
|
53
|
-
describe :in_groups do
|
54
|
-
it "groups" do
|
55
|
-
ParallelTests::Grouper.in_groups([1,2,3],2).should == [[1,3],[2]]
|
56
|
-
end
|
57
|
-
|
58
|
-
it "keeps groups sorted" do
|
59
|
-
ParallelTests::Grouper.in_groups([3,2,1],2).should == [[1,3],[2]]
|
60
|
-
end
|
61
|
-
end
|
62
52
|
end
|
@@ -24,7 +24,7 @@ describe ParallelTests::RSpec::SummaryLogger do
|
|
24
24
|
logger.dump_failures
|
25
25
|
output.output.should == []
|
26
26
|
logger.dump_summary(1,2,3,4)
|
27
|
-
output.output.map{|o| decolorize(o) }.should == ["\nFinished in 1
|
27
|
+
output.output.map{|o| decolorize(o) }.should == ["\nFinished in 1 second\n", "2 examples, 3 failures, 4 pending"]
|
28
28
|
end
|
29
29
|
|
30
30
|
it "does not print anything for pending examples" do
|
@@ -32,6 +32,6 @@ describe ParallelTests::RSpec::SummaryLogger do
|
|
32
32
|
logger.dump_failures
|
33
33
|
output.output.should == []
|
34
34
|
logger.dump_summary(1,2,3,4)
|
35
|
-
output.output.map{|o| decolorize(o) }.should == ["\nFinished in 1
|
35
|
+
output.output.map{|o| decolorize(o) }.should == ["\nFinished in 1 second\n", "2 examples, 3 failures, 4 pending"]
|
36
36
|
end
|
37
37
|
end
|
@@ -5,7 +5,7 @@ describe ParallelTests::Tasks do
|
|
5
5
|
describe ".parse_args" do
|
6
6
|
it "should return the count" do
|
7
7
|
args = {:count => 2}
|
8
|
-
ParallelTests::Tasks.parse_args(args).should == [2,
|
8
|
+
ParallelTests::Tasks.parse_args(args).should == [2, "", ""]
|
9
9
|
end
|
10
10
|
|
11
11
|
it "should default to the prefix" do
|
@@ -19,7 +19,7 @@ describe ParallelTests::Tasks do
|
|
19
19
|
end
|
20
20
|
|
21
21
|
it "should return the count, pattern, and options" do
|
22
|
-
args = {:count => 2, :pattern => "plain", :options => "-p default"
|
22
|
+
args = {:count => 2, :pattern => "plain", :options => "-p default"}
|
23
23
|
ParallelTests::Tasks.parse_args(args).should == [2, "plain", "-p default"]
|
24
24
|
end
|
25
25
|
end
|
@@ -38,20 +38,41 @@ describe ParallelTests::Test::Runner do
|
|
38
38
|
|
39
39
|
it "does not sort when passed false do_sort option" do
|
40
40
|
ParallelTests::Test::Runner.should_not_receive(:smallest_first)
|
41
|
-
call
|
41
|
+
call([], 1, :group_by => :found)
|
42
42
|
end
|
43
43
|
|
44
44
|
it "does sort when not passed do_sort option" do
|
45
45
|
ParallelTests::Test::Runner.stub!(:tests_with_runtime).and_return([])
|
46
46
|
ParallelTests::Grouper.should_receive(:largest_first).and_return([])
|
47
|
-
call
|
47
|
+
call([], 1)
|
48
48
|
end
|
49
49
|
|
50
50
|
it "groups by single_process pattern and then via size" do
|
51
|
-
ParallelTests::Test::Runner.should_receive(:with_runtime_info).
|
52
|
-
|
51
|
+
ParallelTests::Test::Runner.should_receive(:with_runtime_info).
|
52
|
+
and_return([
|
53
|
+
['aaa', 5],
|
54
|
+
['aaa2', 5],
|
55
|
+
['bbb', 2],
|
56
|
+
['ccc', 1],
|
57
|
+
['ddd', 1]
|
58
|
+
])
|
59
|
+
result = call([], 3, :single_process => [/^a.a/])
|
53
60
|
result.should == [["aaa", "aaa2"], ["bbb"], ["ccc", "ddd"]]
|
54
61
|
end
|
62
|
+
|
63
|
+
it "groups by size and adds isolated separately" do
|
64
|
+
ParallelTests::Test::Runner.should_receive(:with_runtime_info).
|
65
|
+
and_return([
|
66
|
+
['aaa', 0],
|
67
|
+
['bbb', 3],
|
68
|
+
['ccc', 1],
|
69
|
+
['ddd', 2],
|
70
|
+
['eee', 1]
|
71
|
+
])
|
72
|
+
|
73
|
+
result = call([], 3, :isolate => true, :single_process => [/^aaa/])
|
74
|
+
result.should == [["aaa"], ["bbb", "eee"], ["ccc", "ddd"]]
|
75
|
+
end
|
55
76
|
end
|
56
77
|
|
57
78
|
describe :find_results do
|
data/spec/spec_helper.rb
CHANGED
@@ -135,7 +135,7 @@ def test_tests_in_groups(klass, folder, suffix)
|
|
135
135
|
it "partitions by round-robin when not sorting" do
|
136
136
|
files = ["file1.rb", "file2.rb", "file3.rb", "file4.rb"]
|
137
137
|
klass.should_receive(:find_tests).and_return(files)
|
138
|
-
groups = klass.tests_in_groups(files, 2, :group_by => :found)
|
138
|
+
groups = klass.tests_in_groups(files, 2, :group_by => :found).sort
|
139
139
|
groups[0].should == ["file1.rb", "file3.rb"]
|
140
140
|
groups[1].should == ["file2.rb", "file4.rb"]
|
141
141
|
end
|
@@ -143,7 +143,7 @@ def test_tests_in_groups(klass, folder, suffix)
|
|
143
143
|
it "alpha-sorts partitions when not sorting by runtime" do
|
144
144
|
files = %w[q w e r t y u i o p a s d f g h j k l z x c v b n m]
|
145
145
|
klass.should_receive(:find_tests).and_return(files)
|
146
|
-
groups = klass.tests_in_groups(files, 2, :group_by => :found)
|
146
|
+
groups = klass.tests_in_groups(files, 2, :group_by => :found).sort
|
147
147
|
groups[0].should == groups[0].sort
|
148
148
|
groups[1].should == groups[1].sort
|
149
149
|
end
|
metadata
CHANGED
@@ -1,32 +1,32 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: parallel_tests
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.14
|
5
4
|
prerelease:
|
5
|
+
version: 0.9.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Michael Grosser
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-12-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
-
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
15
|
+
version_requirements: !ruby/object:Gem::Requirement
|
18
16
|
requirements:
|
19
17
|
- - ! '>='
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '0'
|
22
|
-
type: :runtime
|
23
|
-
prerelease: false
|
24
|
-
version_requirements: !ruby/object:Gem::Requirement
|
25
20
|
none: false
|
21
|
+
prerelease: false
|
22
|
+
name: parallel
|
23
|
+
requirement: !ruby/object:Gem::Requirement
|
26
24
|
requirements:
|
27
25
|
- - ! '>='
|
28
26
|
- !ruby/object:Gem::Version
|
29
27
|
version: '0'
|
28
|
+
none: false
|
29
|
+
type: :runtime
|
30
30
|
description:
|
31
31
|
email: michael@grosser.it
|
32
32
|
executables:
|
@@ -84,23 +84,23 @@ rdoc_options: []
|
|
84
84
|
require_paths:
|
85
85
|
- lib
|
86
86
|
required_ruby_version: !ruby/object:Gem::Requirement
|
87
|
-
none: false
|
88
87
|
requirements:
|
89
88
|
- - ! '>='
|
90
89
|
- !ruby/object:Gem::Version
|
91
90
|
version: '0'
|
92
91
|
segments:
|
93
92
|
- 0
|
94
|
-
hash:
|
95
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
|
+
hash: -4090660521181020432
|
96
94
|
none: false
|
95
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
96
|
requirements:
|
98
97
|
- - ! '>='
|
99
98
|
- !ruby/object:Gem::Version
|
100
99
|
version: '0'
|
101
100
|
segments:
|
102
101
|
- 0
|
103
|
-
hash:
|
102
|
+
hash: -4090660521181020432
|
103
|
+
none: false
|
104
104
|
requirements: []
|
105
105
|
rubyforge_project:
|
106
106
|
rubygems_version: 1.8.24
|