objective_command 0.1.5.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/AUTHORS +5 -0
- data/ChangeLog +17 -0
- data/NEWS +3 -0
- data/README +2 -0
- data/Rakefile +8 -0
- data/SPEC.gemspec +15 -0
- data/SPEC.yml +43 -0
- data/bin/ocmd +32 -0
- data/lib/hookable.rb +284 -0
- data/lib/hooker.rb +47 -0
- data/lib/objective_command/all.rb +32 -0
- data/lib/objective_command/commands/command.rb +535 -0
- data/lib/objective_command/commands/factory.rb +69 -0
- data/lib/objective_command/commands/pipe.rb +121 -0
- data/lib/objective_command/commands/seq.rb +35 -0
- data/lib/objective_command/datas/composite.rb +55 -0
- data/lib/objective_command/datas/data.rb +175 -0
- data/lib/objective_command/datas/factory.rb +74 -0
- data/lib/objective_command/datas/pipe.rb +55 -0
- data/lib/objective_command/datas/temp.rb +24 -0
- data/lib/objective_command/datas.rb +11 -0
- data/lib/objective_command/helpers.rb +113 -0
- data/lib/objective_command/runners/exec.rb +46 -0
- data/lib/objective_command/runners/fork.rb +91 -0
- data/lib/objective_command/runners/mockable.rb +62 -0
- data/lib/objective_command/runners/no_run.rb +44 -0
- data/lib/objective_command/runners/popen.rb +49 -0
- data/lib/objective_command/runners/runner.rb +227 -0
- data/lib/objective_command/runners/system.rb +54 -0
- data/lib/objective_command/runners.rb +11 -0
- data/lib/objective_command/shell.rb +173 -0
- data/lib/objective_command/version_id.rb +10 -0
- data/lib/objective_command.rb +54 -0
- data/test/check-objective_command.yml +10 -0
- data/test/check-pkg-objective_command.yml +13 -0
- data/test/sanity/multiple-requires.yml +62 -0
- data/test/sanity/single-requires.yml +40 -0
- data/test/sanity-suite.yml +10 -0
- data/test/unit-suite.yml +14 -0
- metadata +97 -0
@@ -0,0 +1,535 @@
|
|
1
|
+
# Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
|
2
|
+
# Copyright:: Copyright (c) 2005, 2006 Nicolas Pouillard. All rights reserved.
|
3
|
+
# License:: GNU General Public License (GPL).
|
4
|
+
# Revision:: $Id: /w/fey/cmd/trunk/lib/objective_command/commands/command.rb 29674 2006-09-12T21:05:16.387536Z ertai $
|
5
|
+
|
6
|
+
module ObjectiveCommand
|
7
|
+
|
8
|
+
module Commands
|
9
|
+
|
10
|
+
class Command
|
11
|
+
|
12
|
+
attr_accessor :command
|
13
|
+
attr_accessor :dir
|
14
|
+
attr_accessor :input
|
15
|
+
attr_accessor :output
|
16
|
+
attr_accessor :error
|
17
|
+
attr_accessor :args
|
18
|
+
attr_accessor :open_mode
|
19
|
+
|
20
|
+
#
|
21
|
+
# Construction methods.
|
22
|
+
#
|
23
|
+
|
24
|
+
def initialize ( command_name, *args )
|
25
|
+
@command = command_name
|
26
|
+
@args = args.flatten
|
27
|
+
@open_mode = :w
|
28
|
+
@dir = nil
|
29
|
+
@input, @output, @error = nil, nil, nil
|
30
|
+
end
|
31
|
+
|
32
|
+
#
|
33
|
+
# Running methods.
|
34
|
+
#
|
35
|
+
|
36
|
+
@@default_runners = {}
|
37
|
+
def run_with_options ( runner_class, options )
|
38
|
+
if options.empty?
|
39
|
+
runner = @@default_runners[runner_class] ||= runner_class.new
|
40
|
+
else
|
41
|
+
runner = runner_class.new.apply_options options
|
42
|
+
end
|
43
|
+
run(runner)
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
# Simulate Kernel#system() to run the command (No shell expansion).
|
48
|
+
def system ( *options )
|
49
|
+
run_with_options(Runners::System, options.flatten)
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
# Use the ExecRunner.
|
54
|
+
def exec ( *options )
|
55
|
+
run_with_options(Runners::Exec, options.flatten)
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
# FIXME test me
|
60
|
+
def sys ( *options )
|
61
|
+
run_with_options(Runners::System, [:v, :r] + options.flatten)
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
# Use Kernel#system() but with a string to have the shell expansion.
|
66
|
+
# FIXME make me a runner
|
67
|
+
def sh
|
68
|
+
Kernel.system(to_sh)
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
# Use Kernel#exec() but with a string to have the shell expansion.
|
73
|
+
# FIXME make me a runner
|
74
|
+
def sh!
|
75
|
+
Kernel.exec(to_sh)
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
# Use Kernel#` and return the resulting string.
|
80
|
+
# FIXME make me a runner
|
81
|
+
def expand
|
82
|
+
`#{to_sh}`
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
def popen ( *options )
|
87
|
+
run_with_options(Runners::Popen, options.flatten)
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
def fork ( *options )
|
92
|
+
run_with_options(Runners::Fork, options.flatten)
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
# FIXME design me!
|
97
|
+
# FIXME make me a runner
|
98
|
+
def ruby
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
# Use a ObjectiveCommand::Runners::Runner and return a ObjectiveCommand::Datas::Data.
|
103
|
+
def run ( runner=@runner )
|
104
|
+
unless runner.respond_to? :run
|
105
|
+
raise ArgumentError, "need a runner not: #{runner.inspect}"
|
106
|
+
end
|
107
|
+
runner.run(self)
|
108
|
+
end
|
109
|
+
|
110
|
+
|
111
|
+
|
112
|
+
#
|
113
|
+
# Operators.
|
114
|
+
#
|
115
|
+
|
116
|
+
|
117
|
+
# Pipe two commands.
|
118
|
+
def | ( rhs )
|
119
|
+
Commands::Pipe.new(self, rhs)
|
120
|
+
end
|
121
|
+
|
122
|
+
|
123
|
+
# Supply return a new commands with these arguments added.
|
124
|
+
def [] ( *args )
|
125
|
+
cmd = dup
|
126
|
+
cmd.args += args.flatten
|
127
|
+
cmd
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
# Chain two commands (like a `;' in shell), and return a new one.
|
132
|
+
def + ( rhs )
|
133
|
+
case rhs
|
134
|
+
when Command
|
135
|
+
Seq.new(self, rhs)
|
136
|
+
else
|
137
|
+
self[rhs]
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
# Return a new command with the given command input.
|
143
|
+
def < ( arg )
|
144
|
+
cmd = dup
|
145
|
+
cmd.input = arg
|
146
|
+
cmd
|
147
|
+
end
|
148
|
+
|
149
|
+
|
150
|
+
def add_outputs ( out, err )
|
151
|
+
cmd = dup
|
152
|
+
cmd.output = out.dup if out
|
153
|
+
cmd.error = err.dup if err
|
154
|
+
cmd
|
155
|
+
end
|
156
|
+
protected :add_outputs
|
157
|
+
|
158
|
+
|
159
|
+
# Return a new command with the given command output.
|
160
|
+
def > ( arg )
|
161
|
+
out, err = (arg.is_a?(Array))? arg : [arg, nil]
|
162
|
+
add_outputs(out, err)
|
163
|
+
end
|
164
|
+
|
165
|
+
|
166
|
+
# Like > but open the output in append mode.
|
167
|
+
def >> ( arg )
|
168
|
+
out, err = (arg.is_a?(Array))? arg : [arg, nil]
|
169
|
+
@open_mode = :a
|
170
|
+
add_outputs(out, err)
|
171
|
+
end
|
172
|
+
|
173
|
+
|
174
|
+
# Add an argument to a command.
|
175
|
+
# cmd = Command.new('ls')
|
176
|
+
# cmd << '-la'
|
177
|
+
# cmd.sh
|
178
|
+
def << ( arg )
|
179
|
+
@args << arg
|
180
|
+
self
|
181
|
+
end
|
182
|
+
|
183
|
+
|
184
|
+
|
185
|
+
#
|
186
|
+
# Misc
|
187
|
+
#
|
188
|
+
|
189
|
+
def arg_string
|
190
|
+
@args.map { |arg| arg.to_s.to_sh }.join(' ')
|
191
|
+
end
|
192
|
+
|
193
|
+
def whereis ( path=ENV['PATH'] )
|
194
|
+
# FIXME
|
195
|
+
end
|
196
|
+
|
197
|
+
|
198
|
+
#
|
199
|
+
# Conversion methods
|
200
|
+
#
|
201
|
+
|
202
|
+
def to_s
|
203
|
+
str = @command.to_s.to_sh
|
204
|
+
arg_str = arg_string
|
205
|
+
str += ' ' + arg_str unless arg_str.empty?
|
206
|
+
str
|
207
|
+
end
|
208
|
+
|
209
|
+
|
210
|
+
def to_sh
|
211
|
+
cmd = instanciate_args
|
212
|
+
"#{cmd.to_s}#{cmd.sh_args}"
|
213
|
+
end
|
214
|
+
|
215
|
+
|
216
|
+
def inspect_for_unified_matchers
|
217
|
+
"#{to_s.inspect}.to_ocmd"
|
218
|
+
end
|
219
|
+
|
220
|
+
|
221
|
+
def instanciate_args!
|
222
|
+
if defined? @input and @input and @args.include? '%i'
|
223
|
+
@args.map! { |a| (a == '%i')? @input : a }
|
224
|
+
@input = nil
|
225
|
+
end
|
226
|
+
if defined? @output and @output and @args.include? '%o'
|
227
|
+
@args.map! { |a| (a == '%o')? @output : a }
|
228
|
+
@output = nil
|
229
|
+
end
|
230
|
+
if defined? @error and @error and @args.include? '%e'
|
231
|
+
@args.map! { |a| (a == '%e')? @error : a }
|
232
|
+
@error = nil
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
def instanciate_args
|
237
|
+
copy = dup
|
238
|
+
copy.instanciate_args!
|
239
|
+
copy
|
240
|
+
end
|
241
|
+
|
242
|
+
def sh_args
|
243
|
+
args = ''
|
244
|
+
[ ['<', input], ['>', output], ['2>', error] ].each do |str, io|
|
245
|
+
args += " #{str} #{io.to_s.to_sh}" if io and not (io.respond_to? :pipe? and io.pipe?)
|
246
|
+
end
|
247
|
+
args
|
248
|
+
end
|
249
|
+
|
250
|
+
|
251
|
+
def to_a
|
252
|
+
[@command.dup, *@args.map { |arg| arg.to_s }]
|
253
|
+
end
|
254
|
+
|
255
|
+
def to_ocmd
|
256
|
+
self
|
257
|
+
end
|
258
|
+
|
259
|
+
def freeze
|
260
|
+
super
|
261
|
+
for i in [@command, @dir, @input, @output, @error, @args] do
|
262
|
+
i.freeze
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
end # class Command
|
267
|
+
|
268
|
+
Helpers.import!
|
269
|
+
|
270
|
+
test_section __FILE__ do
|
271
|
+
|
272
|
+
class CommandTest < Test::Unit::TestCase
|
273
|
+
|
274
|
+
def setup
|
275
|
+
@file = TempPath.new
|
276
|
+
@tmp = TempPath.new
|
277
|
+
@tmp2 = TempPath.new
|
278
|
+
@file.open('w') { |f| f.puts "bla bla\n foo bar"}
|
279
|
+
ENV['TEST_FILE'] = @file.to_s
|
280
|
+
@touch = Command.new('touch')
|
281
|
+
@cp = Command.new('cp')
|
282
|
+
@cat = Command.new('cat')
|
283
|
+
@wc = Command.new('wc')
|
284
|
+
@sleep = Command.new('sleep')
|
285
|
+
@dne = Command.new('ThisCommandDoesNotExist')
|
286
|
+
@dev_null = Pathname.new('/dev/null')
|
287
|
+
end
|
288
|
+
|
289
|
+
def teardown
|
290
|
+
[@file, @tmp, @tmp2].each { |t| t.clean }
|
291
|
+
end
|
292
|
+
|
293
|
+
def test_0_initialize
|
294
|
+
end
|
295
|
+
|
296
|
+
def test_system_dne
|
297
|
+
@dne.system
|
298
|
+
assert_equal(127, $?.exitstatus)
|
299
|
+
end
|
300
|
+
|
301
|
+
def test_system
|
302
|
+
@touch << @tmp.to_s
|
303
|
+
@touch.system
|
304
|
+
assert_equal(0, $?)
|
305
|
+
assert(@tmp.exist?)
|
306
|
+
end
|
307
|
+
|
308
|
+
def test_system_raise_on_failures
|
309
|
+
assert_raise(Runners::Runner::FailureHooker::Error) do
|
310
|
+
'false'.to_ocmd.system(:r)
|
311
|
+
end
|
312
|
+
assert_not_equal(0, $?)
|
313
|
+
end
|
314
|
+
|
315
|
+
def test_sh_and_pipe
|
316
|
+
((@cat | @wc) < @file > @tmp).sh
|
317
|
+
assert_equal(0, $?)
|
318
|
+
assert(@tmp.exist?)
|
319
|
+
assert_match(/\s*2\s*4\s*17\s+/, @tmp.read)
|
320
|
+
end
|
321
|
+
|
322
|
+
def test_system_and_pipe
|
323
|
+
((@cat | @wc) < @file.open('r+') > @tmp).system
|
324
|
+
assert_equal(0, $?)
|
325
|
+
assert(@tmp.exist?)
|
326
|
+
assert_match(/\s*2\s*4\s*17\s+/, @tmp.read)
|
327
|
+
end
|
328
|
+
|
329
|
+
def test_system_is_not_sh
|
330
|
+
@cat << '$TEST_FILE'
|
331
|
+
@cat.error = @dev_null
|
332
|
+
(@cat > @tmp).system
|
333
|
+
assert_not_equal(0, $?)
|
334
|
+
assert(!@tmp.exist? || @tmp.zero?)
|
335
|
+
end
|
336
|
+
|
337
|
+
def test_exec
|
338
|
+
@cp << @file << @tmp
|
339
|
+
pid = fork do
|
340
|
+
@cp.exec
|
341
|
+
end
|
342
|
+
Process.waitpid pid
|
343
|
+
assert_equal(0, $?)
|
344
|
+
assert(@tmp.exist?)
|
345
|
+
assert_equal(@file.read, @tmp.read)
|
346
|
+
end
|
347
|
+
|
348
|
+
def test_exec_not_sh!
|
349
|
+
@cat << '$TEST_FILE'
|
350
|
+
@cat.error = @dev_null
|
351
|
+
pid = fork do
|
352
|
+
(@cat > @tmp).exec
|
353
|
+
end
|
354
|
+
Process.waitpid pid
|
355
|
+
assert_not_equal(0, $?)
|
356
|
+
assert(!@tmp.exist? || @tmp.size.zero?)
|
357
|
+
end
|
358
|
+
|
359
|
+
def test_sh
|
360
|
+
@cat << '$TEST_FILE'
|
361
|
+
(@cat > @tmp).sh
|
362
|
+
assert_equal(0, $?)
|
363
|
+
assert(@tmp.exist?)
|
364
|
+
assert_equal(@file.read, @tmp.read)
|
365
|
+
end
|
366
|
+
|
367
|
+
def test_sh2
|
368
|
+
((@cat | @wc) < @file > @tmp).sh
|
369
|
+
assert_equal(0, $?)
|
370
|
+
assert(@tmp.exist?)
|
371
|
+
assert_match(/\s*2\s*4\s*17\s+/, @tmp.read)
|
372
|
+
end
|
373
|
+
|
374
|
+
def test_sh!
|
375
|
+
@cat << '$TEST_FILE'
|
376
|
+
pid = fork do
|
377
|
+
(@cat > @tmp).sh!
|
378
|
+
end
|
379
|
+
Process.waitpid pid
|
380
|
+
assert_equal(0, $?)
|
381
|
+
assert(@tmp.exist?)
|
382
|
+
assert_equal(@file.read, @tmp.read)
|
383
|
+
end
|
384
|
+
|
385
|
+
def test_expand
|
386
|
+
@cat << '$TEST_FILE'
|
387
|
+
str = (@cat).expand
|
388
|
+
assert_equal(0, $?)
|
389
|
+
assert_equal(@file.read, str)
|
390
|
+
|
391
|
+
str = ((@cat | @wc) < @file).expand
|
392
|
+
assert_equal(0, $?)
|
393
|
+
assert_match(/\s*2\s*4\s*17\s+/, str)
|
394
|
+
end
|
395
|
+
|
396
|
+
# FIXME
|
397
|
+
def test_popen
|
398
|
+
cmd = (@touch + @tmp) + (@sleep + 1)
|
399
|
+
diff = DTime.diff { @data = cmd.popen }
|
400
|
+
assert(@tmp.exist?)
|
401
|
+
@data.waitpid
|
402
|
+
assert(@tmp.exist?)
|
403
|
+
assert(diff.to_f < 1)
|
404
|
+
end
|
405
|
+
|
406
|
+
def test_fork
|
407
|
+
sleep_arg = 2
|
408
|
+
cmd = (@touch + @tmp) + (@sleep + sleep_arg)
|
409
|
+
diff = DTime.diff { @data = cmd.fork }
|
410
|
+
assert(@tmp.exist?)
|
411
|
+
@data.waitpid
|
412
|
+
assert(@tmp.exist?)
|
413
|
+
assert(diff.to_f < sleep_arg, "#{diff} should be < #{sleep_arg}")
|
414
|
+
end
|
415
|
+
|
416
|
+
def test_ruby
|
417
|
+
# FIXME
|
418
|
+
end
|
419
|
+
|
420
|
+
def test_pipe # test_|
|
421
|
+
assert_kind_of(Pipe, (@cat | @wc) < @file)
|
422
|
+
end
|
423
|
+
|
424
|
+
def test_subscript # test_[]
|
425
|
+
assert_equal(['a', 'b'], @cat['a', 'b'].args)
|
426
|
+
assert_equal(['a'], @cat['a'].args)
|
427
|
+
assert_equal([], @cat[].args)
|
428
|
+
assert_equal(['a', 'b', 'c'], @cat[[['a'], 'b', ['c']]].args)
|
429
|
+
end
|
430
|
+
|
431
|
+
def test_chain # test_+
|
432
|
+
assert_kind_of(Seq, (@cat + @wc) < @file)
|
433
|
+
cmd = @cat + @file.to_s
|
434
|
+
assert_kind_of(Command, cmd)
|
435
|
+
assert_equal([@file.to_s], cmd.args)
|
436
|
+
cmd += ['a', 'b']
|
437
|
+
assert_equal([@file.to_s, 'a', 'b'], cmd.args)
|
438
|
+
cmd += @file.to_s
|
439
|
+
assert_equal([@file.to_s, 'a', 'b', @file.to_s], cmd.args)
|
440
|
+
end
|
441
|
+
|
442
|
+
def test_chain_complex
|
443
|
+
((@cat < @file > @tmp) + (@wc + [@tmp] > @tmp2)).sh
|
444
|
+
assert_equal(0, $?)
|
445
|
+
assert(@tmp.exist?)
|
446
|
+
assert(@tmp2.exist?)
|
447
|
+
assert_equal(@file.read, @tmp.read)
|
448
|
+
assert_match(/\s*2\s*4\s*17\s*#{@tmp}\s+/, @tmp2.read)
|
449
|
+
end
|
450
|
+
|
451
|
+
def test_add_input # test_<
|
452
|
+
@cat.input = 'foo'
|
453
|
+
assert_equal('foo', @cat.input)
|
454
|
+
cmd = @cat < 'bar'
|
455
|
+
assert_equal('bar', cmd.input)
|
456
|
+
assert_not_equal(cmd.object_id, @cat.object_id)
|
457
|
+
end
|
458
|
+
|
459
|
+
def test_add_output # test_>
|
460
|
+
@cat.output = 'foo'
|
461
|
+
assert_equal('foo', @cat.output)
|
462
|
+
cmd = @cat > 'bar'
|
463
|
+
assert_equal('bar', cmd.output)
|
464
|
+
cmd = @cat > @file
|
465
|
+
assert_equal(@file, cmd.output)
|
466
|
+
assert_equal(:w, cmd.open_mode)
|
467
|
+
assert_not_equal(cmd.object_id, @cat.object_id)
|
468
|
+
cmd = @cat > [ 'outbar', 'errbar' ]
|
469
|
+
assert_equal('outbar', cmd.output)
|
470
|
+
assert_equal('errbar', cmd.error)
|
471
|
+
cmd = @cat > [ @file, @file ]
|
472
|
+
assert_equal(:w, cmd.open_mode)
|
473
|
+
end
|
474
|
+
|
475
|
+
def test_append_output # test_>>
|
476
|
+
@cat.output = 'foo'
|
477
|
+
assert_equal('foo', @cat.output)
|
478
|
+
cmd = @cat >> 'bar'
|
479
|
+
assert_equal('bar', cmd.output)
|
480
|
+
assert_not_equal(cmd.object_id, @cat.object_id)
|
481
|
+
cmd = @cat >> @file
|
482
|
+
assert_equal(@file, cmd.output)
|
483
|
+
assert_equal(:a, cmd.open_mode)
|
484
|
+
cmd = @cat >> [ 'outbar', 'errbar' ]
|
485
|
+
assert_equal('outbar', cmd.output)
|
486
|
+
assert_equal('errbar', cmd.error)
|
487
|
+
cmd = @cat >> [ @file, @file ]
|
488
|
+
assert_equal(:a, cmd.open_mode)
|
489
|
+
end
|
490
|
+
|
491
|
+
def test_args
|
492
|
+
assert_equal([], @cp.args)
|
493
|
+
@cat << 'foo bar' << 'baz'
|
494
|
+
assert_equal(['foo bar', 'baz'], @cat.args)
|
495
|
+
end
|
496
|
+
|
497
|
+
def test_arg_string
|
498
|
+
assert_equal('', @cp.arg_string)
|
499
|
+
@cat << 'foo bar' << 'baz' << 'b"o' << '\o/' << '>' << 'b3o'
|
500
|
+
assert_equal('"foo bar" baz "b\\"o" "\\\\o/" ">" b3o', @cat.arg_string)
|
501
|
+
end
|
502
|
+
|
503
|
+
def test_to_s
|
504
|
+
assert_equal('cp', @cp.to_s)
|
505
|
+
@cat << 'foo bar' << 'baz'
|
506
|
+
assert_equal('cat "foo bar" baz', @cat.to_s)
|
507
|
+
end
|
508
|
+
|
509
|
+
def test_to_sh
|
510
|
+
assert_equal('cp > ya', (@cp > 'ya').to_sh)
|
511
|
+
@cat << 'foo > bar' << '< baz'
|
512
|
+
assert_equal(
|
513
|
+
'(cat "foo > bar" "< baz" < yay) | (cp > yoy)',
|
514
|
+
((@cat | @cp) < 'yay' > 'yoy').to_sh)
|
515
|
+
@wc.error = 'foo'
|
516
|
+
assert_equal('wc 2> foo', @wc.to_sh)
|
517
|
+
end
|
518
|
+
|
519
|
+
def test_complex
|
520
|
+
ls = 'ls'.to_ocmd
|
521
|
+
wc = 'wc'.to_ocmd
|
522
|
+
(ls | wc) < @file > @tmp
|
523
|
+
end
|
524
|
+
|
525
|
+
def test_where
|
526
|
+
# FIXME
|
527
|
+
end
|
528
|
+
|
529
|
+
end # class CommandTest
|
530
|
+
|
531
|
+
end
|
532
|
+
|
533
|
+
end # module Commands
|
534
|
+
|
535
|
+
end # module ObjectiveCommand
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
|
2
|
+
# Copyright:: Copyright (c) 2005, 2006 Nicolas Pouillard. All rights reserved.
|
3
|
+
# License:: GNU General Public License (GPL).
|
4
|
+
# Revision:: $Id: /w/fey/cmd/trunk/lib/objective_command/commands/factory.rb 22684 2006-03-12T16:36:11.301558Z pouillar $
|
5
|
+
|
6
|
+
module ObjectiveCommand
|
7
|
+
|
8
|
+
module Commands
|
9
|
+
|
10
|
+
class Factory < Command
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
super(nil)
|
14
|
+
@command_class = Command
|
15
|
+
end
|
16
|
+
|
17
|
+
def new_command ( *a, &b )
|
18
|
+
cmd = @command_class.new(*a, &b)
|
19
|
+
instance_variables.each do |var|
|
20
|
+
next if var =~ /^@command(_class)?$/
|
21
|
+
cmd.send(var[1..-1] + '=', instance_variable_get(var))
|
22
|
+
end
|
23
|
+
cmd
|
24
|
+
end
|
25
|
+
|
26
|
+
alias :create :new_command
|
27
|
+
|
28
|
+
end # class Factory
|
29
|
+
|
30
|
+
|
31
|
+
|
32
|
+
test_section __FILE__ do
|
33
|
+
|
34
|
+
class FactoryTest < Test::Unit::TestCase
|
35
|
+
|
36
|
+
def setup
|
37
|
+
assert_nothing_raised { @fa = Factory.new }
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_0_initialize
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_new_command
|
44
|
+
assert_nothing_raised do
|
45
|
+
assert_kind_of(Command, @fa.create('wc'))
|
46
|
+
assert_kind_of(Command, @fa.new_command('ls'))
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_simple
|
51
|
+
assert_nothing_raised do
|
52
|
+
@fa << 42
|
53
|
+
@fa.input = 'inp'
|
54
|
+
@fa = @fa > 'out'
|
55
|
+
@cmd = @fa.create('foo')
|
56
|
+
end
|
57
|
+
assert_equal('foo', @cmd.command)
|
58
|
+
assert_equal(42, @cmd.args.first)
|
59
|
+
assert_equal('inp', @cmd.input)
|
60
|
+
assert_equal('out', @cmd.output)
|
61
|
+
end
|
62
|
+
|
63
|
+
end # class FactoryTest
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
end # module Commands
|
68
|
+
|
69
|
+
end # module ObjectiveCommand
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# Author:: Nicolas Pouillard <ertai@lrde.epita.fr>.
|
2
|
+
# Copyright:: Copyright (c) 2005, 2006 Nicolas Pouillard. All rights reserved.
|
3
|
+
# License:: GNU General Public License (GPL).
|
4
|
+
# Revision:: $Id: /w/fey/cmd/trunk/lib/objective_command/commands/pipe.rb 22779 2006-03-19T18:30:55.288309Z ertai $
|
5
|
+
|
6
|
+
class IO
|
7
|
+
|
8
|
+
def pipe?
|
9
|
+
false
|
10
|
+
end
|
11
|
+
|
12
|
+
class << self
|
13
|
+
|
14
|
+
alias_method :pipe_without_pipe?, :pipe unless method_defined? :pipe_without_pipe?
|
15
|
+
|
16
|
+
def pipe
|
17
|
+
ios = pipe_without_pipe?
|
18
|
+
ios.each do |io|
|
19
|
+
io.send(:define_singleton_method, :pipe?) { true }
|
20
|
+
end
|
21
|
+
ios
|
22
|
+
end
|
23
|
+
|
24
|
+
end # class << self
|
25
|
+
|
26
|
+
end # class IO
|
27
|
+
|
28
|
+
module ObjectiveCommand
|
29
|
+
|
30
|
+
module Commands
|
31
|
+
|
32
|
+
class Pipe < Command
|
33
|
+
|
34
|
+
def initialize ( *cmds )
|
35
|
+
@cmds = cmds.flatten.map { |x| x.dup }
|
36
|
+
end
|
37
|
+
|
38
|
+
def run ( runner=@runner, *a )
|
39
|
+
if runner.nil?
|
40
|
+
raise ArgumentError, "need a runner not: #{runner.inspect}"
|
41
|
+
end
|
42
|
+
datas = Datas::Composite.new
|
43
|
+
runner = runner.dup
|
44
|
+
runner.hook_trigger :display_command, self
|
45
|
+
runner.disable_hook :display_command
|
46
|
+
runner.disable_hook :waitpid
|
47
|
+
([nil] + @cmds).zip(@cmds + [nil]).each do |cmd1, cmd2|
|
48
|
+
next if cmd1.nil? or cmd2.nil?
|
49
|
+
rd, wr = IO.pipe
|
50
|
+
cmd1_runner = runner.dup
|
51
|
+
cmd1_runner.disable_hook :waitpid
|
52
|
+
cmd1_runner.subscribe_hook(:son) { rd.close }
|
53
|
+
cmd1.output = wr
|
54
|
+
cmd2.input = rd
|
55
|
+
datas << cmd1.run(cmd1_runner)
|
56
|
+
wr.close
|
57
|
+
end
|
58
|
+
runner = runner.dup
|
59
|
+
datas << @cmds.last.run(runner, *a)
|
60
|
+
datas.waitpid if runner.is_a? Runners::System
|
61
|
+
datas
|
62
|
+
end
|
63
|
+
|
64
|
+
def input= ( arg )
|
65
|
+
@cmds.first.input = arg
|
66
|
+
end
|
67
|
+
|
68
|
+
def input
|
69
|
+
@cmds.first.input
|
70
|
+
end
|
71
|
+
|
72
|
+
def output= ( arg )
|
73
|
+
@cmds.last.output = arg
|
74
|
+
end
|
75
|
+
|
76
|
+
def output
|
77
|
+
@cmds.last.output
|
78
|
+
end
|
79
|
+
|
80
|
+
def error= ( arg )
|
81
|
+
@cmds.last.error = arg
|
82
|
+
end
|
83
|
+
|
84
|
+
def error
|
85
|
+
@cmds.last.error
|
86
|
+
end
|
87
|
+
|
88
|
+
%w[ args command ].each do |meth|
|
89
|
+
class_eval %Q{
|
90
|
+
def #{meth} ( *a, &b )
|
91
|
+
raise ArgumentError, "no method `#{meth}' on a pipe"
|
92
|
+
end
|
93
|
+
}
|
94
|
+
end
|
95
|
+
|
96
|
+
def [] ( *args )
|
97
|
+
new_cmds = @cmds.dup
|
98
|
+
new_cmds[-1] = new_cmds.last[*args]
|
99
|
+
Pipe.new(*new_cmds)
|
100
|
+
end
|
101
|
+
|
102
|
+
#
|
103
|
+
# Conversion methods
|
104
|
+
#
|
105
|
+
|
106
|
+
def to_sh
|
107
|
+
strs = @cmds.map { |cmd| "(#{cmd.to_sh})" }
|
108
|
+
"#{strs.join(' | ')}"
|
109
|
+
end
|
110
|
+
|
111
|
+
def to_s
|
112
|
+
to_sh
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
|
117
|
+
end # class Pipe
|
118
|
+
|
119
|
+
end # module Commands
|
120
|
+
|
121
|
+
end # module ObjectiveCommand
|