mattock 0.3.4 → 0.4.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.
@@ -1,7 +1,7 @@
1
1
  require 'mattock/command-task'
2
2
 
3
3
  module Mattock
4
- class BundleCommandTask < CommandTask
4
+ class BundleCommandTask < Rake::CommandTask
5
5
  def cleaned_env
6
6
  env = {}
7
7
  if defined? Bundler
@@ -23,12 +23,12 @@ module Mattock
23
23
  module CascadingDefinition
24
24
  include Configurable
25
25
 
26
- def initialize(*tasklibs)
26
+ def setup_cascade(*other_definitions)
27
27
  @runtime = false
28
28
  setup_defaults
29
29
 
30
30
  confirm_steps(:default_configuration, :resolve_configuration, :confirm_configuration) do
31
- default_configuration(*tasklibs)
31
+ default_configuration(*other_definitions)
32
32
 
33
33
  yield self if block_given?
34
34
 
@@ -93,10 +93,9 @@ module Mattock
93
93
  mod.setting(:configuration_block, proc{})
94
94
  end
95
95
 
96
- def initialize(*args, &block)
96
+ def setup_deferred
97
97
  @runtime = false
98
98
  @finalized = false
99
- super
100
99
  end
101
100
 
102
101
  def runtime_definition(&block)
@@ -77,7 +77,7 @@ module Mattock
77
77
  alias_method :command_environment, :env
78
78
 
79
79
  def verbose
80
- Rake.verbose && Rake.verbose != Rake::FileUtilsExt::DEFAULT
80
+ ::Rake.verbose && ::Rake.verbose != ::Rake::FileUtilsExt::DEFAULT
81
81
  end
82
82
 
83
83
  def name
@@ -136,8 +136,8 @@ module Mattock
136
136
  def collect_result(pid, host_stdout, host_stderr)
137
137
  pid, status = Process.wait2(pid)
138
138
 
139
- stdout = host_stdout.read
140
- stderr = host_stderr.read
139
+ stdout = consume_buffer(host_stdout)
140
+ stderr = consume_buffer(host_stderr)
141
141
  result = CommandRunResult.new(command, status, {1 => stdout, 2 => stderr})
142
142
  host_stdout.close
143
143
  host_stderr.close
@@ -145,6 +145,24 @@ module Mattock
145
145
  return result
146
146
  end
147
147
 
148
+ #Gets all the data out of buffer, even if somehow it doesn't have an EOF
149
+ #Escpecially useful for programs (e.g. ssh) that sometime set their stderr
150
+ #to O_NONBLOCK
151
+ def consume_buffer(io)
152
+ accumulate = []
153
+ waits = 3
154
+ begin
155
+ while chunk = io.read_nonblock(4096)
156
+ accumulate << chunk
157
+ end
158
+ rescue IO::WaitReadable => ex
159
+ retry if (waits -= 1) > 0
160
+ end
161
+ return accumulate.join
162
+ rescue EOFError
163
+ return accumulate.join
164
+ end
165
+
148
166
  #If I wasn't worried about writing my own limited shell, I'd say e.g.
149
167
  #Pipeline would be an explicit chain of pipes... which is probably as
150
168
  #originally intended :/
@@ -152,11 +170,20 @@ module Mattock
152
170
  collect_result(*spawn_process)
153
171
  end
154
172
 
173
+ #Run a command in the background. The command can survive the caller
174
+ def spin_off
175
+ pid, out, err = spawn_process
176
+ Process.detach(pid)
177
+ return pid, out, err
178
+ end
179
+
180
+ #Run a command in parallel with the parent process - will kill it if it
181
+ #outlasts us
155
182
  def background
156
183
  pid, out, err = spawn_process
184
+ Process.detach(pid)
157
185
  at_exit do
158
186
  kill_process(pid)
159
- Process.detach(pid)
160
187
  end
161
188
  return pid, out, err
162
189
  end
@@ -2,13 +2,14 @@ require 'mattock/task'
2
2
  require 'mattock/command-line'
3
3
 
4
4
  module Mattock
5
- class CommandTask < Task
5
+ module CommandTaskMixin
6
6
  include CommandLineDSL
7
- extend CommandLineDSL
8
7
 
9
- setting(:task_name, :run)
10
- runtime_setting(:verify_command, nil)
11
- runtime_setting(:command)
8
+ def self.included(sub)
9
+ sub.extend CommandLineDSL
10
+ sub.runtime_setting(:verify_command, nil)
11
+ sub.runtime_setting(:command)
12
+ end
12
13
 
13
14
  def resolve_runtime_configuration
14
15
  super
@@ -38,17 +39,41 @@ module Mattock
38
39
  command
39
40
  end
40
41
 
41
- def action
42
+ def action(args)
42
43
  decorated(command).must_succeed!
43
44
  end
44
45
 
45
46
  def needed?
46
47
  finalize_configuration
47
- unless verify_command.nil?
48
- !decorated(verify_command).succeeds?
49
- else
48
+ if verify_command.nil?
50
49
  super
50
+ else
51
+ !decorated(verify_command).succeeds?
51
52
  end
52
53
  end
53
54
  end
55
+
56
+ class Rake::CommandTask < Rake::Task
57
+ include CommandTaskMixin
58
+ setting :task_name, :run
59
+ end
60
+
61
+ class Rake::FileCommandTask < Rake::FileTask
62
+ include CommandTaskMixin
63
+
64
+ setting :target_path
65
+
66
+ def resolve_configuration
67
+ super
68
+ self.target_path ||= task_name
69
+ end
70
+ end
71
+
72
+ class CommandTask < DeprecatedTaskAPI
73
+ def target_class; Rake::CommandTask; end
74
+ end
75
+
76
+ class FileCommandTask < DeprecatedTaskAPI
77
+ def target_class; Rake::FileCommandTask; end
78
+ end
54
79
  end
@@ -10,6 +10,15 @@ module Mattock
10
10
  #
11
11
  #@example (see ClassMethods)
12
12
  module Configurable
13
+ class Exception < ::StandardError
14
+ end
15
+
16
+ class NoDefaultValue < Exception
17
+ def initialize(field_name, klass)
18
+ super("No default value for field #{field_name} on class #{klass.name}")
19
+ end
20
+ end
21
+
13
22
  class FieldMetadata
14
23
  attr_accessor :name, :default_value
15
24
 
@@ -132,7 +141,7 @@ module Mattock
132
141
  attr_reader :source, :field
133
142
 
134
143
  def inspect
135
- "#{self.class.name.split(':').last}: #{value}"
144
+ "#{self.class.name.split(':').last}: #{source.class.name}.#{field.inspect}"
136
145
  end
137
146
  end
138
147
 
@@ -222,6 +231,13 @@ module Mattock
222
231
  # ce.hoo = "hallo"
223
232
  # ce.check_required #=> raises error because :must and :foo aren't set
224
233
  module ClassMethods
234
+ def inspect_instance(instance, indent="")
235
+ field_names.map do |name|
236
+ meta = field_metadata(name)
237
+ "#{indent}#{meta.inspect} => #{meta.immediate_value_on(instance).inspect}(#{meta.value_on(instance).inspect})"
238
+ end.join("\n")
239
+ end
240
+
225
241
  def default_values
226
242
  @default_values ||= []
227
243
  end
@@ -244,6 +260,13 @@ module Mattock
244
260
  end
245
261
  end
246
262
 
263
+ #@raises NoDefaultValue
264
+ def default_value_for(name)
265
+ field = field_metadata(name)
266
+ raise NoDefaultValue.new(name,self) unless field.is?(:defaulting)
267
+ return field.default_value
268
+ end
269
+
247
270
  #Creates an anonymous Configurable - useful in complex setups for nested
248
271
  #settings
249
272
  #@example SSH options
@@ -297,8 +320,8 @@ module Mattock
297
320
 
298
321
  if existing = default_values.find{|field| field.name == name} and existing.default_value != default_value
299
322
  source_line = caller.drop_while{|line| /#{__FILE__}/ =~ line}.first
300
- warn "Changing default value of #{self.name}##{name} from #{existing.default_value.inspect} to #{default_value.inspect}"
301
- " (at: #{source_line})"
323
+ warn "Changing default value of #{self.name}##{name} from #{existing.default_value.inspect} to #{default_value.inspect}"
324
+ " (at: #{source_line})"
302
325
  end
303
326
  default_values << metadata
304
327
  metadata
@@ -413,6 +436,64 @@ module Mattock
413
436
 
414
437
  extend ClassMethods
415
438
 
439
+ module DirectoryStructure
440
+ module ClassMethods
441
+ RequiredField = ::Mattock::Configurable::ClassMethods::RequiredField
442
+
443
+ attr_accessor :path_heirarchy
444
+ attr_accessor :path_fields
445
+
446
+ def dir(field_name, *args)
447
+ rel_path = RequiredField
448
+ if String === args.first
449
+ rel_path = args.shift
450
+ end
451
+ parent_field = path(field_name, rel_path)
452
+ self.path_heirarchy += args.map do |child_field|
453
+ [parent_field, child_field]
454
+ end
455
+ return parent_field
456
+ end
457
+
458
+ def path(field_name, rel_path=RequiredField)
459
+ field = setting(field_name, nested{
460
+ required_field :absolute_path
461
+ setting :relative_path, rel_path
462
+ })
463
+ path_fields << field
464
+ return field
465
+ end
466
+ end
467
+
468
+ def self.included(sub)
469
+ sub.extend ClassMethods
470
+ sub.path_heirarchy = []
471
+ sub.path_fields = []
472
+ end
473
+
474
+ def resolve_paths
475
+ missing_relatives = []
476
+ self.class.path_heirarchy.reverse.each do |parent_field, child_field|
477
+ child = child_field.value_on(self)
478
+ next unless child.field_unset?(:absolute_path)
479
+ if child.field_unset?(:relative_path)
480
+ missing_relatives << child_field
481
+ next
482
+ end
483
+ parent = parent_field.value_on(self)
484
+ child.absolute_path = File::join(parent.absolute_path, child.relative_path)
485
+ end
486
+ unless missing_relatives.empty?
487
+ raise "Required field#{missing_relatives.length == 1 ? "" : "s"} #{missing_relatives.map{|field| "#{field.name}.relative_path".inspect}.join(", ")} unset on #{self.inspect}"
488
+ end
489
+ self.class.path_fields.each do |field|
490
+ value = field.value_on(self)
491
+ next unless value.field_unset?(:relative_path)
492
+ value.relative_path = value.absolute_path
493
+ end
494
+ end
495
+ end
496
+
416
497
  def copy_settings
417
498
  SettingsCopier.new(self)
418
499
  end
@@ -1,39 +1,45 @@
1
1
  require 'mattock/command-task'
2
2
  module Mattock
3
- class RemoteCommandTask < CommandTask
4
- runtime_setting(:remote_server, nested(
5
- :address => nil,
6
- :user => nil
7
- ))
8
- setting(:ssh_options, [])
9
- nil_fields(:id_file, :free_arguments)
10
- runtime_setting(:remote_target)
3
+ module Rake
4
+ class RemoteCommandTask < CommandTask
5
+ runtime_setting(:remote_server, nested(
6
+ :address => nil,
7
+ :user => nil
8
+ ))
9
+ setting(:ssh_options, [])
10
+ nil_fields(:id_file, :free_arguments)
11
+ runtime_setting(:remote_target)
11
12
 
12
- def resolve_runtime_configuration
13
- super
14
- self.remote_target ||= [remote_server.user, remote_server.address].compact.join('@') unless remote_server.address.nil?
15
- end
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
16
17
 
17
- def ssh_option(name, value)
18
- ssh_options << "\"#{name}=#{value}\""
19
- end
18
+ def ssh_option(name, value)
19
+ ssh_options << "\"#{name}=#{value}\""
20
+ end
20
21
 
21
- def decorated(command_on_remote)
22
- fail "Need remote server for #{self.class.name}" unless remote_server.address
22
+ def decorated(command_on_remote)
23
+ fail "Need remote server for #{self.class.name}" unless remote_server.address
23
24
 
24
- raise "Empty remote command" if command_on_remote.nil?
25
- Mattock::WrappingChain.new do |cmd|
26
- cmd.add Mattock::CommandLine.new("ssh") do |cmd|
27
- cmd.options << "-i #{id_file}" if id_file
28
- unless ssh_options.empty?
29
- ssh_options.each do |opt|
30
- cmd.options << "-o #{opt}"
25
+ raise "Empty remote command" if command_on_remote.nil?
26
+ Mattock::WrappingChain.new do |cmd|
27
+ cmd.add Mattock::CommandLine.new("ssh") do |cmd|
28
+ cmd.options << "-i #{id_file}" if id_file
29
+ unless ssh_options.empty?
30
+ ssh_options.each do |opt|
31
+ cmd.options << "-o #{opt}"
32
+ end
31
33
  end
34
+ cmd.options << remote_target
32
35
  end
33
- cmd.options << remote_target
36
+ cmd.add Mattock::ShellEscaped.new(command_on_remote)
34
37
  end
35
- cmd.add Mattock::ShellEscaped.new(command_on_remote)
36
38
  end
37
39
  end
38
40
  end
41
+
42
+ class RemoteCommandTask < DeprecatedTaskAPI
43
+ def target_class; Rake::RemoteCommandTask; end
44
+ end
39
45
  end
data/lib/mattock/task.rb CHANGED
@@ -9,114 +9,107 @@ module Mattock
9
9
  # A configurable subclass of Rake::Task, such that you can use a
10
10
  # configuration block to change how a common task behaves, while still
11
11
  # overriding Rake API methods like Task#needed? and Task#timestamp
12
-
13
- module TaskMixin
12
+ module ConfigurableTask
13
+ include Configurable
14
14
  include CascadingDefinition
15
15
  include DeferredDefinition
16
16
 
17
- setting :task_name
18
- setting :task_args
19
-
20
17
  module ClassMethods
21
18
  def default_taskname(name)
22
19
  setting(:task_name, name)
23
20
  end
24
- end
25
21
 
26
- def self.included(mod)
27
- super
28
- mod.class_eval do
29
- extend ClassMethods
30
- DeferredDefinition.add_settings(self)
22
+ def define_task(*args)
23
+ configs = args.take_while{|arg| Configurable === arg}
24
+ extracted_task_args = args[configs.length..-1]
25
+ if extracted_task_args.any?{|arg| Configurable === arg}
26
+ raise "Mattock::Task classes should be created with parent configs, then Rake task args"
27
+ end
28
+
29
+ if extracted_task_args.empty?
30
+ extracted_task_args = [default_value_for(:task_name)]
31
+ end
32
+
33
+ task = ::Rake.application.define_task(self, *extracted_task_args) do |task, args|
34
+ task.finalize_configuration
35
+ task.action(args)
36
+ end
37
+
38
+ unless self === task
39
+ raise "Task already defined for #{task.name} - attempted to redefine with #{self.name}"
40
+ end
41
+
42
+ task.setup_deferred
43
+ task.setup_cascade(*configs) do |t|
44
+ t.task_name = task.name
45
+ t.task_args = extracted_task_args
46
+
47
+ yield(t) if block_given?
48
+ end
31
49
  end
32
50
  end
33
51
 
34
- def initialize(*args)
35
- configs = args.take_while{|arg| Configurable === arg}
36
- @extracted_task_args = args[configs.length..-1]
37
- if @extracted_task_args.any?{|arg| Configurable === arg}
38
- raise "Mattock::Task classes should be created with parent configs, then Rake task args"
39
- end
40
- super(*configs)
52
+ def self.included(sub)
53
+ sub.extend ClassMethods
54
+ Configurable.included(sub)
55
+ DeferredDefinition.add_settings(sub)
41
56
  end
42
57
 
58
+ setting :task_name
59
+ setting :task_args
60
+
61
+ attr_accessor :base_task
62
+
43
63
  def resolve_configuration
44
64
  super
45
- if @extracted_task_args.empty?
46
- self.task_args = [task_name]
47
- else
48
- self.task_args = @extracted_task_args
49
- end
50
65
  end
51
66
 
52
- def action
67
+ def action(*task_args)
53
68
  end
54
69
 
70
+ def inspect
71
+ "#{self.class.name}: #{self.task_args.inspect}\nConfiguration:\n#{self.class.inspect_instance(self, " ")}"
72
+ end
73
+ end
55
74
 
56
- module ChildTask
57
- attr_accessor :source_task
58
-
59
- def unset_defaults_guard
60
- source_task.unset_defaults_guard
61
- end
62
-
63
- def inspect
64
- "From: " + source_task.inspect
75
+ class DeprecatedTaskAPI
76
+ def self.deprecated(message)
77
+ @deprecations ||= {}
78
+ unless @deprecations.has_key?(message)
79
+ warn message
80
+ @deprecations[message] = :delivered
65
81
  end
66
82
  end
67
83
 
68
- =begin
69
- # I continue to look for an alternative here.
70
- # The trouble is that deep inside of define_task, Rake actually
71
- # instantiates the Task - so in wanting to be able to override members of
72
- # Task, it's hard to get the virtues of CascadingDefinition as well (maybe
73
- # the virtues could be had without the actual mixin?)
74
- #
75
- # So, what we're doing is to dynamically create a child class and then
76
- # carry forward the Rake::Task#initialize
77
- =end
78
- def task_class
79
- return @task_class if @task_class
80
- @task_class = Class.new(self.class) do
81
- define_method :initialize, Rake::Task.instance_method(:initialize)
82
- include ChildTask
83
- end
84
+ def initialize(*args, &block)
85
+ self.class.deprecated "#{self.class.name}.new(...) is deprecated - instead use #{target_class.name}.define_task(...)\n (from #{caller[0]})"
86
+ target_class.define_task(*args, &block)
84
87
  end
88
+ end
85
89
 
86
- def inspect
87
- "#{self.class.name}: #{self.task_args.inspect}"
90
+ module Rake
91
+ class Task < ::Rake::Task
92
+ include ConfigurableTask
88
93
  end
89
94
 
90
- attr_accessor :rake_task
91
- def define
92
- self.rake_task = task_class.define_task(*task_args) do
93
- finalize_configuration
94
- copy_settings_to(rake_task)
95
- rake_task.action
96
- end
97
- copy_settings_to(rake_task)
98
- rake_task.source_task = self
95
+ class FileTask < ::Rake::FileTask
96
+ include ConfigurableTask
99
97
  end
100
- end
101
98
 
102
- #I'm having misgivings about this design choice. Rightly, this is probably a
103
- #"Task Definer" that knows what class to ::define_task and then mixin a
104
- #module to handle the original purpose of being able to override e.g.
105
- ##needed? There's a lot of client code that relies on this pattern now,
106
- #though.
107
- class Task < Rake::Task
108
- include TaskMixin
109
- end
99
+ class FileCreationTask < ::Rake::FileCreationTask
100
+ include ConfigurableTask
101
+ end
110
102
 
111
- class FileTask < Rake::FileTask
112
- include TaskMixin
103
+ class MultiTask < ::Rake::MultiTask
104
+ include ConfigurableTask
105
+ end
113
106
  end
114
107
 
115
- class FileCreationTask < Rake::FileCreationTask
116
- include TaskMixin
108
+ class Task < DeprecatedTaskAPI
109
+ def target_class; Rake::Task; end
117
110
  end
118
111
 
119
- class MultiTask < Rake::MultiTask
120
- include TaskMixin
112
+ class FileTask < DeprecatedTaskAPI
113
+ def target_class; Rake::FileTask; end
121
114
  end
122
115
  end
@@ -37,7 +37,7 @@ module Mattock
37
37
  #
38
38
  #The configuration handling is provided by {CascadingDefinition}, and
39
39
  #configuration options are built using {Configurable}
40
- class TaskLib < Rake::TaskLib
40
+ class TaskLib < ::Rake::TaskLib
41
41
  include CascadingDefinition
42
42
 
43
43
  attr_writer :namespace_name
@@ -50,9 +50,9 @@ module Mattock
50
50
 
51
51
  attr_reader :tasks
52
52
 
53
- def initialize(*toolkits)
53
+ def initialize(*toolkits, &block)
54
54
  @tasks = []
55
- super
55
+ setup_cascade(*toolkits, &block)
56
56
  end
57
57
 
58
58
  #Records tasks as they are created
@@ -62,11 +62,18 @@ module Mattock
62
62
  return a_task
63
63
  end
64
64
 
65
+ #Shorthand for
66
+ # task name => before
67
+ # task after => name
68
+ #Which ensures that if "after" is ever invoked,
69
+ #the execution will be before, name, then after
65
70
  def bracket_task(before, name, after)
66
71
  task self[name] => before
67
72
  task after => self[name]
68
73
  end
69
74
 
75
+ #Builds a series of tasks in a sequence - the idea is that
76
+ #dependant tasklibs can depend on stages of a larger process
70
77
  def task_spine(*list)
71
78
  task list.first
72
79
  list.each_cons(2) do |first, second|
@@ -4,49 +4,29 @@ require 'valise'
4
4
  module Mattock
5
5
  module ValiseManager
6
6
  def default_valise(*dirs)
7
- Valise::Set.define do
8
- dirs.each do |dir|
9
- ro dir
10
- end
11
- end
7
+ Valise::read_only(*dirs)
12
8
  end
13
9
 
14
10
  def rel_dir(base_path = nil, up_to = nil)
15
- base_path ||= /(.*):\d+/.match(caller[0])[1]
16
- up_to ||= "lib"
17
-
18
- abs_path = File::expand_path(base_path)
19
- base_path = abs_path.split(File::Separator)
20
- until base_path.empty?
21
- unless base_path.last == up_to
22
- base_path.pop
23
- else
24
- break
25
- end
26
- end
27
-
28
- if base_path.empty?
29
- raise "Relative root #{up_to.inspect} not found in #{abs_path.inspect}"
30
- end
31
-
32
- return base_path
11
+ Valise::Unpath.up_to(up_to, base_path)
33
12
  end
34
13
  module_function :rel_dir, :default_valise
35
14
  public :rel_dir, :default_valise
36
15
  end
37
16
 
38
17
  module TemplateHost
39
- def self.template_cache
40
- @template_cache ||= Tilt::Cache.new
41
- end
42
-
43
18
  attr_accessor :valise
44
19
 
20
+ def templates_are_in(valise)
21
+ self.valise = valise.templates
22
+ end
23
+
24
+ #XXX Better to let clients stem or subset
45
25
  def find_template(path)
46
- valise.find(["templates"] + valise.unpath(path))
26
+ valise.find(path)
47
27
  end
48
28
 
49
- def template_contents(path)
29
+ def template(path)
50
30
  find_template(path).contents
51
31
  end
52
32
 
@@ -54,19 +34,13 @@ module Mattock
54
34
  find_template(path).full_path
55
35
  end
56
36
 
57
- def render(path, template_options = nil)
58
- template = TemplateHost::template_cache.fetch(path) do
59
- Tilt.new(path, template_options || {}) do |tmpl|
60
- template_contents(tmpl.file)
61
- end
62
- end
63
-
37
+ def render(path)
64
38
  locals = {}
65
39
  if block_given?
66
40
  yield locals
67
41
  end
68
42
 
69
- template.render(self, locals)
43
+ template(path).render(self, locals)
70
44
  end
71
45
  end
72
46
 
@@ -74,10 +48,14 @@ module Mattock
74
48
  include TemplateHost
75
49
 
76
50
  def template_task(template_source, destination_path, template_options = nil)
51
+ unless template_options.nil?
52
+ valise.add_serialization_handler(template_source, :tilt, :template_options => template_options)
53
+ end
54
+
77
55
  file template_path(template_source)
78
56
  file destination_path => template_path(template_source) do
79
57
  File::open(destination_path, "w") do |file|
80
- file.write(render(template_source, template_options))
58
+ file.write(render(template_source))
81
59
  end
82
60
  end
83
61
  end
@@ -4,20 +4,20 @@ module Mattock
4
4
  module RakeExampleGroup
5
5
  SavedEnvironmentVariables = %w{APPDATA HOME HOMEDRIVE HOMEPATH RAKE_COLUMNS RAKE_SYSTEM RAKEOPT USERPROFILE}
6
6
  DeletedEnvironmentVariables = %w{RAKE_COLUMNS RAKE_SYSTEM RAKEOPT}
7
- include Rake::DSL
7
+ include ::Rake::DSL
8
8
  #include FileUtils
9
9
 
10
10
  class TaskManager
11
- include Rake::TaskManager
11
+ include ::Rake::TaskManager
12
12
  end
13
13
 
14
14
  def self.included(mod)
15
15
  mod.class_eval do
16
16
  let! :rake do
17
- Rake.application = Rake::Application.new
18
- Rake::TaskManager.record_task_metadata = true
17
+ ::Rake.application = ::Rake::Application.new
18
+ ::Rake::TaskManager.record_task_metadata = true
19
19
  RakeFileUtils.verbose_flag = false
20
- Rake.application
20
+ ::Rake.application
21
21
  end
22
22
 
23
23
  before :each do
data/spec/command-task.rb CHANGED
@@ -9,7 +9,7 @@ describe Mattock::RemoteCommandTask do
9
9
 
10
10
  let! :remote_task do
11
11
  namespace :test do
12
- Mattock::RemoteCommandTask.new do |t|
12
+ Mattock::Rake::RemoteCommandTask.define_task do |t|
13
13
  t.remote_server.address = "nowhere.com"
14
14
  t.command = Mattock::PrereqChain.new do |prereq|
15
15
  prereq.add Mattock::CommandLine.new("cd", "a_dir")
@@ -42,7 +42,7 @@ describe Mattock::BundleCommandTask do
42
42
  include Mattock::CommandLineExampleGroup
43
43
 
44
44
  let! :bundle_task do
45
- Mattock::BundleCommandTask.new(:bundle_test) do |t|
45
+ Mattock::BundleCommandTask.define_task(:bundle_test) do |t|
46
46
  t.command = cmd("bundle", "install", "--standalone")
47
47
  end
48
48
  end
data/spec/configurable.rb CHANGED
@@ -51,6 +51,113 @@ describe Mattock::Configurable do
51
51
  end.to_not raise_error
52
52
  end
53
53
 
54
+ describe "with DirectoryStructure" do
55
+ class DirectoryThing
56
+ include Mattock::Configurable
57
+ include DirectoryStructure
58
+
59
+ dir(:ephemeral_mountpoint,
60
+ dir(:bundle_workdir, "bundle_workdir",
61
+ path(:bundle_manifest),
62
+ path(:credentials_archive, "aws-creds.tar.gz"),
63
+ dir(:credentials_dir, "aws-creds",
64
+ path(:private_key_file, "pk.pem"),
65
+ path(:certificate_file, "cert.pem")
66
+ )
67
+ )
68
+ )
69
+ end
70
+
71
+ def subject
72
+ DirectoryThing.new.tap do |thing|
73
+ thing.setup_defaults
74
+ end
75
+ end
76
+
77
+ it "should complain about missing fields" do
78
+ expect do
79
+ subject.check_required
80
+ end.to raise_error /Required field/
81
+ end
82
+
83
+ describe "with root path configured, but missing a relative path" do
84
+ def subject
85
+ DirectoryThing.new.tap do |thing|
86
+ thing.setup_defaults
87
+ thing.ephemeral_mountpoint.absolute_path = "/tmp"
88
+ thing.resolve_paths
89
+ end
90
+ end
91
+
92
+ it "should complain about missing fields" do
93
+ expect do
94
+ subject.check_required
95
+ end.to raise_error /Required field/
96
+ end
97
+ end
98
+
99
+ describe "with required paths configured" do
100
+ def subject
101
+ DirectoryThing.new.tap do |thing|
102
+ thing.setup_defaults
103
+ thing.ephemeral_mountpoint.absolute_path = "/tmp"
104
+ thing.bundle_manifest.relative_path = "image.manifest.xml"
105
+ thing.resolve_paths
106
+ end
107
+ end
108
+
109
+ it "should not complain about required fields" do
110
+ expect do
111
+ subject.check_required
112
+ end.not_to raise_error
113
+ end
114
+
115
+ its("certificate_file.absolute_path"){ should == "/tmp/bundle_workdir/aws-creds/cert.pem" }
116
+ its("bundle_manifest.absolute_path"){ should == "/tmp/bundle_workdir/image.manifest.xml" }
117
+ its("credentials_dir.absolute_path"){ should == "/tmp/bundle_workdir/aws-creds" }
118
+ end
119
+ end
120
+
121
+ describe "multiple instances" do
122
+ class MultiSource
123
+ include Mattock::Configurable
124
+
125
+ setting :one, 1
126
+ setting :nest, nested{
127
+ setting :two, 2
128
+ }
129
+ end
130
+
131
+ let :first do
132
+ MultiSource.new.setup_defaults
133
+ end
134
+
135
+ let :second do
136
+ MultiSource.new.setup_defaults
137
+ end
138
+
139
+ before :each do
140
+ first.one = "one"
141
+ first.nest.two = "two"
142
+ second
143
+ end
144
+
145
+ it "should not have any validation errors" do
146
+ expect do
147
+ first.check_required
148
+ second.check_required
149
+ end.not_to raise_error
150
+ end
151
+
152
+ it "should accurately reflect settings" do
153
+ first.one.should == "one"
154
+ second.one.should == 1
155
+
156
+ first.nest.two.should == "two"
157
+ second.nest.two.should == 2
158
+ end
159
+ end
160
+
54
161
  describe "copying settings" do
55
162
  class LeftStruct
56
163
  include Mattock::Configurable
@@ -9,9 +9,7 @@ describe Mattock::TemplateHost do
9
9
  end
10
10
 
11
11
  it "should be able to do easy templating" do
12
- template_host.valise = Mattock::ValiseManager.default_valise("spec_help")
12
+ template_host.templates_are_in(Mattock::ValiseManager.default_valise("spec_help"))
13
13
  template_host.render("test.erb").should == "Templated: A test value\n"
14
-
15
14
  end
16
-
17
15
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mattock
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.4
4
+ version: 0.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-25 00:00:00.000000000 Z
12
+ date: 2013-03-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: corundum
16
- requirement: &84793580 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,24 +21,37 @@ dependencies:
21
21
  version: 0.0.1
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *84793580
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 0.0.1
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: valise
27
- requirement: &84792520 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ! '>='
31
36
  - !ruby/object:Gem::Version
32
- version: '0.6'
37
+ version: '0.9'
33
38
  segments:
34
39
  - 0
35
- - 6
40
+ - 9
36
41
  type: :runtime
37
42
  prerelease: false
38
- version_requirements: *84792520
43
+ version_requirements: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ! '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0.9'
49
+ segments:
50
+ - 0
51
+ - 9
39
52
  - !ruby/object:Gem::Dependency
40
53
  name: tilt
41
- requirement: &84791720 !ruby/object:Gem::Requirement
54
+ requirement: !ruby/object:Gem::Requirement
42
55
  none: false
43
56
  requirements:
44
57
  - - ! '>'
@@ -48,7 +61,14 @@ dependencies:
48
61
  - 0
49
62
  type: :runtime
50
63
  prerelease: false
51
- version_requirements: *84791720
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>'
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ segments:
71
+ - 0
52
72
  description: ! " If Rake won't do it by itself, you oughtta Mattock.\n\n If you
53
73
  survived the pun, you might enjoy this gem.\n\n Features:\n\n * Extensions to
54
74
  Tasklibs to support powerful deerpaths.\n * A commandline library that supports
@@ -102,7 +122,7 @@ rdoc_options:
102
122
  - --main
103
123
  - doc/README
104
124
  - --title
105
- - mattock-0.3.4 RDoc
125
+ - mattock-0.4.0 RDoc
106
126
  require_paths:
107
127
  - lib/
108
128
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -113,7 +133,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
113
133
  version: '0'
114
134
  segments:
115
135
  - 0
116
- hash: -1040167503
136
+ hash: 725889327
117
137
  required_rubygems_version: !ruby/object:Gem::Requirement
118
138
  none: false
119
139
  requirements:
@@ -122,7 +142,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
122
142
  version: '0'
123
143
  requirements: []
124
144
  rubyforge_project: mattock
125
- rubygems_version: 1.8.15
145
+ rubygems_version: 1.8.24
126
146
  signing_key:
127
147
  specification_version: 3
128
148
  summary: A powerful companion to Rake