capistrano 2.5.0 → 2.5.1

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 (33) hide show
  1. data/CHANGELOG.rdoc +29 -0
  2. data/capistrano.gemspec +3 -3
  3. data/lib/capistrano/cli/help.rb +28 -14
  4. data/lib/capistrano/cli/help.txt +5 -2
  5. data/lib/capistrano/cli/options.rb +16 -5
  6. data/lib/capistrano/configuration/actions/invocation.rb +2 -1
  7. data/lib/capistrano/configuration/connections.rb +6 -1
  8. data/lib/capistrano/configuration/namespaces.rb +2 -2
  9. data/lib/capistrano/configuration/servers.rb +11 -2
  10. data/lib/capistrano/extensions.rb +1 -1
  11. data/lib/capistrano/logger.rb +1 -1
  12. data/lib/capistrano/recipes/deploy.rb +8 -1
  13. data/lib/capistrano/recipes/deploy/remote_dependency.rb +3 -2
  14. data/lib/capistrano/recipes/deploy/scm/base.rb +12 -8
  15. data/lib/capistrano/recipes/deploy/scm/cvs.rb +2 -2
  16. data/lib/capistrano/recipes/deploy/scm/git.rb +10 -3
  17. data/lib/capistrano/recipes/deploy/scm/mercurial.rb +3 -3
  18. data/lib/capistrano/recipes/deploy/scm/subversion.rb +3 -3
  19. data/lib/capistrano/recipes/deploy/strategy/base.rb +12 -3
  20. data/lib/capistrano/recipes/deploy/strategy/copy.rb +8 -1
  21. data/lib/capistrano/recipes/deploy/strategy/remote_cache.rb +1 -1
  22. data/lib/capistrano/version.rb +1 -1
  23. data/test/cli/help_test.rb +32 -6
  24. data/test/cli/options_test.rb +3 -2
  25. data/test/configuration/actions/invocation_test.rb +6 -0
  26. data/test/configuration/loading_test.rb +1 -1
  27. data/test/configuration/namespace_dsl_test.rb +2 -2
  28. data/test/configuration/servers_test.rb +19 -3
  29. data/test/deploy/remote_dependency_test.rb +1 -1
  30. data/test/deploy/scm/git_test.rb +1 -1
  31. data/test/deploy/strategy/copy_test.rb +4 -4
  32. data/test/role_test.rb +1 -1
  33. metadata +2 -2
@@ -1,3 +1,32 @@
1
+ == 2.5.1 / November 7, 2008
2
+
3
+ * Add -t (--tools) switch for better task lists for external tools [Jamis Buck]
4
+
5
+ * Make the RemoteDependency#try method use invoke_command instead of run, for sudo-ability [Matthias Marschall]
6
+
7
+ * Make locally executed commands in Windows more Windows-friendly [esad@esse.at]
8
+
9
+ * Added :scm_arguments variable for custom SCM arguments (subversion-only, currently) [David Abdemoulaie]
10
+
11
+ * Don't emit -p for sudo when :sudo_prompt is blank [Matthias Marschall]
12
+
13
+ * Copy symlinks when using rsync [Paul Paradise]
14
+
15
+ * Make sure git query-revision matches on exact branch name [grant@nightriot.com]
16
+
17
+ * Use -T <arg> to filter listed tasks by a pattern [Mathias Meyer, Geoffrey Grosenbach]
18
+
19
+ * Expose the #scm method on SCM::Base for building custom scm commands [Mathias Meyer]
20
+
21
+ * Start logging some locally executed commands [springyweb]
22
+
23
+ * Added HOSTFILTER environment variable for constraining tasks so they run only on hosts matching the given list of servers [Walter Smith]
24
+
25
+ * Make sure the glob matching for copy excludes does not delete parent directories [Fabio Akita]
26
+
27
+ * Ruby 1.9 compatibility [Jamis Buck]
28
+
29
+
1
30
  == 2.5.0 / August 28, 2008
2
31
 
3
32
  * Allow :gateway to be set to an array, in which case a chain of tunnels is created [Kerry Buckley]
@@ -1,14 +1,14 @@
1
1
 
2
- # Gem::Specification for Capistrano-2.5.0
2
+ # Gem::Specification for Capistrano-2.5.1
3
3
  # Originally generated by Echoe
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = %q{capistrano}
7
- s.version = "2.5.0"
7
+ s.version = "2.5.1"
8
8
 
9
9
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
10
10
  s.authors = ["Jamis Buck"]
11
- s.date = %q{2008-08-28}
11
+ s.date = %q{2008-11-07}
12
12
  s.description = %q{Capistrano is a utility and framework for executing commands in parallel on multiple remote machines, via SSH.}
13
13
  s.email = %q{jamis@jamisbuck.org}
14
14
  s.executables = ["cap", "capify"]
@@ -12,7 +12,7 @@ module Capistrano
12
12
 
13
13
  def execute_requested_actions_with_help(config)
14
14
  if options[:tasks]
15
- task_list(config)
15
+ task_list(config, options[:tasks])
16
16
  elsif options[:explain]
17
17
  explain_task(config, options[:explain])
18
18
  else
@@ -20,11 +20,19 @@ module Capistrano
20
20
  end
21
21
  end
22
22
 
23
- def task_list(config) #:nodoc:
24
- tasks = config.task_list(:all)
23
+ def task_list(config, pattern = true) #:nodoc:
24
+ tool_output = options[:tool]
25
+
26
+ if pattern.is_a?(String)
27
+ tasks = config.task_list(:all).select {|t| t.fully_qualified_name =~ /#{pattern}/}
28
+ end
29
+ if tasks.nil? || tasks.length == 0
30
+ warn "Pattern '#{pattern}' not found. Listing all tasks.\n\n" if !tool_output && !pattern.is_a?(TrueClass)
31
+ tasks = config.task_list(:all)
32
+ end
25
33
 
26
34
  if tasks.empty?
27
- warn "There are no tasks available. Please specify a recipe file to load."
35
+ warn "There are no tasks available. Please specify a recipe file to load." unless tool_output
28
36
  else
29
37
  all_tasks_length = tasks.length
30
38
  if options[:verbose].to_i < 1
@@ -38,19 +46,25 @@ module Capistrano
38
46
  max_length = MIN_MAX_LEN if max_length < MIN_MAX_LEN
39
47
 
40
48
  tasks.each do |task|
41
- puts "cap %-#{longest}s # %s" % [task.fully_qualified_name, task.brief_description(max_length)]
49
+ if tool_output
50
+ puts "cap #{task.fully_qualified_name}"
51
+ else
52
+ puts "cap %-#{longest}s # %s" % [task.fully_qualified_name, task.brief_description(max_length)]
53
+ end
42
54
  end
43
55
 
44
- if all_tasks_length > tasks.length
56
+ unless tool_output
57
+ if all_tasks_length > tasks.length
58
+ puts
59
+ puts "Some tasks were not listed, either because they have no description,"
60
+ puts "or because they are only used internally by other tasks. To see all"
61
+ puts "tasks, type `#{File.basename($0)} -vT'."
62
+ end
63
+
45
64
  puts
46
- puts "Some tasks were not listed, either because they have no description,"
47
- puts "or because they are only used internally by other tasks. To see all"
48
- puts "tasks, type `#{File.basename($0)} -Tv'."
65
+ puts "Extended help may be available for these tasks."
66
+ puts "Type `#{File.basename($0)} -e taskname' to view it."
49
67
  end
50
-
51
- puts
52
- puts "Extended help may be available for these tasks."
53
- puts "Type `#{File.basename($0)} -e taskname' to view it."
54
68
  end
55
69
  end
56
70
 
@@ -101,4 +115,4 @@ module Capistrano
101
115
  end
102
116
  end
103
117
  end
104
- end
118
+ end
@@ -43,8 +43,11 @@ The following options are understood:
43
43
  <%= color '-s, --set NAME=VALUE', :bold %>
44
44
  Sets the given variable to the given value, after loading all recipe files. This is useful when you want to override the value of a variable which is used in a task. Note that this will set the variables too late for them to affect conditions that are executed as the recipes are loaded.
45
45
 
46
- <%= color '-T, --tasks', :bold %>
47
- Displays the list of all tasks in all loaded recipe files. If a task has no description, or if the description starts with the [internal] tag, the task will not be listed unless you also specify -v.
46
+ <%= color '-T, --tasks PATTERN', :bold %>
47
+ Displays the list of all tasks (matching optional PATTERN) in all loaded recipe files. If a task has no description, or if the description starts with the [internal] tag, the task will not be listed unless you also specify -v.
48
+
49
+ <%= color '-t, --tool', :bold %>
50
+ Abbreviates the output of -T for integration with other tools. Without -t, -T will list tasks with their summaries, and may include additional instructive text at the bottom. When integrating with other tools (e.g., bash auto-expansion and the like) that additional text can get in the way. This switch makes it easier for those tools to parse the list of tasks. (The -t switch has no effect if the -T switch is not specified.)
48
51
 
49
52
  <%= color '-V, --version', :bold %>
50
53
  Shows the current Capistrano version number and exits.
@@ -79,13 +79,21 @@ module Capistrano
79
79
  options[:vars][name.to_sym] = value
80
80
  end
81
81
 
82
- opts.on("-T", "--tasks",
83
- "List all tasks in the loaded recipe files."
84
- ) do
85
- options[:tasks] = true
82
+ opts.on("-T", "--tasks [PATTERN]",
83
+ "List all tasks (matching optional PATTERN) in the loaded recipe files."
84
+ ) do |value|
85
+ options[:tasks] = if value
86
+ value
87
+ else
88
+ true
89
+ end
86
90
  options[:verbose] ||= 0
87
91
  end
88
92
 
93
+ opts.on("-t", "--tool",
94
+ "Abbreviates the output of -T for tool integration."
95
+ ) { options[:tool] = true }
96
+
89
97
  opts.on("-V", "--version",
90
98
  "Display the Capistrano version, and exit."
91
99
  ) do
@@ -96,7 +104,10 @@ module Capistrano
96
104
 
97
105
  opts.on("-v", "--verbose",
98
106
  "Be more verbose. May be given more than once."
99
- ) { options[:verbose] ||= 0; options[:verbose] += 1 }
107
+ ) do
108
+ options[:verbose] ||= 0
109
+ options[:verbose] += 1
110
+ end
100
111
 
101
112
  opts.on("-X", "--skip-system-config",
102
113
  "Don't load the system config file (capistrano.conf)"
@@ -103,7 +103,8 @@ module Capistrano
103
103
  command = parameters.first
104
104
  user = options[:as] && "-u #{options.delete(:as)}"
105
105
 
106
- sudo_command = [fetch(:sudo, "sudo"), "-p '#{sudo_prompt}'", user].compact.join(" ")
106
+ sudo_prompt_option = "-p '#{sudo_prompt}'" unless sudo_prompt.empty?
107
+ sudo_command = [fetch(:sudo, "sudo"), sudo_prompt_option, user].compact.join(" ")
107
108
 
108
109
  if command
109
110
  command = sudo_command + " " + command
@@ -131,7 +131,12 @@ module Capistrano
131
131
  servers = find_servers_for_task(task, options)
132
132
 
133
133
  if servers.empty?
134
- raise Capistrano::NoMatchingServersError, "`#{task.fully_qualified_name}' is only run for servers matching #{task.options.inspect}, but no servers matched"
134
+ if ENV['HOSTFILTER']
135
+ logger.info "skipping `#{task.fully_qualified_name}' because no servers matched"
136
+ return
137
+ else
138
+ raise Capistrano::NoMatchingServersError, "`#{task.fully_qualified_name}' is only run for servers matching #{task.options.inspect}, but no servers matched"
139
+ end
135
140
  end
136
141
 
137
142
  if task.continue_on_error?
@@ -67,7 +67,7 @@ module Capistrano
67
67
  raise ArgumentError, "expected a block" unless block_given?
68
68
 
69
69
  namespace_already_defined = namespaces.key?(name)
70
- if all_methods.include?(name.to_s) && !namespace_already_defined
70
+ if all_methods.any? { |m| m.to_sym == name } && !namespace_already_defined
71
71
  thing = tasks.key?(name) ? "task" : "method"
72
72
  raise ArgumentError, "defining a namespace named `#{name}' would shadow an existing #{thing} with that name"
73
73
  end
@@ -92,7 +92,7 @@ module Capistrano
92
92
  raise ArgumentError, "expected a block" unless block_given?
93
93
 
94
94
  task_already_defined = tasks.key?(name)
95
- if all_methods.include?(name.to_s) && !task_already_defined
95
+ if all_methods.any? { |m| m.to_sym == name } && !task_already_defined
96
96
  thing = namespaces.key?(name) ? "namespace" : "method"
97
97
  raise ArgumentError, "defining a task named `#{name}' would shadow an existing #{thing} with that name"
98
98
  end
@@ -21,6 +21,9 @@ module Capistrano
21
21
  # variable will take precedence over other options. If both HOSTS and
22
22
  # ROLES are given, HOSTS wins.
23
23
  #
24
+ # Yet additionally, if the HOSTFILTER environment variable is set, it
25
+ # will limit the result to hosts found in that (comma-separated) list.
26
+ #
24
27
  # Usage:
25
28
  #
26
29
  # # return all known servers
@@ -37,7 +40,7 @@ module Capistrano
37
40
  hosts = server_list_from(ENV['HOSTS'] || options[:hosts])
38
41
 
39
42
  if hosts.any?
40
- hosts.uniq
43
+ filter_server_list(hosts.uniq)
41
44
  else
42
45
  roles = role_list_from(ENV['ROLES'] || options[:roles] || self.roles.keys)
43
46
  only = options[:only] || {}
@@ -46,12 +49,18 @@ module Capistrano
46
49
  servers = roles.inject([]) { |list, role| list.concat(self.roles[role]) }
47
50
  servers = servers.select { |server| only.all? { |key,value| server.options[key] == value } }
48
51
  servers = servers.reject { |server| except.any? { |key,value| server.options[key] == value } }
49
- servers.uniq
52
+ filter_server_list(servers.uniq)
50
53
  end
51
54
  end
52
55
 
53
56
  protected
54
57
 
58
+ def filter_server_list(servers)
59
+ return servers unless ENV['HOSTFILTER']
60
+ filters = ENV['HOSTFILTER'].split(/,/)
61
+ servers.select { |server| filters.include?(server.host) }
62
+ end
63
+
55
64
  def server_list_from(hosts)
56
65
  hosts = hosts.split(/,/) if String === hosts
57
66
  hosts = build_list(hosts)
@@ -25,7 +25,7 @@ module Capistrano
25
25
  Capistrano::Configuration.protected_instance_methods +
26
26
  Capistrano::Configuration.private_instance_methods
27
27
 
28
- if methods.include?(name.to_s)
28
+ if methods.any? { |m| m.to_sym == name }
29
29
  raise Capistrano::Error, "registering a plugin named `#{name}' would shadow a method on Capistrano::Configuration with the same name"
30
30
  end
31
31
 
@@ -30,7 +30,7 @@ module Capistrano
30
30
  def log(level, message, line_prefix=nil)
31
31
  if level <= self.level
32
32
  indent = "%*s" % [MAX_LEVEL, "*" * (MAX_LEVEL - level)]
33
- message.each do |line|
33
+ (RUBY_VERSION >= "1.9" ? message.lines : message).each do |line|
34
34
  if line_prefix
35
35
  device.puts "#{indent} [#{line_prefix}] #{line.strip}\n"
36
36
  else
@@ -34,7 +34,7 @@ _cset(:revision) { source.head }
34
34
  # =========================================================================
35
35
 
36
36
  _cset(:source) { Capistrano::Deploy::SCM.new(scm, self) }
37
- _cset(:real_revision) { source.local.query_revision(revision) { |cmd| with_env("LC_ALL", "C") { `#{cmd}` } } }
37
+ _cset(:real_revision) { source.local.query_revision(revision) { |cmd| with_env("LC_ALL", "C") { run_locally(cmd) } } }
38
38
 
39
39
  _cset(:strategy) { Capistrano::Deploy::Strategy.new(deploy_via, self) }
40
40
 
@@ -90,6 +90,13 @@ ensure
90
90
  ENV[name] = saved
91
91
  end
92
92
 
93
+ # logs the command then executes it locally.
94
+ # returns the command output as a string
95
+ def run_locally(cmd)
96
+ logger.trace "executing locally: #{cmd.inspect}" if logger
97
+ `#{cmd}`
98
+ end
99
+
93
100
  # If a command is given, this will try to execute the given command, as
94
101
  # described below. Otherwise, it will return a string for use in embedding in
95
102
  # another command, for executing that command as described below.
@@ -9,6 +9,7 @@ module Capistrano
9
9
  def initialize(configuration)
10
10
  @configuration = configuration
11
11
  @success = true
12
+ @hosts = nil
12
13
  end
13
14
 
14
15
  def directory(path, options={})
@@ -83,7 +84,7 @@ module Capistrano
83
84
 
84
85
  def message
85
86
  s = @message.dup
86
- s << " (#{@hosts})" if @hosts && @hosts.any?
87
+ s << " (#{@hosts})" if @hosts
87
88
  s
88
89
  end
89
90
 
@@ -91,7 +92,7 @@ module Capistrano
91
92
 
92
93
  def try(command, options)
93
94
  return unless @success # short-circuit evaluation
94
- configuration.run(command, options) do |ch,stream,out|
95
+ configuration.invoke_command(command, options) do |ch,stream,out|
95
96
  warn "#{ch[:server]}: #{out}" if stream == :err
96
97
  yield ch, stream, out if block_given?
97
98
  end
@@ -54,7 +54,7 @@ module Capistrano
54
54
  # and "local_scm_command" to be set, if the two differ.
55
55
  #
56
56
  # Alternatively, it may be called with a block, and for the duration of
57
- # the block, all requests on this configuration object will be
57
+ # the block, all requests on this configuration object will be
58
58
  # considered local.
59
59
  def local
60
60
  if block_given?
@@ -150,6 +150,13 @@ module Capistrano
150
150
  command || default_command
151
151
  end
152
152
 
153
+ # A helper method that can be used to define SCM commands naturally.
154
+ # It returns a single string with all arguments joined by spaces,
155
+ # with the scm command prefixed onto it.
156
+ def scm(*args)
157
+ [command, *args].compact.join(" ")
158
+ end
159
+
153
160
  private
154
161
 
155
162
  # A helper for accessing variable values, which takes into
@@ -174,17 +181,14 @@ module Capistrano
174
181
  self.class.default_command
175
182
  end
176
183
 
177
- # A helper method that can be used to define SCM commands naturally.
178
- # It returns a single string with all arguments joined by spaces,
179
- # with the scm command prefixed onto it.
180
- def scm(*args)
181
- [command, *args].compact.join(" ")
182
- end
183
-
184
184
  # A convenience method for accessing the declared repository value.
185
185
  def repository
186
186
  variable(:repository)
187
187
  end
188
+
189
+ def arguments
190
+ variable(:scm_arguments)
191
+ end
188
192
  end
189
193
 
190
194
  end
@@ -123,9 +123,9 @@ module Capistrano
123
123
  def cvs_revision(rev)
124
124
  revision = ""
125
125
  revision << case revision_type(rev)
126
- when :date:
126
+ when :date
127
127
  "-D \"#{rev}\"" if revision_type(rev) == :date
128
- when :revision:
128
+ when :revision
129
129
  "-r #{rev}"
130
130
  else
131
131
  "-r #{head}"
@@ -210,10 +210,17 @@ module Capistrano
210
210
  def query_revision(revision)
211
211
  raise ArgumentError, "Deploying remote branches has been deprecated. Specify the remote branch as a local branch for the git repository you're deploying from (ie: '#{revision.gsub('origin/', '')}' rather than '#{revision}')." if revision =~ /^origin\//
212
212
  return revision if revision =~ /^[0-9a-f]{40}$/
213
- command = scm('ls-remote', repository, revision)
213
+ command = scm('ls-remote -h -t', repository, revision)
214
214
  result = yield(command)
215
- revdata = result.split("\t")
216
- newrev = revdata[0]
215
+ revdata = result.split(/[\t\n]/)
216
+ newrev = nil
217
+ revdata.each_slice(2) do |refs|
218
+ rev, ref = *refs
219
+ if ref.sub(/refs\/.*?\//, '') == revision
220
+ newrev = rev
221
+ break
222
+ end
223
+ end
217
224
  raise "Unable to resolve revision for '#{revision}' on repository '#{repository}'." unless newrev =~ /^[0-9a-f]{40}$/
218
225
  return newrev
219
226
  end
@@ -119,9 +119,9 @@ module Capistrano
119
119
  # verbosity configuration grokking :)
120
120
  def verbose
121
121
  case variable(:scm_verbose)
122
- when nil: nil
123
- when false: "--quiet"
124
- else "--verbose"
122
+ when nil then nil
123
+ when false then "--quiet"
124
+ else "--verbose"
125
125
  end
126
126
  end
127
127
 
@@ -21,19 +21,19 @@ module Capistrano
21
21
  # Returns the command that will check out the given revision to the
22
22
  # given destination.
23
23
  def checkout(revision, destination)
24
- scm :checkout, verbose, authentication, "-r#{revision}", repository, destination
24
+ scm :checkout, arguments, verbose, authentication, "-r#{revision}", repository, destination
25
25
  end
26
26
 
27
27
  # Returns the command that will do an "svn update" to the given
28
28
  # revision, for the working copy at the given destination.
29
29
  def sync(revision, destination)
30
- scm :update, verbose, authentication, "-r#{revision}", destination
30
+ scm :update, arguments, verbose, authentication, "-r#{revision}", destination
31
31
  end
32
32
 
33
33
  # Returns the command that will do an "svn export" of the given revision
34
34
  # to the given destination.
35
35
  def export(revision, destination)
36
- scm :export, verbose, authentication, "-r#{revision}", repository, destination
36
+ scm :export, arguments, verbose, authentication, "-r#{revision}", repository, destination
37
37
  end
38
38
 
39
39
  # Returns the command that will do an "svn diff" for the two revisions.
@@ -48,8 +48,17 @@ module Capistrano
48
48
 
49
49
  # A wrapper for Kernel#system that logs the command being executed.
50
50
  def system(*args)
51
- logger.trace "executing locally: #{args.join(' ')}"
52
- super
51
+ cmd = args.join(' ')
52
+ if RUBY_PLATFORM =~ /win32/
53
+ cmd.gsub!('/','\\') # Replace / with \\
54
+ cmd.gsub!(/^cd /,'cd /D ') # Replace cd with cd /D
55
+ cmd.gsub!(/&& cd /,'&& cd /D ') # Replace cd with cd /D
56
+ logger.trace "executing locally: #{cmd}"
57
+ super(cmd)
58
+ else
59
+ logger.trace "executing locally: #{cmd}"
60
+ super
61
+ end
53
62
  end
54
63
 
55
64
  private
@@ -67,4 +76,4 @@ module Capistrano
67
76
 
68
77
  end
69
78
  end
70
- end
79
+ end
@@ -80,7 +80,14 @@ module Capistrano
80
80
 
81
81
  if copy_exclude.any?
82
82
  logger.debug "processing exclusions..."
83
- copy_exclude.each { |pattern| FileUtils.rm_rf(Dir.glob(File.join(destination, pattern), File::FNM_DOTMATCH)) }
83
+ if copy_exclude.any?
84
+ copy_exclude.each do |pattern|
85
+ delete_list = Dir.glob(File.join(destination, pattern), File::FNM_DOTMATCH)
86
+ # avoid the /.. trap that deletes the parent directories
87
+ delete_list.delete_if { |dir| dir =~ /\/\.\.$/ }
88
+ FileUtils.rm_rf(delete_list.compact)
89
+ end
90
+ end
84
91
  end
85
92
  end
86
93
 
@@ -42,7 +42,7 @@ module Capistrano
42
42
  run "cp -RPp #{repository_cache} #{configuration[:release_path]} && #{mark}"
43
43
  else
44
44
  exclusions = copy_exclude.map { |e| "--exclude=\"#{e}\"" }.join(' ')
45
- run "rsync -rp #{exclusions} #{repository_cache}/* #{configuration[:release_path]} && #{mark}"
45
+ run "rsync -lrp #{exclusions} #{repository_cache}/* #{configuration[:release_path]} && #{mark}"
46
46
  end
47
47
  end
48
48
 
@@ -6,7 +6,7 @@ module Capistrano
6
6
  class Version < Net::SSH::Version
7
7
  MAJOR = 2
8
8
  MINOR = 5
9
- TINY = 0
9
+ TINY = 1
10
10
 
11
11
  # The current version, as a Version instance
12
12
  CURRENT = new(MAJOR, MINOR, TINY)
@@ -33,7 +33,7 @@ class CLIHelpTest < Test::Unit::TestCase
33
33
 
34
34
  def test_execute_requested_actions_with_tasks_should_call_task_list
35
35
  @cli.options[:tasks] = true
36
- @cli.expects(:task_list).with(:config)
36
+ @cli.expects(:task_list).with(:config, true)
37
37
  @cli.expects(:explain_task).never
38
38
  @cli.execute_requested_actions(:config)
39
39
  assert !@cli.called_original
@@ -57,13 +57,38 @@ class CLIHelpTest < Test::Unit::TestCase
57
57
  expected_max_len = 80 - 3 - MockCLI::LINE_PADDING
58
58
  task_list = [task("c"), task("g", "c:g"), task("b", "c:b"), task("a")]
59
59
  task_list.each { |t| t.expects(:brief_description).with(expected_max_len).returns(t.fully_qualified_name) }
60
-
60
+
61
61
  config = mock("config")
62
62
  config.expects(:task_list).with(:all).returns(task_list)
63
63
  @cli.stubs(:puts)
64
64
  @cli.task_list(config)
65
65
  end
66
66
 
67
+ def test_task_list_should_query_tasks_with_pattern
68
+ expected_max_len = 80 - 3 - MockCLI::LINE_PADDING
69
+ task_list = [task("g", "c:g"), task("b", "c:b")]
70
+ task_list.each { |t| t.expects(:brief_description).with(expected_max_len).returns(t.fully_qualified_name)}
71
+
72
+ config = mock("config")
73
+ config.expects(:task_list).with(:all).once.returns(task_list)
74
+
75
+ @cli.stubs(:puts)
76
+ @cli.task_list(config, "c")
77
+ end
78
+
79
+ def test_task_list_should_query_for_all_tasks_when_pattern_doesnt_match
80
+ expected_max_len = 80 - 3 - MockCLI::LINE_PADDING
81
+ task_list = [task("g", "c:g"), task("b", "c:b")]
82
+ task_list.each { |t| t.expects(:brief_description).with(expected_max_len).returns(t.fully_qualified_name) }
83
+
84
+ config = mock("config")
85
+ config.expects(:task_list).with(:all).times(2).returns(task_list)
86
+
87
+ @cli.stubs(:warn)
88
+ @cli.stubs(:puts)
89
+ @cli.task_list(config, "z")
90
+ end
91
+
67
92
  def test_task_list_should_never_use_less_than_MIN_MAX_LEN_chars_for_descriptions
68
93
  @ui.stubs(:output_cols).returns(20)
69
94
  t = task("c")
@@ -133,7 +158,8 @@ class CLIHelpTest < Test::Unit::TestCase
133
158
 
134
159
  private
135
160
 
136
- def task(name, fqn=name, desc="a description")
137
- stub("task", :name => name, :fully_qualified_name => fqn, :description => desc)
138
- end
139
- end
161
+ def task(name, fqn=name, desc="a description")
162
+ stub("task", :name => name, :fully_qualified_name => fqn, :description => desc)
163
+ end
164
+
165
+ end
@@ -261,7 +261,8 @@ class CLIOptionsTest < Test::Unit::TestCase
261
261
  assert_equal "world", ENV["HELLO"]
262
262
  assert_equal "value", ENV["ANOTHER"]
263
263
  ensure
264
- ENV["HELLO"] = ENV["ANOTHER"] = nil
264
+ ENV.delete("HELLO")
265
+ ENV.delete("ANOTHER")
265
266
  end
266
267
 
267
268
  def test_remaining_args_should_be_added_to_actions_list
@@ -269,7 +270,7 @@ class CLIOptionsTest < Test::Unit::TestCase
269
270
  @cli.parse_options!
270
271
  assert_equal %w(something else), @cli.args
271
272
  ensure
272
- ENV["HELLO"] = nil
273
+ ENV.delete("HELLO")
273
274
  end
274
275
 
275
276
  def test_search_for_default_recipe_file_should_look_for_Capfile
@@ -114,6 +114,12 @@ class ConfigurationActionsInvocationTest < Test::Unit::TestCase
114
114
  @config.sudo "ls", :foo => "bar"
115
115
  end
116
116
 
117
+ def test_sudo_should_avoid_minus_p_when_sudo_prompt_is_empty
118
+ @config.set :sudo_prompt, ""
119
+ @config.expects(:run).with("sudo ls", {})
120
+ @config.sudo "ls"
121
+ end
122
+
117
123
  def test_sudo_should_interpret_sudo_prompt_variable_as_custom_prompt
118
124
  @config.set :sudo_prompt, "give it to me: "
119
125
  @config.expects(:run).with("sudo -p 'give it to me: ' ls", {})
@@ -23,7 +23,7 @@ class ConfigurationLoadingTest < Test::Unit::TestCase
23
23
 
24
24
  def teardown
25
25
  MockConfig.instance = nil
26
- $".delete "#{File.dirname(__FILE__)}/../fixtures/custom.rb"
26
+ $LOADED_FEATURES.delete_if { |a| a =~ /fixtures\/custom\.rb$/ }
27
27
  end
28
28
 
29
29
  def test_initialize_should_init_collections
@@ -108,9 +108,9 @@ class ConfigurationNamespacesDSLTest < Test::Unit::TestCase
108
108
  end
109
109
 
110
110
  def test_defining_ask_should_add_task_as_method
111
- assert !@config.methods.include?("original")
111
+ assert !@config.methods.any? { |m| m.to_sym == :original }
112
112
  @config.task(:original) { puts "foo" }
113
- assert @config.methods.include?("original")
113
+ assert @config.methods.any? { |m| m.to_sym == :original }
114
114
  end
115
115
 
116
116
  def test_calling_defined_task_should_delegate_to_execute_task
@@ -59,7 +59,7 @@ class ConfigurationServersTest < Test::Unit::TestCase
59
59
  task = new_task(:testing)
60
60
  assert_equal %w(app1 app2 app3 file).sort, @config.find_servers_for_task(task).map { |s| s.host }.sort
61
61
  ensure
62
- ENV['ROLES'] = nil
62
+ ENV.delete('ROLES')
63
63
  end
64
64
 
65
65
  def test_task_with_hosts_as_environment_variable_should_apply_only_to_those_hosts
@@ -67,7 +67,7 @@ class ConfigurationServersTest < Test::Unit::TestCase
67
67
  task = new_task(:testing)
68
68
  assert_equal %w(foo bar).sort, @config.find_servers_for_task(task).map { |s| s.host }.sort
69
69
  ensure
70
- ENV['HOSTS'] = nil
70
+ ENV.delete('HOSTS')
71
71
  end
72
72
 
73
73
  def test_task_with_hosts_as_environment_variable_should_not_inspect_roles_at_all
@@ -75,7 +75,23 @@ class ConfigurationServersTest < Test::Unit::TestCase
75
75
  task = new_task(:testing, @config, :roles => :bogus)
76
76
  assert_equal %w(foo bar).sort, @config.find_servers_for_task(task).map { |s| s.host }.sort
77
77
  ensure
78
- ENV['HOSTS'] = nil
78
+ ENV.delete('HOSTS')
79
+ end
80
+
81
+ def test_task_with_onlyhosts_environment_variable_should_apply_only_to_those_hosts
82
+ ENV['HOSTFILTER'] = "app1,web1"
83
+ task = new_task(:testing)
84
+ assert_equal %w(app1 web1).sort, @config.find_servers_for_task(task).map { |s| s.host }.sort
85
+ ensure
86
+ ENV.delete('HOSTFILTER')
87
+ end
88
+
89
+ def test_task_with_onlyhosts_environment_variable_should_filter_hosts_option
90
+ ENV['HOSTFILTER'] = "foo"
91
+ task = new_task(:testing, @config, :hosts => %w(foo bar))
92
+ assert_equal %w(foo).sort, @config.find_servers_for_task(task).map { |s| s.host }.sort
93
+ ensure
94
+ ENV.delete('HOSTFILTER')
79
95
  end
80
96
 
81
97
  def test_task_with_only_should_apply_only_to_matching_tasks
@@ -96,7 +96,7 @@ class RemoteDependencyTest < Test::Unit::TestCase
96
96
  private
97
97
 
98
98
  def setup_for_a_configuration_run(command, passing)
99
- expectation = @config.expects(:run).with(command, {})
99
+ expectation = @config.expects(:invoke_command).with(command, {})
100
100
  if passing
101
101
  expectation.returns(true)
102
102
  else
@@ -59,7 +59,7 @@ class DeploySCMGitTest < Test::Unit::TestCase
59
59
 
60
60
  def test_query_revision
61
61
  revision = @source.query_revision('HEAD') do |o|
62
- assert_equal "git ls-remote . HEAD", o
62
+ assert_equal "git ls-remote -h -t . HEAD", o
63
63
  "d11006102c07c94e5d54dd0ee63dca825c93ed61\tHEAD"
64
64
  end
65
65
  assert_equal "d11006102c07c94e5d54dd0ee63dca825c93ed61", revision
@@ -29,9 +29,9 @@ class DeployStrategyCopyTest < Test::Unit::TestCase
29
29
  Dir.expects(:tmpdir).returns("/temp/dir")
30
30
  @source.expects(:checkout).with("154", "/temp/dir/1234567890").returns(:local_checkout)
31
31
  @strategy.expects(:system).with(:local_checkout)
32
- Dir.expects(:glob).with("/temp/dir/1234567890/.git", File::FNM_DOTMATCH).returns("/temp/dir/1234567890/.git")
32
+ Dir.expects(:glob).with("/temp/dir/1234567890/.git", File::FNM_DOTMATCH).returns(%w(/temp/dir/1234567890/.git))
33
33
 
34
- FileUtils.expects(:rm_rf).with("/temp/dir/1234567890/.git")
34
+ FileUtils.expects(:rm_rf).with(%w(/temp/dir/1234567890/.git))
35
35
  prepare_standard_compress_and_copy!
36
36
  @strategy.deploy!
37
37
  end
@@ -41,9 +41,9 @@ class DeployStrategyCopyTest < Test::Unit::TestCase
41
41
  Dir.expects(:tmpdir).returns("/temp/dir")
42
42
  @source.expects(:checkout).with("154", "/temp/dir/1234567890").returns(:local_checkout)
43
43
  @strategy.expects(:system).with(:local_checkout)
44
- Dir.expects(:glob).with("/temp/dir/1234567890/.gi*", File::FNM_DOTMATCH).returns("/temp/dir/1234567890/.git")
44
+ Dir.expects(:glob).with("/temp/dir/1234567890/.gi*", File::FNM_DOTMATCH).returns(%w(/temp/dir/1234567890/.git))
45
45
 
46
- FileUtils.expects(:rm_rf).with("/temp/dir/1234567890/.git")
46
+ FileUtils.expects(:rm_rf).with(%w(/temp/dir/1234567890/.git))
47
47
  prepare_standard_compress_and_copy!
48
48
  @strategy.deploy!
49
49
  end
@@ -3,7 +3,7 @@ require 'capistrano/role'
3
3
 
4
4
  class RoleTest < Test::Unit::TestCase
5
5
  def test_clearing_a_populated_role_should_yield_no_servers
6
- role = Capistrano::Role.new("app1.capistrano.test", lambda { "app2.capistrano.test" })
6
+ role = Capistrano::Role.new("app1.capistrano.test", lambda { |o| "app2.capistrano.test" })
7
7
  assert_equal 2, role.servers.size
8
8
  role.clear
9
9
  assert role.servers.empty?
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capistrano
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.0
4
+ version: 2.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jamis Buck
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-08-28 00:00:00 -06:00
12
+ date: 2008-11-07 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency