summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Lincoln <max@devopsy.com>2014-07-09 16:05:17 -0400
committerMax Lincoln <max@devopsy.com>2014-07-17 13:01:04 -0400
commit5ce6ead83be1a46241db53e401f44c9a40f598ce (patch)
treede80864f2c23906496195ed55ad98e420d4ae558
parentb5e27147f0a5f0ccf44ff4968be2bdfb0c2ce35d (diff)
downloadmixlib-shellout-5ce6ead83be1a46241db53e401f44c9a40f598ce.tar.gz
Support separate live stream for stderr
-rw-r--r--lib/mixlib/shellout.rb24
-rw-r--r--lib/mixlib/shellout/unix.rb2
-rw-r--r--lib/mixlib/shellout/windows.rb2
-rw-r--r--spec/mixlib/shellout_spec.rb82
4 files changed, 102 insertions, 8 deletions
diff --git a/lib/mixlib/shellout.rb b/lib/mixlib/shellout.rb
index e446448..a633819 100644
--- a/lib/mixlib/shellout.rb
+++ b/lib/mixlib/shellout.rb
@@ -54,10 +54,13 @@ module Mixlib
attr_accessor :valid_exit_codes
# When live_stream is set, stdout and stderr of the subprocess will be
- # copied to it as the subprocess is running. For example, if live_stream is
- # set to STDOUT, the command's output will be echoed to STDOUT.
+ # copied to it as the subprocess is running. The stderr will also be copied,
+ # unless live_stderr_stream is set to nil or a different object. For example,
+ # if live_stream is set to STDOUT, the command's output will be echoed to STDOUT.
attr_accessor :live_stream
+ attr_writer :live_stderr_stream
+
# ShellOut will push data from :input down the stdin of the subprocss.
# Normally set via options passed to new.
# Default: nil
@@ -163,6 +166,20 @@ module Mixlib
@command = command_args.size == 1 ? command_args.first : command_args
end
+ # When live_stderr_stream is set, the stderr of the subprocess will be
+ # copied to it as the subprocess is running. For example, if live_stderr_stream is
+ # set to STDERR, the command's output will be echoed to STDERR. The default
+ # value is to match live_stream, so setting live_stream to STDOUT will also
+ # set live_stderr_stream to STDOUT. If you only want the stdout of the subprocess
+ # copied, then you should explicitly set live_stderr_stream to nil.
+ def live_stderr_stream
+ # We can't use ||= because it would override an explicit nil
+ unless defined?(@live_stderr_stream)
+ @live_stderr_stream = live_stream
+ end
+ @live_stderr_stream
+ end
+
# Set the umask that the subprocess will have. If given as a string, it
# will be converted to an integer by String#oct.
def umask=(new_umask)
@@ -287,6 +304,9 @@ module Mixlib
self.valid_exit_codes = Array(setting)
when 'live_stream'
self.live_stream = setting
+ when 'live_stderr_stream'
+ puts "Setting to #{setting}"
+ self.live_stderr_stream = setting
when 'input'
self.input = setting
when 'logger'
diff --git a/lib/mixlib/shellout/unix.rb b/lib/mixlib/shellout/unix.rb
index 46c2c73..249c3d4 100644
--- a/lib/mixlib/shellout/unix.rb
+++ b/lib/mixlib/shellout/unix.rb
@@ -288,7 +288,7 @@ module Mixlib
def read_stderr_to_buffer
while chunk = child_stderr.read_nonblock(READ_SIZE)
@stderr << chunk
- @live_stream << chunk if @live_stream
+ live_stderr_stream << chunk if live_stderr_stream
end
rescue Errno::EAGAIN
rescue EOFError
diff --git a/lib/mixlib/shellout/windows.rb b/lib/mixlib/shellout/windows.rb
index 832584a..62adc37 100644
--- a/lib/mixlib/shellout/windows.rb
+++ b/lib/mixlib/shellout/windows.rb
@@ -167,7 +167,7 @@ module Mixlib
begin
next_chunk = stderr_read.readpartial(READ_SIZE)
@stderr << next_chunk
- @live_stream << next_chunk if @live_stream
+ @live_stderr_stream << next_chunk if @live_stderr_stream
rescue EOFError
stderr_read.close
open_streams.delete(stderr_read)
diff --git a/spec/mixlib/shellout_spec.rb b/spec/mixlib/shellout_spec.rb
index 5dcb6a7..72d550e 100644
--- a/spec/mixlib/shellout_spec.rb
+++ b/spec/mixlib/shellout_spec.rb
@@ -187,8 +187,56 @@ describe Mixlib::ShellOut do
let(:value) { stream }
let(:stream) { StringIO.new }
+ before(:each) do
+ shell_cmd.live_stream = stream
+ end
+
it "should set the live stream" do
- should eql(value)
+ shell_cmd.live_stream.should eql(stream)
+ end
+
+ it "should set the live stderr stream" do
+ shell_cmd.live_stderr_stream.should eql(stream)
+ end
+ end
+
+ context 'when setting a live stream and live stderr stream separately' do
+ let(:accessor) { :live_stream }
+ let(:stream) { StringIO.new }
+ let(:value) { stream }
+ let(:stdout_stream) { StringIO.new }
+ let(:stderr_stream) { StringIO.new }
+
+ before(:each) do
+ shell_cmd.live_stream = stdout_stream
+ shell_cmd.live_stderr_stream = stderr_stream
+ end
+
+ it "should set the live stream" do
+ shell_cmd.live_stream.should eql(stdout_stream)
+ end
+
+ it "should set the live stream" do
+ shell_cmd.live_stderr_stream.should eql(stderr_stream)
+ end
+ end
+
+ context 'when setting a live stream and explicitly disabling live stderr stream' do
+ let(:accessor) { :live_stream }
+ let(:value) { stream }
+ let(:stream) { StringIO.new }
+
+ before(:each) do
+ shell_cmd.live_stream = stream
+ shell_cmd.live_stderr_stream = nil
+ end
+
+ it "should set the live stream" do
+ shell_cmd.live_stream.should eql(stream)
+ end
+
+ it "should set the live stderr stream" do
+ shell_cmd.live_stderr_stream.should eql(nil)
end
end
@@ -457,9 +505,35 @@ describe Mixlib::ShellOut do
stream.string.should include("hello#{LINE_ENDING}")
end
- it "should copy the child's stderr to the live stream" do
- shell_cmd.run_command
- stream.string.should include("world#{LINE_ENDING}")
+ context "with default stderr stream" do
+ it "should copy the child's stderr to the live stream" do
+ shell_cmd.run_command
+ stream.string.should include("world#{LINE_ENDING}")
+ end
+ end
+
+ context "without an stderr stream" do
+ it "should not copy the child's stderr to the live stream" do
+ shell_cmd.live_stderr_stream = nil
+ shell_cmd.run_command
+ stream.string.should_not include("world#{LINE_ENDING}")
+ end
+ end
+
+ context "with a separate stderr stream" do
+ let(:stderr_stream) { StringIO.new }
+
+ it "should not copy the child's stderr to the live stream" do
+ shell_cmd.live_stderr_stream = stderr_stream
+ shell_cmd.run_command
+ stream.string.should_not include("world#{LINE_ENDING}")
+ end
+
+ it "should copy the child's stderr to the live stderr stream" do
+ shell_cmd.live_stderr_stream = stderr_stream
+ shell_cmd.run_command
+ stderr_stream.string.should include("world#{LINE_ENDING}")
+ end
end
end