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