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