capistrano 2.0.0 → 2.15.9

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.
Files changed (124) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.travis.yml +9 -0
  4. data/CHANGELOG +755 -18
  5. data/Gemfile +13 -0
  6. data/README.md +94 -0
  7. data/Rakefile +11 -0
  8. data/bin/cap +0 -0
  9. data/bin/capify +37 -22
  10. data/capistrano.gemspec +40 -0
  11. data/lib/capistrano/callback.rb +5 -1
  12. data/lib/capistrano/cli/execute.rb +10 -7
  13. data/lib/capistrano/cli/help.rb +39 -16
  14. data/lib/capistrano/cli/help.txt +44 -16
  15. data/lib/capistrano/cli/options.rb +71 -11
  16. data/lib/capistrano/cli/ui.rb +13 -1
  17. data/lib/capistrano/cli.rb +5 -5
  18. data/lib/capistrano/command.rb +215 -58
  19. data/lib/capistrano/configuration/actions/file_transfer.rb +29 -14
  20. data/lib/capistrano/configuration/actions/inspect.rb +3 -3
  21. data/lib/capistrano/configuration/actions/invocation.rb +224 -22
  22. data/lib/capistrano/configuration/alias_task.rb +26 -0
  23. data/lib/capistrano/configuration/callbacks.rb +26 -27
  24. data/lib/capistrano/configuration/connections.rb +130 -52
  25. data/lib/capistrano/configuration/execution.rb +34 -18
  26. data/lib/capistrano/configuration/loading.rb +99 -6
  27. data/lib/capistrano/configuration/log_formatters.rb +75 -0
  28. data/lib/capistrano/configuration/namespaces.rb +45 -12
  29. data/lib/capistrano/configuration/roles.rb +34 -2
  30. data/lib/capistrano/configuration/servers.rb +51 -10
  31. data/lib/capistrano/configuration/variables.rb +3 -3
  32. data/lib/capistrano/configuration.rb +20 -4
  33. data/lib/capistrano/errors.rb +12 -8
  34. data/lib/capistrano/ext/multistage.rb +67 -0
  35. data/lib/capistrano/ext/string.rb +5 -0
  36. data/lib/capistrano/extensions.rb +1 -1
  37. data/lib/capistrano/fix_rake_deprecated_dsl.rb +8 -0
  38. data/lib/capistrano/logger.rb +112 -5
  39. data/lib/capistrano/processable.rb +55 -0
  40. data/lib/capistrano/recipes/compat.rb +2 -2
  41. data/lib/capistrano/recipes/deploy/assets.rb +202 -0
  42. data/lib/capistrano/recipes/deploy/dependencies.rb +2 -2
  43. data/lib/capistrano/recipes/deploy/local_dependency.rb +10 -2
  44. data/lib/capistrano/recipes/deploy/remote_dependency.rb +54 -2
  45. data/lib/capistrano/recipes/deploy/scm/accurev.rb +169 -0
  46. data/lib/capistrano/recipes/deploy/scm/base.rb +31 -11
  47. data/lib/capistrano/recipes/deploy/scm/bzr.rb +14 -14
  48. data/lib/capistrano/recipes/deploy/scm/cvs.rb +11 -9
  49. data/lib/capistrano/recipes/deploy/scm/darcs.rb +12 -1
  50. data/lib/capistrano/recipes/deploy/scm/git.rb +299 -0
  51. data/lib/capistrano/recipes/deploy/scm/mercurial.rb +23 -15
  52. data/lib/capistrano/recipes/deploy/scm/none.rb +55 -0
  53. data/lib/capistrano/recipes/deploy/scm/perforce.rb +54 -28
  54. data/lib/capistrano/recipes/deploy/scm/subversion.rb +36 -18
  55. data/lib/capistrano/recipes/deploy/scm.rb +1 -1
  56. data/lib/capistrano/recipes/deploy/strategy/base.rb +32 -4
  57. data/lib/capistrano/recipes/deploy/strategy/copy.rb +238 -43
  58. data/lib/capistrano/recipes/deploy/strategy/remote.rb +1 -1
  59. data/lib/capistrano/recipes/deploy/strategy/remote_cache.rb +11 -1
  60. data/lib/capistrano/recipes/deploy/strategy/unshared_remote_cache.rb +21 -0
  61. data/lib/capistrano/recipes/deploy/strategy.rb +4 -3
  62. data/lib/capistrano/recipes/deploy.rb +265 -123
  63. data/lib/capistrano/recipes/standard.rb +1 -1
  64. data/lib/capistrano/role.rb +102 -0
  65. data/lib/capistrano/server_definition.rb +6 -1
  66. data/lib/capistrano/shell.rb +30 -33
  67. data/lib/capistrano/ssh.rb +46 -60
  68. data/lib/capistrano/task_definition.rb +16 -8
  69. data/lib/capistrano/transfer.rb +218 -0
  70. data/lib/capistrano/version.rb +8 -17
  71. data/lib/capistrano.rb +4 -1
  72. data/test/cli/execute_test.rb +3 -3
  73. data/test/cli/help_test.rb +33 -7
  74. data/test/cli/options_test.rb +109 -6
  75. data/test/cli/ui_test.rb +2 -2
  76. data/test/cli_test.rb +3 -3
  77. data/test/command_test.rb +144 -124
  78. data/test/configuration/actions/file_transfer_test.rb +41 -20
  79. data/test/configuration/actions/inspect_test.rb +21 -7
  80. data/test/configuration/actions/invocation_test.rb +141 -30
  81. data/test/configuration/alias_task_test.rb +118 -0
  82. data/test/configuration/callbacks_test.rb +41 -46
  83. data/test/configuration/connections_test.rb +187 -36
  84. data/test/configuration/execution_test.rb +18 -2
  85. data/test/configuration/loading_test.rb +33 -4
  86. data/test/configuration/namespace_dsl_test.rb +54 -5
  87. data/test/configuration/roles_test.rb +114 -4
  88. data/test/configuration/servers_test.rb +97 -4
  89. data/test/configuration/variables_test.rb +12 -2
  90. data/test/configuration_test.rb +9 -13
  91. data/test/deploy/local_dependency_test.rb +76 -0
  92. data/test/deploy/remote_dependency_test.rb +146 -0
  93. data/test/deploy/scm/accurev_test.rb +23 -0
  94. data/test/deploy/scm/base_test.rb +1 -1
  95. data/test/deploy/scm/bzr_test.rb +51 -0
  96. data/test/deploy/scm/darcs_test.rb +37 -0
  97. data/test/deploy/scm/git_test.rb +274 -0
  98. data/test/deploy/scm/mercurial_test.rb +134 -0
  99. data/test/deploy/scm/none_test.rb +35 -0
  100. data/test/deploy/scm/perforce_test.rb +23 -0
  101. data/test/deploy/scm/subversion_test.rb +68 -0
  102. data/test/deploy/strategy/copy_test.rb +240 -26
  103. data/test/extensions_test.rb +2 -2
  104. data/test/logger_formatting_test.rb +149 -0
  105. data/test/logger_test.rb +13 -2
  106. data/test/recipes_test.rb +25 -0
  107. data/test/role_test.rb +11 -0
  108. data/test/server_definition_test.rb +15 -2
  109. data/test/shell_test.rb +33 -1
  110. data/test/ssh_test.rb +40 -24
  111. data/test/task_definition_test.rb +18 -2
  112. data/test/transfer_test.rb +168 -0
  113. data/test/utils.rb +28 -33
  114. data/test/version_test.rb +4 -17
  115. metadata +215 -100
  116. data/MIT-LICENSE +0 -20
  117. data/README +0 -43
  118. data/examples/sample.rb +0 -14
  119. data/lib/capistrano/gateway.rb +0 -131
  120. data/lib/capistrano/recipes/deploy/templates/maintenance.rhtml +0 -53
  121. data/lib/capistrano/recipes/upgrade.rb +0 -33
  122. data/lib/capistrano/upload.rb +0 -146
  123. data/test/gateway_test.rb +0 -167
  124. data/test/upload_test.rb +0 -131
@@ -1,12 +1,19 @@
1
- require "#{File.dirname(__FILE__)}/../../utils"
1
+ require "utils"
2
2
  require 'capistrano/configuration/actions/invocation'
3
+ require 'capistrano/configuration/actions/file_transfer'
3
4
 
4
5
  class ConfigurationActionsInvocationTest < Test::Unit::TestCase
5
6
  class MockConfig
6
7
  attr_reader :options
8
+ attr_accessor :debug
9
+ attr_accessor :dry_run
10
+ attr_accessor :preserve_roles
11
+ attr_accessor :servers
12
+ attr_accessor :roles
7
13
 
8
14
  def initialize
9
15
  @options = {}
16
+ @servers = []
10
17
  end
11
18
 
12
19
  def [](*args)
@@ -21,13 +28,21 @@ class ConfigurationActionsInvocationTest < Test::Unit::TestCase
21
28
  @options.fetch(*args)
22
29
  end
23
30
 
31
+ def filter_servers(options = {})
32
+ [nil, @servers]
33
+ end
34
+
35
+ def execute_on_servers(options = {})
36
+ yield @servers
37
+ end
38
+
24
39
  include Capistrano::Configuration::Actions::Invocation
40
+ include Capistrano::Configuration::Actions::FileTransfer
25
41
  end
26
42
 
27
43
  def setup
28
- @config = MockConfig.new
44
+ @config = make_config
29
45
  @original_io_proc = MockConfig.default_io_proc
30
- @config.stubs(:logger).returns(stub_everything)
31
46
  end
32
47
 
33
48
  def teardown
@@ -35,24 +50,23 @@ class ConfigurationActionsInvocationTest < Test::Unit::TestCase
35
50
  end
36
51
 
37
52
  def test_run_options_should_be_passed_to_execute_on_servers
38
- @config.expects(:execute_on_servers).with(:foo => "bar")
53
+ @config.expects(:execute_on_servers).with(:foo => "bar", :eof => true)
39
54
  @config.run "ls", :foo => "bar"
40
55
  end
41
56
 
42
- def test_run_without_block_should_use_default_io_proc
43
- @config.expects(:execute_on_servers).yields(%w(s1 s2 s3).map { |s| server(s) })
44
- @config.expects(:sessions).returns(Hash.new { |h,k| h[k] = k.host.to_sym }).times(3)
45
- prepare_command("ls", [:s1, :s2, :s3], {:logger => @config.logger})
46
- MockConfig.default_io_proc = inspectable_proc
47
- @config.run "ls"
57
+ def test_run_will_return_if_dry_run
58
+ @config.expects(:dry_run).returns(true)
59
+ @config.expects(:execute_on_servers).never
60
+ @config.run "ls", :foo => "bar"
48
61
  end
49
62
 
50
- def test_run_with_block_should_use_block
51
- @config.expects(:execute_on_servers).yields(%w(s1 s2 s3).map { |s| mock(:host => s) })
52
- @config.expects(:sessions).returns(Hash.new { |h,k| h[k] = k.host.to_sym }).times(3)
53
- prepare_command("ls", [:s1, :s2, :s3], {:logger => @config.logger})
54
- MockConfig.default_io_proc = Proc.new { |a,b,c| raise "shouldn't get here" }
55
- @config.run("ls", &inspectable_proc)
63
+ def test_put_wont_transfer_if_dry_run
64
+ config = make_config
65
+ config.dry_run = true
66
+ config.servers = %w[ foo ]
67
+ config.expects(:execute_on_servers).never
68
+ ::Capistrano::Transfer.expects(:process).never
69
+ config.put "foo", "bar", :mode => 0644
56
70
  end
57
71
 
58
72
  def test_add_default_command_options_should_return_bare_options_if_there_is_no_env_or_shell_specified
@@ -75,6 +89,11 @@ class ConfigurationActionsInvocationTest < Test::Unit::TestCase
75
89
  assert_equal({:foo => "bar", :shell => "/bin/bash"}, @config.add_default_command_options(:foo => "bar"))
76
90
  end
77
91
 
92
+ def test_add_default_command_options_should_use_default_shell_of_false_if_present
93
+ @config.set :default_shell, false
94
+ assert_equal({:foo => "bar", :shell => false}, @config.add_default_command_options(:foo => "bar"))
95
+ end
96
+
78
97
  def test_add_default_command_options_should_use_shell_in_preference_of_default_shell
79
98
  @config.set :default_shell, "/bin/bash"
80
99
  assert_equal({:foo => "bar", :shell => "/bin/sh"}, @config.add_default_command_options(:foo => "bar", :shell => "/bin/sh"))
@@ -97,38 +116,56 @@ class ConfigurationActionsInvocationTest < Test::Unit::TestCase
97
116
  end
98
117
 
99
118
  def test_sudo_should_default_to_sudo
100
- @config.expects(:run).with("sudo ls", {})
119
+ @config.expects(:run).with("sudo -p 'sudo password: ' ls", {})
101
120
  @config.sudo "ls"
102
121
  end
103
122
 
123
+ def test_sudo_should_keep_input_stream_open
124
+ @config.expects(:execute_on_servers).with(:foo => "bar")
125
+ @config.sudo "ls", :foo => "bar"
126
+ end
127
+
104
128
  def test_sudo_should_use_sudo_variable_definition
105
- @config.expects(:run).with("/opt/local/bin/sudo ls", {})
129
+ @config.expects(:run).with("/opt/local/bin/sudo -p 'sudo password: ' ls", {})
106
130
  @config.options[:sudo] = "/opt/local/bin/sudo"
107
131
  @config.sudo "ls"
108
132
  end
109
133
 
110
134
  def test_sudo_should_interpret_as_option_as_user
111
- @config.expects(:run).with("sudo -u app ls", {})
135
+ @config.expects(:run).with("sudo -p 'sudo password: ' -u app ls", {})
112
136
  @config.sudo "ls", :as => "app"
113
137
  end
114
138
 
115
139
  def test_sudo_should_pass_options_through_to_run
116
- @config.expects(:run).with("sudo ls", :foo => "bar")
140
+ @config.expects(:run).with("sudo -p 'sudo password: ' ls", :foo => "bar")
117
141
  @config.sudo "ls", :foo => "bar"
118
142
  end
119
143
 
120
- def test_sudo_behavior_callback_should_send_password_when_prompted
144
+ def test_sudo_should_avoid_minus_p_when_sudo_prompt_is_empty
145
+ @config.set :sudo_prompt, ""
146
+ @config.expects(:run).with("sudo ls", {})
147
+ @config.sudo "ls"
148
+ end
149
+
150
+ def test_sudo_should_interpret_sudo_prompt_variable_as_custom_prompt
151
+ @config.set :sudo_prompt, "give it to me: "
152
+ @config.expects(:run).with("sudo -p 'give it to me: ' ls", {})
153
+ @config.sudo "ls"
154
+ end
155
+
156
+ def test_sudo_behavior_callback_should_send_password_when_prompted_with_default_sudo_prompt
121
157
  ch = mock("channel")
122
158
  ch.expects(:send_data).with("g00b3r\n")
123
159
  @config.options[:password] = "g00b3r"
124
- @config.sudo_behavior_callback(nil)[ch, nil, "Password: "]
160
+ @config.sudo_behavior_callback(nil)[ch, nil, "sudo password: "]
125
161
  end
126
162
 
127
- def test_sudo_behavior_callback_should_send_password_when_prompted_with_SuSE_dialect
163
+ def test_sudo_behavior_callback_should_send_password_when_prompted_with_custom_sudo_prompt
128
164
  ch = mock("channel")
129
165
  ch.expects(:send_data).with("g00b3r\n")
166
+ @config.set :sudo_prompt, "give it to me: "
130
167
  @config.options[:password] = "g00b3r"
131
- @config.sudo_behavior_callback(nil)[ch, nil, "user's password: "]
168
+ @config.sudo_behavior_callback(nil)[ch, nil, "give it to me: "]
132
169
  end
133
170
 
134
171
  def test_sudo_behavior_callback_with_incorrect_password_on_first_prompt
@@ -136,7 +173,7 @@ class ConfigurationActionsInvocationTest < Test::Unit::TestCase
136
173
  ch.stubs(:[]).with(:host).returns("capistrano")
137
174
  ch.stubs(:[]).with(:server).returns(server("capistrano"))
138
175
  @config.expects(:reset!).with(:password)
139
- @config.sudo_behavior_callback(nil)[ch, nil, "blah blah try again blah blah"]
176
+ @config.sudo_behavior_callback(nil)[ch, nil, "Sorry, try again."]
140
177
  end
141
178
 
142
179
  def test_sudo_behavior_callback_with_incorrect_password_on_subsequent_prompts
@@ -151,9 +188,23 @@ class ConfigurationActionsInvocationTest < Test::Unit::TestCase
151
188
 
152
189
  @config.expects(:reset!).with(:password).times(2)
153
190
 
154
- callback[ch, nil, "blah blah try again blah blah"]
155
- callback[ch2, nil, "blah blah try again blah blah"] # shouldn't call reset!
156
- callback[ch, nil, "blah blah try again blah blah"]
191
+ callback[ch, nil, "Sorry, try again."]
192
+ callback[ch2, nil, "Sorry, try again."] # shouldn't call reset!
193
+ callback[ch, nil, "Sorry, try again."]
194
+ end
195
+
196
+ def test_sudo_behavior_callback_should_reset_password_and_prompt_again_if_output_includes_both_cues
197
+ ch = mock("channel")
198
+ ch.stubs(:[]).with(:host).returns("capistrano")
199
+ ch.stubs(:[]).with(:server).returns(server("capistrano"))
200
+ ch.expects(:send_data, "password!\n").times(2)
201
+
202
+ @config.set(:password, "password!")
203
+ @config.expects(:reset!).with(:password)
204
+
205
+ callback = @config.sudo_behavior_callback(nil)
206
+ callback[ch, :out, "sudo password: "]
207
+ callback[ch, :out, "Sorry, try again.\nsudo password: "]
157
208
  end
158
209
 
159
210
  def test_sudo_behavior_callback_should_defer_to_fallback_for_other_output
@@ -176,8 +227,63 @@ class ConfigurationActionsInvocationTest < Test::Unit::TestCase
176
227
  @config.invoke_command("ls", :once => true, :via => :foobar)
177
228
  end
178
229
 
230
+ def test_parallel_command_execution_with_no_match
231
+ assert_block("should not raise argument error") do
232
+ begin
233
+ @config.parallel do |session|
234
+ session.when("in?(:app)", "ls") {|ch,stream,data| puts "noop"}
235
+ session.when("in?(:db)", "pwd") {|ch,stream,data| puts "noop"}
236
+ end
237
+ true
238
+ rescue
239
+ false
240
+ end
241
+ end
242
+ end
243
+
244
+ def test_parallel_command_execution_with_matching_servers
245
+ @config.expects(:execute_on_servers)
246
+
247
+ logger = mock('logger')
248
+ logger.stubs(:debug).with("executing multiple commands in parallel").once
249
+ logger.stubs(:trace).twice
250
+ @config.stubs(:logger).returns(logger)
251
+
252
+ assert_block("should not raise Argument error") do
253
+ begin
254
+ @config.servers = [:app, :db]
255
+ @config.roles = {:app => [:app], :db => [:db] }
256
+ @config.parallel do |session|
257
+ session.when("in?(:app)", "ls") {|ch,stream,data| puts "noop"}
258
+ session.when("in?(:db)", "pwd") {|ch,stream,data| puts "noop"}
259
+ end
260
+ true
261
+ rescue
262
+ false
263
+ end
264
+ end
265
+ end
266
+
267
+ def test_run_only_logs_once
268
+ @config.servers = [:app, :db]
269
+
270
+ logger = mock('logger')
271
+ logger.stubs(:debug).with("executing \"ls\"")
272
+ @config.stubs(:logger).returns(logger)
273
+
274
+ @config.expects(:execute_on_servers)
275
+
276
+ @config.run("ls")
277
+ end
278
+
179
279
  private
180
280
 
281
+ def make_config
282
+ config = MockConfig.new
283
+ config.stubs(:logger).returns(stub_everything)
284
+ config
285
+ end
286
+
181
287
  def inspectable_proc
182
288
  Proc.new do |ch, stream, data|
183
289
  ch.called
@@ -190,6 +296,11 @@ class ConfigurationActionsInvocationTest < Test::Unit::TestCase
190
296
  a = mock("channel", :called => true)
191
297
  b = mock("stream", :called => true)
192
298
  c = mock("data", :called => true)
193
- Capistrano::Command.expects(:process).with(command, sessions, options).yields(a, b, c)
299
+
300
+ compare_args = Proc.new do |tree, sess, opts|
301
+ tree.fallback.command == command && sess == sessions && opts == options
302
+ end
303
+
304
+ Capistrano::Command.expects(:process).with(&compare_args)
194
305
  end
195
- end
306
+ end
@@ -0,0 +1,118 @@
1
+ require 'utils'
2
+ require 'capistrano/configuration/alias_task'
3
+ require 'capistrano/configuration/execution'
4
+ require 'capistrano/configuration/namespaces'
5
+ require 'capistrano/task_definition'
6
+
7
+ class AliasTaskTest < Test::Unit::TestCase
8
+ class MockConfig
9
+ attr_reader :options
10
+ attr_accessor :logger
11
+
12
+ def initialize(options={})
13
+ @options = {}
14
+ @logger = options.delete(:logger)
15
+ end
16
+
17
+ include Capistrano::Configuration::AliasTask
18
+ include Capistrano::Configuration::Execution
19
+ include Capistrano::Configuration::Namespaces
20
+ end
21
+
22
+ def setup
23
+ @config = MockConfig.new( :logger => stub(:debug => nil, :info => nil, :important => nil) )
24
+ end
25
+
26
+ def test_makes_a_copy_of_the_task
27
+ @config.task(:foo) { 42 }
28
+ @config.alias_task 'new_foo', 'foo'
29
+
30
+ assert @config.tasks.key?(:new_foo)
31
+ end
32
+
33
+ def test_original_task_remain_with_same_name
34
+ @config.task(:foo) { 42 }
35
+ @config.alias_task 'new_foo', 'foo'
36
+
37
+ assert_equal :foo, @config.tasks[:foo].name
38
+ assert_equal :new_foo, @config.tasks[:new_foo].name
39
+ end
40
+
41
+ def test_aliased_task_do_the_same
42
+ @config.task(:foo) { 42 }
43
+ @config.alias_task 'new_foo', 'foo'
44
+
45
+ assert_equal 42, @config.find_and_execute_task('new_foo')
46
+ end
47
+
48
+ def test_aliased_task_should_preserve_description
49
+ @config.task(:foo, :desc => "the Ultimate Question of Life, the Universe, and Everything" ) { 42 }
50
+ @config.alias_task 'new_foo', 'foo'
51
+
52
+ task = @config.find_task('foo')
53
+ new_task = @config.find_task('new_foo')
54
+
55
+ assert_equal task.description, new_task.description
56
+ end
57
+
58
+ def test_aliased_task_should_preserve_on_error
59
+ @config.task(:foo, :on_error => :continue) { 42 }
60
+ @config.alias_task 'new_foo', 'foo'
61
+
62
+ task = @config.find_task('foo')
63
+ new_task = @config.find_task('new_foo')
64
+
65
+ assert_equal task.on_error, new_task.on_error
66
+ end
67
+
68
+ def test_aliased_task_should_preserve_max_hosts
69
+ @config.task(:foo, :max_hosts => 5) { 42 }
70
+ @config.alias_task 'new_foo', 'foo'
71
+
72
+ task = @config.find_task('foo')
73
+ new_task = @config.find_task('new_foo')
74
+
75
+ assert_equal task.max_hosts, new_task.max_hosts
76
+ end
77
+
78
+ def test_raise_exception_when_task_doesnt_exist
79
+ assert_raises(Capistrano::NoSuchTaskError) { @config.alias_task 'non_existant_task', 'fail_miserably' }
80
+ end
81
+
82
+ def test_convert_task_names_using_to_str
83
+ @config.task(:foo, :role => :app) { 42 }
84
+
85
+ @config.alias_task 'one', 'foo'
86
+ @config.alias_task :two, 'foo'
87
+ @config.alias_task 'three', :foo
88
+ @config.alias_task :four, :foo
89
+
90
+ assert @config.tasks.key?(:one)
91
+ assert @config.tasks.key?(:two)
92
+ assert @config.tasks.key?(:three)
93
+ assert @config.tasks.key?(:four)
94
+ end
95
+
96
+ def test_raise_an_exception_when_task_names_can_not_be_converted
97
+ @config.task(:foo, :role => :app) { 42 }
98
+
99
+ assert_raises(ArgumentError) { @config.alias_task mock('x'), :foo }
100
+ end
101
+
102
+ def test_should_include_namespace
103
+ @config.namespace(:outer) do
104
+ task(:foo) { 42 }
105
+ alias_task 'new_foo', 'foo'
106
+
107
+ namespace(:inner) do
108
+ task(:foo) { 43 }
109
+ alias_task 'new_foo', 'foo'
110
+ end
111
+ end
112
+
113
+ assert_equal 42, @config.find_and_execute_task('outer:new_foo')
114
+ assert_equal 42, @config.find_and_execute_task('outer:foo')
115
+ assert_equal 43, @config.find_and_execute_task('outer:inner:new_foo')
116
+ assert_equal 43, @config.find_and_execute_task('outer:inner:foo')
117
+ end
118
+ end
@@ -1,4 +1,4 @@
1
- require "#{File.dirname(__FILE__)}/../utils"
1
+ require "utils"
2
2
  require 'capistrano/configuration/callbacks'
3
3
 
4
4
  class ConfigurationCallbacksTest < Test::Unit::TestCase
@@ -12,9 +12,15 @@ class ConfigurationCallbacksTest < Test::Unit::TestCase
12
12
  end
13
13
 
14
14
  def execute_task(task)
15
- @called << task
15
+ invoke_task_directly(task)
16
16
  end
17
17
 
18
+ protected
19
+
20
+ def invoke_task_directly(task)
21
+ @called << task
22
+ end
23
+
18
24
  include Capistrano::Configuration::Callbacks
19
25
  end
20
26
 
@@ -33,11 +39,35 @@ class ConfigurationCallbacksTest < Test::Unit::TestCase
33
39
  @config.before :bar, :foo, "bing:blang", :zip => :zing
34
40
  end
35
41
 
42
+ def test_before_should_map_before_deploy_symlink
43
+ @config.before "deploy:symlink", "bing:blang", "deploy:symlink"
44
+ assert_equal "bing:blang", @config.callbacks[:before][0].source
45
+ assert_equal "deploy:create_symlink", @config.callbacks[:before][1].source
46
+ assert_equal ["deploy:create_symlink"], @config.callbacks[:before][1].only
47
+ end
48
+
49
+ def test_before_should_map_before_deploy_symlink_array
50
+ @config.before ["deploy:symlink", "bingo:blast"], "bing:blang"
51
+ assert_equal ["deploy:create_symlink", "bingo:blast"], @config.callbacks[:before].last.only
52
+ end
53
+
36
54
  def test_after_should_delegate_to_on
37
55
  @config.expects(:on).with(:after, :foo, "bing:blang", {:only => :bar, :zip => :zing})
38
56
  @config.after :bar, :foo, "bing:blang", :zip => :zing
39
57
  end
40
58
 
59
+ def test_after_should_map_before_deploy_symlink
60
+ @config.after "deploy:symlink", "bing:blang", "deploy:symlink"
61
+ assert_equal "bing:blang", @config.callbacks[:after][0].source
62
+ assert_equal "deploy:create_symlink", @config.callbacks[:after][1].source
63
+ assert_equal ["deploy:create_symlink"], @config.callbacks[:after][1].only
64
+ end
65
+
66
+ def test_after_should_map_before_deploy_symlink_array
67
+ @config.after ["deploy:symlink", "bingo:blast"], "bing:blang"
68
+ assert_equal ["deploy:create_symlink", "bingo:blast"], @config.callbacks[:after].last.only
69
+ end
70
+
41
71
  def test_on_with_single_reference_should_add_task_callback
42
72
  @config.on :before, :a_test
43
73
  assert_equal 1, @config.callbacks[:before].length
@@ -97,6 +127,14 @@ class ConfigurationCallbacksTest < Test::Unit::TestCase
97
127
  assert_equal %w(primary), @config.callbacks[:before].first.except
98
128
  end
99
129
 
130
+ def test_on_without_tasks_or_block_should_raise_error
131
+ assert_raises(ArgumentError) { @config.on(:before) }
132
+ end
133
+
134
+ def test_on_with_both_tasks_and_block_should_raise_error
135
+ assert_raises(ArgumentError) { @config.on(:before, :first) { blah } }
136
+ end
137
+
100
138
  def test_trigger_without_constraints_should_invoke_all_callbacks
101
139
  task = stub(:fully_qualified_name => "any:old:thing")
102
140
  @config.on(:before, :first, "second:third")
@@ -160,47 +198,4 @@ class ConfigurationCallbacksTest < Test::Unit::TestCase
160
198
  assert_equal [task], @config.called
161
199
  end
162
200
 
163
- def test_execute_task_with_named_before_hook_should_call_named_before_hook
164
- ns = stub("namespace", :default_task => nil, :name => "old", :fully_qualified_name => "any:old")
165
- task = stub(:fully_qualified_name => "any:old:thing", :name => "thing", :namespace => ns)
166
- before_task = stub(:fully_qualified_name => "any:old:before_thing", :name => "before_thing", :namespace => ns)
167
-
168
- ns.stubs(:search_task).returns(nil)
169
- ns.expects(:search_task).with("before_thing").returns(before_task)
170
-
171
- @config.execute_task(task)
172
- assert_equal [before_task, task], @config.called
173
- end
174
-
175
- def test_execute_task_with_named_after_hook_should_call_named_after_hook
176
- ns = stub("namespace", :default_task => nil, :name => "old", :fully_qualified_name => "any:old")
177
- task = stub(:fully_qualified_name => "any:old:thing", :name => "thing", :namespace => ns)
178
- after_task = stub(:fully_qualified_name => "any:old:after_thing", :name => "after_thing", :namespace => ns)
179
-
180
- ns.stubs(:search_task).returns(nil)
181
- ns.expects(:search_task).with("after_thing").returns(after_task)
182
-
183
- @config.execute_task(task)
184
- assert_equal [task, after_task], @config.called
185
- end
186
-
187
- def test_execute_task_with_on_hooks_should_trigger_hooks_around_task
188
- ns = stub("namespace", :default_task => nil, :name => "old", :fully_qualified_name => "any:old")
189
- task = stub(:fully_qualified_name => "any:old:thing", :name => "thing", :namespace => ns)
190
- before_task = stub(:fully_qualified_name => "any:old:before_thing", :name => "before_thing", :namespace => ns)
191
- after_task = stub(:fully_qualified_name => "any:old:after_thing", :name => "after_thing", :namespace => ns)
192
-
193
- ns.stubs(:search_task).returns(nil)
194
- ns.expects(:search_task).with("before_thing").returns(before_task)
195
- ns.expects(:search_task).with("after_thing").returns(after_task)
196
-
197
- @config.before("any:old:thing", :first_this, :then_this)
198
- @config.after("any:old:thing", :and_then_this, :lastly_this)
199
-
200
- [:first_this, :then_this, :and_then_this, :lastly_this].each do |t|
201
- @config.expects(:find_and_execute_task).with(t)
202
- end
203
-
204
- @config.execute_task(task)
205
- end
206
- end
201
+ end