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.
- data/History +34 -0
- data/README +62 -41
- data/bin/tap +36 -40
- data/cmd/console.rb +14 -6
- data/cmd/manifest.rb +62 -58
- data/cmd/run.rb +49 -31
- data/doc/API +84 -0
- data/doc/Class Reference +83 -115
- data/doc/Examples/Command Line +36 -0
- data/doc/Examples/Workflow +40 -0
- data/lib/tap/app.rb +293 -214
- data/lib/tap/app/node.rb +43 -0
- data/lib/tap/app/queue.rb +77 -0
- data/lib/tap/app/stack.rb +16 -0
- data/lib/tap/app/state.rb +22 -0
- data/lib/tap/constants.rb +2 -2
- data/lib/tap/env.rb +400 -314
- data/lib/tap/env/constant.rb +227 -0
- data/lib/tap/env/gems.rb +63 -0
- data/lib/tap/env/manifest.rb +89 -0
- data/lib/tap/env/minimap.rb +292 -0
- data/lib/tap/{support → env}/string_ext.rb +2 -2
- data/lib/tap/exe.rb +113 -125
- data/lib/tap/join.rb +175 -0
- data/lib/tap/joins.rb +9 -0
- data/lib/tap/joins/switch.rb +44 -0
- data/lib/tap/joins/sync.rb +99 -0
- data/lib/tap/root.rb +100 -491
- data/lib/tap/root/utils.rb +220 -0
- data/lib/tap/{support → root}/versions.rb +31 -29
- data/lib/tap/schema.rb +248 -0
- data/lib/tap/schema/parser.rb +413 -0
- data/lib/tap/schema/utils.rb +82 -0
- data/lib/tap/support/intern.rb +19 -6
- data/lib/tap/support/templater.rb +8 -3
- data/lib/tap/task.rb +175 -171
- data/lib/tap/tasks/dump.rb +58 -0
- data/lib/tap/tasks/load.rb +62 -0
- metadata +30 -73
- data/cmd/destroy.rb +0 -27
- data/cmd/generate.rb +0 -27
- data/doc/Command Reference +0 -105
- data/doc/Syntax Reference +0 -234
- data/doc/Tutorial +0 -348
- data/lib/tap/dump.rb +0 -142
- data/lib/tap/file_task.rb +0 -384
- data/lib/tap/generator/arguments.rb +0 -13
- data/lib/tap/generator/base.rb +0 -176
- data/lib/tap/generator/destroy.rb +0 -60
- data/lib/tap/generator/generate.rb +0 -93
- data/lib/tap/generator/generators/command/command_generator.rb +0 -21
- data/lib/tap/generator/generators/command/templates/command.erb +0 -32
- data/lib/tap/generator/generators/config/config_generator.rb +0 -98
- data/lib/tap/generator/generators/generator/generator_generator.rb +0 -37
- data/lib/tap/generator/generators/generator/templates/task.erb +0 -27
- data/lib/tap/generator/generators/generator/templates/test.erb +0 -26
- data/lib/tap/generator/generators/root/root_generator.rb +0 -84
- data/lib/tap/generator/generators/root/templates/MIT-LICENSE +0 -22
- data/lib/tap/generator/generators/root/templates/README +0 -14
- data/lib/tap/generator/generators/root/templates/Rakefile +0 -84
- data/lib/tap/generator/generators/root/templates/Rapfile +0 -11
- data/lib/tap/generator/generators/root/templates/gemspec +0 -27
- data/lib/tap/generator/generators/root/templates/test/tap_test_helper.rb +0 -3
- data/lib/tap/generator/generators/task/task_generator.rb +0 -25
- data/lib/tap/generator/generators/task/templates/task.erb +0 -14
- data/lib/tap/generator/generators/task/templates/test.erb +0 -19
- data/lib/tap/generator/manifest.rb +0 -20
- data/lib/tap/generator/preview.rb +0 -69
- data/lib/tap/load.rb +0 -64
- data/lib/tap/spec.rb +0 -41
- data/lib/tap/support/aggregator.rb +0 -65
- data/lib/tap/support/audit.rb +0 -333
- data/lib/tap/support/constant.rb +0 -143
- data/lib/tap/support/constant_manifest.rb +0 -126
- data/lib/tap/support/dependencies.rb +0 -54
- data/lib/tap/support/dependency.rb +0 -44
- data/lib/tap/support/executable.rb +0 -198
- data/lib/tap/support/executable_queue.rb +0 -125
- data/lib/tap/support/gems.rb +0 -43
- data/lib/tap/support/join.rb +0 -144
- data/lib/tap/support/joins.rb +0 -12
- data/lib/tap/support/joins/switch.rb +0 -27
- data/lib/tap/support/joins/sync_merge.rb +0 -38
- data/lib/tap/support/manifest.rb +0 -171
- data/lib/tap/support/minimap.rb +0 -90
- data/lib/tap/support/node.rb +0 -176
- data/lib/tap/support/parser.rb +0 -450
- data/lib/tap/support/schema.rb +0 -385
- data/lib/tap/support/shell_utils.rb +0 -67
- data/lib/tap/test.rb +0 -77
- data/lib/tap/test/assertions.rb +0 -38
- data/lib/tap/test/env_vars.rb +0 -29
- data/lib/tap/test/extensions.rb +0 -73
- data/lib/tap/test/file_test.rb +0 -362
- data/lib/tap/test/file_test_class.rb +0 -15
- data/lib/tap/test/regexp_escape.rb +0 -87
- data/lib/tap/test/script_test.rb +0 -46
- data/lib/tap/test/script_tester.rb +0 -115
- data/lib/tap/test/subset_test.rb +0 -260
- data/lib/tap/test/subset_test_class.rb +0 -99
- data/lib/tap/test/tap_test.rb +0 -109
- data/lib/tap/test/utils.rb +0 -231
data/doc/Tutorial
DELETED
@@ -1,348 +0,0 @@
|
|
1
|
-
= Tap (Task Application)
|
2
|
-
|
3
|
-
Tap is a framework for creating configurable, distributable tasks and workflows.
|
4
|
-
Although scalable for complex workflows, at it simplest tap works like a
|
5
|
-
supercharged rake. Using the rap executable, you can declare tasks using a
|
6
|
-
syntax almost identical to rake, but with added support for configurations and
|
7
|
-
documentation.
|
8
|
-
|
9
|
-
Note: this tutorial spans several modules in the {Tap-Suite}[http://tap.rubyforge.org/tap-suite].
|
10
|
-
Be sure to install both tap and rap (or the full suite) beforehand.
|
11
|
-
|
12
|
-
% gem install tap-suite
|
13
|
-
|
14
|
-
== Quickstart
|
15
|
-
|
16
|
-
If you've used rake, tap will be easy to pick up. To get started, make a
|
17
|
-
Rapfile with a simple task declaration:
|
18
|
-
|
19
|
-
[Rapfile]
|
20
|
-
|
21
|
-
# ::desc your basic goodnight moon task
|
22
|
-
# Says goodnight with a configurable message.
|
23
|
-
Rap.task(:goodnight, :obj, :message => 'goodnight') do |task, args|
|
24
|
-
puts "#{task.message} #{args.obj}\n"
|
25
|
-
end
|
26
|
-
|
27
|
-
Now from the command line:
|
28
|
-
|
29
|
-
% rap goodnight moon
|
30
|
-
goodnight moon
|
31
|
-
|
32
|
-
% rap goodnight world --message hello
|
33
|
-
hello world
|
34
|
-
|
35
|
-
% rap goodnight --help
|
36
|
-
Goodnight -- your basic goodnight moon task
|
37
|
-
--------------------------------------------------------------------------------
|
38
|
-
Says goodnight with a configurable message.
|
39
|
-
--------------------------------------------------------------------------------
|
40
|
-
usage: rap goodnight OBJ
|
41
|
-
|
42
|
-
configurations:
|
43
|
-
--message MESSAGE
|
44
|
-
|
45
|
-
options:
|
46
|
-
-h, --help Print this help
|
47
|
-
--name NAME Specify a name
|
48
|
-
--use FILE Loads inputs from file
|
49
|
-
|
50
|
-
Just like that you have a command-line application with inputs, configuration,
|
51
|
-
and documentation.
|
52
|
-
|
53
|
-
The declaration syntax is obviously similar to rake; configurations are new but
|
54
|
-
the task-block style is the same, as are inputs. Other rake constructs are
|
55
|
-
available. Here is a similar goodnight task using dependencies, rake-style.
|
56
|
-
|
57
|
-
[Rapfile]
|
58
|
-
|
59
|
-
# make the declarations available everywhere
|
60
|
-
# (normally they're accessed via Tap, as above)
|
61
|
-
include Rap::Declarations
|
62
|
-
|
63
|
-
namespace :example do
|
64
|
-
task(:say, :message) do |task, args|
|
65
|
-
print(args.message || 'goodnight')
|
66
|
-
end
|
67
|
-
|
68
|
-
desc "your basic goodnight moon task"
|
69
|
-
task({:goodnight => 'example:say'}, :obj) do |task, args|
|
70
|
-
puts " #{args.obj}\n"
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
And now from the command line:
|
75
|
-
|
76
|
-
% rap goodnight moon
|
77
|
-
goodnight moon
|
78
|
-
|
79
|
-
% rap goodnight world --* say hello
|
80
|
-
hello world
|
81
|
-
|
82
|
-
Unlike rake, rap inputs are written out individually and tasks are delimited
|
83
|
-
by a modified double-dash. Aside from that, you can see rap is basically a
|
84
|
-
supercharged rake. Furthermore, rap runs rake. Directly substitute rap for
|
85
|
-
rake on the command line and your tasks should run as normal (see the Rap
|
86
|
-
{Syntax Reference}[http://tap.rubyforge.org/rap/files/doc/Syntax%20Reference.html]
|
87
|
-
for more details).
|
88
|
-
|
89
|
-
However, supercharging rake isn't the point of Tap. Declarations bridge the
|
90
|
-
gap between rake and tap, but tap itself is a more general framework. To get
|
91
|
-
at other features like imperative workflows, testing, and distribution, we
|
92
|
-
have to go beyond rap and take a look at what declarations do.
|
93
|
-
|
94
|
-
Spoiler: declarations make subclasses of Tap::Task.
|
95
|
-
|
96
|
-
== Beyond Rap
|
97
|
-
|
98
|
-
Going back to the first example, lets take a look at how a task declaration
|
99
|
-
maps to a class definition:
|
100
|
-
|
101
|
-
[Rapfile]
|
102
|
-
|
103
|
-
# ::desc your basic goodnight moon task
|
104
|
-
# Says goodnight with a configurable message.
|
105
|
-
Rap.task(:goodnight, :obj, :message => 'goodnight') do
|
106
|
-
puts "#{task.message} #{args.obj}\n"
|
107
|
-
end
|
108
|
-
|
109
|
-
Here is a corresponding class:
|
110
|
-
|
111
|
-
# Goodnight::manifest your basic goodnight moon task
|
112
|
-
# Says goodnight with a configurable message.
|
113
|
-
class Goodnight < Tap::Task
|
114
|
-
config :message, 'goodnight'
|
115
|
-
|
116
|
-
def process(obj)
|
117
|
-
"#{message} #{obj}"
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
Simple enough; the name corresponds to the class, configurations (and
|
122
|
-
dependencies, although they aren't show) are written out individually, and the
|
123
|
-
block corresponds to process. There are a few differences, especially relating
|
124
|
-
to process, but for the moment lets gloss over them and see how Goodnight works.
|
125
|
-
|
126
|
-
goodnight = Goodnight.new
|
127
|
-
goodnight.message # => 'goodnight'
|
128
|
-
goodnight.process('moon') # => 'goodnight moon'
|
129
|
-
|
130
|
-
hello = Goodnight.new(:message => 'hello')
|
131
|
-
hello.message # => 'hello'
|
132
|
-
hello.process('world') # => 'hello world'
|
133
|
-
|
134
|
-
Totally straightforward. Goodnight stores the default configurations, each
|
135
|
-
instance has accessors to the configurations, and the defaults may be overridden
|
136
|
-
during initialization, or later. Class definitions allow validation/transformation
|
137
|
-
blocks to be specified for configurations. These blocks process inputs (ex the
|
138
|
-
string inputs from the command line), quite literally defining the writer for a
|
139
|
-
configuration accessor. A set of standard blocks are available through +c+, an
|
140
|
-
alias for the {Configurable::Validation}[http://tap.rubyforge.org/configurable/classes/Configurable/Validation.html]
|
141
|
-
module.
|
142
|
-
|
143
|
-
[lib/goodnight.rb]
|
144
|
-
|
145
|
-
# Goodnight::manifest a fancy goodnight moon task
|
146
|
-
# Says goodnight with a configurable message.
|
147
|
-
class Goodnight < Tap::Task
|
148
|
-
config :message, 'goodnight' # a goodnight message
|
149
|
-
config :reverse, false, &c.switch # reverses the message
|
150
|
-
config :n, 1, &c.integer # repeats message n times
|
151
|
-
|
152
|
-
def process(*objects)
|
153
|
-
print "#{reverse == true ? message.reverse : message} " * n
|
154
|
-
puts objects.join(', ')
|
155
|
-
puts
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
A few examples show a validation block in action:
|
160
|
-
|
161
|
-
goodnight = Goodnight.new
|
162
|
-
|
163
|
-
goodnight.n = 10
|
164
|
-
goodnight.n # => 10
|
165
|
-
|
166
|
-
goodnight.n = "100"
|
167
|
-
goodnight.n # => 100
|
168
|
-
|
169
|
-
goodnight.n = "not an integer" # !> ValidationError
|
170
|
-
|
171
|
-
Now from the command line:
|
172
|
-
|
173
|
-
% rap goodnight moon
|
174
|
-
goodnight moon
|
175
|
-
|
176
|
-
% rap goodnight moon mittens "little toy boat"
|
177
|
-
goodnight moon, mittens, little toy boat
|
178
|
-
|
179
|
-
% rap goodnight world --message hello --reverse --n 3
|
180
|
-
olleh olleh olleh world
|
181
|
-
|
182
|
-
% rap goodnight --help
|
183
|
-
Goodnight -- a fancy goodnight moon task
|
184
|
-
--------------------------------------------------------------------------------
|
185
|
-
Says goodnight with a configurable message.
|
186
|
-
--------------------------------------------------------------------------------
|
187
|
-
usage: rap goodnight OBJECTS...
|
188
|
-
|
189
|
-
configurations:
|
190
|
-
--message MESSAGE a goodnight message
|
191
|
-
--[no-]reverse reverses the message
|
192
|
-
--n N repeats message n times
|
193
|
-
|
194
|
-
options:
|
195
|
-
-h, --help Print this help
|
196
|
-
--name NAME Specify a name
|
197
|
-
--use FILE Loads inputs from file
|
198
|
-
|
199
|
-
Take a quick look at the documentation. Class definitions map documentation
|
200
|
-
and, in some cases, metadata to the command line; the configurations now have
|
201
|
-
comments and reverse is a switch! Rich mapping allows tasks to act as an
|
202
|
-
script interface, not unlike {OptionParser}[http://www.ruby-doc.org/stdlib/libdoc/optparse/rdoc/classes/OptionParser.html]
|
203
|
-
(check out the {Configurable}[http://tap.rubyforge.org/configurable/] gem and
|
204
|
-
specifically {ConfigParser}[http://tap.rubyforge.org/configurable/classes/ConfigParser.html]
|
205
|
-
for more details).
|
206
|
-
|
207
|
-
This is a stand-alone goodnight script:
|
208
|
-
|
209
|
-
[goodnight]
|
210
|
-
|
211
|
-
#!/usr/bin/env ruby
|
212
|
-
|
213
|
-
require 'rubygems'
|
214
|
-
require 'tap'
|
215
|
-
|
216
|
-
# Goodnight::manifest a goodnight moon script
|
217
|
-
# Says goodnight with a configurable message.
|
218
|
-
class Goodnight < Tap::Task
|
219
|
-
config :message, 'goodnight'
|
220
|
-
|
221
|
-
def process(obj)
|
222
|
-
puts "#{message} #{obj}\n"
|
223
|
-
end
|
224
|
-
end
|
225
|
-
|
226
|
-
instance, args = Goodnight.parse!(ARGV)
|
227
|
-
instance.execute(*args)
|
228
|
-
|
229
|
-
Now, from the command line:
|
230
|
-
|
231
|
-
% ./goodnight moon
|
232
|
-
goodnight moon
|
233
|
-
|
234
|
-
% ./goodnight --help
|
235
|
-
...
|
236
|
-
|
237
|
-
As simple as it is to take a task to the command line, it's nice to note that
|
238
|
-
tasks may be subclassed, tested, and distributed as usual. No magic, just
|
239
|
-
convenience.
|
240
|
-
|
241
|
-
== Tap
|
242
|
-
|
243
|
-
Tap comes with two executables, rap and tap. The tap executable is more
|
244
|
-
verbose than rap for running tasks, but it is more configurable, scalable, and
|
245
|
-
logically pure. Tap comes with a number of {commands}[link:/files/doc/Command%20Reference.html]
|
246
|
-
but we'll focus on generate to make, test, and package a task library. Begin
|
247
|
-
by creating a tap directory structure and a task:
|
248
|
-
|
249
|
-
% tap generate root sample
|
250
|
-
% cd sample
|
251
|
-
% tap generate task goodnight
|
252
|
-
|
253
|
-
Take a look at the task files and you find something like this:
|
254
|
-
|
255
|
-
[lib/goodnight.rb]
|
256
|
-
|
257
|
-
# Goodnight::manifest <replace with manifest summary>
|
258
|
-
# <replace with command line description>
|
259
|
-
|
260
|
-
# Goodnight Documentation
|
261
|
-
class Goodnight < Tap::Task
|
262
|
-
|
263
|
-
# <config file documentation>
|
264
|
-
config :message, 'goodnight' # a sample config
|
265
|
-
|
266
|
-
def process(name)
|
267
|
-
log message, name
|
268
|
-
"#{message} #{name}"
|
269
|
-
end
|
270
|
-
end
|
271
|
-
|
272
|
-
[test/goodnight_test.rb]
|
273
|
-
|
274
|
-
require File.join(File.dirname(__FILE__), 'tap_test_helper.rb')
|
275
|
-
require 'goodnight'
|
276
|
-
|
277
|
-
class GoodnightTest < Test::Unit::TestCase
|
278
|
-
acts_as_tap_test
|
279
|
-
|
280
|
-
def test_goodnight
|
281
|
-
task = Goodnight.new :message => "goodnight"
|
282
|
-
|
283
|
-
# a simple test
|
284
|
-
assert_equal({:message => 'goodnight'}, task.config)
|
285
|
-
assert_equal "goodnight moon", task.process("moon")
|
286
|
-
|
287
|
-
# a more complex test
|
288
|
-
task.enq("moon")
|
289
|
-
app.run
|
290
|
-
|
291
|
-
assert_equal ["goodnight moon"], app.results(task)
|
292
|
-
assert_audit_equal [[nil, "moon"], [task, "goodnight moon"]], app._results(task)[0]
|
293
|
-
end
|
294
|
-
end
|
295
|
-
|
296
|
-
Run the test:
|
297
|
-
|
298
|
-
% rap test
|
299
|
-
|
300
|
-
Run the task:
|
301
|
-
|
302
|
-
% rap goodnight moon
|
303
|
-
I[23:22:19] goodnight moon
|
304
|
-
|
305
|
-
Ok, lets share it. Print the current gemspec manifest:
|
306
|
-
|
307
|
-
% rap print_manifest
|
308
|
-
true README
|
309
|
-
Rakefile
|
310
|
-
lib/goodnight.rb
|
311
|
-
sample.gemspec
|
312
|
-
true tap.yml
|
313
|
-
test/goodnight_test.rb
|
314
|
-
true test/tap_test_helper.rb
|
315
|
-
true test/tap_test_suite.rb
|
316
|
-
|
317
|
-
As you can see, this needs an update to include the task file. Open up
|
318
|
-
sample.gemspec and fix the manifest.
|
319
|
-
|
320
|
-
[sample.gemspec]
|
321
|
-
|
322
|
-
Gem::Specification.new do |s|
|
323
|
-
s.name = "sample"
|
324
|
-
s.version = "0.0.1"
|
325
|
-
s.platform = Gem::Platform::RUBY
|
326
|
-
s.summary = "sample"
|
327
|
-
s.require_path = "lib"
|
328
|
-
s.add_dependency("tap")
|
329
|
-
s.files = %W{
|
330
|
-
lib/goodnight.rb
|
331
|
-
tap.yml
|
332
|
-
}
|
333
|
-
end
|
334
|
-
|
335
|
-
Now package the gem and install it (gem may require sudo):
|
336
|
-
|
337
|
-
% rap gem
|
338
|
-
% gem install pkg/sample-0.0.1.gem
|
339
|
-
|
340
|
-
Now you can say goodnight anywhere, using 'tap run' or rap:
|
341
|
-
|
342
|
-
% cd ~/Desktop
|
343
|
-
% tap run -- goodnight moon
|
344
|
-
goodnight moon
|
345
|
-
% rap goodnight opus
|
346
|
-
goodnight opus
|
347
|
-
|
348
|
-
And that is that.
|
data/lib/tap/dump.rb
DELETED
@@ -1,142 +0,0 @@
|
|
1
|
-
module Tap
|
2
|
-
|
3
|
-
# :startdoc::manifest the default dump task
|
4
|
-
#
|
5
|
-
# A dump task to output results. Unlike most tasks, dump does not enque
|
6
|
-
# arguments from the command line; instead command line arguments are only
|
7
|
-
# used to setup the dump. Specifically dump accepts a filepath.
|
8
|
-
#
|
9
|
-
# % tap run -- [task] --: dump FILEPATH
|
10
|
-
#
|
11
|
-
# Results that come to dump are appended to the file. Dump only accepts
|
12
|
-
# one object at a time, so joins that produce an array need to iterate
|
13
|
-
# outputs to dump:
|
14
|
-
#
|
15
|
-
# % tap run -- load hello -- load world "--2(0,1)i" dump
|
16
|
-
#
|
17
|
-
# Note that dump uses $stdout by default so you can pipe or redirect dumps
|
18
|
-
# as normal.
|
19
|
-
#
|
20
|
-
# % tap run -- load hello --: dump | cat
|
21
|
-
# hello
|
22
|
-
#
|
23
|
-
# % tap run -- load hello --: dump 1> results.txt
|
24
|
-
# % cat results.txt
|
25
|
-
# hello
|
26
|
-
#
|
27
|
-
# :startdoc::manifest-
|
28
|
-
#
|
29
|
-
# Dump serves as a baseclass for more complicated dump tasks. A YAML dump
|
30
|
-
# task (see {tap-tasks}[http://tap.rubyforge.org/tap-tasks]) looks like this:
|
31
|
-
#
|
32
|
-
# class Yaml < Tap::Dump
|
33
|
-
# def dump(obj, io)
|
34
|
-
# YAML.dump(obj, io)
|
35
|
-
# end
|
36
|
-
# end
|
37
|
-
#
|
38
|
-
# === Implementation Notes
|
39
|
-
#
|
40
|
-
# Dump passes on the command line arguments to setup rather than process.
|
41
|
-
# Moreover, process will always receive the audits passed to _execute, rather
|
42
|
-
# than the audit values. This allows a user to provide setup arguments (such
|
43
|
-
# as a dump path) on the command line, and provides dump the opportunity to
|
44
|
-
# inspect audit trails within process.
|
45
|
-
#
|
46
|
-
class Dump < Tap::Task
|
47
|
-
class << self
|
48
|
-
|
49
|
-
# Same as an ordinary parse!, except the arguments normally reserved for
|
50
|
-
# executing the task are used to call setup. The return will always be
|
51
|
-
# an instance and an empty array.
|
52
|
-
def parse!(argv=ARGV, app=Tap::App.instance)
|
53
|
-
instance, args = super
|
54
|
-
instance.setup(*args)
|
55
|
-
[instance, []]
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
lazy_attr :args, :setup
|
60
|
-
lazy_register :setup, Lazydoc::Arguments
|
61
|
-
|
62
|
-
config :date_format, '%Y-%m-%d %H:%M:%S' # The date format
|
63
|
-
config :audit, false, &c.switch # Include the audit trails
|
64
|
-
config :date, false, &c.switch # Include a date
|
65
|
-
|
66
|
-
# The dump target, by default $stdout. Target may be a filepath,
|
67
|
-
# in which case dumps append the file.
|
68
|
-
attr_accessor :target
|
69
|
-
|
70
|
-
def initialize(config={}, name=nil, app=App.instance)
|
71
|
-
super(config, name, app)
|
72
|
-
@target = $stdout
|
73
|
-
end
|
74
|
-
|
75
|
-
# Setup self with the input target. Setup receives arguments passed from
|
76
|
-
# the command line, via parse!
|
77
|
-
def setup(output=$stdout)
|
78
|
-
@target = output
|
79
|
-
self
|
80
|
-
end
|
81
|
-
|
82
|
-
# Overrides the standard _execute to send process the audits and not
|
83
|
-
# the audit values. This allows process to inspect audit trails.
|
84
|
-
def _execute(input)
|
85
|
-
resolve_dependencies
|
86
|
-
|
87
|
-
previous = input.kind_of?(Support::Audit) ? input : Support::Audit.new(nil, input)
|
88
|
-
input = previous.value
|
89
|
-
|
90
|
-
# this is the overridden part
|
91
|
-
audit = Support::Audit.new(self, input, app.audit ? previous : nil)
|
92
|
-
send(method_name, audit)
|
93
|
-
|
94
|
-
if complete_block = on_complete_block || app.on_complete_block
|
95
|
-
complete_block.call(audit)
|
96
|
-
else
|
97
|
-
app.aggregator.store(audit)
|
98
|
-
end
|
99
|
-
|
100
|
-
audit
|
101
|
-
end
|
102
|
-
|
103
|
-
# The default process prints dump headers as specified in the config,
|
104
|
-
# then append the audit value to io.
|
105
|
-
def process(_audit)
|
106
|
-
open_io(target) do |io|
|
107
|
-
if date
|
108
|
-
io.puts "# date: #{Time.now.strftime(date_format)}"
|
109
|
-
end
|
110
|
-
|
111
|
-
if audit
|
112
|
-
io.puts "# audit:"
|
113
|
-
io.puts "# #{_audit.dump.gsub("\n", "\n# ")}"
|
114
|
-
end
|
115
|
-
|
116
|
-
dump(_audit.value, io)
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
# Dumps the object to io, by default dump puts (not prints) obj.to_s.
|
121
|
-
def dump(obj, io)
|
122
|
-
io.puts obj.to_s
|
123
|
-
end
|
124
|
-
|
125
|
-
protected
|
126
|
-
|
127
|
-
# helper to open and yield the io specified by target. open_io
|
128
|
-
# ensures file targets are closed when the block returns.
|
129
|
-
def open_io(io) # :nodoc:
|
130
|
-
case io
|
131
|
-
when IO, StringIO
|
132
|
-
yield(io)
|
133
|
-
when String
|
134
|
-
dir = File.dirname(io)
|
135
|
-
FileUtils.mkdir_p(dir) unless File.directory?(dir)
|
136
|
-
File.open(io, 'a') {|file| yield(file) }
|
137
|
-
else
|
138
|
-
raise "cannot open io: #{target.inspect}"
|
139
|
-
end
|
140
|
-
end
|
141
|
-
end
|
142
|
-
end
|