mattock 0.4.1 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/mattock/command-line.rb +16 -69
- data/lib/mattock/command-line/command-run-result.rb +131 -0
- data/lib/mattock/command-task.rb +5 -1
- data/lib/mattock/configurable.rb +8 -546
- data/lib/mattock/configurable/class-methods.rb +208 -0
- data/lib/mattock/configurable/directory-structure.rb +147 -0
- data/lib/mattock/configurable/field-metadata.rb +125 -0
- data/lib/mattock/configurable/field-processor.rb +54 -0
- data/lib/mattock/configurable/instance-methods.rb +75 -0
- data/lib/mattock/configurable/proxy-value.rb +30 -0
- data/lib/mattock/remote-command-task.rb +12 -11
- data/lib/mattock/task.rb +5 -0
- data/lib/mattock/tasklib.rb +22 -2
- data/lib/mattock/template-host.rb +3 -0
- data/lib/mattock/testing/mock-command-line.rb +1 -1
- data/spec/command-line.rb +1 -1
- data/spec/command-task.rb +4 -0
- data/spec/configurable.rb +22 -1
- data/spec/template-host.rb +1 -1
- data/spec_help/spec_helper.rb +7 -0
- metadata +29 -26
@@ -0,0 +1,54 @@
|
|
1
|
+
module Mattock
|
2
|
+
module Configurable
|
3
|
+
class FieldProcessor
|
4
|
+
def initialize(source)
|
5
|
+
@source = source
|
6
|
+
@field_names = filter(source.class.field_names)
|
7
|
+
end
|
8
|
+
attr_accessor :field_names
|
9
|
+
attr_reader :source
|
10
|
+
|
11
|
+
def filter_attribute
|
12
|
+
raise NotImplementedError
|
13
|
+
end
|
14
|
+
|
15
|
+
def filter(field_names)
|
16
|
+
field_names.find_all do |name|
|
17
|
+
source.class.field_metadata(name).is?(filter_attribute)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def value(field)
|
22
|
+
source.__send__(field.reader_method)
|
23
|
+
end
|
24
|
+
|
25
|
+
def to(target)
|
26
|
+
field_names.each do |name|
|
27
|
+
field = source.class.field_metadata(name)
|
28
|
+
next unless target.respond_to?(field.writer_method)
|
29
|
+
target.__send__(field.writer_method, value(field))
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class SettingsCopier < FieldProcessor
|
35
|
+
def filter_attribute
|
36
|
+
:copiable
|
37
|
+
end
|
38
|
+
|
39
|
+
def value(field)
|
40
|
+
field.immediate_value_on(source)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class SettingsProxier < FieldProcessor
|
45
|
+
def filter_attribute
|
46
|
+
:proxiable
|
47
|
+
end
|
48
|
+
|
49
|
+
def value(field)
|
50
|
+
ProxyValue.new(source, field)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Mattock
|
2
|
+
module Configurable
|
3
|
+
def copy_settings
|
4
|
+
SettingsCopier.new(self)
|
5
|
+
end
|
6
|
+
|
7
|
+
def copy_settings_to(other)
|
8
|
+
copy_settings.to(other)
|
9
|
+
self
|
10
|
+
end
|
11
|
+
|
12
|
+
def proxy_settings
|
13
|
+
SettingsProxier.new(self)
|
14
|
+
end
|
15
|
+
|
16
|
+
def proxy_settings_to(other)
|
17
|
+
proxy_settings.to(other)
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_hash
|
21
|
+
self.class.to_hash(self)
|
22
|
+
end
|
23
|
+
|
24
|
+
def unset_defaults_guard
|
25
|
+
raise "Tried to check required settings before running setup_defaults"
|
26
|
+
end
|
27
|
+
|
28
|
+
#Call during initialize to set default values on settings - if you're using
|
29
|
+
#Configurable outside of Mattock, be sure this gets called.
|
30
|
+
def setup_defaults
|
31
|
+
def self.unset_defaults_guard
|
32
|
+
end
|
33
|
+
|
34
|
+
self.class.set_defaults_on(self)
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
#Checks that all required fields have be set, otherwise raises an error
|
39
|
+
#@raise RuntimeError if any required fields are unset
|
40
|
+
def check_required
|
41
|
+
unset_defaults_guard
|
42
|
+
missing = self.class.missing_required_fields_on(self)
|
43
|
+
unless missing.empty?
|
44
|
+
raise "Required field#{missing.length > 1 ? "s" : ""} #{missing.map{|field| field.to_s.inspect}.join(", ")} unset on #{self.inspect}"
|
45
|
+
end
|
46
|
+
self
|
47
|
+
end
|
48
|
+
|
49
|
+
def proxy_value
|
50
|
+
ProxyDecorator.new(self)
|
51
|
+
end
|
52
|
+
|
53
|
+
#XXX deprecate
|
54
|
+
def unset?(value)
|
55
|
+
value.nil?
|
56
|
+
end
|
57
|
+
|
58
|
+
def field_unset?(name)
|
59
|
+
self.class.field_metadata(name).unset_on?(self)
|
60
|
+
end
|
61
|
+
|
62
|
+
#Requires that a named field be set
|
63
|
+
def fail_unless_set(name)
|
64
|
+
if field_unset?(name)
|
65
|
+
raise "Assertion failed: Field #{name} unset"
|
66
|
+
end
|
67
|
+
true
|
68
|
+
end
|
69
|
+
alias fail_if_unset fail_unless_set
|
70
|
+
|
71
|
+
class Struct
|
72
|
+
include Configurable
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Mattock
|
2
|
+
module Configurable
|
3
|
+
class ProxyValue
|
4
|
+
def initialize(source, field)
|
5
|
+
@source, @field = source, field
|
6
|
+
end
|
7
|
+
attr_reader :source, :field
|
8
|
+
|
9
|
+
def inspect
|
10
|
+
"#{self.class.name.split(':').last}: #{source.class.name}.#{field.inspect}"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class ProxyDecorator
|
15
|
+
def initialize(configurable)
|
16
|
+
@configurable = configurable
|
17
|
+
end
|
18
|
+
|
19
|
+
def method_missing(name, *args, &block)
|
20
|
+
unless block.nil? and args.empty?
|
21
|
+
raise NoMethodError, "method `#{name}' not defined with arguments or block when proxied"
|
22
|
+
end
|
23
|
+
unless @configurable.respond_to?(name)
|
24
|
+
raise NoMethodError, "cannot proxy `#{name}' - undefined on #{@configurable}"
|
25
|
+
end
|
26
|
+
return ProxyValue.new(@configurable, @configurable.class.field_metadata(name))
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -2,18 +2,15 @@ require 'mattock/command-task'
|
|
2
2
|
module Mattock
|
3
3
|
module Rake
|
4
4
|
class RemoteCommandTask < CommandTask
|
5
|
-
|
6
|
-
:address
|
7
|
-
:
|
8
|
-
|
5
|
+
setting(:remote_server, nested{
|
6
|
+
setting :address
|
7
|
+
setting :port, 22
|
8
|
+
setting :user, nil
|
9
|
+
})
|
10
|
+
|
9
11
|
setting(:ssh_options, [])
|
12
|
+
setting(:verbose, 0)
|
10
13
|
nil_fields(:id_file, :free_arguments)
|
11
|
-
runtime_setting(:remote_target)
|
12
|
-
|
13
|
-
def resolve_runtime_configuration
|
14
|
-
super
|
15
|
-
self.remote_target ||= [remote_server.user, remote_server.address].compact.join('@') unless remote_server.address.nil?
|
16
|
-
end
|
17
14
|
|
18
15
|
def ssh_option(name, value)
|
19
16
|
ssh_options << "\"#{name}=#{value}\""
|
@@ -26,12 +23,16 @@ module Mattock
|
|
26
23
|
Mattock::WrappingChain.new do |cmd|
|
27
24
|
cmd.add Mattock::CommandLine.new("ssh") do |cmd|
|
28
25
|
cmd.options << "-i #{id_file}" if id_file
|
26
|
+
cmd.options << "-l #{remote_server.user}" unless remote_server.user.nil?
|
27
|
+
cmd.options << remote_server.address
|
28
|
+
cmd.options << "-p #{remote_server.port}" #ok
|
29
|
+
cmd.options << "-n"
|
30
|
+
cmd.options << "-#{'v'*verbose}" if verbose > 0
|
29
31
|
unless ssh_options.empty?
|
30
32
|
ssh_options.each do |opt|
|
31
33
|
cmd.options << "-o #{opt}"
|
32
34
|
end
|
33
35
|
end
|
34
|
-
cmd.options << remote_target
|
35
36
|
end
|
36
37
|
cmd.add Mattock::ShellEscaped.new(command_on_remote)
|
37
38
|
end
|
data/lib/mattock/task.rb
CHANGED
@@ -13,6 +13,7 @@ module Mattock
|
|
13
13
|
include Configurable
|
14
14
|
include CascadingDefinition
|
15
15
|
include DeferredDefinition
|
16
|
+
include Configurable::DirectoryStructure
|
16
17
|
|
17
18
|
module ClassMethods
|
18
19
|
def default_taskname(name)
|
@@ -35,6 +36,9 @@ module Mattock
|
|
35
36
|
task.action(args)
|
36
37
|
end
|
37
38
|
|
39
|
+
#XXX ?? Dilemma: this prevents an existing task action from being
|
40
|
+
#enriched with this one, but not v/v - it also doesn't prevent double
|
41
|
+
#-definition of this task...
|
38
42
|
unless self === task
|
39
43
|
raise "Task already defined for #{task.name} - attempted to redefine with #{self.name}"
|
40
44
|
end
|
@@ -53,6 +57,7 @@ module Mattock
|
|
53
57
|
def self.included(sub)
|
54
58
|
sub.extend ClassMethods
|
55
59
|
Configurable.included(sub)
|
60
|
+
Configurable::DirectoryStructure.included(sub)
|
56
61
|
DeferredDefinition.add_settings(sub)
|
57
62
|
end
|
58
63
|
|
data/lib/mattock/tasklib.rb
CHANGED
@@ -39,6 +39,7 @@ module Mattock
|
|
39
39
|
#configuration options are built using {Configurable}
|
40
40
|
class TaskLib < ::Rake::TaskLib
|
41
41
|
include CascadingDefinition
|
42
|
+
include Configurable::DirectoryStructure
|
42
43
|
|
43
44
|
attr_writer :namespace_name
|
44
45
|
|
@@ -67,8 +68,8 @@ module Mattock
|
|
67
68
|
# task after => name
|
68
69
|
#Which ensures that if "after" is ever invoked,
|
69
70
|
#the execution will be before, name, then after
|
70
|
-
def bracket_task(before, name, after)
|
71
|
-
task self[name] => before
|
71
|
+
def bracket_task(before, name, after, &block)
|
72
|
+
task self[name] => before, &block
|
72
73
|
task after => self[name]
|
73
74
|
end
|
74
75
|
|
@@ -112,6 +113,25 @@ module Mattock
|
|
112
113
|
nil
|
113
114
|
end
|
114
115
|
|
116
|
+
#Default define defines some tasks related to debugging Rakefiles -
|
117
|
+
#subclasses can get these just by remembering to call 'super' in their
|
118
|
+
#define
|
119
|
+
def define
|
120
|
+
debug_settings_task
|
121
|
+
end
|
122
|
+
|
123
|
+
def debug_settings_task
|
124
|
+
in_namespace do
|
125
|
+
task :debug_settings do
|
126
|
+
require 'pp'
|
127
|
+
puts self.class.name
|
128
|
+
pp self.to_hash
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
task :debug_settings => self[:debug_settings]
|
133
|
+
end
|
134
|
+
|
115
135
|
#Wraps a single task in lib's namespace
|
116
136
|
def [](taskname)
|
117
137
|
in_namespace(taskname).first
|
@@ -14,6 +14,7 @@ module Mattock
|
|
14
14
|
public :rel_dir, :default_valise
|
15
15
|
end
|
16
16
|
|
17
|
+
#@deprecated Use {Valise::Set#templates} instead
|
17
18
|
module TemplateHost
|
18
19
|
attr_accessor :valise
|
19
20
|
|
@@ -44,9 +45,11 @@ module Mattock
|
|
44
45
|
end
|
45
46
|
end
|
46
47
|
|
48
|
+
#@deprecated Use {Valise::Set#templates} instead
|
47
49
|
module TemplateTaskLib
|
48
50
|
include TemplateHost
|
49
51
|
|
52
|
+
#@deprecated Use {Valise::Set#templates} instead
|
50
53
|
def template_task(template_source, destination_path, template_options = nil)
|
51
54
|
unless template_options.nil?
|
52
55
|
valise.add_serialization_handler(template_source, :tilt, :template_options => template_options)
|
data/spec/command-line.rb
CHANGED
data/spec/command-task.rb
CHANGED
@@ -27,6 +27,10 @@ describe Mattock::RemoteCommandTask do
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
+
it "should inspect cleanly" do
|
31
|
+
rake["test:run"].inspect.should be_a(String)
|
32
|
+
end
|
33
|
+
|
30
34
|
describe "when verification indicates command should proceed" do
|
31
35
|
it "should run both commands" do
|
32
36
|
expect_command(/should_do/, 1)
|
data/spec/configurable.rb
CHANGED
@@ -6,11 +6,16 @@ describe Mattock::Configurable do
|
|
6
6
|
|
7
7
|
setting(:three, 3)
|
8
8
|
required_field(:four)
|
9
|
+
required_field(:override)
|
9
10
|
end
|
10
11
|
|
11
12
|
class TestStruct < TestSuperStruct
|
12
13
|
settings(:one => 1, :two => nested(:a => "a"){ required_field(:b)} )
|
13
14
|
nil_field(:five)
|
15
|
+
|
16
|
+
def override
|
17
|
+
17
|
18
|
+
end
|
14
19
|
end
|
15
20
|
|
16
21
|
subject do
|
@@ -49,6 +54,11 @@ describe Mattock::Configurable do
|
|
49
54
|
expect do
|
50
55
|
subject.check_required
|
51
56
|
end.to_not raise_error
|
57
|
+
subject.override.should == 17
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should inspect cleanly" do
|
61
|
+
subject.inspect.should be_a(String)
|
52
62
|
end
|
53
63
|
|
54
64
|
describe "with DirectoryStructure" do
|
@@ -66,6 +76,10 @@ describe Mattock::Configurable do
|
|
66
76
|
)
|
67
77
|
)
|
68
78
|
)
|
79
|
+
|
80
|
+
dir(:next_to_me, "rainbow", dir(:in_there, "a_place", path(:nearby, "a.file")))
|
81
|
+
|
82
|
+
path(:loose_path, "here")
|
69
83
|
end
|
70
84
|
|
71
85
|
def subject
|
@@ -80,6 +94,10 @@ describe Mattock::Configurable do
|
|
80
94
|
end.to raise_error /Required field/
|
81
95
|
end
|
82
96
|
|
97
|
+
it "should inspect cleanly" do
|
98
|
+
subject.inspect.should be_a(String)
|
99
|
+
end
|
100
|
+
|
83
101
|
describe "with root path configured, but missing a relative path" do
|
84
102
|
def subject
|
85
103
|
DirectoryThing.new.tap do |thing|
|
@@ -112,6 +130,9 @@ describe Mattock::Configurable do
|
|
112
130
|
end.not_to raise_error
|
113
131
|
end
|
114
132
|
|
133
|
+
its("nearby.absolute_path"){ should =~ %r"rainbow/a_place/a.file$"}
|
134
|
+
its("nearby.absolute_path"){ should =~ %r"^#{subject.absolute_path}"}
|
135
|
+
|
115
136
|
its("certificate_file.absolute_path"){ should == "/tmp/bundle_workdir/aws-creds/cert.pem" }
|
116
137
|
its("bundle_manifest.absolute_path"){ should == "/tmp/bundle_workdir/image.manifest.xml" }
|
117
138
|
its("credentials_dir.absolute_path"){ should == "/tmp/bundle_workdir/aws-creds" }
|
@@ -184,7 +205,7 @@ describe Mattock::Configurable do
|
|
184
205
|
end
|
185
206
|
|
186
207
|
it "should not copy no_copy" do
|
187
|
-
left.
|
208
|
+
left.copy_settings_to(right)
|
188
209
|
right.unset?(right.normal).should be_false
|
189
210
|
right.normal.should == 1
|
190
211
|
right.unset?(right.no_copy).should be_true
|
data/spec/template-host.rb
CHANGED
@@ -9,7 +9,7 @@ describe Mattock::TemplateHost do
|
|
9
9
|
end
|
10
10
|
|
11
11
|
it "should handle relative paths nicely" do
|
12
|
-
Mattock::ValiseManager.rel_dir(__FILE__, "spec").should =~ /.*spec$/
|
12
|
+
Mattock::ValiseManager.rel_dir(__FILE__, "spec").to_s.should =~ /.*spec$/
|
13
13
|
end
|
14
14
|
|
15
15
|
it "should be able to do easy templating" do
|
data/spec_help/spec_helper.rb
CHANGED
@@ -1,2 +1,9 @@
|
|
1
1
|
require 'rspec'
|
2
2
|
require 'file-sandbox'
|
3
|
+
require 'cadre/rspec'
|
4
|
+
|
5
|
+
RSpec.configure do |config|
|
6
|
+
config.run_all_when_everything_filtered = true
|
7
|
+
config.add_formatter(Cadre::RSpec::NotifyOnCompleteFormatter)
|
8
|
+
config.add_formatter(Cadre::RSpec::QuickfixFormatter)
|
9
|
+
end
|
metadata
CHANGED
@@ -1,68 +1,64 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mattock
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.1
|
5
4
|
prerelease:
|
5
|
+
version: 0.5.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Judson Lester
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-10-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
+
prerelease: false
|
16
|
+
type: :development
|
15
17
|
name: corundum
|
16
|
-
|
17
|
-
none: false
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
18
19
|
requirements:
|
19
20
|
- - ~>
|
20
21
|
- !ruby/object:Gem::Version
|
21
22
|
version: 0.0.1
|
22
|
-
type: :development
|
23
|
-
prerelease: false
|
24
|
-
version_requirements: !ruby/object:Gem::Requirement
|
25
23
|
none: false
|
24
|
+
requirement: !ruby/object:Gem::Requirement
|
26
25
|
requirements:
|
27
26
|
- - ~>
|
28
27
|
- !ruby/object:Gem::Version
|
29
28
|
version: 0.0.1
|
29
|
+
none: false
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
|
+
prerelease: false
|
32
|
+
type: :runtime
|
31
33
|
name: valise
|
32
|
-
|
33
|
-
none: false
|
34
|
+
version_requirements: !ruby/object:Gem::Requirement
|
34
35
|
requirements:
|
35
36
|
- - ! '>='
|
36
37
|
- !ruby/object:Gem::Version
|
37
38
|
version: 0.9.1
|
38
|
-
type: :runtime
|
39
|
-
prerelease: false
|
40
|
-
version_requirements: !ruby/object:Gem::Requirement
|
41
39
|
none: false
|
40
|
+
requirement: !ruby/object:Gem::Requirement
|
42
41
|
requirements:
|
43
42
|
- - ! '>='
|
44
43
|
- !ruby/object:Gem::Version
|
45
44
|
version: 0.9.1
|
45
|
+
none: false
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
|
+
prerelease: false
|
48
|
+
type: :runtime
|
47
49
|
name: tilt
|
48
|
-
|
49
|
-
none: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
51
|
requirements:
|
51
52
|
- - ! '>'
|
52
53
|
- !ruby/object:Gem::Version
|
53
54
|
version: '0'
|
54
|
-
segments:
|
55
|
-
- 0
|
56
|
-
type: :runtime
|
57
|
-
prerelease: false
|
58
|
-
version_requirements: !ruby/object:Gem::Requirement
|
59
55
|
none: false
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
60
57
|
requirements:
|
61
58
|
- - ! '>'
|
62
59
|
- !ruby/object:Gem::Version
|
63
60
|
version: '0'
|
64
|
-
|
65
|
-
- 0
|
61
|
+
none: false
|
66
62
|
description: ! " If Rake won't do it by itself, you oughtta Mattock.\n\n If you
|
67
63
|
survived the pun, you might enjoy this gem.\n\n Features:\n\n * Extensions to
|
68
64
|
Tasklibs to support powerful deerpaths.\n * A commandline library that supports
|
@@ -82,6 +78,7 @@ files:
|
|
82
78
|
- yard_templates/default/layout/html/setup.rb
|
83
79
|
- yard_templates/default/layout/html/tasklib_list.erb
|
84
80
|
- lib/mattock/command-line.rb
|
81
|
+
- lib/mattock/command-line/command-run-result.rb
|
85
82
|
- lib/mattock/command-task.rb
|
86
83
|
- lib/mattock/testing/rake-example-group.rb
|
87
84
|
- lib/mattock/testing/mock-command-line.rb
|
@@ -93,6 +90,12 @@ files:
|
|
93
90
|
- lib/mattock/tasklib.rb
|
94
91
|
- lib/mattock/task.rb
|
95
92
|
- lib/mattock/configurable.rb
|
93
|
+
- lib/mattock/configurable/field-processor.rb
|
94
|
+
- lib/mattock/configurable/proxy-value.rb
|
95
|
+
- lib/mattock/configurable/instance-methods.rb
|
96
|
+
- lib/mattock/configurable/class-methods.rb
|
97
|
+
- lib/mattock/configurable/directory-structure.rb
|
98
|
+
- lib/mattock/configurable/field-metadata.rb
|
96
99
|
- lib/mattock/configuration-store.rb
|
97
100
|
- lib/mattock/cascading-definition.rb
|
98
101
|
- lib/mattock.rb
|
@@ -116,24 +119,24 @@ rdoc_options:
|
|
116
119
|
- --main
|
117
120
|
- doc/README
|
118
121
|
- --title
|
119
|
-
- mattock-0.
|
122
|
+
- mattock-0.5.0 RDoc
|
120
123
|
require_paths:
|
121
124
|
- lib/
|
122
125
|
required_ruby_version: !ruby/object:Gem::Requirement
|
123
|
-
none: false
|
124
126
|
requirements:
|
125
127
|
- - ! '>='
|
126
128
|
- !ruby/object:Gem::Version
|
127
|
-
version: '0'
|
128
129
|
segments:
|
129
130
|
- 0
|
130
|
-
hash: -
|
131
|
-
|
131
|
+
hash: -700278895
|
132
|
+
version: '0'
|
132
133
|
none: false
|
134
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
133
135
|
requirements:
|
134
136
|
- - ! '>='
|
135
137
|
- !ruby/object:Gem::Version
|
136
138
|
version: '0'
|
139
|
+
none: false
|
137
140
|
requirements: []
|
138
141
|
rubyforge_project: mattock
|
139
142
|
rubygems_version: 1.8.24
|