tap 0.12.4 → 0.17.0

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