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.
@@ -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
- runtime_setting(:remote_server, nested(
6
- :address => nil,
7
- :user => nil
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
 
@@ -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)
@@ -1,7 +1,7 @@
1
1
  require 'mattock/command-line'
2
2
 
3
3
  module Mattock
4
- class MockCommandResult < CommandRunResult
4
+ class MockCommandResult < CommandLine::CommandRunResult
5
5
  def self.create(*args)
6
6
  if args.length == 1
7
7
  args = [args[0], {1 => ""}]
data/spec/command-line.rb CHANGED
@@ -31,7 +31,7 @@ describe Mattock::CommandLine do
31
31
  end.to_not raise_error
32
32
  end
33
33
 
34
- describe Mattock::CommandRunResult do
34
+ describe Mattock::CommandLine::CommandRunResult do
35
35
  let :result do
36
36
  commandline.run
37
37
  end
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.copy_settings.to(right)
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
@@ -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
@@ -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-03-31 00:00:00.000000000 Z
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
- requirement: !ruby/object:Gem::Requirement
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
- requirement: !ruby/object:Gem::Requirement
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
- requirement: !ruby/object:Gem::Requirement
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
- segments:
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.4.1 RDoc
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: -492969553
131
- required_rubygems_version: !ruby/object:Gem::Requirement
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