diff --git a/lib/capistrano/command.rb b/lib/capistrano/command.rb index 928c21b1..ed7d265c 100644 --- a/lib/capistrano/command.rb +++ b/lib/capistrano/command.rb @@ -51,8 +51,11 @@ module Capistrano logger.trace "command finished" if logger - if failed = @channels.detect { |ch| ch[:status] != 0 } - raise CommandError, "command #{command.inspect} failed on #{failed[:host]}" + if (failed = @channels.select { |ch| ch[:status] != 0 }).any? + hosts = failed.map { |ch| ch[:host] } + error = CommandError.new("command #{command.inspect} failed on #{hosts.join(',')}") + error.hosts = hosts + raise error end self diff --git a/lib/capistrano/errors.rb b/lib/capistrano/errors.rb index 15d85a21..098d0753 100644 --- a/lib/capistrano/errors.rb +++ b/lib/capistrano/errors.rb @@ -2,8 +2,11 @@ module Capistrano class Error < RuntimeError; end class CaptureError < Error; end - class CommandError < Error; end class ConnectionError < Error; end class UploadError < Error; end class NoSuchTaskError < Error; end + + class CommandError < Error + attr_accessor :hosts + end end \ No newline at end of file diff --git a/test/command_test.rb b/test/command_test.rb index 690193dd..2a0d1672 100644 --- a/test/command_test.rb +++ b/test/command_test.rb @@ -166,6 +166,21 @@ class CommandTest < Test::Unit::TestCase assert_raises(Capistrano::CommandError) { cmd.process! } end + def test_command_error_should_include_accessor_with_host_array + sessions = [mock("session", :open_channel => new_channel(true, 0)), + mock("session", :open_channel => new_channel(true, 0)), + mock("session", :open_channel => new_channel(true, 1))] + cmd = Capistrano::Command.new("ls", sessions) + + begin + cmd.process! + flunk "expected an exception to be raised" + rescue Capistrano::CommandError => e + assert e.respond_to?(:hosts) + assert_equal %w(capistrano), e.hosts + end + end + def test_process_should_loop_until_all_channels_are_closed new_channel = Proc.new do |times| ch = mock("channel")