mattock 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|