capistrano 2.2.0 → 2.3.0
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/CHANGELOG +29 -0
- data/README +4 -7
- data/bin/cap +0 -0
- data/bin/capify +0 -0
- data/lib/capistrano/command.rb +32 -38
- data/lib/capistrano/configuration/actions/file_transfer.rb +21 -13
- data/lib/capistrano/configuration/actions/invocation.rb +1 -1
- data/lib/capistrano/configuration/connections.rb +30 -20
- data/lib/capistrano/errors.rb +1 -1
- data/lib/capistrano/processable.rb +53 -0
- data/lib/capistrano/recipes/deploy/remote_dependency.rb +6 -0
- data/lib/capistrano/recipes/deploy/scm/git.rb +26 -11
- data/lib/capistrano/recipes/deploy/scm/none.rb +44 -0
- data/lib/capistrano/recipes/deploy/strategy/base.rb +6 -0
- data/lib/capistrano/recipes/deploy/strategy/copy.rb +74 -3
- data/lib/capistrano/recipes/deploy.rb +15 -13
- data/lib/capistrano/role.rb +0 -14
- data/lib/capistrano/server_definition.rb +5 -0
- data/lib/capistrano/shell.rb +21 -17
- data/lib/capistrano/ssh.rb +24 -58
- data/lib/capistrano/transfer.rb +216 -0
- data/lib/capistrano/version.rb +1 -1
- data/test/cli/execute_test.rb +1 -1
- data/test/cli/help_test.rb +1 -1
- data/test/cli/options_test.rb +1 -1
- data/test/cli/ui_test.rb +1 -1
- data/test/cli_test.rb +1 -1
- data/test/command_test.rb +31 -51
- data/test/configuration/actions/file_transfer_test.rb +21 -19
- data/test/configuration/actions/inspect_test.rb +1 -1
- data/test/configuration/actions/invocation_test.rb +6 -6
- data/test/configuration/callbacks_test.rb +1 -1
- data/test/configuration/connections_test.rb +11 -12
- data/test/configuration/execution_test.rb +1 -1
- data/test/configuration/loading_test.rb +1 -1
- data/test/configuration/namespace_dsl_test.rb +1 -1
- data/test/configuration/roles_test.rb +1 -1
- data/test/configuration/servers_test.rb +1 -1
- data/test/configuration/variables_test.rb +1 -1
- data/test/configuration_test.rb +1 -1
- data/test/deploy/scm/accurev_test.rb +1 -1
- data/test/deploy/scm/base_test.rb +1 -1
- data/test/deploy/scm/git_test.rb +10 -6
- data/test/deploy/scm/mercurial_test.rb +1 -1
- data/test/deploy/strategy/copy_test.rb +120 -27
- data/test/extensions_test.rb +1 -1
- data/test/logger_test.rb +1 -1
- data/test/server_definition_test.rb +1 -1
- data/test/shell_test.rb +27 -1
- data/test/ssh_test.rb +27 -21
- data/test/task_definition_test.rb +1 -1
- data/test/transfer_test.rb +160 -0
- data/test/utils.rb +30 -34
- data/test/version_test.rb +1 -1
- metadata +26 -14
- data/lib/capistrano/gateway.rb +0 -131
- data/lib/capistrano/upload.rb +0 -152
- data/test/gateway_test.rb +0 -167
- data/test/upload_test.rb +0 -131
data/lib/capistrano/upload.rb
DELETED
@@ -1,152 +0,0 @@
|
|
1
|
-
begin
|
2
|
-
require 'rubygems'
|
3
|
-
gem 'net-sftp', "< 1.99.0"
|
4
|
-
rescue LoadError, NameError
|
5
|
-
end
|
6
|
-
|
7
|
-
require 'net/sftp'
|
8
|
-
require 'net/sftp/operations/errors'
|
9
|
-
require 'capistrano/errors'
|
10
|
-
|
11
|
-
module Capistrano
|
12
|
-
unless ENV['SKIP_VERSION_CHECK']
|
13
|
-
require 'capistrano/version'
|
14
|
-
require 'net/sftp/version'
|
15
|
-
sftp_version = [Net::SFTP::Version::MAJOR, Net::SFTP::Version::MINOR, Net::SFTP::Version::TINY]
|
16
|
-
required_version = [1,1,0]
|
17
|
-
if !Capistrano::Version.check(required_version, sftp_version)
|
18
|
-
raise "You have Net::SFTP #{sftp_version.join(".")}, but you need at least #{required_version.join(".")}. Net::SFTP will not be used."
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
# This class encapsulates a single file upload to be performed in parallel
|
23
|
-
# across multiple machines, using the SFTP protocol. Although it is intended
|
24
|
-
# to be used primarily from within Capistrano, it may also be used standalone
|
25
|
-
# if you need to simply upload a file to multiple servers.
|
26
|
-
#
|
27
|
-
# Basic Usage:
|
28
|
-
#
|
29
|
-
# begin
|
30
|
-
# uploader = Capistrano::Upload.new(sessions, "remote-file.txt",
|
31
|
-
# :data => "the contents of the file to upload")
|
32
|
-
# uploader.process!
|
33
|
-
# rescue Capistrano::UploadError => e
|
34
|
-
# warn "Could not upload the file: #{e.message}"
|
35
|
-
# end
|
36
|
-
class Upload
|
37
|
-
def self.process(sessions, filename, options)
|
38
|
-
new(sessions, filename, options).process!
|
39
|
-
end
|
40
|
-
|
41
|
-
attr_reader :sessions, :filename, :options
|
42
|
-
attr_reader :failed, :completed
|
43
|
-
|
44
|
-
# Creates and prepares a new Upload instance. The +sessions+ parameter
|
45
|
-
# must be an array of open Net::SSH sessions. The +filename+ is the name
|
46
|
-
# (including path) of the destination file on the remote server. The
|
47
|
-
# +options+ hash accepts the following keys (as symbols):
|
48
|
-
#
|
49
|
-
# * data: required. Should refer to a String containing the contents of
|
50
|
-
# the file to upload.
|
51
|
-
# * mode: optional. The "mode" of the destination file. Defaults to 0664.
|
52
|
-
# * logger: optional. Should point to a Capistrano::Logger instance, if
|
53
|
-
# given.
|
54
|
-
def initialize(sessions, filename, options)
|
55
|
-
raise ArgumentError, "you must specify the data to upload via the :data option" unless options[:data]
|
56
|
-
|
57
|
-
@sessions = sessions
|
58
|
-
@filename = filename
|
59
|
-
@options = options
|
60
|
-
|
61
|
-
@completed = @failed = 0
|
62
|
-
@sftps = setup_sftp
|
63
|
-
end
|
64
|
-
|
65
|
-
# Uploads to all specified servers in parallel. If any one of the servers
|
66
|
-
# fails, an exception will be raised (UploadError).
|
67
|
-
def process!
|
68
|
-
logger.debug "uploading #{filename}" if logger
|
69
|
-
while running?
|
70
|
-
@sftps.each do |sftp|
|
71
|
-
next if sftp.channel[:done]
|
72
|
-
begin
|
73
|
-
sftp.channel.connection.process(true)
|
74
|
-
rescue Net::SFTP::Operations::StatusException => error
|
75
|
-
logger.important "uploading failed: #{error.description}", sftp.channel[:server] if logger
|
76
|
-
failed!(sftp)
|
77
|
-
end
|
78
|
-
end
|
79
|
-
sleep 0.01 # a brief respite, to keep the CPU from going crazy
|
80
|
-
end
|
81
|
-
logger.trace "upload finished" if logger
|
82
|
-
|
83
|
-
if (failed = @sftps.select { |sftp| sftp.channel[:failed] }).any?
|
84
|
-
hosts = failed.map { |sftp| sftp.channel[:server] }
|
85
|
-
error = UploadError.new("upload of #{filename} failed on #{hosts.join(',')}")
|
86
|
-
error.hosts = hosts
|
87
|
-
raise error
|
88
|
-
end
|
89
|
-
|
90
|
-
self
|
91
|
-
end
|
92
|
-
|
93
|
-
private
|
94
|
-
|
95
|
-
def logger
|
96
|
-
options[:logger]
|
97
|
-
end
|
98
|
-
|
99
|
-
def setup_sftp
|
100
|
-
sessions.map do |session|
|
101
|
-
server = session.xserver
|
102
|
-
sftp = session.sftp
|
103
|
-
sftp.connect unless sftp.state == :open
|
104
|
-
|
105
|
-
sftp.channel[:server] = server
|
106
|
-
sftp.channel[:done] = false
|
107
|
-
sftp.channel[:failed] = false
|
108
|
-
|
109
|
-
real_filename = filename.gsub(/\$CAPISTRANO:HOST\$/, server.host)
|
110
|
-
sftp.open(real_filename, IO::WRONLY | IO::CREAT | IO::TRUNC, options[:mode] || 0664) do |status, handle|
|
111
|
-
break unless check_status(sftp, "open #{real_filename}", server, status)
|
112
|
-
|
113
|
-
logger.info "uploading data to #{server}:#{real_filename}" if logger
|
114
|
-
sftp.write(handle, options[:data] || "") do |status|
|
115
|
-
break unless check_status(sftp, "write to #{server}:#{real_filename}", server, status)
|
116
|
-
sftp.close_handle(handle) do
|
117
|
-
logger.debug "done uploading data to #{server}:#{real_filename}" if logger
|
118
|
-
completed!(sftp)
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
sftp
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
def check_status(sftp, action, server, status)
|
128
|
-
return true if status.code == Net::SFTP::Session::FX_OK
|
129
|
-
|
130
|
-
logger.error "could not #{action} on #{server} (#{status.message})" if logger
|
131
|
-
failed!(sftp)
|
132
|
-
|
133
|
-
return false
|
134
|
-
end
|
135
|
-
|
136
|
-
def running?
|
137
|
-
completed < @sftps.length
|
138
|
-
end
|
139
|
-
|
140
|
-
def failed!(sftp)
|
141
|
-
completed!(sftp)
|
142
|
-
@failed += 1
|
143
|
-
sftp.channel[:failed] = true
|
144
|
-
end
|
145
|
-
|
146
|
-
def completed!(sftp)
|
147
|
-
@completed += 1
|
148
|
-
sftp.channel[:done] = true
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
end
|
data/test/gateway_test.rb
DELETED
@@ -1,167 +0,0 @@
|
|
1
|
-
require "#{File.dirname(__FILE__)}/utils"
|
2
|
-
require 'capistrano/gateway'
|
3
|
-
|
4
|
-
class GatewayTest < Test::Unit::TestCase
|
5
|
-
def teardown
|
6
|
-
Thread.list { |t| t.kill unless Thread.current == t }
|
7
|
-
end
|
8
|
-
|
9
|
-
def test_initialize_should_open_and_set_session_value
|
10
|
-
run_test_initialize_should_open_and_set_session_value
|
11
|
-
end
|
12
|
-
|
13
|
-
def test_initialize_when_connect_lags_should_open_and_set_session_value
|
14
|
-
run_test_initialize_should_open_and_set_session_value do |expects|
|
15
|
-
expects.with { |*args| sleep 0.2; true }
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def test_shutdown_without_any_open_connections_should_terminate_session
|
20
|
-
gateway = new_gateway
|
21
|
-
gateway.shutdown!
|
22
|
-
assert !gateway.thread.alive?
|
23
|
-
assert !gateway.session.looping?
|
24
|
-
end
|
25
|
-
|
26
|
-
def test_connect_to_should_start_local_ports_at_65535
|
27
|
-
gateway = new_gateway
|
28
|
-
expect_connect_to(:host => "127.0.0.1", :port => 65535).returns(result = sess_with_xserver("app1"))
|
29
|
-
newsess = gateway.connect_to(server("app1"))
|
30
|
-
assert_equal result, newsess
|
31
|
-
assert_equal [65535, "app1", 22], gateway.session.forward.active_locals[65535]
|
32
|
-
end
|
33
|
-
|
34
|
-
def test_connect_to_should_decrement_port_and_retry_if_ports_are_in_use
|
35
|
-
gateway = new_gateway(:reserved => lambda { |n| n > 65000 })
|
36
|
-
expect_connect_to(:host => "127.0.0.1", :port => 65000).returns(result = sess_with_xserver("app1"))
|
37
|
-
newsess = gateway.connect_to(server("app1"))
|
38
|
-
assert_equal result, newsess
|
39
|
-
assert_equal [65000, "app1", 22], gateway.session.forward.active_locals[65000]
|
40
|
-
end
|
41
|
-
|
42
|
-
def test_connect_to_should_honor_user_specification_in_server_definition
|
43
|
-
gateway = new_gateway
|
44
|
-
expect_connect_to(:host => "127.0.0.1", :user => "jamis", :port => 65535).returns(result = sess_with_xserver("app1"))
|
45
|
-
newsess = gateway.connect_to(server("jamis@app1"))
|
46
|
-
assert_equal result, newsess
|
47
|
-
assert_equal [65535, "app1", 22], gateway.session.forward.active_locals[65535]
|
48
|
-
end
|
49
|
-
|
50
|
-
def test_connect_to_should_honor_port_specification_in_server_definition
|
51
|
-
gateway = new_gateway
|
52
|
-
expect_connect_to(:host => "127.0.0.1", :port => 65535).returns(result = sess_with_xserver("app1"))
|
53
|
-
newsess = gateway.connect_to(server("app1:1234"))
|
54
|
-
assert_equal result, newsess
|
55
|
-
assert_equal [65535, "app1", 1234], gateway.session.forward.active_locals[65535]
|
56
|
-
end
|
57
|
-
|
58
|
-
def test_connect_to_should_set_xserver_to_tunnel_target
|
59
|
-
gateway = new_gateway
|
60
|
-
expect_connect_to(:host => "127.0.0.1", :port => 65535).returns(result = sess_with_xserver("app1"))
|
61
|
-
newsess = gateway.connect_to(server("app1:1234"))
|
62
|
-
assert_equal result, newsess
|
63
|
-
end
|
64
|
-
|
65
|
-
def test_shutdown_should_cancel_active_forwarded_ports
|
66
|
-
gateway = new_gateway
|
67
|
-
expect_connect_to(:host => "127.0.0.1", :port => 65535).returns(sess_with_xserver("app1"))
|
68
|
-
gateway.connect_to(server("app1"))
|
69
|
-
assert !gateway.session.forward.active_locals.empty?
|
70
|
-
gateway.shutdown!
|
71
|
-
assert gateway.session.forward.active_locals.empty?
|
72
|
-
end
|
73
|
-
|
74
|
-
def test_error_while_connecting_should_cause_connection_to_fail
|
75
|
-
gateway = new_gateway
|
76
|
-
expect_connect_to(:host => "127.0.0.1").raises(RuntimeError)
|
77
|
-
gateway.expects(:warn).times(2)
|
78
|
-
assert_raises(Capistrano::ConnectionError) { gateway.connect_to(server("app1")) }
|
79
|
-
end
|
80
|
-
|
81
|
-
def test_connection_error_should_include_accessor_with_host_array
|
82
|
-
gateway = new_gateway
|
83
|
-
expect_connect_to(:host => "127.0.0.1").raises(RuntimeError)
|
84
|
-
gateway.expects(:warn).times(2)
|
85
|
-
|
86
|
-
begin
|
87
|
-
gateway.connect_to(server("app1"))
|
88
|
-
flunk "expected an exception to be raised"
|
89
|
-
rescue Capistrano::ConnectionError => e
|
90
|
-
assert e.respond_to?(:hosts)
|
91
|
-
assert_equal %w(app1), e.hosts.map { |h| h.to_s }
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
private
|
96
|
-
|
97
|
-
def sess_with_xserver(host)
|
98
|
-
s = server(host)
|
99
|
-
sess = mock("session")
|
100
|
-
sess.expects(:xserver=).with { |v| v.host == host }
|
101
|
-
sess
|
102
|
-
end
|
103
|
-
|
104
|
-
def expect_connect_to(options={})
|
105
|
-
Capistrano::SSH.expects(:connect).with do |server,config|
|
106
|
-
options.all? do |key, value|
|
107
|
-
case key
|
108
|
-
when :host then server.host == value
|
109
|
-
when :user then server.user == value
|
110
|
-
when :port then server.port == value
|
111
|
-
else false
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
def new_gateway(options={})
|
118
|
-
expect_connect_to(:host => "capistrano").yields(MockSession.new(options))
|
119
|
-
Capistrano::Gateway.new(server("capistrano"))
|
120
|
-
end
|
121
|
-
|
122
|
-
def run_test_initialize_should_open_and_set_session_value
|
123
|
-
session = mock("Net::SSH session")
|
124
|
-
session.expects(:loop)
|
125
|
-
expectation = Capistrano::SSH.expects(:connect).yields(session)
|
126
|
-
yield expectation if block_given?
|
127
|
-
gateway = Capistrano::Gateway.new(server("capistrano"))
|
128
|
-
gateway.thread.join
|
129
|
-
assert_equal session, gateway.session
|
130
|
-
end
|
131
|
-
|
132
|
-
class MockForward
|
133
|
-
attr_reader :active_locals
|
134
|
-
|
135
|
-
def initialize(options)
|
136
|
-
@options = options
|
137
|
-
@active_locals = {}
|
138
|
-
end
|
139
|
-
|
140
|
-
def cancel_local(port)
|
141
|
-
@active_locals.delete(port)
|
142
|
-
end
|
143
|
-
|
144
|
-
def local(lport, host, rport)
|
145
|
-
raise Errno::EADDRINUSE if @options[:reserved] && @options[:reserved][lport]
|
146
|
-
@active_locals[lport] = [lport, host, rport]
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
class MockSession
|
151
|
-
attr_reader :forward
|
152
|
-
|
153
|
-
def initialize(options={})
|
154
|
-
@forward = MockForward.new(options)
|
155
|
-
end
|
156
|
-
|
157
|
-
def looping?
|
158
|
-
@looping
|
159
|
-
end
|
160
|
-
|
161
|
-
def loop
|
162
|
-
@looping = true
|
163
|
-
sleep 0.1 while yield
|
164
|
-
@looping = false
|
165
|
-
end
|
166
|
-
end
|
167
|
-
end
|
data/test/upload_test.rb
DELETED
@@ -1,131 +0,0 @@
|
|
1
|
-
require "#{File.dirname(__FILE__)}/utils"
|
2
|
-
require 'capistrano/upload'
|
3
|
-
|
4
|
-
class UploadTest < Test::Unit::TestCase
|
5
|
-
def setup
|
6
|
-
@mode = IO::WRONLY | IO::CREAT | IO::TRUNC
|
7
|
-
end
|
8
|
-
|
9
|
-
def test_initialize_should_raise_error_if_data_is_missing
|
10
|
-
assert_raises(ArgumentError) do
|
11
|
-
Capistrano::Upload.new([], "test.txt", :foo => "bar")
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def test_initialize_should_get_sftp_for_each_session
|
16
|
-
new_sftp = Proc.new do |state|
|
17
|
-
sftp = mock("sftp", :state => state, :open => nil)
|
18
|
-
sftp.expects(:connect) unless state == :open
|
19
|
-
sftp.stubs(:channel).returns({})
|
20
|
-
sftp
|
21
|
-
end
|
22
|
-
|
23
|
-
sessions = [mock("session", :xserver => server("a"), :sftp => new_sftp[:closed]),
|
24
|
-
mock("session", :xserver => server("b"), :sftp => new_sftp[:closed]),
|
25
|
-
mock("session", :xserver => server("c"), :sftp => new_sftp[:open])]
|
26
|
-
Capistrano::Upload.new(sessions, "test.txt", :data => "data")
|
27
|
-
end
|
28
|
-
|
29
|
-
def test_self_process_should_instantiate_uploader_and_start_process
|
30
|
-
Capistrano::Upload.expects(:new).with([:s1, :s2], "test.txt", :data => "data").returns(mock(:process! => nil))
|
31
|
-
Capistrano::Upload.process([:s1, :s2], "test.txt", :data => "data")
|
32
|
-
end
|
33
|
-
|
34
|
-
def test_process_when_sftp_open_fails_should_raise_error
|
35
|
-
sftp = mock_sftp
|
36
|
-
sftp.expects(:open).with("test.txt", @mode, 0664).yields(mock("status", :code => "bad status", :message => "bad status"), :file_handle)
|
37
|
-
session = mock("session", :sftp => sftp, :xserver => server("capistrano"))
|
38
|
-
upload = Capistrano::Upload.new([session], "test.txt", :data => "data", :logger => stub_everything)
|
39
|
-
assert_raises(Capistrano::UploadError) { upload.process! }
|
40
|
-
assert_equal 1, upload.failed
|
41
|
-
assert_equal 1, upload.completed
|
42
|
-
end
|
43
|
-
|
44
|
-
def test_process_when_sftp_write_fails_should_raise_error
|
45
|
-
sftp = mock_sftp
|
46
|
-
sftp.expects(:open).with("test.txt", @mode, 0664).yields(mock("status1", :code => Net::SFTP::Session::FX_OK), :file_handle)
|
47
|
-
sftp.expects(:write).with(:file_handle, "data").yields(mock("status2", :code => "bad status", :message => "bad status"))
|
48
|
-
session = mock("session", :sftp => sftp, :xserver => server("capistrano"))
|
49
|
-
upload = Capistrano::Upload.new([session], "test.txt", :data => "data", :logger => stub_everything)
|
50
|
-
assert_raises(Capistrano::UploadError) { upload.process! }
|
51
|
-
assert_equal 1, upload.failed
|
52
|
-
assert_equal 1, upload.completed
|
53
|
-
end
|
54
|
-
|
55
|
-
def test_upload_error_should_include_accessor_with_host_array
|
56
|
-
sftp = mock_sftp
|
57
|
-
sftp.expects(:open).with("test.txt", @mode, 0664).yields(mock("status1", :code => Net::SFTP::Session::FX_OK), :file_handle)
|
58
|
-
sftp.expects(:write).with(:file_handle, "data").yields(mock("status2", :code => "bad status", :message => "bad status"))
|
59
|
-
session = mock("session", :sftp => sftp, :xserver => server("capistrano"))
|
60
|
-
upload = Capistrano::Upload.new([session], "test.txt", :data => "data", :logger => stub_everything)
|
61
|
-
|
62
|
-
begin
|
63
|
-
upload.process!
|
64
|
-
flunk "expected an exception to be raised"
|
65
|
-
rescue Capistrano::UploadError => e
|
66
|
-
assert e.respond_to?(:hosts)
|
67
|
-
assert_equal %w(capistrano), e.hosts.map { |h| h.to_s }
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def test_process_when_sftp_succeeds_should_raise_nothing
|
72
|
-
sftp = mock_sftp
|
73
|
-
sftp.expects(:open).with("test.txt", @mode, 0664).yields(mock("status1", :code => Net::SFTP::Session::FX_OK), :file_handle)
|
74
|
-
sftp.expects(:write).with(:file_handle, "data").yields(mock("status2", :code => Net::SFTP::Session::FX_OK))
|
75
|
-
sftp.expects(:close_handle).with(:file_handle).yields
|
76
|
-
session = mock("session", :sftp => sftp, :xserver => server("capistrano"))
|
77
|
-
upload = Capistrano::Upload.new([session], "test.txt", :data => "data", :logger => stub_everything)
|
78
|
-
assert_nothing_raised { upload.process! }
|
79
|
-
assert_equal 0, upload.failed
|
80
|
-
assert_equal 1, upload.completed
|
81
|
-
end
|
82
|
-
|
83
|
-
def test_process_should_loop_while_running
|
84
|
-
con = mock("connection")
|
85
|
-
con.expects(:process).with(true).times(10)
|
86
|
-
channel = {}
|
87
|
-
channel.expects(:connection).returns(con).times(10)
|
88
|
-
sftp = mock("sftp", :state => :open, :open => nil)
|
89
|
-
sftp.stubs(:channel).returns(channel)
|
90
|
-
session = mock("session", :sftp => sftp, :xserver => server("capistrano"))
|
91
|
-
upload = Capistrano::Upload.new([session], "test.txt", :data => "data")
|
92
|
-
upload.expects(:running?).times(11).returns(*([true]*10 + [false]))
|
93
|
-
upload.process!
|
94
|
-
end
|
95
|
-
|
96
|
-
def test_process_should_loop_but_not_process_done_channels
|
97
|
-
new_sftp = Proc.new do |done|
|
98
|
-
channel = {}
|
99
|
-
channel[:needs_done] = done
|
100
|
-
|
101
|
-
if !done
|
102
|
-
con = mock("connection")
|
103
|
-
con.expects(:process).with(true).times(10)
|
104
|
-
channel.expects(:connection).returns(con).times(10)
|
105
|
-
end
|
106
|
-
|
107
|
-
sftp = mock("sftp", :state => :open, :open => nil)
|
108
|
-
sftp.stubs(:channel).returns(channel)
|
109
|
-
sftp
|
110
|
-
end
|
111
|
-
|
112
|
-
sessions = [stub("session", :sftp => new_sftp[true], :xserver => server("capistrano")),
|
113
|
-
stub("session", :sftp => new_sftp[false], :xserver => server("cap2"))]
|
114
|
-
upload = Capistrano::Upload.new(sessions, "test.txt", :data => "data")
|
115
|
-
|
116
|
-
# make sure the sftp channels we wanted to be done, start as done
|
117
|
-
# (Upload.new marks each channel as not-done, so we have to do it here)
|
118
|
-
sessions.each { |s| s.sftp.channel[:done] = true if s.sftp.channel[:needs_done] }
|
119
|
-
upload.expects(:running?).times(11).returns(*([true]*10 + [false]))
|
120
|
-
upload.process!
|
121
|
-
end
|
122
|
-
|
123
|
-
private
|
124
|
-
|
125
|
-
def mock_sftp
|
126
|
-
sftp = mock("sftp", :state => :open)
|
127
|
-
sftp.stubs(:channel).returns(Hash.new)
|
128
|
-
yield sftp if block_given?
|
129
|
-
sftp
|
130
|
-
end
|
131
|
-
end
|