mattock 0.3.4 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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