rubysh 0.0.10 → 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
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
- variables. (You should still always think twice before putting
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
- - Support for environment variables
116
- - Finer-grained IO control
115
+ - Better support for streaming output
117
116
  - Subshell syntax (`cat <(ls)`, `echo $(ls)`)
@@ -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
- @parallel_io.run_once until state[:buffer].length != state[:read_pos]
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
- private
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
@@ -1,3 +1,3 @@
1
1
  module Rubysh
2
- VERSION = '0.0.10'
2
+ VERSION = '0.0.11'
3
3
  end
@@ -3,5 +3,3 @@ require File.expand_path('../_lib', File.dirname(__FILE__))
3
3
  module RubyshTest::Functional
4
4
  class FunctionalTest < RubyshTest::Test; end
5
5
  end
6
-
7
- MiniTest::Unit.runner = MiniTest::Unit.new
@@ -1,7 +1,7 @@
1
1
  require File.expand_path('../_lib', File.dirname(__FILE__))
2
2
 
3
3
  module RubyshTest::Functional
4
- class TripleLessThanTest < FunctionalTest
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
@@ -3,5 +3,3 @@ require File.expand_path('../_lib', File.dirname(__FILE__))
3
3
  module RubyshTest::Integration
4
4
  class IntegrationTest < RubyshTest::Test; end
5
5
  end
6
-
7
- MiniTest::Unit.runner = MiniTest::Unit.new
data/test/unit/_lib.rb CHANGED
@@ -3,5 +3,3 @@ require File.expand_path('../_lib', File.dirname(__FILE__))
3
3
  module RubyshTest::Unit
4
4
  class UnitTest < RubyshTest::Test; end
5
5
  end
6
-
7
- MiniTest::Unit.runner = MiniTest::Unit.new
@@ -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.10
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-10-13 00:00:00.000000000 Z
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: 1275881591566036262
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: 1275881591566036262
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