tap 0.17.1 → 0.18.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/History +22 -0
- data/README +15 -14
- data/cmd/console.rb +1 -1
- data/cmd/manifest.rb +25 -5
- data/cmd/run.rb +60 -25
- data/doc/API +37 -38
- data/doc/Class Reference +36 -46
- data/doc/Examples/Workflow +1 -1
- data/lib/tap.rb +1 -1
- data/lib/tap/app.rb +15 -80
- data/lib/tap/app/node.rb +0 -14
- data/lib/tap/env.rb +55 -27
- data/lib/tap/env/manifest.rb +2 -2
- data/lib/tap/intern.rb +50 -0
- data/lib/tap/join.rb +12 -9
- data/lib/tap/middleware.rb +56 -0
- data/lib/tap/schema.rb +182 -14
- data/lib/tap/schema/utils.rb +5 -3
- data/lib/tap/task.rb +53 -130
- data/lib/tap/tasks/dump.rb +1 -1
- data/lib/tap/tasks/load.rb +8 -9
- data/lib/tap/templater.rb +203 -0
- data/lib/tap/{constants.rb → version.rb} +2 -2
- metadata +6 -5
- data/lib/tap/support/intern.rb +0 -53
- data/lib/tap/support/templater.rb +0 -207
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'configurable'
|
2
|
+
|
3
|
+
module Tap
|
4
|
+
class Middleware
|
5
|
+
class << self
|
6
|
+
|
7
|
+
# Instantiates an instance of self and causes app to use the instance
|
8
|
+
# as middleware.
|
9
|
+
def parse(argv=ARGV, app=Tap::App.instance)
|
10
|
+
parse!(argv.dup, app)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Same as parse, but removes arguments destructively.
|
14
|
+
def parse!(argv=ARGV, app=Tap::App.instance)
|
15
|
+
opts = ConfigParser.new
|
16
|
+
opts.separator "configurations:"
|
17
|
+
opts.add(configurations)
|
18
|
+
|
19
|
+
args = opts.parse!(argv, :add_defaults => false)
|
20
|
+
instantiate({:config => opts.nested_config}, app)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Instantiates an instance of self and causes app to use the instance
|
24
|
+
# as middleware.
|
25
|
+
def instantiate(argh, app=Tap::App.instance)
|
26
|
+
app.use(self, argh[:config] || {})
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
include Configurable
|
31
|
+
|
32
|
+
# The call stack.
|
33
|
+
attr_reader :stack
|
34
|
+
|
35
|
+
def initialize(stack, config={})
|
36
|
+
@stack = stack
|
37
|
+
initialize_config(config)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns the app at the base of the stack.
|
41
|
+
def app
|
42
|
+
@app ||= begin
|
43
|
+
current = stack
|
44
|
+
until current.kind_of?(App::Stack)
|
45
|
+
current = current.stack
|
46
|
+
end
|
47
|
+
current.app
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# By default call simply calls stack with the node and inputs.
|
52
|
+
def call(node, inputs=[])
|
53
|
+
stack.call(node, inputs)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/tap/schema.rb
CHANGED
@@ -1,11 +1,63 @@
|
|
1
|
+
require 'tap/app'
|
1
2
|
require 'tap/schema/utils'
|
2
3
|
require 'tap/schema/parser'
|
3
4
|
|
4
5
|
module Tap
|
6
|
+
class App
|
7
|
+
def build(schema, options={})
|
8
|
+
options = {
|
9
|
+
:clean => true,
|
10
|
+
:validate => true
|
11
|
+
}.merge(options)
|
12
|
+
|
13
|
+
unless schema.kind_of?(Schema)
|
14
|
+
schema = Schema.new(schema)
|
15
|
+
end
|
16
|
+
|
17
|
+
if resources = options[:resources]
|
18
|
+
schema.resolve! do |type, id|
|
19
|
+
resources[type][id]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
if options[:clean]
|
24
|
+
reset
|
25
|
+
end
|
26
|
+
|
27
|
+
schema.build!(self, options[:validate])
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_schema
|
31
|
+
schema = Schema.new
|
32
|
+
queue.to_a.each do |task, inputs|
|
33
|
+
schema.add(task, inputs)
|
34
|
+
end
|
35
|
+
|
36
|
+
middleware.reverse_each do |m|
|
37
|
+
schema.use(m)
|
38
|
+
end
|
39
|
+
|
40
|
+
index = 0
|
41
|
+
schema.tasks.keys.each do |task|
|
42
|
+
schema.rename(task, index)
|
43
|
+
index += 1
|
44
|
+
end
|
45
|
+
|
46
|
+
if block_given?
|
47
|
+
schema.resources.each_pair do |type, resource|
|
48
|
+
yield(type, resource)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
schema
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
5
56
|
class Schema
|
6
57
|
class << self
|
7
58
|
def load(str)
|
8
|
-
|
59
|
+
schema = YAML.load(str)
|
60
|
+
new(schema ? Utils.symbolize(schema) : {})
|
9
61
|
end
|
10
62
|
|
11
63
|
def load_file(path)
|
@@ -51,11 +103,86 @@ module Tap
|
|
51
103
|
# An array of middleware to build onto the app.
|
52
104
|
attr_reader :middleware
|
53
105
|
|
106
|
+
# The app used to build self
|
107
|
+
attr_reader :app
|
108
|
+
|
54
109
|
def initialize(schema={})
|
55
|
-
@tasks = schema[
|
56
|
-
@joins = schema[
|
57
|
-
@queue = schema[
|
58
|
-
@middleware = schema[
|
110
|
+
@tasks = schema[:tasks] || {}
|
111
|
+
@joins = schema[:joins] || []
|
112
|
+
@queue = schema[:queue] || []
|
113
|
+
@middleware = schema[:middleware] || []
|
114
|
+
|
115
|
+
@app = nil
|
116
|
+
end
|
117
|
+
|
118
|
+
def add(node, inputs=nil)
|
119
|
+
collect_tasks(node).collect do |task|
|
120
|
+
tasks[task] = task.to_hash
|
121
|
+
task.joins
|
122
|
+
end.flatten.uniq.each do |join|
|
123
|
+
joins << [join.inputs, join.outputs, join.to_hash]
|
124
|
+
end
|
125
|
+
|
126
|
+
if inputs
|
127
|
+
queue << [node, inputs]
|
128
|
+
end
|
129
|
+
|
130
|
+
self
|
131
|
+
end
|
132
|
+
|
133
|
+
def use(middleware)
|
134
|
+
self.middleware << middleware.to_hash
|
135
|
+
self
|
136
|
+
end
|
137
|
+
|
138
|
+
def resources
|
139
|
+
{
|
140
|
+
:task => tasks.values,
|
141
|
+
:join => joins.collect {|join| join[2] },
|
142
|
+
:middleware => middleware
|
143
|
+
}
|
144
|
+
end
|
145
|
+
|
146
|
+
# Renames the current_key task to new_key. References in joins and
|
147
|
+
# queue are updated by rename. Raises an error if built? or if the
|
148
|
+
# specified task does not exist.
|
149
|
+
def rename(current_key, new_key)
|
150
|
+
if built?
|
151
|
+
raise "cannot rename if built"
|
152
|
+
end
|
153
|
+
|
154
|
+
# rename task
|
155
|
+
unless task = tasks.delete(current_key)
|
156
|
+
raise "unknown task: #{current_key.inspect}"
|
157
|
+
end
|
158
|
+
tasks[new_key] = task
|
159
|
+
|
160
|
+
# update join references
|
161
|
+
joins.each do |inputs, outputs, join|
|
162
|
+
inputs.each_index do |index|
|
163
|
+
inputs[index] = new_key if inputs[index] == current_key
|
164
|
+
end
|
165
|
+
|
166
|
+
outputs.each_index do |index|
|
167
|
+
outputs[index] = new_key if outputs[index] == current_key
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
# update queue references, note both array and
|
172
|
+
# reference-style entries must be handled
|
173
|
+
queue.each_index do |index|
|
174
|
+
if queue[index].kind_of?(Array)
|
175
|
+
if queue[index][0] == current_key
|
176
|
+
queue[index][0] = new_key
|
177
|
+
end
|
178
|
+
else
|
179
|
+
if queue[index] == current_key
|
180
|
+
queue[index] = new_key
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
self
|
59
186
|
end
|
60
187
|
|
61
188
|
def resolve!
|
@@ -91,13 +218,13 @@ module Tap
|
|
91
218
|
errors = []
|
92
219
|
tasks.each_value do |task|
|
93
220
|
unless resolved?(task)
|
94
|
-
errors << "
|
221
|
+
errors << "unresolvable task: #{task.inspect}"
|
95
222
|
end
|
96
223
|
end
|
97
224
|
|
98
225
|
joins.each do |inputs, outputs, join|
|
99
226
|
unless resolved?(join)
|
100
|
-
errors << "
|
227
|
+
errors << "unresolvable join: #{join.inspect}"
|
101
228
|
end
|
102
229
|
|
103
230
|
inputs.each do |key|
|
@@ -125,7 +252,7 @@ module Tap
|
|
125
252
|
|
126
253
|
middleware.each do |m|
|
127
254
|
unless resolved?(m)
|
128
|
-
errors << "
|
255
|
+
errors << "unresolvable middleware: #{m.inspect}"
|
129
256
|
end
|
130
257
|
end
|
131
258
|
|
@@ -163,11 +290,14 @@ module Tap
|
|
163
290
|
self
|
164
291
|
end
|
165
292
|
|
166
|
-
def build!(app)
|
293
|
+
def build!(app, validate=true)
|
294
|
+
validate! if validate
|
295
|
+
|
167
296
|
# instantiate tasks
|
168
297
|
tasks.each_pair do |key, task|
|
169
298
|
tasks[key] = instantiate(task, app)
|
170
299
|
end
|
300
|
+
tasks.freeze
|
171
301
|
|
172
302
|
# build the workflow
|
173
303
|
joins.collect! do |inputs, outputs, join|
|
@@ -175,26 +305,47 @@ module Tap
|
|
175
305
|
outputs = outputs.collect {|key| tasks[key] }
|
176
306
|
instantiate(join, app).join(inputs, outputs)
|
177
307
|
end
|
308
|
+
joins.freeze
|
178
309
|
|
179
310
|
# utilize middleware
|
180
311
|
middleware.collect! do |middleware|
|
181
312
|
instantiate(middleware, app)
|
182
313
|
end
|
314
|
+
middleware.freeze
|
183
315
|
|
184
316
|
# enque tasks
|
185
317
|
queue.each do |(key, inputs)|
|
186
318
|
app.enq(tasks[key], *inputs)
|
187
319
|
end
|
320
|
+
queue.clear.freeze
|
321
|
+
|
322
|
+
@app = app
|
323
|
+
self
|
324
|
+
end
|
325
|
+
|
326
|
+
def built?
|
327
|
+
@app != nil
|
328
|
+
end
|
329
|
+
|
330
|
+
def enque(key, *inputs)
|
331
|
+
unless built?
|
332
|
+
raise "cannot enque unless built"
|
333
|
+
end
|
334
|
+
|
335
|
+
unless task = tasks[key]
|
336
|
+
raise "unknown task: #{key.inspect}"
|
337
|
+
end
|
188
338
|
|
189
|
-
|
339
|
+
app.queue.enq(task, inputs)
|
340
|
+
task
|
190
341
|
end
|
191
342
|
|
192
343
|
# Creates an hash dump of self.
|
193
344
|
def to_hash
|
194
|
-
{
|
195
|
-
|
196
|
-
|
197
|
-
|
345
|
+
{ :tasks => tasks,
|
346
|
+
:joins => joins,
|
347
|
+
:queue => queue,
|
348
|
+
:middleware => middleware
|
198
349
|
}
|
199
350
|
end
|
200
351
|
|
@@ -202,5 +353,22 @@ module Tap
|
|
202
353
|
def dump(io=nil)
|
203
354
|
YAML.dump(to_hash, io)
|
204
355
|
end
|
356
|
+
|
357
|
+
protected
|
358
|
+
|
359
|
+
# helper to collect all tasks and tasks joined to task
|
360
|
+
def collect_tasks(task, collection=[]) # :nodoc:
|
361
|
+
unless collection.include?(task)
|
362
|
+
collection << task
|
363
|
+
|
364
|
+
task.joins.each do |join|
|
365
|
+
(join.inputs + join.outputs).each do |input|
|
366
|
+
collect_tasks(input, collection)
|
367
|
+
end
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
371
|
+
collection
|
372
|
+
end
|
205
373
|
end
|
206
374
|
end
|
data/lib/tap/schema/utils.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
module Tap
|
2
2
|
class Schema
|
3
3
|
module Utils
|
4
|
+
module_function
|
4
5
|
|
5
6
|
def instantiate(data, app)
|
6
7
|
case data
|
7
|
-
when Hash then data[
|
8
|
+
when Hash then data[:class].instantiate(data, app)
|
8
9
|
when Array then data.shift.parse!(data, app)
|
9
10
|
else raise "cannot instantiate: #{data.inspect}"
|
10
11
|
end
|
@@ -12,7 +13,7 @@ module Tap
|
|
12
13
|
|
13
14
|
def resolved?(data)
|
14
15
|
case data
|
15
|
-
when Hash then data[
|
16
|
+
when Hash then data[:class].respond_to?(:instantiate)
|
16
17
|
when Array then data[0].respond_to?(:parse!)
|
17
18
|
else false
|
18
19
|
end
|
@@ -24,7 +25,8 @@ module Tap
|
|
24
25
|
case data
|
25
26
|
when Hash
|
26
27
|
unless resolved?(data)
|
27
|
-
data
|
28
|
+
data = symbolize(data)
|
29
|
+
data[:class] = yield(data[:id]) || data[:id]
|
28
30
|
end
|
29
31
|
when Array
|
30
32
|
data[0] = yield(data[0]) || data[0]
|
data/lib/tap/task.rb
CHANGED
@@ -3,14 +3,28 @@ require 'tap/root'
|
|
3
3
|
require 'tap/env/string_ext'
|
4
4
|
|
5
5
|
module Tap
|
6
|
-
module Support
|
7
|
-
autoload(:Templater, 'tap/support/templater')
|
8
|
-
end
|
9
|
-
|
10
6
|
class App
|
11
|
-
# Generates a task initialized to self.
|
7
|
+
# Generates a task with the specified config, initialized to self.
|
8
|
+
#
|
9
|
+
# A block may be provided to overrride the process method; it will be
|
10
|
+
# called with the task instance, plus any inputs.
|
11
|
+
#
|
12
|
+
# no_inputs = app.task {|task| [] }
|
13
|
+
# one_input = app.task {|task, input| [input] }
|
14
|
+
# mixed_inputs = app.task {|task, a, b, *args| [a, b, args] }
|
15
|
+
#
|
16
|
+
# no_inputs.execute # => []
|
17
|
+
# one_input.execute(:a) # => [:a]
|
18
|
+
# mixed_inputs.execute(:a, :b) # => [:a, :b, []]
|
19
|
+
# mixed_inputs.execute(:a, :b, 1, 2, 3) # => [:a, :b, [1,2,3]]
|
20
|
+
#
|
12
21
|
def task(config={}, klass=Task, &block)
|
13
|
-
klass.
|
22
|
+
instance = klass.new(config, self)
|
23
|
+
if block_given?
|
24
|
+
instance.extend Intern
|
25
|
+
instance.process_block = block
|
26
|
+
end
|
27
|
+
instance
|
14
28
|
end
|
15
29
|
end
|
16
30
|
|
@@ -40,18 +54,6 @@ module Tap
|
|
40
54
|
# MixedInputs.new.execute(:a, :b) # => [:a, :b, []]
|
41
55
|
# MixedInputs.new.execute(:a, :b, 1, 2, 3) # => [:a, :b, [1,2,3]]
|
42
56
|
#
|
43
|
-
# Tasks may be created with new, or with intern. Intern overrides process
|
44
|
-
# using a block that receives the task and the inputs.
|
45
|
-
#
|
46
|
-
# no_inputs = Task.intern {|task| [] }
|
47
|
-
# one_input = Task.intern {|task, input| [input] }
|
48
|
-
# mixed_inputs = Task.intern {|task, a, b, *args| [a, b, args] }
|
49
|
-
#
|
50
|
-
# no_inputs.execute # => []
|
51
|
-
# one_input.execute(:a) # => [:a]
|
52
|
-
# mixed_inputs.execute(:a, :b) # => [:a, :b, []]
|
53
|
-
# mixed_inputs.execute(:a, :b, 1, 2, 3) # => [:a, :b, [1,2,3]]
|
54
|
-
#
|
55
57
|
# === Configuration
|
56
58
|
#
|
57
59
|
# Tasks are configurable. By default each task will be configured as
|
@@ -124,47 +126,31 @@ module Tap
|
|
124
126
|
include Configurable
|
125
127
|
|
126
128
|
class << self
|
127
|
-
# Returns class dependencies
|
128
|
-
attr_reader :dependencies
|
129
|
-
|
130
|
-
# Returns or initializes the instance of self cached with app.
|
131
|
-
def instance(app=Tap::App.instance, auto_initialize=true)
|
132
|
-
app.cache[self] ||= (auto_initialize ? new({}, app) : nil)
|
133
|
-
end
|
134
|
-
|
135
129
|
def inherited(child) # :nodoc:
|
136
130
|
unless child.instance_variable_defined?(:@source_file)
|
137
131
|
caller[0] =~ Lazydoc::CALLER_REGEXP
|
138
132
|
child.instance_variable_set(:@source_file, File.expand_path($1))
|
139
133
|
end
|
140
|
-
|
141
|
-
child.instance_variable_set(:@dependencies, dependencies.dup)
|
142
134
|
super
|
143
135
|
end
|
144
136
|
|
145
|
-
# Instantiates a new task with the input arguments and overrides
|
146
|
-
# process with the block. The block will be called with the task
|
147
|
-
# instance, plus any inputs.
|
148
|
-
#
|
149
|
-
# Simply instantiates a new task if no block is given.
|
150
|
-
def intern(config={}, app=Tap::App.instance, &block) # :yields: task, inputs...
|
151
|
-
instance = new(config, app)
|
152
|
-
if block_given?
|
153
|
-
instance.extend Support::Intern(:process)
|
154
|
-
instance.process_block = block
|
155
|
-
end
|
156
|
-
instance
|
157
|
-
end
|
158
|
-
|
159
137
|
# Parses the argv into an instance of self. By default parse
|
160
138
|
# parses an argh then calls instantiate, but there is no requirement
|
161
139
|
# that this occurs in subclasses.
|
162
|
-
|
163
|
-
|
140
|
+
#
|
141
|
+
# ==== Block Overrides
|
142
|
+
#
|
143
|
+
# For convenience, parse will yield the internal ConfigParser to the
|
144
|
+
# block, if given. This functionality was added to Task so they are
|
145
|
+
# more flexible in executable files but it is not a part of the API
|
146
|
+
# requirements for parse/parse!.
|
147
|
+
#
|
148
|
+
def parse(argv=ARGV, app=Tap::App.instance, &block) # :yields: opts
|
149
|
+
parse!(argv.dup, app, &block)
|
164
150
|
end
|
165
151
|
|
166
152
|
# Same as parse, but removes arguments destructively.
|
167
|
-
def parse!(argv=ARGV, app=Tap::App.instance)
|
153
|
+
def parse!(argv=ARGV, app=Tap::App.instance) # :yields: opts
|
168
154
|
opts = ConfigParser.new
|
169
155
|
|
170
156
|
unless configurations.empty?
|
@@ -177,12 +163,17 @@ module Tap
|
|
177
163
|
|
178
164
|
# add option to print help
|
179
165
|
opts.on("--help", "Print this help") do
|
180
|
-
|
181
|
-
|
182
|
-
|
166
|
+
lines = desc.kind_of?(Lazydoc::Comment) ? desc.wrap(77, 2, nil) : []
|
167
|
+
lines.collect! {|line| " #{line}"}
|
168
|
+
unless lines.empty?
|
169
|
+
line = '-' * 80
|
170
|
+
lines.unshift(line)
|
171
|
+
lines.push(line)
|
183
172
|
end
|
184
|
-
|
185
|
-
puts "#{
|
173
|
+
|
174
|
+
puts "#{self}#{desc.empty? ? '' : ' -- '}#{desc.to_s}"
|
175
|
+
puts lines.join("\n")
|
176
|
+
puts "usage: tap run -- #{to_s.underscore} #{args}"
|
186
177
|
puts
|
187
178
|
puts opts
|
188
179
|
exit
|
@@ -193,6 +184,8 @@ module Tap
|
|
193
184
|
opts.config.merge!(load_config(config_file))
|
194
185
|
end
|
195
186
|
|
187
|
+
yield(opts) if block_given?
|
188
|
+
|
196
189
|
# (note defaults are not added so they will not
|
197
190
|
# conflict with string keys from a config file)
|
198
191
|
argv = opts.parse!(argv, :add_defaults => false)
|
@@ -200,45 +193,13 @@ module Tap
|
|
200
193
|
instantiate({:config => opts.nested_config}, app)
|
201
194
|
end
|
202
195
|
|
203
|
-
# Instantiates an instance of self and returns an instance of self
|
204
|
-
# an array of arguments (implicitly to be enqued to the instance).
|
196
|
+
# Instantiates an instance of self and returns an instance of self.
|
205
197
|
def instantiate(argh={}, app=Tap::App.instance)
|
206
|
-
|
207
|
-
instance = new(config, app)
|
208
|
-
|
209
|
-
if argh[:cache]
|
210
|
-
if app.cache.has_key?(self) && app.cache[self] != instance
|
211
|
-
raise "cache already has an instance for: #{self}"
|
212
|
-
end
|
213
|
-
|
214
|
-
app.cache[self] = instance
|
215
|
-
end
|
216
|
-
|
217
|
-
instance
|
218
|
-
end
|
219
|
-
|
220
|
-
DEFAULT_HELP_TEMPLATE = %Q{<% desc = task_class::desc %>
|
221
|
-
<%= task_class %><%= desc.empty? ? '' : ' -- ' %><%= desc.to_s %>
|
222
|
-
|
223
|
-
<% desc = desc.kind_of?(Lazydoc::Comment) ? desc.wrap(77, 2, nil) : [] %>
|
224
|
-
<% unless desc.empty? %>
|
225
|
-
<%= '-' * 80 %>
|
226
|
-
|
227
|
-
<% desc.each do |line| %>
|
228
|
-
<%= line %>
|
229
|
-
<% end %>
|
230
|
-
<%= '-' * 80 %>
|
231
|
-
<% end %>
|
232
|
-
|
233
|
-
}
|
234
|
-
|
235
|
-
# Returns the class help.
|
236
|
-
def help
|
237
|
-
Tap::Support::Templater.new(DEFAULT_HELP_TEMPLATE, :task_class => self).build
|
198
|
+
new(argh[:config] || {}, app)
|
238
199
|
end
|
239
200
|
|
240
201
|
# Recursively loads path into a nested configuration file.
|
241
|
-
def load_config(path)
|
202
|
+
def load_config(path) # :nodoc:
|
242
203
|
# optimization to check for trivial paths
|
243
204
|
return {} if Root::Utils.trivial?(path)
|
244
205
|
|
@@ -249,44 +210,6 @@ module Tap
|
|
249
210
|
|
250
211
|
protected
|
251
212
|
|
252
|
-
# Sets a class-level dependency; when task class B depends_on another
|
253
|
-
# task class A, instances of B are initialized to depend on a shared
|
254
|
-
# instance of A. The shared instance is specific to an app and can
|
255
|
-
# be accessed through instance(app).
|
256
|
-
#
|
257
|
-
# If a non-nil name is specified, depends_on will create a reader of
|
258
|
-
# the dependency instance.
|
259
|
-
#
|
260
|
-
# class A < Tap::Task
|
261
|
-
# end
|
262
|
-
#
|
263
|
-
# class B < Tap::Task
|
264
|
-
# depends_on :a, A
|
265
|
-
# end
|
266
|
-
#
|
267
|
-
# app = Tap::App.new
|
268
|
-
# b = B.new({}, app)
|
269
|
-
# b.dependencies # => [A.instance(app)]
|
270
|
-
# b.a # => A.instance(app)
|
271
|
-
#
|
272
|
-
# Returns self.
|
273
|
-
def depends_on(name, dependency_class)
|
274
|
-
unless dependencies.include?(dependency_class)
|
275
|
-
dependencies << dependency_class
|
276
|
-
end
|
277
|
-
|
278
|
-
if name
|
279
|
-
# returns the resolved result of the dependency
|
280
|
-
define_method(name) do
|
281
|
-
dependency_class.instance(app)
|
282
|
-
end
|
283
|
-
|
284
|
-
public(name)
|
285
|
-
end
|
286
|
-
|
287
|
-
self
|
288
|
-
end
|
289
|
-
|
290
213
|
# Defines a task subclass with the specified configurations and process
|
291
214
|
# block. During initialization the subclass is instantiated and made
|
292
215
|
# accessible through the name method.
|
@@ -379,7 +302,6 @@ module Tap
|
|
379
302
|
end
|
380
303
|
|
381
304
|
instance_variable_set(:@source_file, __FILE__)
|
382
|
-
instance_variable_set(:@dependencies, [])
|
383
305
|
|
384
306
|
lazy_attr :desc, 'task'
|
385
307
|
lazy_attr :args, :process
|
@@ -407,15 +329,9 @@ module Tap
|
|
407
329
|
def initialize(config={}, app=Tap::App.instance)
|
408
330
|
@app = app
|
409
331
|
@joins = []
|
410
|
-
@dependencies = []
|
411
332
|
|
412
333
|
# initialize configs
|
413
334
|
initialize_config(config)
|
414
|
-
|
415
|
-
# setup class dependencies
|
416
|
-
self.class.dependencies.each do |dependency_class|
|
417
|
-
depends_on dependency_class.instance(app)
|
418
|
-
end
|
419
335
|
end
|
420
336
|
|
421
337
|
# Auditing method call. Resolves dependencies, executes method_name,
|
@@ -518,5 +434,12 @@ module Tap
|
|
518
434
|
def inspect
|
519
435
|
"#<#{self.class.to_s}:#{object_id} #{config.to_hash.inspect} >"
|
520
436
|
end
|
437
|
+
|
438
|
+
def to_hash
|
439
|
+
{
|
440
|
+
:class => self.class,
|
441
|
+
:config => config.to_hash
|
442
|
+
}
|
443
|
+
end
|
521
444
|
end
|
522
445
|
end
|