1
0
Fork 0
mirror of https://github.com/capistrano/capistrano synced 2023-03-27 23:21:18 -04:00

Close input streams when sending commands that don't read input.

An :eof option is added to the run method so that this can be specified
explicitly where a block is provided that may or may not need to read from
the input stream.
This commit is contained in:
Dylan Smith 2012-07-26 19:14:10 -04:00
parent dfb6295a5f
commit 784c98a640
7 changed files with 20 additions and 6 deletions

View file

@ -221,6 +221,7 @@ module Capistrano
ch.exec(command_line)
ch.send_data(options[:data]) if options[:data]
ch.eof! if options[:eof]
else
# just log it, don't actually raise an exception, since the
# process method will see that the status is not zero and will

View file

@ -20,7 +20,7 @@ module Capistrano
# stream "tail -f #{shared_path}/log/fastcgi.crash.log"
# end
def stream(command, options={})
invoke_command(command, options) do |ch, stream, out|
invoke_command(command, options.merge(:eof => true)) do |ch, stream, out|
puts out if stream == :out
warn "[err :: #{ch[:server]}] #{out}" if stream == :err
end
@ -31,7 +31,7 @@ module Capistrano
# string. The command is invoked via #invoke_command.
def capture(command, options={})
output = ""
invoke_command(command, options.merge(:once => true)) do |ch, stream, data|
invoke_command(command, options.merge(:once => true, :eof => true)) do |ch, stream, data|
case stream
when :out then output << data
when :err then warn "[err :: #{ch[:server]}] #{data}"

View file

@ -138,11 +138,16 @@ module Capistrano
# and the values should be their corresponding values. The default is
# empty, but may be modified by changing the +default_environment+
# Capistrano variable.
# * :eof - if true, the standard input stream will be closed after sending
# any data specified in the :data option. If false, the input stream is
# left open. The default is to close the input stream only if no block is
# passed.
#
# Note that if you set these keys in the +default_run_options+ Capistrano
# variable, they will apply for all invocations of #run, #invoke_command,
# and #parallel.
def run(cmd, options={}, &block)
options = options.merge(:eof => !block_given?) if options[:eof].nil?
block ||= self.class.default_io_proc
tree = Command::Tree.new(self) { |t| t.else(cmd, &block) }
run_tree(tree, options)

View file

@ -254,6 +254,14 @@ class CommandTest < Test::Unit::TestCase
Capistrano::Command.new("echo $CAPISTRANO:OTHER$", [session])
end
def test_input_stream_closed_when_eof_option_is_true
channel = nil
session = setup_for_extracting_channel_action { |ch| channel = ch }
channel.expects(:eof!)
Capistrano::Command.new("cat", [session], :data => "here we go", :eof => true)
assert_equal({ :data => 'here we go', :eof => true }, channel[:options])
end
private
def mock_session(channel=nil)

View file

@ -12,7 +12,7 @@ class ConfigurationActionsInspectTest < Test::Unit::TestCase
end
def test_stream_should_pass_options_through_to_run
@config.expects(:invoke_command).with("tail -f foo.log", :once => true)
@config.expects(:invoke_command).with("tail -f foo.log", :once => true, :eof => true)
@config.stream("tail -f foo.log", :once => true)
end
@ -33,7 +33,7 @@ class ConfigurationActionsInspectTest < Test::Unit::TestCase
end
def test_capture_should_pass_options_merged_with_once_to_run
@config.expects(:invoke_command).with("hostname", :foo => "bar", :once => true)
@config.expects(:invoke_command).with("hostname", :foo => "bar", :once => true, :eof => true)
@config.capture("hostname", :foo => "bar")
end

View file

@ -45,7 +45,7 @@ class ConfigurationActionsInvocationTest < Test::Unit::TestCase
end
def test_run_options_should_be_passed_to_execute_on_servers
@config.expects(:execute_on_servers).with(:foo => "bar")
@config.expects(:execute_on_servers).with(:foo => "bar", :eof => true)
@config.run "ls", :foo => "bar"
end

View file

@ -16,7 +16,7 @@ class ConfigurationTest < Test::Unit::TestCase
process_args = Proc.new do |tree, session, opts|
tree.fallback.command == "echo 'hello world'" &&
session == [:session] &&
opts == { :logger => @config.logger }
opts == { :logger => @config.logger, :eof => true }
end
Capistrano::Command.expects(:process).with(&process_args)