capistrano 2.0.0 → 2.1.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 +54 -0
- data/bin/capify +1 -0
- data/lib/capistrano/callback.rb +4 -0
- data/lib/capistrano/cli/options.rb +2 -2
- data/lib/capistrano/command.rb +26 -11
- data/lib/capistrano/configuration/actions/invocation.rb +11 -4
- data/lib/capistrano/configuration/loading.rb +91 -5
- data/lib/capistrano/configuration/namespaces.rb +6 -0
- data/lib/capistrano/recipes/deploy.rb +22 -11
- data/lib/capistrano/recipes/deploy/remote_dependency.rb +31 -0
- data/lib/capistrano/recipes/deploy/scm/accurev.rb +169 -0
- data/lib/capistrano/recipes/deploy/scm/base.rb +12 -0
- data/lib/capistrano/recipes/deploy/scm/git.rb +191 -0
- data/lib/capistrano/recipes/deploy/scm/subversion.rb +20 -9
- data/lib/capistrano/recipes/deploy/strategy/copy.rb +2 -1
- data/lib/capistrano/recipes/upgrade.rb +1 -1
- data/lib/capistrano/shell.rb +5 -17
- data/lib/capistrano/upload.rb +1 -1
- data/lib/capistrano/version.rb +1 -1
- data/test/command_test.rb +36 -29
- data/test/configuration/actions/invocation_test.rb +15 -8
- data/test/configuration/connections_test.rb +3 -3
- data/test/configuration/loading_test.rb +8 -0
- data/test/configuration/namespace_dsl_test.rb +14 -0
- data/test/deploy/scm/accurev_test.rb +23 -0
- data/test/deploy/scm/git_test.rb +112 -0
- data/test/deploy/strategy/copy_test.rb +7 -6
- data/test/upload_test.rb +4 -4
- metadata +6 -2
@@ -114,6 +114,18 @@ module Capistrano
|
|
114
114
|
raise NotImplementedError, "`query_revision' is not implemented by #{self.class.name}"
|
115
115
|
end
|
116
116
|
|
117
|
+
# Returns the revision number immediately following revision, if at
|
118
|
+
# all possible. A block should always be passed to this method, which
|
119
|
+
# accepts a command to invoke and returns the result, although a
|
120
|
+
# particular SCM's implementation is not required to invoke the block.
|
121
|
+
#
|
122
|
+
# By default, this method simply returns the revision itself. If a
|
123
|
+
# particular SCM is able to determine a subsequent revision given a
|
124
|
+
# revision identifier, it should override this method.
|
125
|
+
def next_revision(revision)
|
126
|
+
revision
|
127
|
+
end
|
128
|
+
|
117
129
|
# Should analyze the given text and determine whether or not a
|
118
130
|
# response is expected, and if so, return the appropriate response.
|
119
131
|
# If no response is expected, return nil. The +state+ parameter is a
|
@@ -0,0 +1,191 @@
|
|
1
|
+
require 'capistrano/recipes/deploy/scm/base'
|
2
|
+
|
3
|
+
module Capistrano
|
4
|
+
module Deploy
|
5
|
+
module SCM
|
6
|
+
|
7
|
+
# An SCM module for using Git as your source control tool with Capistrano
|
8
|
+
# 2.0. If you are using Capistrano 1.x, use this plugin instead:
|
9
|
+
#
|
10
|
+
# http://scie.nti.st/2007/3/16/capistrano-with-git-shared-repository
|
11
|
+
#
|
12
|
+
# Assumes you are using a shared Git repository.
|
13
|
+
#
|
14
|
+
# Parts of this plugin borrowed from Scott Chacon's version, which I
|
15
|
+
# found on the Capistrano mailing list but failed to be able to get
|
16
|
+
# working.
|
17
|
+
#
|
18
|
+
# FEATURES:
|
19
|
+
#
|
20
|
+
# * Very simple, only requiring 2 lines in your deploy.rb.
|
21
|
+
# * Can deploy different branches, tags, or any SHA1 easily.
|
22
|
+
# * Supports prompting for password / passphrase upon checkout.
|
23
|
+
# (I am amazed at how some plugins don't do this)
|
24
|
+
# * Supports :scm_command, :scm_password, :scm_passphrase Capistrano
|
25
|
+
# directives.
|
26
|
+
#
|
27
|
+
# REQUIREMENTS
|
28
|
+
# ------------
|
29
|
+
#
|
30
|
+
# Git is required to be installed on your remote machine(s), because a
|
31
|
+
# clone and checkout is done to get the code up there. This is the way
|
32
|
+
# I prefer to deploy; there is no alternative to this, so :deploy_via
|
33
|
+
# is ignored.
|
34
|
+
#
|
35
|
+
# CONFIGURATION
|
36
|
+
# -------------
|
37
|
+
#
|
38
|
+
# Use this plugin by adding the following line in your config/deploy.rb:
|
39
|
+
#
|
40
|
+
# set :scm, :git
|
41
|
+
#
|
42
|
+
# Set <tt>:repository</tt> to the path of your Git repo:
|
43
|
+
#
|
44
|
+
# set :repository, "someuser@somehost:/home/myproject"
|
45
|
+
#
|
46
|
+
# The above two options are required to be set, the ones below are
|
47
|
+
# optional.
|
48
|
+
#
|
49
|
+
# You may set <tt>:branch</tt>, which is the reference to the branch, tag,
|
50
|
+
# or any SHA1 you are deploying, for example:
|
51
|
+
#
|
52
|
+
# set :branch, "origin/master"
|
53
|
+
#
|
54
|
+
# Otherwise, HEAD is assumed. I strongly suggest you set this. HEAD is
|
55
|
+
# not always the best assumption.
|
56
|
+
#
|
57
|
+
# The <tt>:scm_command</tt> configuration variable, if specified, will
|
58
|
+
# be used as the full path to the git executable on the *remote* machine:
|
59
|
+
#
|
60
|
+
# set :scm_command, "/opt/local/bin/git"
|
61
|
+
#
|
62
|
+
# For compatibility with deploy scripts that may have used the 1.x
|
63
|
+
# version of this plugin before upgrading, <tt>:git</tt> is still
|
64
|
+
# recognized as an alias for :scm_command.
|
65
|
+
#
|
66
|
+
# Set <tt>:scm_password</tt> to the password needed to clone your repo
|
67
|
+
# if you don't have password-less (public key) entry:
|
68
|
+
#
|
69
|
+
# set :scm_password, "my_secret'
|
70
|
+
#
|
71
|
+
# Otherwise, you will be prompted for a password.
|
72
|
+
#
|
73
|
+
# <tt>:scm_passphrase</tt> is also supported.
|
74
|
+
#
|
75
|
+
# The remote cache strategy is also supported.
|
76
|
+
#
|
77
|
+
# set :repository_cache, "git_master"
|
78
|
+
# set :deploy_via, :remote_cache
|
79
|
+
#
|
80
|
+
# For faster clone, you can also use shallow cloning. This will set the
|
81
|
+
# '--depth' flag using the depth specified. This *cannot* be used
|
82
|
+
# together with the :remote_cache strategy
|
83
|
+
#
|
84
|
+
# set :git_shallow_clone, 1
|
85
|
+
#
|
86
|
+
# AUTHORS
|
87
|
+
# -------
|
88
|
+
#
|
89
|
+
# Garry Dolley http://scie.nti.st
|
90
|
+
# Contributions by Geoffrey Grosenbach http://topfunky.com
|
91
|
+
# and Scott Chacon http://jointheconversation.org
|
92
|
+
|
93
|
+
class Git < Base
|
94
|
+
# Sets the default command name for this SCM on your *local* machine.
|
95
|
+
# Users may override this by setting the :scm_command variable.
|
96
|
+
default_command "git"
|
97
|
+
|
98
|
+
# When referencing "head", use the branch we want to deploy or, by
|
99
|
+
# default, Git's reference of HEAD (the latest changeset in the default
|
100
|
+
# branch, usually called "master").
|
101
|
+
def head
|
102
|
+
configuration[:branch] || 'HEAD'
|
103
|
+
end
|
104
|
+
|
105
|
+
# Performs a clone on the remote machine, then checkout on the branch
|
106
|
+
# you want to deploy.
|
107
|
+
def checkout(revision, destination)
|
108
|
+
git = command
|
109
|
+
|
110
|
+
branch = head
|
111
|
+
|
112
|
+
fail "No branch specified, use for example 'set :branch, \"origin/master\"' in your deploy.rb" unless branch
|
113
|
+
|
114
|
+
if depth = configuration[:git_shallow_clone]
|
115
|
+
execute = "#{git} clone --depth #{depth} #{configuration[:repository]} #{destination} && "
|
116
|
+
else
|
117
|
+
execute = "#{git} clone #{configuration[:repository]} #{destination} && "
|
118
|
+
end
|
119
|
+
|
120
|
+
execute += "cd #{destination} && #{git} checkout -b deploy #{branch}"
|
121
|
+
|
122
|
+
execute
|
123
|
+
end
|
124
|
+
|
125
|
+
# Merges the changes to 'head' since the last fetch, for remote_cache
|
126
|
+
# deployment strategy
|
127
|
+
def sync(revision, destination)
|
128
|
+
execute = "cd #{destination} && git fetch origin && "
|
129
|
+
|
130
|
+
if head == 'HEAD'
|
131
|
+
execute += "git merge origin/HEAD"
|
132
|
+
else
|
133
|
+
execute += "git merge #{head}"
|
134
|
+
end
|
135
|
+
|
136
|
+
execute
|
137
|
+
end
|
138
|
+
|
139
|
+
# Returns a string of diffs between two revisions
|
140
|
+
def diff(from, to=nil)
|
141
|
+
from << "..#{to}" if to
|
142
|
+
scm :diff, from
|
143
|
+
end
|
144
|
+
|
145
|
+
# Returns a log of changes between the two revisions (inclusive).
|
146
|
+
def log(from, to=nil)
|
147
|
+
from << "..#{to}" if to
|
148
|
+
scm :log, from
|
149
|
+
end
|
150
|
+
|
151
|
+
# Getting the actual commit id, in case we were passed a tag
|
152
|
+
# or partial sha or something - it will return the sha if you pass a sha, too
|
153
|
+
def query_revision(revision)
|
154
|
+
yield(scm('rev-parse', revision)).chomp
|
155
|
+
end
|
156
|
+
|
157
|
+
def command
|
158
|
+
# For backwards compatibility with 1.x version of this module
|
159
|
+
configuration[:git] || super
|
160
|
+
end
|
161
|
+
|
162
|
+
# Determines what the response should be for a particular bit of text
|
163
|
+
# from the SCM. Password prompts, connection requests, passphrases,
|
164
|
+
# etc. are handled here.
|
165
|
+
def handle_data(state, stream, text)
|
166
|
+
logger.info "[#{stream}] #{text}"
|
167
|
+
case text
|
168
|
+
when /\bpassword.*:/i
|
169
|
+
# git is prompting for a password
|
170
|
+
unless pass = configuration[:scm_password]
|
171
|
+
pass = Capistrano::CLI.password_prompt
|
172
|
+
end
|
173
|
+
"#{pass}\n"
|
174
|
+
when %r{\(yes/no\)}
|
175
|
+
# git is asking whether or not to connect
|
176
|
+
"yes\n"
|
177
|
+
when /passphrase/i
|
178
|
+
# git is asking for the passphrase for the user's key
|
179
|
+
unless pass = configuration[:scm_passphrase]
|
180
|
+
pass = Capistrano::CLI.password_prompt
|
181
|
+
end
|
182
|
+
"#{pass}\n"
|
183
|
+
when /accept \(t\)emporarily/
|
184
|
+
# git is asking whether to accept the certificate
|
185
|
+
"t\n"
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
@@ -52,8 +52,16 @@ module Capistrano
|
|
52
52
|
# executed (svn info), and will extract the revision from the response.
|
53
53
|
def query_revision(revision)
|
54
54
|
return revision if revision =~ /^\d+$/
|
55
|
-
|
56
|
-
|
55
|
+
command = scm(:info, repository, authentication, "-r#{revision}")
|
56
|
+
result = yield(command)
|
57
|
+
yaml = YAML.load(result)
|
58
|
+
raise "tried to run `#{command}' and got unexpected result #{result.inspect}" unless Hash === yaml
|
59
|
+
yaml['Last Changed Rev'] || yaml['Revision']
|
60
|
+
end
|
61
|
+
|
62
|
+
# Increments the given revision number and returns it.
|
63
|
+
def next_revision(revision)
|
64
|
+
revision.to_i + 1
|
57
65
|
end
|
58
66
|
|
59
67
|
# Determines what the response should be for a particular bit of text
|
@@ -81,14 +89,17 @@ module Capistrano
|
|
81
89
|
|
82
90
|
private
|
83
91
|
|
84
|
-
# If a username
|
85
|
-
#
|
92
|
+
# If a username is configured for the SCM, return the command-line
|
93
|
+
# switches for that. Note that we don't need to return the password
|
94
|
+
# switch, since Capistrano will check for that prompt in the output
|
95
|
+
# and will respond appropriately.
|
86
96
|
def authentication
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
auth
|
97
|
+
username = variable(:scm_username)
|
98
|
+
return "" unless username
|
99
|
+
result = "--username #{variable(:scm_username)} "
|
100
|
+
result << "--password #{variable(:scm_password)} " unless variable(:scm_prefer_prompt)
|
101
|
+
result << "--no-auth-cache " unless variable(:scm_auth_cache)
|
102
|
+
result
|
92
103
|
end
|
93
104
|
|
94
105
|
# If verbose output is requested, return nil, otherwise return the
|
@@ -32,7 +32,8 @@ module Capistrano
|
|
32
32
|
logger.trace "compressing #{destination} to #{filename}"
|
33
33
|
Dir.chdir(tmpdir) { system(compress(File.basename(destination), File.basename(filename)).join(" ")) }
|
34
34
|
|
35
|
-
|
35
|
+
content = File.open(filename, "rb") { |f| f.read }
|
36
|
+
put content, remote_filename
|
36
37
|
run "cd #{configuration[:releases_path]} && #{decompress(remote_filename).join(" ")} && rm #{remote_filename}"
|
37
38
|
ensure
|
38
39
|
FileUtils.rm filename rescue nil
|
@@ -10,7 +10,7 @@ namespace :upgrade do
|
|
10
10
|
tag file used in Capistrano 2.x. It is non-destructive and may be safely \
|
11
11
|
run any number of times.
|
12
12
|
DESC
|
13
|
-
task :revisions do
|
13
|
+
task :revisions, :except => { :no_release => true } do
|
14
14
|
revisions = capture("cat #{deploy_to}/revisions.log")
|
15
15
|
|
16
16
|
mapping = {}
|
data/lib/capistrano/shell.rb
CHANGED
@@ -166,24 +166,12 @@ HELP
|
|
166
166
|
|
167
167
|
# Execute a command on the given list of servers.
|
168
168
|
def exec_command(command, servers)
|
169
|
-
|
170
|
-
|
171
|
-
out.each do |line|
|
172
|
-
if stream == :out
|
173
|
-
if out =~ /Password:\s*/i
|
174
|
-
ch.send_data "#{configuration[:password]}\n"
|
175
|
-
else
|
176
|
-
puts "[#{ch[:server]}] #{line.chomp}"
|
177
|
-
end
|
178
|
-
elsif stream == :err
|
179
|
-
puts "[#{ch[:server]} ERR] #{line.chomp}"
|
180
|
-
end
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
previous = trap("INT") { cmd.stop! }
|
169
|
+
command = command.gsub(/\bsudo\b/, "sudo -p '#{configuration.sudo_prompt}'")
|
170
|
+
processor = configuration.sudo_behavior_callback(Configuration.default_io_proc)
|
185
171
|
sessions = servers.map { |server| configuration.sessions[server] }
|
186
|
-
Command.
|
172
|
+
cmd = Command.new(command, sessions, :logger => configuration.logger, &processor)
|
173
|
+
previous = trap("INT") { cmd.stop! }
|
174
|
+
cmd.process!
|
187
175
|
rescue Capistrano::Error => error
|
188
176
|
warn "error: #{error.message}"
|
189
177
|
ensure
|
data/lib/capistrano/upload.rb
CHANGED
@@ -101,7 +101,7 @@ module Capistrano
|
|
101
101
|
sftp.channel[:failed] = false
|
102
102
|
|
103
103
|
real_filename = filename.gsub(/\$CAPISTRANO:HOST\$/, server.host)
|
104
|
-
sftp.open(real_filename, IO::WRONLY | IO::CREAT | IO::TRUNC, options[:mode] ||
|
104
|
+
sftp.open(real_filename, IO::WRONLY | IO::CREAT | IO::TRUNC, options[:mode] || 0664) do |status, handle|
|
105
105
|
break unless check_status(sftp, "open #{real_filename}", server, status)
|
106
106
|
|
107
107
|
logger.info "uploading data to #{server}:#{real_filename}" if logger
|
data/lib/capistrano/version.rb
CHANGED
data/test/command_test.rb
CHANGED
@@ -19,43 +19,52 @@ class CommandTest < Test::Unit::TestCase
|
|
19
19
|
assert_equal "ls\\\necho", cmd.command
|
20
20
|
end
|
21
21
|
|
22
|
-
def
|
22
|
+
def test_command_with_pty_should_request_pty_and_register_success_callback
|
23
23
|
session = setup_for_extracting_channel_action(:on_success) do |ch|
|
24
|
+
ch.expects(:request_pty).with(:want_reply => true)
|
25
|
+
ch.expects(:exec).with(%(sh -c "ls"))
|
26
|
+
end
|
27
|
+
Capistrano::Command.new("ls", [session], :pty => true)
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_command_with_env_key_should_have_environment_constructed_and_prepended
|
31
|
+
session = setup_for_extracting_channel_action do |ch|
|
32
|
+
ch.expects(:request_pty).never
|
24
33
|
ch.expects(:exec).with(%(env FOO=bar sh -c "ls"))
|
25
34
|
end
|
26
35
|
Capistrano::Command.new("ls", [session], :env => { "FOO" => "bar" })
|
27
36
|
end
|
28
37
|
|
29
38
|
def test_env_with_symbolic_key_should_be_accepted_as_a_string
|
30
|
-
session = setup_for_extracting_channel_action
|
39
|
+
session = setup_for_extracting_channel_action do |ch|
|
31
40
|
ch.expects(:exec).with(%(env FOO=bar sh -c "ls"))
|
32
41
|
end
|
33
42
|
Capistrano::Command.new("ls", [session], :env => { :FOO => "bar" })
|
34
43
|
end
|
35
44
|
|
36
45
|
def test_env_as_string_should_be_substituted_in_directly
|
37
|
-
session = setup_for_extracting_channel_action
|
46
|
+
session = setup_for_extracting_channel_action do |ch|
|
38
47
|
ch.expects(:exec).with(%(env HOWDY=there sh -c "ls"))
|
39
48
|
end
|
40
49
|
Capistrano::Command.new("ls", [session], :env => "HOWDY=there")
|
41
50
|
end
|
42
51
|
|
43
52
|
def test_env_with_symbolic_value_should_be_accepted_as_string
|
44
|
-
session = setup_for_extracting_channel_action
|
53
|
+
session = setup_for_extracting_channel_action do |ch|
|
45
54
|
ch.expects(:exec).with(%(env FOO=bar sh -c "ls"))
|
46
55
|
end
|
47
56
|
Capistrano::Command.new("ls", [session], :env => { "FOO" => :bar })
|
48
57
|
end
|
49
58
|
|
50
59
|
def test_env_value_should_be_escaped
|
51
|
-
session = setup_for_extracting_channel_action
|
60
|
+
session = setup_for_extracting_channel_action do |ch|
|
52
61
|
ch.expects(:exec).with(%(env FOO=(\\ \\\"bar\\\"\\ ) sh -c "ls"))
|
53
62
|
end
|
54
63
|
Capistrano::Command.new("ls", [session], :env => { "FOO" => '( "bar" )' })
|
55
64
|
end
|
56
65
|
|
57
66
|
def test_env_with_multiple_keys_should_chain_the_entries_together
|
58
|
-
session = setup_for_extracting_channel_action
|
67
|
+
session = setup_for_extracting_channel_action do |ch|
|
59
68
|
ch.expects(:exec).with do |command|
|
60
69
|
command =~ /^env / &&
|
61
70
|
command =~ /\ba=b\b/ &&
|
@@ -73,6 +82,7 @@ class CommandTest < Test::Unit::TestCase
|
|
73
82
|
|
74
83
|
session.expects(:open_channel).yields(channel)
|
75
84
|
channel.expects(:[]=).with(:host, "capistrano")
|
85
|
+
channel.stubs(:[]).with(:host).returns("capistrano")
|
76
86
|
|
77
87
|
Capistrano::Command.new("ls", [session])
|
78
88
|
end
|
@@ -83,47 +93,45 @@ class CommandTest < Test::Unit::TestCase
|
|
83
93
|
|
84
94
|
session.expects(:open_channel).yields(channel)
|
85
95
|
channel.expects(:[]=).with(:options, {:data => "here we go"})
|
96
|
+
channel.stubs(:[]).with(:host).returns("capistrano")
|
86
97
|
|
87
98
|
Capistrano::Command.new("ls", [session], :data => "here we go")
|
88
99
|
end
|
89
100
|
|
90
|
-
def test_open_channel_should_request_pty
|
91
|
-
session = mock(:xserver => server("capistrano"))
|
92
|
-
channel = stub_everything
|
93
|
-
|
94
|
-
session.expects(:open_channel).yields(channel)
|
95
|
-
channel.expects(:request_pty).with(:want_reply => true)
|
96
|
-
|
97
|
-
Capistrano::Command.new("ls", [session])
|
98
|
-
end
|
99
|
-
|
100
101
|
def test_successful_channel_should_send_command
|
101
|
-
session = setup_for_extracting_channel_action
|
102
|
+
session = setup_for_extracting_channel_action do |ch|
|
102
103
|
ch.expects(:exec).with(%(sh -c "ls"))
|
103
104
|
end
|
104
105
|
Capistrano::Command.new("ls", [session])
|
105
106
|
end
|
106
107
|
|
107
108
|
def test_successful_channel_with_shell_option_should_send_command_via_specified_shell
|
108
|
-
session = setup_for_extracting_channel_action
|
109
|
+
session = setup_for_extracting_channel_action do |ch|
|
109
110
|
ch.expects(:exec).with(%(/bin/bash -c "ls"))
|
110
111
|
end
|
111
112
|
Capistrano::Command.new("ls", [session], :shell => "/bin/bash")
|
112
113
|
end
|
113
114
|
|
115
|
+
def test_successful_channel_with_shell_false_should_send_command_without_shell
|
116
|
+
session = setup_for_extracting_channel_action do |ch|
|
117
|
+
ch.expects(:exec).with(%(echo `hostname`))
|
118
|
+
end
|
119
|
+
Capistrano::Command.new("echo `hostname`", [session], :shell => false)
|
120
|
+
end
|
121
|
+
|
114
122
|
def test_successful_channel_should_send_data_if_data_key_is_present
|
115
|
-
session = setup_for_extracting_channel_action
|
123
|
+
session = setup_for_extracting_channel_action do |ch|
|
116
124
|
ch.expects(:exec).with(%(sh -c "ls"))
|
117
125
|
ch.expects(:send_data).with("here we go")
|
118
126
|
end
|
119
127
|
Capistrano::Command.new("ls", [session], :data => "here we go")
|
120
128
|
end
|
121
129
|
|
122
|
-
def
|
130
|
+
def test_unsuccessful_pty_request_should_close_channel
|
123
131
|
session = setup_for_extracting_channel_action(:on_failure) do |ch|
|
124
132
|
ch.expects(:close)
|
125
133
|
end
|
126
|
-
Capistrano::Command.new("ls", [session])
|
134
|
+
Capistrano::Command.new("ls", [session], :pty => true)
|
127
135
|
end
|
128
136
|
|
129
137
|
def test_on_data_should_invoke_callback_as_stdout
|
@@ -258,14 +266,14 @@ class CommandTest < Test::Unit::TestCase
|
|
258
266
|
end
|
259
267
|
|
260
268
|
def test_process_with_host_placeholder_should_substitute_placeholder_with_each_host
|
261
|
-
session = setup_for_extracting_channel_action
|
269
|
+
session = setup_for_extracting_channel_action do |ch|
|
262
270
|
ch.expects(:exec).with(%(sh -c "echo capistrano"))
|
263
271
|
end
|
264
272
|
Capistrano::Command.new("echo $CAPISTRANO:HOST$", [session])
|
265
273
|
end
|
266
274
|
|
267
275
|
def test_process_with_unknown_placeholder_should_not_replace_placeholder
|
268
|
-
session = setup_for_extracting_channel_action
|
276
|
+
session = setup_for_extracting_channel_action do |ch|
|
269
277
|
ch.expects(:exec).with(%(sh -c "echo \\$CAPISTRANO:OTHER\\$"))
|
270
278
|
end
|
271
279
|
Capistrano::Command.new("echo $CAPISTRANO:OTHER$", [session])
|
@@ -283,19 +291,18 @@ class CommandTest < Test::Unit::TestCase
|
|
283
291
|
ch
|
284
292
|
end
|
285
293
|
|
286
|
-
def setup_for_extracting_channel_action(action, *args)
|
294
|
+
def setup_for_extracting_channel_action(action=nil, *args)
|
287
295
|
s = server("capistrano")
|
288
296
|
session = mock("session", :xserver => s)
|
289
297
|
|
290
298
|
channel = stub_everything
|
291
299
|
session.expects(:open_channel).yields(channel)
|
292
300
|
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
channel.expects(action).yields(ch, *args)
|
301
|
+
channel.stubs(:[]).with(:server).returns(s)
|
302
|
+
channel.stubs(:[]).with(:host).returns(s.host)
|
303
|
+
channel.expects(action).yields(channel, *args) if action
|
297
304
|
|
298
|
-
yield
|
305
|
+
yield channel if block_given?
|
299
306
|
|
300
307
|
session
|
301
308
|
end
|