capistrano 2.14.2 → 2.15.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.
Files changed (68) hide show
  1. checksums.yaml +7 -0
  2. data/.travis.yml +1 -0
  3. data/CHANGELOG +49 -8
  4. data/Gemfile +1 -1
  5. data/README.md +4 -4
  6. data/capistrano.gemspec +9 -17
  7. data/lib/capistrano/callback.rb +1 -1
  8. data/lib/capistrano/cli.rb +1 -1
  9. data/lib/capistrano/cli/execute.rb +3 -3
  10. data/lib/capistrano/cli/help.rb +3 -3
  11. data/lib/capistrano/cli/help.txt +23 -23
  12. data/lib/capistrano/cli/options.rb +12 -12
  13. data/lib/capistrano/command.rb +20 -7
  14. data/lib/capistrano/configuration/actions/invocation.rb +23 -11
  15. data/lib/capistrano/configuration/connections.rb +22 -15
  16. data/lib/capistrano/configuration/execution.rb +2 -2
  17. data/lib/capistrano/configuration/loading.rb +2 -2
  18. data/lib/capistrano/configuration/log_formatters.rb +5 -1
  19. data/lib/capistrano/configuration/roles.rb +1 -1
  20. data/lib/capistrano/configuration/servers.rb +6 -6
  21. data/lib/capistrano/errors.rb +4 -4
  22. data/lib/capistrano/ext/multistage.rb +2 -2
  23. data/lib/capistrano/logger.rb +14 -1
  24. data/lib/capistrano/recipes/deploy.rb +94 -27
  25. data/lib/capistrano/recipes/deploy/assets.rb +21 -18
  26. data/lib/capistrano/recipes/deploy/dependencies.rb +2 -2
  27. data/lib/capistrano/recipes/deploy/remote_dependency.rb +11 -11
  28. data/lib/capistrano/recipes/deploy/scm.rb +1 -1
  29. data/lib/capistrano/recipes/deploy/scm/accurev.rb +6 -6
  30. data/lib/capistrano/recipes/deploy/scm/cvs.rb +4 -4
  31. data/lib/capistrano/recipes/deploy/scm/darcs.rb +3 -3
  32. data/lib/capistrano/recipes/deploy/scm/git.rb +3 -0
  33. data/lib/capistrano/recipes/deploy/scm/mercurial.rb +3 -3
  34. data/lib/capistrano/recipes/deploy/scm/none.rb +9 -5
  35. data/lib/capistrano/recipes/deploy/scm/perforce.rb +5 -5
  36. data/lib/capistrano/recipes/deploy/scm/subversion.rb +1 -1
  37. data/lib/capistrano/recipes/deploy/strategy.rb +1 -1
  38. data/lib/capistrano/recipes/deploy/strategy/base.rb +5 -1
  39. data/lib/capistrano/recipes/deploy/strategy/copy.rb +14 -2
  40. data/lib/capistrano/recipes/standard.rb +1 -1
  41. data/lib/capistrano/server_definition.rb +1 -1
  42. data/lib/capistrano/shell.rb +4 -1
  43. data/lib/capistrano/ssh.rb +1 -1
  44. data/lib/capistrano/version.rb +2 -2
  45. data/test/cli/options_test.rb +1 -1
  46. data/test/cli/ui_test.rb +1 -1
  47. data/test/command_test.rb +11 -1
  48. data/test/configuration/actions/invocation_test.rb +5 -1
  49. data/test/configuration/callbacks_test.rb +1 -1
  50. data/test/configuration/connections_test.rb +19 -0
  51. data/test/configuration/execution_test.rb +1 -1
  52. data/test/configuration/namespace_dsl_test.rb +6 -6
  53. data/test/configuration/roles_test.rb +2 -2
  54. data/test/configuration/servers_test.rb +12 -12
  55. data/test/configuration/variables_test.rb +3 -3
  56. data/test/deploy/scm/bzr_test.rb +1 -1
  57. data/test/deploy/scm/darcs_test.rb +2 -2
  58. data/test/deploy/scm/git_test.rb +10 -0
  59. data/test/deploy/scm/mercurial_test.rb +3 -3
  60. data/test/deploy/scm/perforce_test.rb +1 -1
  61. data/test/deploy/strategy/copy_test.rb +25 -1
  62. data/test/extensions_test.rb +1 -1
  63. data/test/logger_formatting_test.rb +56 -1
  64. data/test/recipes_test.rb +1 -1
  65. data/test/server_definition_test.rb +2 -2
  66. data/test/shell_test.rb +12 -6
  67. data/test/transfer_test.rb +1 -1
  68. metadata +63 -31
@@ -2,6 +2,7 @@ load 'deploy' unless defined?(_cset)
2
2
 
3
3
  _cset :asset_env, "RAILS_GROUPS=assets"
4
4
  _cset :assets_prefix, "assets"
5
+ _cset :shared_assets_prefix, "assets"
5
6
  _cset :assets_role, [:web]
6
7
  _cset :expire_assets_after, (3600 * 24 * 7)
7
8
 
@@ -21,14 +22,15 @@ namespace :deploy do
21
22
  mid-deploy mismatches between old application html asking for assets \
22
23
  and getting a 404 file not found error. The assets cache is shared \
23
24
  for efficiency. If you customize the assets path prefix, override the \
24
- :assets_prefix variable to match.
25
+ :assets_prefix variable to match. If you customize shared assets path \
26
+ prefix, override :shared_assets_prefix variable to match.
25
27
  DESC
26
- task :symlink, :roles => assets_role, :except => { :no_release => true } do
28
+ task :symlink, :roles => lambda { assets_role }, :except => { :no_release => true } do
27
29
  run <<-CMD.compact
28
30
  rm -rf #{latest_release}/public/#{assets_prefix} &&
29
31
  mkdir -p #{latest_release}/public &&
30
- mkdir -p #{shared_path}/assets &&
31
- ln -s #{shared_path}/assets #{latest_release}/public/#{assets_prefix}
32
+ mkdir -p #{shared_path}/#{shared_assets_prefix} &&
33
+ ln -s #{shared_path}/#{shared_assets_prefix} #{latest_release}/public/#{assets_prefix}
32
34
  CMD
33
35
  end
34
36
 
@@ -42,11 +44,11 @@ namespace :deploy do
42
44
  set :rails_env, "production"
43
45
  set :asset_env, "RAILS_GROUPS=assets"
44
46
  DESC
45
- task :precompile, :roles => assets_role, :except => { :no_release => true } do
47
+ task :precompile, :roles => lambda { assets_role }, :except => { :no_release => true } do
46
48
  run <<-CMD.compact
47
- cd -- #{latest_release.shellescape} &&
49
+ cd -- #{latest_release} &&
48
50
  #{rake} RAILS_ENV=#{rails_env.to_s.shellescape} #{asset_env} assets:precompile &&
49
- cp -- #{shared_path.shellescape}/assets/manifest.yml #{current_release.shellescape}/assets_manifest.yml
51
+ cp -- #{shared_path.shellescape}/#{shared_assets_prefix}/manifest.yml #{current_release.to_s.shellescape}/assets_manifest.yml
50
52
  CMD
51
53
  end
52
54
 
@@ -54,19 +56,19 @@ namespace :deploy do
54
56
  [internal] Updates the mtimes for assets that are required by the current release.
55
57
  This task runs before assets:precompile.
56
58
  DESC
57
- task :update_asset_mtimes, :roles => assets_role, :except => { :no_release => true } do
59
+ task :update_asset_mtimes, :roles => lambda { assets_role }, :except => { :no_release => true } do
58
60
  # Fetch assets/manifest.yml contents.
59
- manifest_path = "#{shared_path}/assets/manifest.yml"
61
+ manifest_path = "#{shared_path}/#{shared_assets_prefix}/manifest.yml"
60
62
  manifest_yml = capture("[ -e #{manifest_path.shellescape} ] && cat #{manifest_path.shellescape} || echo").strip
61
63
 
62
64
  if manifest_yml != ""
63
65
  manifest = YAML.load(manifest_yml)
64
66
  current_assets = manifest.to_a.flatten.map {|a| [a, "#{a}.gz"] }.flatten
65
67
  logger.info "Updating mtimes for ~#{current_assets.count} assets..."
66
- put current_assets.map{|a| "#{shared_path}/assets/#{a}" }.join("\n"), "#{deploy_to}/TOUCH_ASSETS"
68
+ put current_assets.map{|a| "#{shared_path}/#{shared_assets_prefix}/#{a}" }.join("\n"), "#{deploy_to}/TOUCH_ASSETS", :via => :scp
67
69
  run <<-CMD.compact
68
70
  cat #{deploy_to.shellescape}/TOUCH_ASSETS | while read asset; do
69
- touch -cm -- "$asset";
71
+ touch -c -- "$asset";
70
72
  done &&
71
73
  rm -f -- #{deploy_to.shellescape}/TOUCH_ASSETS
72
74
  CMD
@@ -84,7 +86,7 @@ namespace :deploy do
84
86
  set :rails_env, "production"
85
87
  set :asset_env, "RAILS_GROUPS=assets"
86
88
  DESC
87
- task :clean, :roles => assets_role, :except => { :no_release => true } do
89
+ task :clean, :roles => lambda { assets_role }, :except => { :no_release => true } do
88
90
  run "cd #{latest_release} && #{rake} RAILS_ENV=#{rails_env} #{asset_env} assets:clean"
89
91
  end
90
92
 
@@ -94,7 +96,7 @@ namespace :deploy do
94
96
  to change the assets expiry time. Assets will only be deleted if they are not required by
95
97
  an existing release.
96
98
  DESC
97
- task :clean_expired, :roles => assets_role, :except => { :no_release => true } do
99
+ task :clean_expired, :roles => lambda { assets_role }, :except => { :no_release => true } do
98
100
  # Fetch all assets_manifest.yml contents.
99
101
  manifests_output = capture <<-CMD.compact
100
102
  for manifest in #{releases_path.shellescape}/*/assets_manifest.yml; do
@@ -117,7 +119,7 @@ namespace :deploy do
117
119
  # Write the list of required assets to server.
118
120
  logger.info "Writing required assets to #{deploy_to}/REQUIRED_ASSETS..."
119
121
  escaped_assets = current_assets.sort.join("\n").gsub("\"", "\\\"") << "\n"
120
- put escaped_assets, "#{deploy_to}/REQUIRED_ASSETS"
122
+ put escaped_assets, "#{deploy_to}/REQUIRED_ASSETS", :via => :scp
121
123
 
122
124
  # Finds all files older than X minutes, then removes them if they are not referenced
123
125
  # in REQUIRED_ASSETS.
@@ -125,7 +127,9 @@ namespace :deploy do
125
127
  logger.info "Removing assets that haven't been deployed for #{expire_after_mins} minutes..."
126
128
  # LC_COLLATE=C tells the `sort` and `comm` commands to sort files in byte order.
127
129
  run <<-CMD.compact
128
- cd -- #{shared_path.shellescape}/assets/ &&
130
+ cd -- #{deploy_to.shellescape}/ &&
131
+ LC_COLLATE=C sort REQUIRED_ASSETS -o REQUIRED_ASSETS &&
132
+ cd -- #{shared_path.shellescape}/#{shared_assets_prefix}/ &&
129
133
  for f in $(
130
134
  find * -mmin +#{expire_after_mins.to_s.shellescape} -type f | LC_COLLATE=C sort |
131
135
  LC_COLLATE=C comm -23 -- - #{deploy_to.shellescape}/REQUIRED_ASSETS
@@ -142,16 +146,15 @@ namespace :deploy do
142
146
  Rolls back assets to the previous release by symlinking the release's manifest
143
147
  to shared/assets/manifest.yml, and finally recompiling or regenerating nondigest assets.
144
148
  DESC
145
- task :rollback, :roles => assets_role, :except => { :no_release => true } do
149
+ task :rollback, :roles => lambda { assets_role }, :except => { :no_release => true } do
146
150
  previous_manifest = "#{previous_release}/assets_manifest.yml"
147
151
  if capture("[ -e #{previous_manifest.shellescape} ] && echo true || echo false").strip != 'true'
148
152
  puts "#{previous_manifest} is missing! Cannot roll back assets. " <<
149
153
  "Please run deploy:assets:precompile to update your assets when the rollback is finished."
150
- return false
151
154
  else
152
155
  run <<-CMD.compact
153
156
  cd -- #{previous_release.shellescape} &&
154
- cp -f -- #{previous_manifest.shellescape} #{shared_path.shellescape}/assets/manifest.yml &&
157
+ cp -f -- #{previous_manifest.shellescape} #{shared_path.shellescape}/#{shared_assets_prefix}/manifest.yml &&
155
158
  #{rake} RAILS_ENV=#{rails_env.to_s.shellescape} #{asset_env} assets:precompile:nondigest
156
159
  CMD
157
160
  end
@@ -18,7 +18,7 @@ module Capistrano
18
18
  yield self
19
19
  self
20
20
  end
21
-
21
+
22
22
  def remote
23
23
  dep = RemoteDependency.new(configuration)
24
24
  @dependencies << dep
@@ -41,4 +41,4 @@ module Capistrano
41
41
  end
42
42
  end
43
43
  end
44
- end
44
+ end
@@ -58,31 +58,31 @@ module Capistrano
58
58
  def match(command, expect, options={})
59
59
  expect = Regexp.new(Regexp.escape(expect.to_s)) unless expect.is_a?(Regexp)
60
60
 
61
- output_per_server = {}
62
- try("#{command} ", options) do |ch, stream, out|
63
- output_per_server[ch[:server]] ||= ''
64
- output_per_server[ch[:server]] += out
65
- end
61
+ output_per_server = {}
62
+ try("#{command} ", options) do |ch, stream, out|
63
+ output_per_server[ch[:server]] ||= ''
64
+ output_per_server[ch[:server]] += out
65
+ end
66
66
 
67
67
  # It is possible for some of these commands to return a status != 0
68
68
  # (for example, rake --version exits with a 1). For this check we
69
69
  # just care if the output matches, so we reset the success flag.
70
70
  @success = true
71
71
 
72
- errored_hosts = []
73
- output_per_server.each_pair do |server, output|
72
+ errored_hosts = []
73
+ output_per_server.each_pair do |server, output|
74
74
  next if output =~ expect
75
- errored_hosts << server
76
- end
75
+ errored_hosts << server
76
+ end
77
77
 
78
78
  if errored_hosts.any?
79
79
  @hosts = errored_hosts.join(', ')
80
80
  output = output_per_server[errored_hosts.first]
81
81
  @message = "the output #{output.inspect} from #{command.inspect} did not match #{expect.inspect}"
82
82
  @success = false
83
- end
83
+ end
84
84
 
85
- self
85
+ self
86
86
  end
87
87
 
88
88
  def or(message)
@@ -16,4 +16,4 @@ module Capistrano
16
16
  end
17
17
  end
18
18
  end
19
- end
19
+ end
@@ -14,9 +14,9 @@ module Capistrano
14
14
  # * :repository - This should match the depot that code lives in. If your code
15
15
  # exists in a subdirectory, you can append the path depot.
16
16
  # eg. foo-depot/bar_dir
17
- # * :stream - The stream in the depot that code should be pulled from. If
17
+ # * :stream - The stream in the depot that code should be pulled from. If
18
18
  # left blank, the depot stream will be used
19
- # * :revision - Should be in the form 'stream/transaction'.
19
+ # * :revision - Should be in the form 'stream/transaction'.
20
20
  class Accurev < Base
21
21
  include REXML
22
22
  default_command 'accurev'
@@ -54,10 +54,10 @@ module Capistrano
54
54
  end
55
55
  end
56
56
 
57
- # Pops a copy of the code for the specified Accurev revision identifier.
57
+ # Pops a copy of the code for the specified Accurev revision identifier.
58
58
  # The revision identifier is represented as a stream & transaction ID combo.
59
59
  # Accurev can only pop a particular transaction if a stream is created on the server
60
- # with a time basis of that transaction id. Therefore, we will create a stream with
60
+ # with a time basis of that transaction id. Therefore, we will create a stream with
61
61
  # the required criteria and pop that.
62
62
  def export(revision_id, destination)
63
63
  revision = InternalRevision.parse(revision_id)
@@ -89,7 +89,7 @@ module Capistrano
89
89
  ].join(' | ')
90
90
  end
91
91
 
92
- # Returns the command needed to show the diff between what is deployed and what is
92
+ # Returns the command needed to show the diff between what is deployed and what is
93
93
  # pending. Because Accurev can not do this task without creating some streams,
94
94
  # two time basis streams will be created for the purposes of doing the diff.
95
95
  def diff(from, to=head)
@@ -156,7 +156,7 @@ module Capistrano
156
156
  end
157
157
 
158
158
  def to_s
159
- "#{stream}/#{transaction_id}"
159
+ "#{stream}/#{transaction_id}"
160
160
  end
161
161
 
162
162
  def ==(other)
@@ -63,7 +63,7 @@ module Capistrano
63
63
  scm cvs_root, :log, range_arg
64
64
  end
65
65
 
66
- # Unfortunately, cvs doesn't support the concept of a revision number like
66
+ # Unfortunately, cvs doesn't support the concept of a revision number like
67
67
  # subversion and other SCM's do. For now, we'll rely on getting the timestamp
68
68
  # of the latest checkin under the revision that's passed to us.
69
69
  def query_revision(revision)
@@ -99,7 +99,7 @@ module Capistrano
99
99
  root << "-d #{repository} " if repository
100
100
  root
101
101
  end
102
-
102
+
103
103
  # Constructs the destination dir command-line option
104
104
  def cvs_destination(destination)
105
105
  dest = ""
@@ -109,7 +109,7 @@ module Capistrano
109
109
  end
110
110
  dest
111
111
  end
112
-
112
+
113
113
  # attempts to guess what type of revision we're working with
114
114
  def revision_type(rev)
115
115
  return :date if rev =~ /^\d{4}\/\d{2}\/\d{2} \d{2}:\d{2}:\d{2} UTC$/ # i.e 2007-05-15 08:13:25 UTC
@@ -117,7 +117,7 @@ module Capistrano
117
117
  return :revision if rev =~ /^\d/ # i.e. 1.2.1
118
118
  return :tag # i.e. RELEASE_1_2
119
119
  end
120
-
120
+
121
121
  # constructs the appropriate command-line switch for specifying a
122
122
  # "revision" in CVS. This could be a tag, branch, revision (i.e. 1.3)
123
123
  # or a date (to be used with -d)
@@ -25,13 +25,13 @@ module Capistrano
25
25
  "--to-match='hash #{revision}'"
26
26
  end
27
27
  end
28
-
28
+
29
29
  # Returns the command that will check out the given revision to the
30
30
  # given destination. The 'revision' parameter must be the 'hash' value
31
31
  # for the revision in question, as given by 'darcs changes --xml-output'.
32
32
  def checkout(revision, destination)
33
- scm :get, *[verbose,
34
- "--repo-name=#{destination}",
33
+ scm :get, *[verbose,
34
+ "--repo-name=#{destination}",
35
35
  to_match(revision),
36
36
  repository].compact
37
37
  end
@@ -134,6 +134,9 @@ module Capistrano
134
134
  remote = origin
135
135
 
136
136
  args = []
137
+
138
+ # Add an option for the branch name so :git_shallow_clone works with branches
139
+ args << "-b #{variable(:branch)}" unless variable(:branch).nil?
137
140
  args << "-o #{remote}" unless remote == 'origin'
138
141
  if depth = variable(:git_shallow_clone)
139
142
  args << "--depth #{depth}"
@@ -89,11 +89,11 @@ module Capistrano
89
89
  "yes\n"
90
90
  end
91
91
  end
92
-
92
+
93
93
  private
94
94
 
95
95
  # Fine grained mercurial commands
96
- def clone(destination)
96
+ def clone(destination)
97
97
  scm :clone,
98
98
  verbose,
99
99
  "--noupdate", # do not update to tip when cloning is done
@@ -124,7 +124,7 @@ module Capistrano
124
124
  else "--verbose"
125
125
  end
126
126
  end
127
-
127
+
128
128
  # honor Cap 2.1+'s :scm_prefer_prompt if present
129
129
  def scm_password_or_prompt
130
130
  @scm_password_or_prompt ||= variable(:scm_password) ||
@@ -18,6 +18,11 @@ module Capistrano
18
18
  # set :repository, "."
19
19
  # set :scm, :none
20
20
  # set :deploy_via, :copy
21
+ #
22
+ # Dereference symbolic links. Copy files instead. Handy when you
23
+ # reference files and directory outside of your deployment root.
24
+ # set :copy_dereference_symlink, true
25
+
21
26
  class None < Base
22
27
  # No versioning, thus, no head. Returns the empty string.
23
28
  def head
@@ -27,9 +32,8 @@ module Capistrano
27
32
  # Simply does a copy from the :repository directory to the
28
33
  # :destination directory.
29
34
  def checkout(revision, destination)
30
- !Capistrano::Deploy::LocalDependency.on_windows? ? "cp -R #{repository} #{destination}" : "xcopy #{repository} \"#{destination}\" /S/I/Y/Q/E"
35
+ !Capistrano::Deploy::LocalDependency.on_windows? ? "cp -R#{configuration[:copy_dereference_symlink]?'L':''} #{repository} #{destination}" : "xcopy #{repository} \"#{destination}\" /S/I/Y/Q/E"
31
36
  end
32
-
33
37
  alias_method :export, :checkout
34
38
 
35
39
  # No versioning, so this just returns the argument, with no
@@ -37,13 +41,13 @@ module Capistrano
37
41
  def query_revision(revision)
38
42
  revision
39
43
  end
40
-
44
+
41
45
  # log: There's no log, so it just echos from and to.
42
-
46
+
43
47
  def log(from="", to="")
44
48
  "No SCM: #{from} - #{to}"
45
49
  end
46
-
50
+
47
51
  end
48
52
 
49
53
  end
@@ -69,13 +69,13 @@ module Capistrano
69
69
  def handle_data(state, stream, text)
70
70
  case text
71
71
  when /\(P4PASSWD\) invalid or unset\./i
72
- raise Capistrano::Error, "scm_password (or p4passwd) is incorrect or unset"
72
+ raise Capistrano::Error, "scm_password (or p4passwd) is incorrect or unset"
73
73
  when /Can.t create a new user.*/i
74
- raise Capistrano::Error, "scm_username (or p4user) is incorrect or unset"
74
+ raise Capistrano::Error, "scm_username (or p4user) is incorrect or unset"
75
75
  when /Perforce client error\:/i
76
- raise Capistrano::Error, "p4port is incorrect or unset"
76
+ raise Capistrano::Error, "p4port is incorrect or unset"
77
77
  when /Client \'[\w\-\_\.]+\' unknown.*/i
78
- raise Capistrano::Error, "p4client is incorrect or unset"
78
+ raise Capistrano::Error, "p4client is incorrect or unset"
79
79
  end
80
80
  end
81
81
 
@@ -113,7 +113,7 @@ module Capistrano
113
113
  def p4passwd
114
114
  variable(:p4passwd) || variable(:scm_password)
115
115
  end
116
-
116
+
117
117
  def p4charset
118
118
  variable(:p4charset)
119
119
  end
@@ -69,7 +69,7 @@ module Capistrano
69
69
  # etc. are handled here.
70
70
  def handle_data(state, stream, text)
71
71
  host = state[:channel][:host]
72
- logger.info "[#{host} :: #{stream}] #{text}"
72
+ logger.info "[#{host} :: #{stream}] #{text}"
73
73
  case text
74
74
  when /\bpassword.*:/i
75
75
  # subversion is prompting for a password
@@ -16,4 +16,4 @@ module Capistrano
16
16
  end
17
17
  end
18
18
  end
19
- end
19
+ end
@@ -29,7 +29,11 @@ module Capistrano
29
29
  # is setup such that a deploy could succeed.
30
30
  def check!
31
31
  Dependencies.new(configuration) do |d|
32
- d.remote.directory(configuration[:releases_path]).or("`#{configuration[:releases_path]}' does not exist. Please run `cap deploy:setup'.")
32
+ if exists?(:stage)
33
+ d.remote.directory(configuration[:releases_path]).or("`#{configuration[:releases_path]}' does not exist. Please run `cap #{configuration[:stage]} deploy:setup'.")
34
+ else
35
+ d.remote.directory(configuration[:releases_path]).or("`#{configuration[:releases_path]}' does not exist. Please run `cap deploy:setup'.")
36
+ end
33
37
  d.remote.writable(configuration[:deploy_to]).or("You do not have permissions to write to `#{configuration[:deploy_to]}'.")
34
38
  d.remote.writable(configuration[:releases_path]).or("You do not have permissions to write to `#{configuration[:releases_path]}'.")
35
39
  end
@@ -39,6 +39,11 @@ module Capistrano
39
39
  # :zip, and which specifies how the source should be compressed for
40
40
  # transmission to each host.
41
41
  #
42
+ # By default, files will be transferred across to the remote machines via 'sftp'. If you prefer
43
+ # to use 'scp' you can set the :copy_via variable to :scp.
44
+ #
45
+ # set :copy_via, :scp
46
+ #
42
47
  # There is a possibility to pass a build command that will get
43
48
  # executed if your code needs to be compiled or something needs to be
44
49
  # done before the code is ready to run.
@@ -174,7 +179,11 @@ module Capistrano
174
179
  end
175
180
 
176
181
  def pattern_for directory
177
- !directory.nil? ? "#{directory}/*" : "*"
182
+ !directory.nil? ? "#{escape_globs(directory)}/*" : "*"
183
+ end
184
+
185
+ def escape_globs path
186
+ path.gsub(/[*?{}\[\]]/, '\\\\\\&')
178
187
  end
179
188
 
180
189
  def excluded_files_contain? file
@@ -316,7 +325,10 @@ module Capistrano
316
325
 
317
326
  # Distributes the file to the remote servers
318
327
  def distribute!
319
- upload(filename, remote_filename)
328
+ args = [filename, remote_filename]
329
+ args << { :via => configuration[:copy_via] } if configuration[:copy_via]
330
+
331
+ upload(*args)
320
332
  decompress_remote_file
321
333
  end
322
334
  end