rubysh 0.2.1 → 0.2.2
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/lib/rubysh/base_command.rb +4 -0
- data/lib/rubysh/error.rb +3 -2
- data/lib/rubysh/redirect.rb +3 -1
- data/lib/rubysh/runner.rb +28 -19
- data/lib/rubysh/subprocess.rb +3 -2
- data/lib/rubysh/subprocess/parallel_io.rb +6 -4
- data/lib/rubysh/subprocess/pid_aware_parallel_io.rb +1 -1
- data/lib/rubysh/version.rb +1 -1
- data/test/_lib.rb +1 -1
- data/test/functional/lib/on_output.rb +34 -0
- metadata +5 -3
data/lib/rubysh/base_command.rb
CHANGED
data/lib/rubysh/error.rb
CHANGED
@@ -4,10 +4,11 @@ module Rubysh
|
|
4
4
|
|
5
5
|
class ExecError < BaseError
|
6
6
|
# Exception klass and caller from the child process
|
7
|
-
attr_accessor :klass, :caller
|
7
|
+
attr_accessor :raw_message, :klass, :caller
|
8
8
|
|
9
|
-
def initialize(message, klass, caller)
|
9
|
+
def initialize(message, raw_message, klass, caller)
|
10
10
|
super(message)
|
11
|
+
@raw_message = raw_message
|
11
12
|
@klass = klass
|
12
13
|
@caller = caller
|
13
14
|
end
|
data/lib/rubysh/redirect.rb
CHANGED
@@ -126,7 +126,9 @@ module Rubysh
|
|
126
126
|
:target_name => target_name,
|
127
127
|
:read_pos => 0,
|
128
128
|
:subprocess_fd_number => Util.to_fileno(source),
|
129
|
-
:tee => @opts[:tee]
|
129
|
+
:tee => @opts[:tee],
|
130
|
+
:on_read => @opts[:on_read],
|
131
|
+
:on_write => @opts[:on_write],
|
130
132
|
}
|
131
133
|
end
|
132
134
|
|
data/lib/rubysh/runner.rb
CHANGED
@@ -36,6 +36,7 @@ module Rubysh
|
|
36
36
|
# read(:how => :nonblock): Return whatever is immediately available
|
37
37
|
def read(target=nil, opts=nil)
|
38
38
|
raise Rubysh::Error::AlreadyRunError.new("Can only read from a runner in runner_state :started or :waited, not #{@runner_state.inspect}") unless @runner_state == :started || @runner_state == :waited
|
39
|
+
raise Rubysh::Error::BaseError.new("Can't read from a runner where :on_read has been provided") if command.opts[:on_read]
|
39
40
|
|
40
41
|
if target.kind_of?(Hash)
|
41
42
|
opts = target
|
@@ -263,28 +264,36 @@ module Rubysh
|
|
263
264
|
# there.
|
264
265
|
def prepare_io
|
265
266
|
@parallel_io = Subprocess::PidAwareParallelIO.new(readers, writers, subprocesses)
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
buffer
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
267
|
+
if on_read = command.opts[:on_read]
|
268
|
+
@parallel_io.on_read(on_read)
|
269
|
+
else
|
270
|
+
@parallel_io.on_read do |target_name, data|
|
271
|
+
state = @targets[target_name]
|
272
|
+
buffer = state[:buffer]
|
273
|
+
if data == Subprocess::ParallelIO::EOF
|
274
|
+
Rubysh.log.debug("EOF reached on #{target_name.inspect}")
|
275
|
+
buffer.close_write
|
276
|
+
else
|
277
|
+
Rubysh.log.debug("Just read #{data.inspect} on #{target_name.inspect}")
|
278
|
+
tee = state[:tee]
|
279
|
+
tee.write(data) if tee
|
280
|
+
|
281
|
+
# Seek to end
|
282
|
+
buffer.pos = buffer.length
|
283
|
+
buffer.write(data)
|
284
|
+
end
|
280
285
|
end
|
281
286
|
end
|
282
287
|
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
+
if on_write = command.opts[:on_write]
|
289
|
+
@parallel_io.on_write(on_write)
|
290
|
+
else
|
291
|
+
@parallel_io.on_write do |target_name, written, remaining|
|
292
|
+
if data == Subprocess::ParallelIO::EOF
|
293
|
+
Rubysh.log.debug("EOF reached on #{target_name.inspect}")
|
294
|
+
else
|
295
|
+
Rubysh.log.debug("Just wrote #{written.inspect} on #{target_name.inspect}")
|
296
|
+
end
|
288
297
|
end
|
289
298
|
end
|
290
299
|
end
|
data/lib/rubysh/subprocess.rb
CHANGED
@@ -123,7 +123,6 @@ module Rubysh
|
|
123
123
|
def exec_program
|
124
124
|
begin
|
125
125
|
Kernel.exec([command, command], *args)
|
126
|
-
raise Rubysh::Error::UnreachableError.new("This code should be unreachable. If you are seeing this exception, it means someone overrode Kernel.exec. That's not very nice of them.")
|
127
126
|
rescue Exception => e
|
128
127
|
msg = {
|
129
128
|
'message' => e.message,
|
@@ -135,6 +134,8 @@ module Rubysh
|
|
135
134
|
# Note: atexit handlers will fire in this case. May want to do
|
136
135
|
# something about that.
|
137
136
|
exit(1)
|
137
|
+
else
|
138
|
+
raise Rubysh::Error::UnreachableError.new("This code should be unreachable. If you are seeing this exception, it means someone overrode Kernel.exec. That's not very nice of them.")
|
138
139
|
end
|
139
140
|
end
|
140
141
|
|
@@ -145,7 +146,7 @@ module Rubysh
|
|
145
146
|
when false
|
146
147
|
# success!
|
147
148
|
when Hash
|
148
|
-
@exec_error = Rubysh::Error::ExecError.new("Failed to exec in subprocess: #{msg['message']}", msg['klass'], msg['caller'])
|
149
|
+
@exec_error = Rubysh::Error::ExecError.new("Failed to exec in subprocess: #{msg['message']}", msg['message'], msg['klass'], msg['caller'])
|
149
150
|
else
|
150
151
|
@exec_error = Rubysh::Error::BaseError.new("Invalid message received over the exec_status pipe: #{msg.inspect}")
|
151
152
|
end
|
@@ -15,12 +15,14 @@ class Rubysh::Subprocess
|
|
15
15
|
@writer_buffers = {}
|
16
16
|
end
|
17
17
|
|
18
|
-
def on_read(&blk)
|
19
|
-
|
18
|
+
def on_read(method=nil, &blk)
|
19
|
+
raise "Can't provide both method and block" if method && blk
|
20
|
+
@on_read = method || blk
|
20
21
|
end
|
21
22
|
|
22
|
-
def on_write(&blk)
|
23
|
-
|
23
|
+
def on_write(method=nil, &blk)
|
24
|
+
raise "Can't provide both method and block" if method && blk
|
25
|
+
@on_write = method || blk
|
24
26
|
end
|
25
27
|
|
26
28
|
def write(writer_name, data, close_on_complete=true)
|
data/lib/rubysh/version.rb
CHANGED
data/test/_lib.rb
CHANGED
@@ -0,0 +1,34 @@
|
|
1
|
+
require File.expand_path('../_lib', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
module RubyshTest::Functional
|
4
|
+
class ReadTest < FunctionalTest
|
5
|
+
describe 'when using :on_read' do
|
6
|
+
it 'calls back as output is streamed' do
|
7
|
+
stdout = ''
|
8
|
+
stderr = ''
|
9
|
+
|
10
|
+
runner = Rubysh('ruby', '-e', 'puts "hi"; $stderr.puts "hullo there"; puts "hello"',
|
11
|
+
Rubysh.>, Rubysh.stderr > :stderr,
|
12
|
+
:on_read => Proc.new do |target_name, data|
|
13
|
+
case target_name
|
14
|
+
when :stdout then stdout << data unless data == Rubysh::Subprocess::ParallelIO::EOF
|
15
|
+
when :stderr then stderr << data unless data == Rubysh::Subprocess::ParallelIO::EOF
|
16
|
+
else
|
17
|
+
raise "Invalid name: #{target_name.inspect}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
).run
|
21
|
+
assert_equal("hi\nhello\n", stdout)
|
22
|
+
assert_equal("hullo there\n", stderr)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'does not allow reading' do
|
26
|
+
runner = Rubysh('echo', 'hi',
|
27
|
+
Rubysh.>, Rubysh.stderr > :stderr,
|
28
|
+
:on_read => Proc.new {}
|
29
|
+
).run
|
30
|
+
assert_raises(Rubysh::Error::BaseError) {runner.read}
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubysh
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -114,6 +114,7 @@ files:
|
|
114
114
|
- test/functional/lib/fd-lister
|
115
115
|
- test/functional/lib/kill.rb
|
116
116
|
- test/functional/lib/leaked_fds.rb
|
117
|
+
- test/functional/lib/on_output.rb
|
117
118
|
- test/functional/lib/read.rb
|
118
119
|
- test/functional/lib/redirect_ordering.rb
|
119
120
|
- test/functional/lib/triple_less_than.rb
|
@@ -142,7 +143,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
142
143
|
version: '0'
|
143
144
|
segments:
|
144
145
|
- 0
|
145
|
-
hash:
|
146
|
+
hash: -1131101407467327753
|
146
147
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
147
148
|
none: false
|
148
149
|
requirements:
|
@@ -151,7 +152,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
151
152
|
version: '0'
|
152
153
|
segments:
|
153
154
|
- 0
|
154
|
-
hash:
|
155
|
+
hash: -1131101407467327753
|
155
156
|
requirements: []
|
156
157
|
rubyforge_project:
|
157
158
|
rubygems_version: 1.8.23
|
@@ -168,6 +169,7 @@ test_files:
|
|
168
169
|
- test/functional/lib/fd-lister
|
169
170
|
- test/functional/lib/kill.rb
|
170
171
|
- test/functional/lib/leaked_fds.rb
|
172
|
+
- test/functional/lib/on_output.rb
|
171
173
|
- test/functional/lib/read.rb
|
172
174
|
- test/functional/lib/redirect_ordering.rb
|
173
175
|
- test/functional/lib/triple_less_than.rb
|