bahuvrihi-tap 0.10.6 → 0.10.7
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/rap +13 -5
- data/lib/tap.rb +0 -4
- data/lib/tap/app.rb +10 -138
- data/lib/tap/constants.rb +1 -1
- data/lib/tap/declarations.rb +201 -0
- data/lib/tap/env.rb +10 -2
- data/lib/tap/exe.rb +2 -2
- data/lib/tap/generator/generators/root/templates/Rakefile +1 -0
- data/lib/tap/generator/generators/root/templates/test/tap_test_suite.rb +1 -1
- data/lib/tap/spec.rb +38 -63
- data/lib/tap/spec/adapter.rb +8 -31
- data/lib/tap/spec/inheritable_class_test_root.rb +9 -0
- data/lib/tap/support/audit.rb +0 -2
- data/lib/tap/support/combinator.rb +83 -31
- data/lib/tap/support/configurable_class.rb +7 -7
- data/lib/tap/support/{dependable.rb → dependencies.rb} +9 -7
- data/lib/tap/support/executable.rb +226 -19
- data/lib/tap/support/gems/rake.rb +6 -3
- data/lib/tap/support/join.rb +87 -0
- data/lib/tap/support/joins.rb +13 -0
- data/lib/tap/support/joins/fork.rb +18 -0
- data/lib/tap/support/joins/merge.rb +20 -0
- data/lib/tap/support/joins/sequence.rb +21 -0
- data/lib/tap/support/joins/switch.rb +23 -0
- data/lib/tap/support/joins/sync_merge.rb +57 -0
- data/lib/tap/support/lazydoc/document.rb +10 -0
- data/lib/tap/support/node.rb +58 -0
- data/lib/tap/support/parser.rb +379 -0
- data/lib/tap/support/schema.rb +350 -0
- data/lib/tap/support/tdoc.rb +5 -0
- data/lib/tap/support/validation.rb +2 -0
- data/lib/tap/task.rb +26 -61
- data/lib/tap/test.rb +9 -82
- data/lib/tap/test/assertions.rb +38 -0
- data/lib/tap/test/extensions.rb +78 -0
- data/lib/tap/test/{file_methods.rb → file_test.rb} +64 -37
- data/lib/tap/test/{file_methods_class.rb → file_test_class.rb} +2 -2
- data/lib/tap/test/regexp_escape.rb +87 -0
- data/lib/tap/test/script_test.rb +46 -0
- data/lib/tap/test/script_tester.rb +109 -0
- data/lib/tap/test/{subset_methods.rb → subset_test.rb} +9 -9
- data/lib/tap/test/{subset_methods_class.rb → subset_test_class.rb} +22 -14
- data/lib/tap/test/{tap_methods.rb → tap_test.rb} +43 -6
- data/lib/tap/test/utils.rb +6 -3
- metadata +27 -24
- data/lib/tap/parser.rb +0 -619
- data/lib/tap/spec/file_methods.rb +0 -16
- data/lib/tap/spec/file_methods_class.rb +0 -13
- data/lib/tap/spec/subset_methods.rb +0 -14
- data/lib/tap/support/batchable.rb +0 -47
- data/lib/tap/support/batchable_class.rb +0 -107
- data/lib/tap/support/declarations.rb +0 -131
- data/lib/tap/support/lazydoc/declaration.rb +0 -20
- data/lib/tap/support/parsers/base.rb +0 -81
- data/lib/tap/support/parsers/server.rb +0 -113
- data/lib/tap/test/script_methods.rb +0 -75
- data/lib/tap/test/script_methods/regexp_escape.rb +0 -94
- data/lib/tap/test/script_methods/script_test.rb +0 -109
- data/lib/tap/workflow.rb +0 -161
data/bin/rap
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# usage: rap taskname {options} [args]
|
3
3
|
|
4
|
-
|
4
|
+
$:.unshift "#{File.dirname(__FILE__)}/../lib"
|
5
|
+
require 'tap/declarations'
|
5
6
|
|
6
7
|
# setup the environment
|
7
8
|
begin
|
@@ -11,9 +12,9 @@ begin
|
|
11
12
|
env = Tap::Exe.instantiate
|
12
13
|
|
13
14
|
# add the DEFAULT_TASK_FILE if it exists
|
14
|
-
task_file = File.expand_path('
|
15
|
+
task_file = File.expand_path('Tapfile')
|
15
16
|
if File.exists?(task_file)
|
16
|
-
env.
|
17
|
+
env.loads.unshift(task_file)
|
17
18
|
env.manifest(:tasks).search_paths << [Dir.pwd, task_file]
|
18
19
|
end
|
19
20
|
|
@@ -68,7 +69,11 @@ begin
|
|
68
69
|
puts Tap::Support::Lazydoc.usage(__FILE__)
|
69
70
|
puts
|
70
71
|
puts "=== tap tasks ==="
|
71
|
-
|
72
|
+
str = env.summarize(:tasks) do |const|
|
73
|
+
const.document.resolve
|
74
|
+
const.document[const.name]['manifest'].subject
|
75
|
+
end
|
76
|
+
puts str
|
72
77
|
puts
|
73
78
|
puts "=== rake tasks ==="
|
74
79
|
Tap::Tasks::Rake.new.enq('-T')
|
@@ -79,7 +84,10 @@ begin
|
|
79
84
|
puts "version #{Tap::VERSION} -- #{Tap::WEBSITE}"
|
80
85
|
exit
|
81
86
|
else
|
82
|
-
queues = env.build(ARGV)
|
87
|
+
queues = env.build(ARGV) do |args|
|
88
|
+
warn "warning: implict rake for [#{args.join(' ')}]"
|
89
|
+
Tap::Tasks::Rake
|
90
|
+
end
|
83
91
|
ARGV.clear
|
84
92
|
|
85
93
|
if queues.empty?
|
data/lib/tap.rb
CHANGED
@@ -14,10 +14,6 @@ require 'tap/constants'
|
|
14
14
|
require 'tap/exe'
|
15
15
|
require 'tap/task'
|
16
16
|
require 'tap/file_task'
|
17
|
-
require 'tap/workflow'
|
18
|
-
|
19
|
-
require 'tap/support/declarations'
|
20
|
-
Tap.extend Tap::Support::Declarations
|
21
17
|
|
22
18
|
# Apply platform-specific patches
|
23
19
|
# case RUBY_PLATFORM
|
data/lib/tap/app.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'logger'
|
2
2
|
require 'tap/support/aggregator'
|
3
|
+
require 'tap/support/dependencies'
|
3
4
|
require 'tap/support/executable_queue'
|
4
5
|
|
5
6
|
module Tap
|
@@ -77,8 +78,8 @@ module Tap
|
|
77
78
|
#
|
78
79
|
# t1 = Task.new {|task, input| input += 1 }
|
79
80
|
# t2 = Task.new {|task, input| input += 10 }
|
80
|
-
# Task.batch(t1, t2) # => [t1, t2]
|
81
81
|
#
|
82
|
+
# t1.batch_with(t2)
|
82
83
|
# t1.enq 0
|
83
84
|
#
|
84
85
|
# app.run
|
@@ -191,6 +192,8 @@ module Tap
|
|
191
192
|
# methods that have no <tt>on_complete</tt> block
|
192
193
|
attr_reader :aggregator
|
193
194
|
|
195
|
+
attr_reader :dependencies
|
196
|
+
|
194
197
|
config :debug, false, &c.flag # Flag debugging
|
195
198
|
config :force, false, &c.flag # Force execution at checkpoints
|
196
199
|
config :quiet, false, &c.flag # Suppress logging
|
@@ -222,6 +225,7 @@ module Tap
|
|
222
225
|
@state = State::READY
|
223
226
|
@queue = Support::ExecutableQueue.new
|
224
227
|
@aggregator = Support::Aggregator.new
|
228
|
+
@dependencies = Support::Dependencies.new
|
225
229
|
|
226
230
|
initialize_config(config)
|
227
231
|
self.logger = logger
|
@@ -270,9 +274,7 @@ module Tap
|
|
270
274
|
# aggregator unless an on_complete block is set. Returns the audited
|
271
275
|
# result.
|
272
276
|
def execute(m, inputs)
|
273
|
-
|
274
|
-
aggregator.store(_result) unless m.on_complete_block
|
275
|
-
_result
|
277
|
+
m._execute(*inputs)
|
276
278
|
end
|
277
279
|
|
278
280
|
# Sets state = State::READY unless the app is running. Returns self.
|
@@ -371,140 +373,6 @@ module Tap
|
|
371
373
|
m = object._method(method_name)
|
372
374
|
enq(m, *inputs)
|
373
375
|
end
|
374
|
-
|
375
|
-
# Sets a sequence workflow pattern for the tasks; each task will enque
|
376
|
-
# the next task with it's results.
|
377
|
-
#
|
378
|
-
# Notes:
|
379
|
-
# - Batched tasks will have the pattern set for each task in the batch
|
380
|
-
# - The current audited results are yielded to the block, if given,
|
381
|
-
# before the next task is enqued.
|
382
|
-
# - Executables may provided as well as tasks.
|
383
|
-
def sequence(tasks) # :yields: _result
|
384
|
-
current_task = tasks.shift
|
385
|
-
tasks.each do |next_task|
|
386
|
-
# simply pass results from one task to the next.
|
387
|
-
current_task.on_complete do |_result|
|
388
|
-
yield(_result) if block_given?
|
389
|
-
enq(next_task, _result)
|
390
|
-
end
|
391
|
-
current_task = next_task
|
392
|
-
end
|
393
|
-
end
|
394
|
-
|
395
|
-
# Sets a fork workflow pattern for the source task; each target
|
396
|
-
# will enque the results of source.
|
397
|
-
#
|
398
|
-
# Notes:
|
399
|
-
# - Batched tasks will have the pattern set for each task in the batch
|
400
|
-
# - The current audited results are yielded to the block, if given,
|
401
|
-
# before the next task is enqued.
|
402
|
-
# - Executables may provided as well as tasks.
|
403
|
-
def fork(source, targets) # :yields: _result
|
404
|
-
source.on_complete do |_result|
|
405
|
-
targets.each do |target|
|
406
|
-
yield(_result) if block_given?
|
407
|
-
enq(target, _result)
|
408
|
-
end
|
409
|
-
end
|
410
|
-
end
|
411
|
-
|
412
|
-
# Sets a simple merge workflow pattern for the source tasks. Each source
|
413
|
-
# enques target with it's result; no synchronization occurs, nor are
|
414
|
-
# results grouped before being sent to the target.
|
415
|
-
#
|
416
|
-
# Notes:
|
417
|
-
# - Batched tasks will have the pattern set for each task in the batch
|
418
|
-
# - The current audited results are yielded to the block, if given,
|
419
|
-
# before the next task is enqued.
|
420
|
-
# - Executables may provided as well as tasks.
|
421
|
-
def merge(target, sources) # :yields: _result
|
422
|
-
sources.each do |source|
|
423
|
-
# merging can use the existing audit trails... each distinct
|
424
|
-
# input is getting sent to one place (the target)
|
425
|
-
source.on_complete do |_result|
|
426
|
-
yield(_result) if block_given?
|
427
|
-
enq(target, _result)
|
428
|
-
end
|
429
|
-
end
|
430
|
-
end
|
431
|
-
|
432
|
-
# Sets a synchronized merge workflow for the source tasks. Results from
|
433
|
-
# each source task are collected and enqued as a single group to the target.
|
434
|
-
# The target is not enqued until all sources have completed. Raises an
|
435
|
-
# error if a source returns twice before the target is enqued.
|
436
|
-
#
|
437
|
-
# Notes:
|
438
|
-
# - Batched tasks will have the pattern set for each task in the batch
|
439
|
-
# - The current audited results are yielded to the block, if given,
|
440
|
-
# before the next task is enqued.
|
441
|
-
# - Executables may provided as well as tasks.
|
442
|
-
#
|
443
|
-
#-- TODO: add notes on testing and the way results are received
|
444
|
-
# (ie as a single object)
|
445
|
-
def sync_merge(target, sources) # :yields: _result
|
446
|
-
group = Array.new(sources.length, nil)
|
447
|
-
sources.each_with_index do |source, index|
|
448
|
-
batch_map = Hash.new(0)
|
449
|
-
batch_length = if source.kind_of?(Support::Batchable)
|
450
|
-
source.batch.each_with_index {|obj, i| batch_map[obj] = i }
|
451
|
-
source.batch.length
|
452
|
-
else
|
453
|
-
1
|
454
|
-
end
|
455
|
-
|
456
|
-
group[index] = Array.new(batch_length, nil)
|
457
|
-
|
458
|
-
source.on_complete do |_result|
|
459
|
-
batch_index = batch_map[_result._current_source]
|
460
|
-
|
461
|
-
if group[index][batch_index] != nil
|
462
|
-
raise "sync_merge collision... already got a result for #{_result._current_source}"
|
463
|
-
end
|
464
|
-
|
465
|
-
group[index][batch_index] = _result
|
466
|
-
|
467
|
-
unless group.flatten.include?(nil)
|
468
|
-
Support::Combinator.new(*group).each do |*combination|
|
469
|
-
# merge the source audits
|
470
|
-
_group_result = Support::Audit.merge(*combination)
|
471
|
-
|
472
|
-
yield(_group_result) if block_given?
|
473
|
-
target.enq(_group_result)
|
474
|
-
end
|
475
|
-
|
476
|
-
# reset the group array
|
477
|
-
group.collect! {|i| nil }
|
478
|
-
end
|
479
|
-
end
|
480
|
-
end
|
481
|
-
end
|
482
|
-
|
483
|
-
# Sets a choice workflow pattern for the source task. When the
|
484
|
-
# source task completes, switch yields the audited result to the
|
485
|
-
# block which then returns the index of the target to enque with
|
486
|
-
# the results. No target will be enqued if the index is false or
|
487
|
-
# nil; an error is raised if no target can be found for the
|
488
|
-
# specified index.
|
489
|
-
#
|
490
|
-
# Notes:
|
491
|
-
# - Batched tasks will have the pattern set for each task in the batch
|
492
|
-
# - The current audited results are yielded to the block, if given,
|
493
|
-
# before the next task is enqued.
|
494
|
-
# - Executables may provided as well as tasks.
|
495
|
-
def switch(source, targets) # :yields: _result
|
496
|
-
source.on_complete do |_result|
|
497
|
-
if index = yield(_result)
|
498
|
-
unless target = targets[index]
|
499
|
-
raise "no switch target for index: #{index}"
|
500
|
-
end
|
501
|
-
|
502
|
-
enq(target, _result)
|
503
|
-
else
|
504
|
-
aggregator.store(_result)
|
505
|
-
end
|
506
|
-
end
|
507
|
-
end
|
508
376
|
|
509
377
|
# Returns all aggregated, audited results for the specified tasks.
|
510
378
|
# Results are joined into a single array. Arrays of tasks are
|
@@ -531,6 +399,10 @@ module Tap
|
|
531
399
|
_results(tasks).collect {|_result| _result._current}
|
532
400
|
end
|
533
401
|
|
402
|
+
def inspect
|
403
|
+
"#<#{self.class.to_s}:#{object_id} root: #{root} >"
|
404
|
+
end
|
405
|
+
|
534
406
|
protected
|
535
407
|
|
536
408
|
# A hook for handling unknown configurations in subclasses, called from
|
data/lib/tap/constants.rb
CHANGED
@@ -0,0 +1,201 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/../tap"
|
2
|
+
autoload(:OpenStruct, 'ostruct')
|
3
|
+
|
4
|
+
module Tap
|
5
|
+
module Declarations
|
6
|
+
Lazydoc = Tap::Support::Lazydoc
|
7
|
+
|
8
|
+
module Lazydoc
|
9
|
+
class Declaration < Comment
|
10
|
+
def resolve(lines)
|
11
|
+
super
|
12
|
+
|
13
|
+
@subject = case
|
14
|
+
when content.empty? || content[0][0].to_s !~ /^::desc(.*)/ then ""
|
15
|
+
else
|
16
|
+
content[0].shift
|
17
|
+
$1.strip
|
18
|
+
end
|
19
|
+
|
20
|
+
self
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.set_declaration_base(base)
|
26
|
+
# TODO -- warn if base is Object -- conflict with Rake
|
27
|
+
declaration_base = base.to_s
|
28
|
+
declaration_base = "" if ["Object", "Tap"].include?(declaration_base)
|
29
|
+
|
30
|
+
base.instance_variable_set(:@tap_declaration_base, declaration_base.underscore)
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.included(base)
|
34
|
+
set_declaration_base(base)
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.extended(base)
|
38
|
+
set_declaration_base(base)
|
39
|
+
end
|
40
|
+
|
41
|
+
def tasc(*args, &block)
|
42
|
+
# in this scheme, arg_names will be empty
|
43
|
+
name, configs, dependencies, arg_names = resolve_args(args)
|
44
|
+
declare(Tap::Task, name, configs, dependencies, arg_names, &block)
|
45
|
+
end
|
46
|
+
|
47
|
+
def task(*args, &block)
|
48
|
+
name, configs, dependencies, arg_names = resolve_args(args)
|
49
|
+
|
50
|
+
task_class = declare(Tap::Task, name, configs, dependencies, arg_names) do |*inputs|
|
51
|
+
args = {}
|
52
|
+
arg_names.each do |arg_name|
|
53
|
+
break if inputs.empty?
|
54
|
+
args[arg_name] = inputs.shift
|
55
|
+
end
|
56
|
+
|
57
|
+
args = OpenStruct.new(args)
|
58
|
+
self.class::BLOCKS.each do |task_block|
|
59
|
+
case task_block.arity
|
60
|
+
when 0 then task_block.call()
|
61
|
+
when 1 then task_block.call(self)
|
62
|
+
else task_block.call(self, args)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
unless task_class.const_defined?(:BLOCKS)
|
68
|
+
task_class.const_set(:BLOCKS, [])
|
69
|
+
end
|
70
|
+
task_class::BLOCKS << block unless block == nil
|
71
|
+
|
72
|
+
task_class.instance
|
73
|
+
end
|
74
|
+
|
75
|
+
protected
|
76
|
+
|
77
|
+
def config(key, value=nil, options={}, &block)
|
78
|
+
if options[:desc] == nil
|
79
|
+
caller[0] =~ Lazydoc::CALLER_REGEXP
|
80
|
+
options[:desc] = Lazydoc.register($1, $3.to_i - 1)
|
81
|
+
end
|
82
|
+
|
83
|
+
[:config, key, value, options, block]
|
84
|
+
end
|
85
|
+
|
86
|
+
def config_attr(key, value=nil, options={}, &block)
|
87
|
+
if options[:desc] == nil
|
88
|
+
caller[0] =~ Lazydoc::CALLER_REGEXP
|
89
|
+
options[:desc] = Lazydoc.register($1, $3.to_i - 1)
|
90
|
+
end
|
91
|
+
|
92
|
+
[:config_attr, key, value, options, block]
|
93
|
+
end
|
94
|
+
|
95
|
+
def c
|
96
|
+
Tap::Support::Validation
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
# Resolve the arguments for a task/rule. Returns a triplet of
|
102
|
+
# [task_name, configs, prerequisites, arg_name_list].
|
103
|
+
#
|
104
|
+
# From Rake 0.8.3
|
105
|
+
# Changes:
|
106
|
+
# - no :needs support for the trailing Hash (which is now config)
|
107
|
+
def resolve_args(args)
|
108
|
+
task_name = args.shift
|
109
|
+
arg_names = args
|
110
|
+
configs = {}
|
111
|
+
needs = []
|
112
|
+
|
113
|
+
if task_name.is_a?(Hash)
|
114
|
+
hash = task_name
|
115
|
+
task_name = hash.keys[0]
|
116
|
+
needs = hash[task_name]
|
117
|
+
end
|
118
|
+
|
119
|
+
if arg_names.last.is_a?(Hash)
|
120
|
+
configs = arg_names.pop
|
121
|
+
end
|
122
|
+
|
123
|
+
needs = needs.respond_to?(:to_ary) ? needs.to_ary : [needs]
|
124
|
+
needs = needs.compact.collect do |need|
|
125
|
+
dependency, argv = case need
|
126
|
+
when Array then need
|
127
|
+
else [need, []]
|
128
|
+
end
|
129
|
+
|
130
|
+
unless dependency.kind_of?(Class)
|
131
|
+
dependency = declare(Tap::Task, dependency)
|
132
|
+
end
|
133
|
+
|
134
|
+
if dependency.ancestors.include?(Tap::Task)
|
135
|
+
[File.basename(dependency.default_name), dependency, argv]
|
136
|
+
else
|
137
|
+
raise ArgumentError, "malformed dependency declaration: #{need}"
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
[task_name, configs, needs, arg_names]
|
142
|
+
end
|
143
|
+
|
144
|
+
def arity(block)
|
145
|
+
arity = block.arity
|
146
|
+
|
147
|
+
case
|
148
|
+
when arity > 0 then arity -= 1
|
149
|
+
when arity < 0 then arity += 1
|
150
|
+
end
|
151
|
+
|
152
|
+
arity
|
153
|
+
end
|
154
|
+
|
155
|
+
def declare(klass, name, configs={}, dependencies=[], arg_names=[], &block)
|
156
|
+
# nest the constant name
|
157
|
+
base = (self.kind_of?(Module) ? self : self.class).instance_variable_get(:@tap_declaration_base)
|
158
|
+
name = File.join(base, name.to_s)
|
159
|
+
|
160
|
+
# generate the subclass
|
161
|
+
subclass = klass.subclass(name, configs, dependencies, &block)
|
162
|
+
|
163
|
+
# register documentation
|
164
|
+
caller[1] =~ Lazydoc::CALLER_REGEXP
|
165
|
+
subclass.source_file = File.expand_path($1)
|
166
|
+
lazydoc = subclass.lazydoc(false)
|
167
|
+
lazydoc[subclass.to_s]['manifest'] = lazydoc.register($3.to_i - 1, Lazydoc::Declaration)
|
168
|
+
|
169
|
+
if arg_names.empty?
|
170
|
+
arity = block_given? ? arity(block) : -1
|
171
|
+
case
|
172
|
+
when arity > 0
|
173
|
+
arg_names = Array.new(arity, "INPUT")
|
174
|
+
when arity < 0
|
175
|
+
arg_names = Array.new(-1 * arity - 1, "INPUT")
|
176
|
+
arg_names << "INPUTS..."
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
comment = Lazydoc::Comment.new
|
181
|
+
comment.subject = arg_names.join(' ')
|
182
|
+
lazydoc[subclass.to_s]['args'] = comment
|
183
|
+
|
184
|
+
# update any dependencies in instance
|
185
|
+
subclass.dependencies.each do |dependency, args|
|
186
|
+
subclass.instance.depends_on(dependency.instance, *args)
|
187
|
+
end
|
188
|
+
|
189
|
+
dir = File.dirname(lazydoc.source_file)
|
190
|
+
manifest = Tap::Env.instance_for(dir).manifest(:tasks).build
|
191
|
+
const_name = subclass.to_s
|
192
|
+
unless manifest.entries.find {|lookup, const| const.name == const_name }
|
193
|
+
manifest.entries << [const_name.underscore, Tap::Support::Constant.new(const_name, lazydoc.source_file)]
|
194
|
+
end
|
195
|
+
|
196
|
+
subclass
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
extend Declarations
|
201
|
+
end
|