tap 0.12.4 → 0.17.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.
Files changed (102) hide show
  1. data/History +34 -0
  2. data/README +62 -41
  3. data/bin/tap +36 -40
  4. data/cmd/console.rb +14 -6
  5. data/cmd/manifest.rb +62 -58
  6. data/cmd/run.rb +49 -31
  7. data/doc/API +84 -0
  8. data/doc/Class Reference +83 -115
  9. data/doc/Examples/Command Line +36 -0
  10. data/doc/Examples/Workflow +40 -0
  11. data/lib/tap/app.rb +293 -214
  12. data/lib/tap/app/node.rb +43 -0
  13. data/lib/tap/app/queue.rb +77 -0
  14. data/lib/tap/app/stack.rb +16 -0
  15. data/lib/tap/app/state.rb +22 -0
  16. data/lib/tap/constants.rb +2 -2
  17. data/lib/tap/env.rb +400 -314
  18. data/lib/tap/env/constant.rb +227 -0
  19. data/lib/tap/env/gems.rb +63 -0
  20. data/lib/tap/env/manifest.rb +89 -0
  21. data/lib/tap/env/minimap.rb +292 -0
  22. data/lib/tap/{support → env}/string_ext.rb +2 -2
  23. data/lib/tap/exe.rb +113 -125
  24. data/lib/tap/join.rb +175 -0
  25. data/lib/tap/joins.rb +9 -0
  26. data/lib/tap/joins/switch.rb +44 -0
  27. data/lib/tap/joins/sync.rb +99 -0
  28. data/lib/tap/root.rb +100 -491
  29. data/lib/tap/root/utils.rb +220 -0
  30. data/lib/tap/{support → root}/versions.rb +31 -29
  31. data/lib/tap/schema.rb +248 -0
  32. data/lib/tap/schema/parser.rb +413 -0
  33. data/lib/tap/schema/utils.rb +82 -0
  34. data/lib/tap/support/intern.rb +19 -6
  35. data/lib/tap/support/templater.rb +8 -3
  36. data/lib/tap/task.rb +175 -171
  37. data/lib/tap/tasks/dump.rb +58 -0
  38. data/lib/tap/tasks/load.rb +62 -0
  39. metadata +30 -73
  40. data/cmd/destroy.rb +0 -27
  41. data/cmd/generate.rb +0 -27
  42. data/doc/Command Reference +0 -105
  43. data/doc/Syntax Reference +0 -234
  44. data/doc/Tutorial +0 -348
  45. data/lib/tap/dump.rb +0 -142
  46. data/lib/tap/file_task.rb +0 -384
  47. data/lib/tap/generator/arguments.rb +0 -13
  48. data/lib/tap/generator/base.rb +0 -176
  49. data/lib/tap/generator/destroy.rb +0 -60
  50. data/lib/tap/generator/generate.rb +0 -93
  51. data/lib/tap/generator/generators/command/command_generator.rb +0 -21
  52. data/lib/tap/generator/generators/command/templates/command.erb +0 -32
  53. data/lib/tap/generator/generators/config/config_generator.rb +0 -98
  54. data/lib/tap/generator/generators/generator/generator_generator.rb +0 -37
  55. data/lib/tap/generator/generators/generator/templates/task.erb +0 -27
  56. data/lib/tap/generator/generators/generator/templates/test.erb +0 -26
  57. data/lib/tap/generator/generators/root/root_generator.rb +0 -84
  58. data/lib/tap/generator/generators/root/templates/MIT-LICENSE +0 -22
  59. data/lib/tap/generator/generators/root/templates/README +0 -14
  60. data/lib/tap/generator/generators/root/templates/Rakefile +0 -84
  61. data/lib/tap/generator/generators/root/templates/Rapfile +0 -11
  62. data/lib/tap/generator/generators/root/templates/gemspec +0 -27
  63. data/lib/tap/generator/generators/root/templates/test/tap_test_helper.rb +0 -3
  64. data/lib/tap/generator/generators/task/task_generator.rb +0 -25
  65. data/lib/tap/generator/generators/task/templates/task.erb +0 -14
  66. data/lib/tap/generator/generators/task/templates/test.erb +0 -19
  67. data/lib/tap/generator/manifest.rb +0 -20
  68. data/lib/tap/generator/preview.rb +0 -69
  69. data/lib/tap/load.rb +0 -64
  70. data/lib/tap/spec.rb +0 -41
  71. data/lib/tap/support/aggregator.rb +0 -65
  72. data/lib/tap/support/audit.rb +0 -333
  73. data/lib/tap/support/constant.rb +0 -143
  74. data/lib/tap/support/constant_manifest.rb +0 -126
  75. data/lib/tap/support/dependencies.rb +0 -54
  76. data/lib/tap/support/dependency.rb +0 -44
  77. data/lib/tap/support/executable.rb +0 -198
  78. data/lib/tap/support/executable_queue.rb +0 -125
  79. data/lib/tap/support/gems.rb +0 -43
  80. data/lib/tap/support/join.rb +0 -144
  81. data/lib/tap/support/joins.rb +0 -12
  82. data/lib/tap/support/joins/switch.rb +0 -27
  83. data/lib/tap/support/joins/sync_merge.rb +0 -38
  84. data/lib/tap/support/manifest.rb +0 -171
  85. data/lib/tap/support/minimap.rb +0 -90
  86. data/lib/tap/support/node.rb +0 -176
  87. data/lib/tap/support/parser.rb +0 -450
  88. data/lib/tap/support/schema.rb +0 -385
  89. data/lib/tap/support/shell_utils.rb +0 -67
  90. data/lib/tap/test.rb +0 -77
  91. data/lib/tap/test/assertions.rb +0 -38
  92. data/lib/tap/test/env_vars.rb +0 -29
  93. data/lib/tap/test/extensions.rb +0 -73
  94. data/lib/tap/test/file_test.rb +0 -362
  95. data/lib/tap/test/file_test_class.rb +0 -15
  96. data/lib/tap/test/regexp_escape.rb +0 -87
  97. data/lib/tap/test/script_test.rb +0 -46
  98. data/lib/tap/test/script_tester.rb +0 -115
  99. data/lib/tap/test/subset_test.rb +0 -260
  100. data/lib/tap/test/subset_test_class.rb +0 -99
  101. data/lib/tap/test/tap_test.rb +0 -109
  102. data/lib/tap/test/utils.rb +0 -231
@@ -1,333 +0,0 @@
1
- module Tap
2
- module Support
3
-
4
- # Audit provides a way to track the values passed among tasks or, more
5
- # generally, any Executable. Audits collectively build a {directed
6
- # acyclic graph}[http://en.wikipedia.org/wiki/Directed_acyclic_graph]
7
- # of task execution and have great utility in debugging and record keeping.
8
- #
9
- # Audits record a key, a current value, and the previous audit(s) in the
10
- # trail. Keys are arbitrary identifiers of where the value comes from.
11
- # To illustrate, lets use symbols as keys.
12
- #
13
- # # initialize a new audit
14
- # _a = Audit.new(:one, 1)
15
- # _a.key # => :one
16
- # _a.value # => 1
17
- #
18
- # # build a short trail
19
- # _b = Audit.new(:two, 2, _a)
20
- # _c = Audit.new(:three, 3, _b)
21
- #
22
- # _a.sources # => []
23
- # _b.sources # => [_a]
24
- # _c.sources # => [_b]
25
- #
26
- # Audits allow you track back through the sources of each audit to build
27
- # a trail describing how a particular value was produced.
28
- #
29
- # _c.trail # => [_a,_b,_c]
30
- # _c.trail {|audit| audit.key } # => [:one, :two, :three]
31
- # _c.trail {|audit| audit.value } # => [1,2,3]
32
- #
33
- # Any number of audits may share the same source, so forks are naturally
34
- # supported.
35
- #
36
- # _d = Audit.new(:four, 4, _b)
37
- # _d.trail # => [_a,_b,_d]
38
- #
39
- # _e = Audit.new(:five, 5, _b)
40
- # _e.trail # => [_a,_b,_e]
41
- #
42
- # Merges are supported by specifying more than one source. Merges have
43
- # the effect of nesting audit trails within an array:
44
- #
45
- # _f = Audit.new(:six, 6)
46
- # _g = Audit.new(:seven, 7, _f)
47
- # _h = Audit.new(:eight, 8, [_c,_d,_g])
48
- # _h.trail # => [[[_a,_b,_c], [_a,_b,_d], [_f,_g]], _h]
49
- #
50
- # Nesting can get quite ugly after a couple merges so Audit provides a
51
- # scalable pretty-print dump that helps visualize the audit trail.
52
- #
53
- # "\n" + _h.dump
54
- # # => %q{
55
- # # o-[one] 1
56
- # # o-[two] 2
57
- # # |
58
- # # |-o-[three] 3
59
- # # | |
60
- # # `---o-[four] 4
61
- # # | |
62
- # # | | o-[six] 6
63
- # # | | o-[seven] 7
64
- # # | | |
65
- # # `-`-`-o-[eight] 8
66
- # # }
67
- #
68
- # In practice, tasks are recorded as keys. Thus audit trails can be used
69
- # to access task configurations and other information that may be useful
70
- # when creating reports or making workflow decisions. Note that by
71
- # convention Audits and non-Audit methods that return Audits are
72
- # prefixed with an underscore.
73
- #
74
- #--
75
- # Note Audit could easily be expanded to track sinks as well as sources.
76
- # In initialize:
77
- #
78
- # @sinks = []
79
- # sources.each do |source|
80
- # source.sinks << self
81
- # end
82
- #
83
- # The downside is that this may not circumvent cleanly if you want light
84
- # or no auditing. It also adds additonal references which will prevent
85
- # garbage collection. On the plus side, sinks will make it easier to
86
- # truly use Audits as a DAG
87
- class Audit
88
- class << self
89
-
90
- # Produces a pretty-print dump of the specified audits to target.
91
- # A block may be provided to format the trailer of each line.
92
- def dump(audits, target=$stdout) # :yields: audit
93
- return dump(audits, target) do |audit|
94
- "o-[#{audit.key}] #{audit.value.inspect}"
95
- end unless block_given?
96
-
97
- # arrayify audits
98
- audits = [audits].flatten
99
-
100
- # the order of audits
101
- order = []
102
-
103
- # (audit, sinks) hash preventing double iteration over
104
- # audits, and identifying sinks for a particular audit
105
- sinks = {}
106
-
107
- # iterate over all audits, collecting in order
108
- audits.each do |audit|
109
- traverse(audit, order, sinks)
110
- end
111
-
112
- # visit each audit, collecting audits into indent groups
113
- groups = []
114
- current = nil
115
- order.each do |audit|
116
- sources = audit.sources
117
- unless sources.length == 1 && sinks[sources[0]].length <= 1
118
- current = []
119
- groups << current
120
- end
121
-
122
- current << audit
123
- end
124
-
125
- # identify nodes at which a fork occurs... these are audits
126
- # that have more than one sink, and they cause a fork-style
127
- # leader to be printed
128
- forks = {}
129
- sinks.each_pair do |audit, audit_sinks|
130
- n = audit_sinks.length
131
- forks[audit] = [0, n] if n > 1
132
- end
133
-
134
- # setup print
135
- index = 0
136
- leader = ""
137
-
138
- # print each group
139
- groups.each do |group|
140
- sources = group[0].sources
141
- complete = audits.include?(group[-1])
142
-
143
- case
144
- when sources.length > 1
145
- # print a merge
146
- # `-`-`-o-[merge]
147
-
148
- leader =~ /^(.*)((\| *){#{sources.length}})$/
149
- leader = "#{$1}#{' ' * $2.length} "
150
- target << "#{$1}#{$2.gsub('|', '`').gsub(' ', '-')}-#{yield(group.shift)}\n"
151
-
152
- when fork = forks[sources[0]]
153
- # print a fork
154
- # |-o-[a]
155
- # |
156
- # `---o-[b]
157
-
158
- n = fork[0] += 1
159
- base = leader[0, leader.length - (2 * n - 1)]
160
- target << "#{base}#{fork[0] == fork[1] ? '`-' : '|-'}#{'--' * (n-1)}#{yield(group.shift)}\n"
161
- leader = "#{base}#{fork[0] == fork[1] ? ' ' : '| '}#{'| ' * (n-1)}"
162
-
163
- when index > 0
164
- # simply get ready to print the next series of audits
165
- # o-[a]
166
- # o-[b]
167
-
168
- leader = "#{leader} "
169
- leader = "" if leader.strip.empty?
170
- end
171
-
172
- # print the next series of audits
173
- group.each do |audit|
174
- target << "#{leader}#{yield(audit)}\n"
175
- end
176
-
177
- # add a continuation line, if necessary
178
- unless group == groups.last
179
- if complete
180
- leader = "#{leader} "
181
- else
182
- leader = "#{leader}|"
183
- end
184
- target << "#{leader}\n"
185
- end
186
-
187
- index += 1
188
- end
189
-
190
- target
191
- end
192
-
193
- protected
194
-
195
- # helper to determine the order and sinks for a node
196
- def traverse(node, order=[], sinks={}) # :nodoc:
197
- return if sinks.has_key?(node)
198
-
199
- node.sources.each do |source|
200
- traverse(source, order, sinks)
201
- (sinks[source] ||= []) << node
202
- end
203
-
204
- order << node
205
- end
206
- end
207
-
208
- # A key for self (typically the task producing value, or
209
- # nil if the value has an unknown origin)
210
- attr_reader :key
211
-
212
- # The current value
213
- attr_reader :value
214
-
215
- # Initializes a new Audit. Sources may be an array, a single value
216
- # (which is turned into an array), or nil (indicating no sources).
217
- #
218
- # _a = Audit.new(nil, nil, nil)
219
- # _a.sources # => []
220
- #
221
- # _b = Audit.new(nil, nil, _a)
222
- # _b.sources # => [_a]
223
- #
224
- # _c = Audit.new(nil, nil, [_a,_b])
225
- # _c.sources # => [_a,_b]
226
- #
227
- def initialize(key=nil, value=nil, sources=nil)
228
- @key = key
229
- @value = value
230
- @source = singularize(sources)
231
- end
232
-
233
- # An array of source audits for self. Sources may be empty.
234
- def sources
235
- arrayify(@source)
236
- end
237
-
238
- # Produces a fork of self for each item in value, using the index of
239
- # the item as a key. Splat is useful for developing each item of an
240
- # array value along different paths.
241
- #
242
- # _a = Audit.new(nil, [:x, :y, :z])
243
- # _b,_c,_d = _a.splat
244
- #
245
- # _b.key # => 0
246
- # _b.value # => :x
247
- #
248
- # _c.key # => 1
249
- # _c.value # => :y
250
- #
251
- # _d.key # => 2
252
- # _d.value # => :z
253
- # _d.trail # => [_a,_d]
254
- #
255
- # If value does not respond to 'each', an array with self as the only
256
- # member will be returned. This ensures that the result of splat
257
- # is an array of audits ready for further development.
258
- #
259
- # _a = Audit.new(nil, :value)
260
- # _a.splat # => [_a]
261
- #
262
- def splat
263
- return [self] unless value.respond_to?(:each)
264
-
265
- collection = []
266
- index = 0
267
- value.each do |obj|
268
- collection << Audit.new(index, obj, self)
269
- index += 1
270
- end
271
- collection
272
- end
273
-
274
- # Recursively collects an audit trail leading to self. Single sources
275
- # are collected into the trail directly, while multiple sources are
276
- # collected into arrays.
277
- #
278
- # _a = Audit.new(:one, 1)
279
- # _b = Audit.new(:two, 2, _a)
280
- # _b.trail # => [_a,_b]
281
- #
282
- # _a = Audit.new(:one, 1)
283
- # _b = Audit.new(:two, 2)
284
- # _c = Audit.new(:three, 3, [_a, _b])
285
- # _c.trail # => [[[_a],[_b]],_c]
286
- #
287
- # A block may be provided to collect a specific audit attribute
288
- # instead of the audit itself.
289
- #
290
- # _c.trail {|audit| audit.value } # => [[[1],[2]],3]
291
- #
292
- def trail(trail=[], &block)
293
- trail.unshift(block_given? ? block.call(self) : self)
294
-
295
- case @source
296
- when Audit
297
- @source.trail(trail, &block)
298
- when Array
299
- trail.unshift @source.collect {|audit| audit.trail(&block) }
300
- end
301
-
302
- trail
303
- end
304
-
305
- # A kind of pretty-print for Audits.
306
- def dump(&block)
307
- Audit.dump(self, "", &block)
308
- end
309
-
310
- private
311
-
312
- # helper to optimize storage of nodes
313
- def singularize(obj) # :nodoc:
314
- return obj unless obj.kind_of?(Array)
315
-
316
- case obj.length
317
- when 0 then nil
318
- when 1 then obj[0]
319
- else obj
320
- end
321
- end
322
-
323
- # helper to optimize storage of nodes
324
- def arrayify(obj) # :nodoc:
325
- case obj
326
- when nil then []
327
- when Array then obj
328
- else [obj]
329
- end
330
- end
331
- end
332
- end
333
- end
@@ -1,143 +0,0 @@
1
- require 'tap/support/string_ext'
2
-
3
- module Tap
4
- module Support
5
-
6
- # A Constant serves as a placeholder for an actual constant, sort of like
7
- # autoload. Use the constantize method to retrieve the actual constant;
8
- # if it doesn't exist, constantize requires require_path and tries again.
9
- #
10
- # Object.const_defined?(:Net) # => false
11
- # $".include?('net/http') # => false
12
- #
13
- # http = Constant.new('Net::HTTP', 'net/http')
14
- # http.constantize # => Net::HTTP
15
- # $".include?('net/http') # => true
16
- #
17
- class Constant
18
- class << self
19
-
20
- # Tries to find a declared constant under base with the specified
21
- # const_name. When a constant is missing, constantize yields
22
- # the current base and any non-existant constant names the block,
23
- # if given, or raises a NameError. The block is expected
24
- # to return the desired constant; in the example 'Non::Existant'
25
- # is effectively mapping to ConstName.
26
- #
27
- # module ConstName; end
28
- #
29
- # Constant.constantize('ConstName') # => ConstName
30
- # Constant.constantize('Non::Existant') { ConstName } # => ConstName
31
- #
32
- def constantize(const_name, base=Object) # :yields: base, missing_const_names
33
- unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ const_name
34
- raise NameError, "#{const_name.inspect} is not a valid constant name!"
35
- end
36
-
37
- constants = $1.split(/::/)
38
- while !constants.empty?
39
- unless const_is_defined?(base, constants[0])
40
- if block_given?
41
- return yield(base, constants)
42
- else
43
- raise NameError.new("uninitialized constant #{const_name}", constants[0])
44
- end
45
- end
46
- base = base.const_get(constants.shift)
47
- end
48
- base
49
- end
50
-
51
- private
52
-
53
- # helper method. Determines if a constant named
54
- # name is defined in const. The implementation
55
- # (annoyingly) has to be different for ruby 1.9
56
- # due to changes in the API.
57
- case RUBY_VERSION
58
- when /^1.9/
59
- def const_is_defined?(const, name) # :nodoc:
60
- const.const_defined?(name, false)
61
- end
62
- else
63
- def const_is_defined?(const, name) # :nodoc:
64
- const.const_defined?(name)
65
- end
66
- end
67
- end
68
-
69
- # The constant name
70
- attr_reader :name
71
-
72
- # The path to load to initialize a missing constant
73
- attr_reader :require_path
74
-
75
- # Initializes a new Constant with the specified constant name and
76
- # require_path. The name should be a valid constant name.
77
- def initialize(name, require_path=nil)
78
- @name = name
79
- @require_path = require_path
80
- end
81
-
82
- # Returns the underscored name.
83
- def path
84
- @path ||= name.underscore
85
- end
86
-
87
- # Returns the basename of path.
88
- def basename
89
- @basename ||= File.basename(path)
90
- end
91
-
92
- # Returns the path, minus the basename of path.
93
- def dirname
94
- @dirname ||= (dirname = File.dirname(path)) == "." ? "" : dirname
95
- end
96
-
97
- # Returns the name of the constant, minus nesting.
98
- def const_name
99
- @const_name ||= (name =~ /.*::(.*)$/ ? $1 : name)
100
- end
101
-
102
- # Returns the nesting constants of name.
103
- def nesting
104
- @nesting ||= (name =~ /(.*)::.*$/ ? $1 : '')
105
- end
106
-
107
- # Returns the number of constants in nesting.
108
- def nesting_depth
109
- @nesting_depth ||= nesting.split(/::/).length
110
- end
111
-
112
- # Returns the Lazydoc document for require_path.
113
- def document
114
- require_path ? Lazydoc[require_path] : nil
115
- end
116
-
117
- # True if another is a Constant with the same name
118
- # and require_path as self.
119
- def ==(another)
120
- another.kind_of?(Constant) &&
121
- another.name == self.name &&
122
- another.require_path == self.require_path
123
- end
124
-
125
- # Looks up and returns the constant indicated by name. If the constant
126
- # cannot be found, constantize requires require_path and tries again.
127
- #
128
- # Raises a NameError if the constant cannot be found.
129
- def constantize
130
- Constant.constantize(name) do
131
- require require_path if require_path
132
- Constant.constantize(name)
133
- end
134
- end
135
-
136
- # Returns a string like:
137
- # "#<Tap::Support::Constant:object_id Const::Name (require_path)>"
138
- def inspect
139
- "#<#{self.class}:#{object_id} #{name}#{@require_path == nil ? "" : " (#{@require_path})"}>"
140
- end
141
- end
142
- end
143
- end