rubysh 0.0.10 → 0.0.11
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/README.md +2 -3
- data/lib/rubysh/command.rb +4 -0
- data/lib/rubysh/runner.rb +17 -2
- data/lib/rubysh/subprocess/pid_aware_parallel_io.rb +7 -0
- data/lib/rubysh/version.rb +1 -1
- data/test/functional/_lib.rb +0 -2
- data/test/functional/lib/env.rb +1 -1
- data/test/functional/lib/kill.rb +25 -0
- data/test/functional/lib/read.rb +18 -0
- data/test/integration/_lib.rb +0 -2
- data/test/unit/_lib.rb +0 -2
- data/test/unit/lib/rubysh/command.rb +4 -0
- metadata +8 -4
data/README.md
CHANGED
@@ -92,7 +92,7 @@ the `AliasRubysh` helper:
|
|
92
92
|
Rubysh takes a splatted array argument as a command specification. In
|
93
93
|
particular, it doesn't convert it back and forth a command-line
|
94
94
|
string, meaning you don't have to worry about spaces in
|
95
|
-
|
95
|
+
arguments. (You should still always think twice before putting
|
96
96
|
untrusted arguments into a shell argument.)
|
97
97
|
|
98
98
|
## Installation
|
@@ -112,6 +112,5 @@ Patches welcome! I'm happy to merge pull requests.
|
|
112
112
|
|
113
113
|
## Future features
|
114
114
|
|
115
|
-
-
|
116
|
-
- Finer-grained IO control
|
115
|
+
- Better support for streaming output
|
117
116
|
- Subshell syntax (`cat <(ls)`, `echo $(ls)`)
|
data/lib/rubysh/command.rb
CHANGED
@@ -3,6 +3,10 @@ module Rubysh
|
|
3
3
|
attr_accessor :raw_args, :directives, :args
|
4
4
|
|
5
5
|
def initialize(args)
|
6
|
+
if args.length == 1 && args[0].kind_of?(Array)
|
7
|
+
raise "It looks like you created a Rubysh::Command with a singleton nested array: #{args.inspect}. That'll never be runnable, and probably indicates you forgot a splat somewhere."
|
8
|
+
end
|
9
|
+
|
6
10
|
@raw_args = args
|
7
11
|
@directives = []
|
8
12
|
@args = nil
|
data/lib/rubysh/runner.rb
CHANGED
@@ -56,9 +56,15 @@ module Rubysh
|
|
56
56
|
case how = opts[:how]
|
57
57
|
when :partial
|
58
58
|
# Read until we get some bytes
|
59
|
-
|
59
|
+
while state[:buffer].length == state[:read_pos]
|
60
|
+
# If everything's exited, just return nil
|
61
|
+
return nil if @parallel_io.finalized
|
62
|
+
@parallel_io.run_once
|
63
|
+
end
|
60
64
|
when :nonblock
|
61
65
|
@parallel_io.read_available(state[:target])
|
66
|
+
# Return nil unless we have something new
|
67
|
+
return nil if state[:buffer].length == state[:read_pos]
|
62
68
|
when nil
|
63
69
|
communicate if @runner_state == :started
|
64
70
|
else
|
@@ -203,13 +209,22 @@ module Rubysh
|
|
203
209
|
target_state
|
204
210
|
end
|
205
211
|
|
206
|
-
|
212
|
+
def kill(signal='TERM')
|
213
|
+
my_pid = pid
|
214
|
+
unless my_pid
|
215
|
+
raise Rubysh::Error::BaseError.new("You haven't started this runner yet.")
|
216
|
+
end
|
217
|
+
Rubysh.log.debug("Sending #{signal} to #{my_pid}")
|
218
|
+
Process.kill(signal, my_pid)
|
219
|
+
end
|
207
220
|
|
208
221
|
def wait
|
209
222
|
run_io
|
210
223
|
do_wait
|
211
224
|
end
|
212
225
|
|
226
|
+
private
|
227
|
+
|
213
228
|
def targets_by_fd_numbers
|
214
229
|
@targets.inject({}) do |hash, (_, target_state)|
|
215
230
|
fd_num = target_state[:subprocess_fd_number]
|
@@ -58,10 +58,13 @@ class Rubysh::Subprocess
|
|
58
58
|
Signal.trap('CHLD', @old_sigchld_handler)
|
59
59
|
end
|
60
60
|
|
61
|
+
attr_reader :finalized
|
62
|
+
|
61
63
|
# readers/writers should be hashes mapping {fd => name}
|
62
64
|
def initialize(readers, writers, subprocesses)
|
63
65
|
@breaker_reader, @breaker_writer = IO.pipe
|
64
66
|
@subprocesses = subprocesses
|
67
|
+
@finalized = false
|
65
68
|
|
66
69
|
readers = readers.dup
|
67
70
|
readers[@breaker_reader] = nil
|
@@ -75,6 +78,8 @@ class Rubysh::Subprocess
|
|
75
78
|
end
|
76
79
|
|
77
80
|
def run_once(timeout=nil)
|
81
|
+
return if @finalized
|
82
|
+
|
78
83
|
@subprocesses.each do |subprocess|
|
79
84
|
subprocess.wait(true)
|
80
85
|
end
|
@@ -98,6 +103,8 @@ class Rubysh::Subprocess
|
|
98
103
|
available_readers.each {|reader| reader.close}
|
99
104
|
available_writers.each {|writer| writer.close}
|
100
105
|
self.class.deregister_parallel_io(self)
|
106
|
+
|
107
|
+
@finalized = true
|
101
108
|
end
|
102
109
|
end
|
103
110
|
end
|
data/lib/rubysh/version.rb
CHANGED
data/test/functional/_lib.rb
CHANGED
data/test/functional/lib/env.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require File.expand_path('../_lib', File.dirname(__FILE__))
|
2
2
|
|
3
3
|
module RubyshTest::Functional
|
4
|
-
class
|
4
|
+
class EnvTest < FunctionalTest
|
5
5
|
describe 'when using <<< string' do
|
6
6
|
it 'the string is delivered on stdin' do
|
7
7
|
ENV['TEST1'] = '1'
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require File.expand_path('../_lib', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
module RubyshTest::Functional
|
4
|
+
class KillTest < FunctionalTest
|
5
|
+
describe 'when killing' do
|
6
|
+
it 'delivers a sigterm by default' do
|
7
|
+
result = Rubysh.run_async('ruby', '-e', 'sleep 10', Rubysh.>)
|
8
|
+
result.kill
|
9
|
+
result.wait
|
10
|
+
|
11
|
+
assert_equal(nil, result.exitstatus)
|
12
|
+
assert_equal(Signal.list['TERM'], result.full_status.termsig)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'delivers the specified signal otherwise' do
|
16
|
+
result = Rubysh.run_async('ruby', '-e', 'sleep 10', Rubysh.>)
|
17
|
+
result.kill('KILL')
|
18
|
+
result.wait
|
19
|
+
|
20
|
+
assert_equal(nil, result.exitstatus)
|
21
|
+
assert_equal(Signal.list['KILL'], result.full_status.termsig)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.expand_path('../_lib', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
module RubyshTest::Functional
|
4
|
+
class ReadTest < FunctionalTest
|
5
|
+
describe 'when reading with :how => :partial' do
|
6
|
+
it 'returns nil once the process is dead' do
|
7
|
+
runner = Rubysh('ruby', '-e', 'puts "hi"', Rubysh.>).run_async
|
8
|
+
|
9
|
+
# Pump stdout
|
10
|
+
while runner.read(:how => :partial)
|
11
|
+
end
|
12
|
+
|
13
|
+
runner.wait
|
14
|
+
assert_equal(nil, runner.read(:how => :partial))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/test/integration/_lib.rb
CHANGED
data/test/unit/_lib.rb
CHANGED
@@ -15,6 +15,10 @@ module RubyshTest::Unit
|
|
15
15
|
command = Rubysh::Command.new(['ls', '/tmp', directive, '/foo'])
|
16
16
|
assert_equal('Command: ls /tmp 2>&1 /foo', command.to_s)
|
17
17
|
end
|
18
|
+
|
19
|
+
it 'raises an error when given an unsplatted array' do
|
20
|
+
assert_raises(RuntimeError) {Rubysh::Command.new([['ls', 'stuff']])}
|
21
|
+
end
|
18
22
|
end
|
19
23
|
|
20
24
|
describe 'when calling #run_async' do
|
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.0.
|
4
|
+
version: 0.0.11
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-11-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -110,7 +110,9 @@ files:
|
|
110
110
|
- test/functional/_lib.rb
|
111
111
|
- test/functional/lib/env.rb
|
112
112
|
- test/functional/lib/fd-lister
|
113
|
+
- test/functional/lib/kill.rb
|
113
114
|
- test/functional/lib/leaked_fds.rb
|
115
|
+
- test/functional/lib/read.rb
|
114
116
|
- test/functional/lib/redirect_ordering.rb
|
115
117
|
- test/functional/lib/triple_less_than.rb
|
116
118
|
- test/integration/_lib.rb
|
@@ -138,7 +140,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
138
140
|
version: '0'
|
139
141
|
segments:
|
140
142
|
- 0
|
141
|
-
hash:
|
143
|
+
hash: 3386670358533092265
|
142
144
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
143
145
|
none: false
|
144
146
|
requirements:
|
@@ -147,7 +149,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
147
149
|
version: '0'
|
148
150
|
segments:
|
149
151
|
- 0
|
150
|
-
hash:
|
152
|
+
hash: 3386670358533092265
|
151
153
|
requirements: []
|
152
154
|
rubyforge_project:
|
153
155
|
rubygems_version: 1.8.23
|
@@ -162,7 +164,9 @@ test_files:
|
|
162
164
|
- test/functional/_lib.rb
|
163
165
|
- test/functional/lib/env.rb
|
164
166
|
- test/functional/lib/fd-lister
|
167
|
+
- test/functional/lib/kill.rb
|
165
168
|
- test/functional/lib/leaked_fds.rb
|
169
|
+
- test/functional/lib/read.rb
|
166
170
|
- test/functional/lib/redirect_ordering.rb
|
167
171
|
- test/functional/lib/triple_less_than.rb
|
168
172
|
- test/integration/_lib.rb
|