capistrano-edge 2.5.6
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.rdoc +770 -0
- data/Manifest +104 -0
- data/README.rdoc +66 -0
- data/Rakefile +35 -0
- data/bin/cap +4 -0
- data/bin/capify +95 -0
- data/capistrano.gemspec +51 -0
- data/examples/sample.rb +14 -0
- data/lib/capistrano.rb +2 -0
- data/lib/capistrano/callback.rb +45 -0
- data/lib/capistrano/cli.rb +47 -0
- data/lib/capistrano/cli/execute.rb +84 -0
- data/lib/capistrano/cli/help.rb +125 -0
- data/lib/capistrano/cli/help.txt +75 -0
- data/lib/capistrano/cli/options.rb +224 -0
- data/lib/capistrano/cli/ui.rb +40 -0
- data/lib/capistrano/command.rb +283 -0
- data/lib/capistrano/configuration.rb +43 -0
- data/lib/capistrano/configuration/actions/file_transfer.rb +47 -0
- data/lib/capistrano/configuration/actions/inspect.rb +46 -0
- data/lib/capistrano/configuration/actions/invocation.rb +293 -0
- data/lib/capistrano/configuration/callbacks.rb +148 -0
- data/lib/capistrano/configuration/connections.rb +204 -0
- data/lib/capistrano/configuration/execution.rb +143 -0
- data/lib/capistrano/configuration/loading.rb +197 -0
- data/lib/capistrano/configuration/namespaces.rb +197 -0
- data/lib/capistrano/configuration/roles.rb +73 -0
- data/lib/capistrano/configuration/servers.rb +85 -0
- data/lib/capistrano/configuration/variables.rb +127 -0
- data/lib/capistrano/errors.rb +15 -0
- data/lib/capistrano/extensions.rb +57 -0
- data/lib/capistrano/logger.rb +59 -0
- data/lib/capistrano/processable.rb +53 -0
- data/lib/capistrano/recipes/compat.rb +32 -0
- data/lib/capistrano/recipes/deploy.rb +438 -0
- data/lib/capistrano/recipes/deploy/dependencies.rb +44 -0
- data/lib/capistrano/recipes/deploy/local_dependency.rb +54 -0
- data/lib/capistrano/recipes/deploy/remote_dependency.rb +105 -0
- data/lib/capistrano/recipes/deploy/scm.rb +19 -0
- data/lib/capistrano/recipes/deploy/scm/accurev.rb +169 -0
- data/lib/capistrano/recipes/deploy/scm/base.rb +196 -0
- data/lib/capistrano/recipes/deploy/scm/bzr.rb +83 -0
- data/lib/capistrano/recipes/deploy/scm/cvs.rb +152 -0
- data/lib/capistrano/recipes/deploy/scm/darcs.rb +85 -0
- data/lib/capistrano/recipes/deploy/scm/git.rb +274 -0
- data/lib/capistrano/recipes/deploy/scm/mercurial.rb +137 -0
- data/lib/capistrano/recipes/deploy/scm/none.rb +44 -0
- data/lib/capistrano/recipes/deploy/scm/perforce.rb +138 -0
- data/lib/capistrano/recipes/deploy/scm/subversion.rb +121 -0
- data/lib/capistrano/recipes/deploy/strategy.rb +19 -0
- data/lib/capistrano/recipes/deploy/strategy/base.rb +79 -0
- data/lib/capistrano/recipes/deploy/strategy/checkout.rb +20 -0
- data/lib/capistrano/recipes/deploy/strategy/copy.rb +210 -0
- data/lib/capistrano/recipes/deploy/strategy/export.rb +20 -0
- data/lib/capistrano/recipes/deploy/strategy/remote.rb +52 -0
- data/lib/capistrano/recipes/deploy/strategy/remote_cache.rb +56 -0
- data/lib/capistrano/recipes/deploy/templates/maintenance.rhtml +53 -0
- data/lib/capistrano/recipes/ext/rails-database-migrations.rb +50 -0
- data/lib/capistrano/recipes/ext/web-disable-enable.rb +40 -0
- data/lib/capistrano/recipes/standard.rb +37 -0
- data/lib/capistrano/recipes/templates/maintenance.rhtml +53 -0
- data/lib/capistrano/recipes/upgrade.rb +33 -0
- data/lib/capistrano/role.rb +102 -0
- data/lib/capistrano/server_definition.rb +56 -0
- data/lib/capistrano/shell.rb +260 -0
- data/lib/capistrano/ssh.rb +99 -0
- data/lib/capistrano/task_definition.rb +70 -0
- data/lib/capistrano/transfer.rb +216 -0
- data/lib/capistrano/version.rb +18 -0
- data/setup.rb +1346 -0
- data/test/cli/execute_test.rb +132 -0
- data/test/cli/help_test.rb +165 -0
- data/test/cli/options_test.rb +317 -0
- data/test/cli/ui_test.rb +28 -0
- data/test/cli_test.rb +17 -0
- data/test/command_test.rb +286 -0
- data/test/configuration/actions/file_transfer_test.rb +61 -0
- data/test/configuration/actions/inspect_test.rb +65 -0
- data/test/configuration/actions/invocation_test.rb +224 -0
- data/test/configuration/callbacks_test.rb +220 -0
- data/test/configuration/connections_test.rb +349 -0
- data/test/configuration/execution_test.rb +175 -0
- data/test/configuration/loading_test.rb +132 -0
- data/test/configuration/namespace_dsl_test.rb +311 -0
- data/test/configuration/roles_test.rb +144 -0
- data/test/configuration/servers_test.rb +121 -0
- data/test/configuration/variables_test.rb +184 -0
- data/test/configuration_test.rb +88 -0
- data/test/deploy/local_dependency_test.rb +76 -0
- data/test/deploy/remote_dependency_test.rb +114 -0
- data/test/deploy/scm/accurev_test.rb +23 -0
- data/test/deploy/scm/base_test.rb +55 -0
- data/test/deploy/scm/git_test.rb +184 -0
- data/test/deploy/scm/mercurial_test.rb +129 -0
- data/test/deploy/scm/none_test.rb +35 -0
- data/test/deploy/strategy/copy_test.rb +258 -0
- data/test/extensions_test.rb +69 -0
- data/test/fixtures/cli_integration.rb +5 -0
- data/test/fixtures/config.rb +5 -0
- data/test/fixtures/custom.rb +3 -0
- data/test/logger_test.rb +123 -0
- data/test/role_test.rb +11 -0
- data/test/server_definition_test.rb +121 -0
- data/test/shell_test.rb +90 -0
- data/test/ssh_test.rb +104 -0
- data/test/task_definition_test.rb +101 -0
- data/test/transfer_test.rb +160 -0
- data/test/utils.rb +38 -0
- metadata +321 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
require 'capistrano/server_definition'
|
|
2
|
+
require 'capistrano/role'
|
|
3
|
+
|
|
4
|
+
module Capistrano
|
|
5
|
+
class Configuration
|
|
6
|
+
module Roles
|
|
7
|
+
def self.included(base) #:nodoc:
|
|
8
|
+
base.send :alias_method, :initialize_without_roles, :initialize
|
|
9
|
+
base.send :alias_method, :initialize, :initialize_with_roles
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# The hash of roles defined for this configuration. Each entry in the
|
|
13
|
+
# hash points to an array of server definitions that belong in that
|
|
14
|
+
# role.
|
|
15
|
+
attr_reader :roles
|
|
16
|
+
|
|
17
|
+
def initialize_with_roles(*args) #:nodoc:
|
|
18
|
+
initialize_without_roles(*args)
|
|
19
|
+
@roles = Hash.new { |h,k| h[k] = Role.new }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Define a new role and its associated servers. You must specify at least
|
|
23
|
+
# one host for each role. Also, you can specify additional information
|
|
24
|
+
# (in the form of a Hash) which can be used to more uniquely specify the
|
|
25
|
+
# subset of servers specified by this specific role definition.
|
|
26
|
+
#
|
|
27
|
+
# Usage:
|
|
28
|
+
#
|
|
29
|
+
# role :db, "db1.example.com", "db2.example.com"
|
|
30
|
+
# role :db, "master.example.com", :primary => true
|
|
31
|
+
# role :app, "app1.example.com", "app2.example.com"
|
|
32
|
+
#
|
|
33
|
+
# You can also encode the username and port number for each host in the
|
|
34
|
+
# server string, if needed:
|
|
35
|
+
#
|
|
36
|
+
# role :web, "www@web1.example.com"
|
|
37
|
+
# role :file, "files.example.com:4144"
|
|
38
|
+
# role :db, "admin@db3.example.com:1234"
|
|
39
|
+
#
|
|
40
|
+
# Lastly, username and port number may be passed as options, if that is
|
|
41
|
+
# preferred; note that the options apply to all servers defined in
|
|
42
|
+
# that call to "role":
|
|
43
|
+
#
|
|
44
|
+
# role :web, "web2", "web3", :user => "www", :port => 2345
|
|
45
|
+
def role(which, *args, &block)
|
|
46
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
|
47
|
+
which = which.to_sym
|
|
48
|
+
|
|
49
|
+
# The roles Hash is defined so that unrecognized keys always auto-initialize
|
|
50
|
+
# to a new Role instance (see the assignment in the initialize_with_roles method,
|
|
51
|
+
# above). However, we explicitly assign here so that role declarations will
|
|
52
|
+
# vivify the role object even if there are no server arguments. (Otherwise,
|
|
53
|
+
# role(:app) won't actually instantiate a Role object for :app.)
|
|
54
|
+
roles[which] ||= Role.new
|
|
55
|
+
|
|
56
|
+
roles[which].push(block, options) if block_given?
|
|
57
|
+
args.each { |host| roles[which] << ServerDefinition.new(host, options) }
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# An alternative way to associate servers with roles. If you have a server
|
|
61
|
+
# that participates in multiple roles, this can be a DRYer way to describe
|
|
62
|
+
# the relationships. Pass the host definition as the first parameter, and
|
|
63
|
+
# the roles as the remaining parameters:
|
|
64
|
+
#
|
|
65
|
+
# server "master.example.com", :web, :app
|
|
66
|
+
def server(host, *roles)
|
|
67
|
+
options = roles.last.is_a?(Hash) ? roles.pop : {}
|
|
68
|
+
raise ArgumentError, "you must associate a server with at least one role" if roles.empty?
|
|
69
|
+
roles.each { |name| role(name, host, options) }
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
module Capistrano
|
|
2
|
+
class Configuration
|
|
3
|
+
module Servers
|
|
4
|
+
# Identifies all servers that the given task should be executed on.
|
|
5
|
+
# The options hash accepts the same arguments as #find_servers, and any
|
|
6
|
+
# preexisting options there will take precedence over the options in
|
|
7
|
+
# the task.
|
|
8
|
+
def find_servers_for_task(task, options={})
|
|
9
|
+
find_servers(task.options.merge(options))
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Attempts to find all defined servers that match the given criteria.
|
|
13
|
+
# The options hash may include a :hosts option (which should specify
|
|
14
|
+
# an array of host names or ServerDefinition instances), a :roles
|
|
15
|
+
# option (specifying an array of roles), an :only option (specifying
|
|
16
|
+
# a hash of key/value pairs that any matching server must match), and
|
|
17
|
+
# an :exception option (like :only, but the inverse).
|
|
18
|
+
#
|
|
19
|
+
# Additionally, if the HOSTS environment variable is set, it will take
|
|
20
|
+
# precedence over any other options. Similarly, the ROLES environment
|
|
21
|
+
# variable will take precedence over other options. If both HOSTS and
|
|
22
|
+
# ROLES are given, HOSTS wins.
|
|
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
|
+
#
|
|
27
|
+
# Usage:
|
|
28
|
+
#
|
|
29
|
+
# # return all known servers
|
|
30
|
+
# servers = find_servers
|
|
31
|
+
#
|
|
32
|
+
# # find all servers in the app role that are not exempted from
|
|
33
|
+
# # deployment
|
|
34
|
+
# servers = find_servers :roles => :app,
|
|
35
|
+
# :except => { :no_release => true }
|
|
36
|
+
#
|
|
37
|
+
# # returns the given hosts, translated to ServerDefinition objects
|
|
38
|
+
# servers = find_servers :hosts => "jamis@example.host.com"
|
|
39
|
+
def find_servers(options={})
|
|
40
|
+
hosts = server_list_from(ENV['HOSTS'] || options[:hosts])
|
|
41
|
+
|
|
42
|
+
if hosts.any?
|
|
43
|
+
filter_server_list(hosts.uniq)
|
|
44
|
+
else
|
|
45
|
+
roles = role_list_from(ENV['ROLES'] || options[:roles] || self.roles.keys)
|
|
46
|
+
only = options[:only] || {}
|
|
47
|
+
except = options[:except] || {}
|
|
48
|
+
|
|
49
|
+
servers = roles.inject([]) { |list, role| list.concat(self.roles[role]) }
|
|
50
|
+
servers = servers.select { |server| only.all? { |key,value| server.options[key] == value } }
|
|
51
|
+
servers = servers.reject { |server| except.any? { |key,value| server.options[key] == value } }
|
|
52
|
+
filter_server_list(servers.uniq)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
protected
|
|
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
|
+
|
|
64
|
+
def server_list_from(hosts)
|
|
65
|
+
hosts = hosts.split(/,/) if String === hosts
|
|
66
|
+
hosts = build_list(hosts)
|
|
67
|
+
hosts.map { |s| String === s ? ServerDefinition.new(s.strip) : s }
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def role_list_from(roles)
|
|
71
|
+
roles = roles.split(/,/) if String === roles
|
|
72
|
+
roles = build_list(roles)
|
|
73
|
+
roles.map do |role|
|
|
74
|
+
role = String === role ? role.strip.to_sym : role
|
|
75
|
+
raise ArgumentError, "unknown role `#{role}'" unless self.roles.key?(role)
|
|
76
|
+
role
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def build_list(list)
|
|
81
|
+
Array(list).map { |item| item.respond_to?(:call) ? item.call : item }.flatten
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
require 'thread'
|
|
2
|
+
|
|
3
|
+
module Capistrano
|
|
4
|
+
class Configuration
|
|
5
|
+
module Variables
|
|
6
|
+
def self.included(base) #:nodoc:
|
|
7
|
+
%w(initialize respond_to? method_missing).each do |m|
|
|
8
|
+
base_name = m[/^\w+/]
|
|
9
|
+
punct = m[/\W+$/]
|
|
10
|
+
base.send :alias_method, "#{base_name}_without_variables#{punct}", m
|
|
11
|
+
base.send :alias_method, m, "#{base_name}_with_variables#{punct}"
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# The hash of variables that have been defined in this configuration
|
|
16
|
+
# instance.
|
|
17
|
+
attr_reader :variables
|
|
18
|
+
|
|
19
|
+
# Set a variable to the given value.
|
|
20
|
+
def set(variable, *args, &block)
|
|
21
|
+
if variable.to_s !~ /^[_a-z]/
|
|
22
|
+
raise ArgumentError, "invalid variable `#{variable}' (variables must begin with an underscore, or a lower-case letter)"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
if !block_given? && args.empty? || block_given? && !args.empty?
|
|
26
|
+
raise ArgumentError, "you must specify exactly one of either a value or a block"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
if args.length > 1
|
|
30
|
+
raise ArgumentError, "wrong number of arguments (#{args.length} for 1)"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
value = args.empty? ? block : args.first
|
|
34
|
+
sym = variable.to_sym
|
|
35
|
+
protect(sym) { @variables[sym] = value }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
alias :[]= :set
|
|
39
|
+
|
|
40
|
+
# Removes any trace of the given variable.
|
|
41
|
+
def unset(variable)
|
|
42
|
+
sym = variable.to_sym
|
|
43
|
+
protect(sym) do
|
|
44
|
+
@original_procs.delete(sym)
|
|
45
|
+
@variables.delete(sym)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Returns true if the variable has been defined, and false otherwise.
|
|
50
|
+
def exists?(variable)
|
|
51
|
+
@variables.key?(variable.to_sym)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# If the variable was originally a proc value, it will be reset to it's
|
|
55
|
+
# original proc value. Otherwise, this method does nothing. It returns
|
|
56
|
+
# true if the variable was actually reset.
|
|
57
|
+
def reset!(variable)
|
|
58
|
+
sym = variable.to_sym
|
|
59
|
+
protect(sym) do
|
|
60
|
+
if @original_procs.key?(sym)
|
|
61
|
+
@variables[sym] = @original_procs.delete(sym)
|
|
62
|
+
true
|
|
63
|
+
else
|
|
64
|
+
false
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Access a named variable. If the value of the variable responds_to? :call,
|
|
70
|
+
# #call will be invoked (without parameters) and the return value cached
|
|
71
|
+
# and returned.
|
|
72
|
+
def fetch(variable, *args)
|
|
73
|
+
if !args.empty? && block_given?
|
|
74
|
+
raise ArgumentError, "you must specify either a default value or a block, but not both"
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
sym = variable.to_sym
|
|
78
|
+
protect(sym) do
|
|
79
|
+
if !@variables.key?(sym)
|
|
80
|
+
return args.first unless args.empty?
|
|
81
|
+
return yield(variable) if block_given?
|
|
82
|
+
raise IndexError, "`#{variable}' not found"
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
if @variables[sym].respond_to?(:call)
|
|
86
|
+
@original_procs[sym] = @variables[sym]
|
|
87
|
+
@variables[sym] = @variables[sym].call
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
@variables[sym]
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def [](variable)
|
|
95
|
+
fetch(variable, nil)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def initialize_with_variables(*args) #:nodoc:
|
|
99
|
+
initialize_without_variables(*args)
|
|
100
|
+
@variables = {}
|
|
101
|
+
@original_procs = {}
|
|
102
|
+
@variable_locks = Hash.new { |h,k| h[k] = Mutex.new }
|
|
103
|
+
|
|
104
|
+
set :ssh_options, {}
|
|
105
|
+
set :logger, logger
|
|
106
|
+
end
|
|
107
|
+
private :initialize_with_variables
|
|
108
|
+
|
|
109
|
+
def protect(variable)
|
|
110
|
+
@variable_locks[variable.to_sym].synchronize { yield }
|
|
111
|
+
end
|
|
112
|
+
private :protect
|
|
113
|
+
|
|
114
|
+
def respond_to_with_variables?(sym, include_priv=false) #:nodoc:
|
|
115
|
+
@variables.has_key?(sym) || respond_to_without_variables?(sym, include_priv)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def method_missing_with_variables(sym, *args, &block) #:nodoc:
|
|
119
|
+
if args.length == 0 && block.nil? && @variables.has_key?(sym)
|
|
120
|
+
self[sym]
|
|
121
|
+
else
|
|
122
|
+
method_missing_without_variables(sym, *args, &block)
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module Capistrano
|
|
2
|
+
class Error < RuntimeError; end
|
|
3
|
+
|
|
4
|
+
class CaptureError < Error; end
|
|
5
|
+
class NoSuchTaskError < Error; end
|
|
6
|
+
class NoMatchingServersError < Error; end
|
|
7
|
+
|
|
8
|
+
class RemoteError < Error
|
|
9
|
+
attr_accessor :hosts
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
class ConnectionError < RemoteError; end
|
|
13
|
+
class TransferError < RemoteError; end
|
|
14
|
+
class CommandError < RemoteError; end
|
|
15
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module Capistrano
|
|
2
|
+
class ExtensionProxy #:nodoc:
|
|
3
|
+
def initialize(config, mod)
|
|
4
|
+
@config = config
|
|
5
|
+
extend(mod)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def method_missing(sym, *args, &block)
|
|
9
|
+
@config.send(sym, *args, &block)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Holds the set of registered plugins, keyed by name (where the name is a
|
|
14
|
+
# symbol).
|
|
15
|
+
EXTENSIONS = {}
|
|
16
|
+
|
|
17
|
+
# Register the given module as a plugin with the given name. It will henceforth
|
|
18
|
+
# be available via a proxy object on Configuration instances, accessible by
|
|
19
|
+
# a method with the given name.
|
|
20
|
+
def self.plugin(name, mod)
|
|
21
|
+
name = name.to_sym
|
|
22
|
+
return false if EXTENSIONS.has_key?(name)
|
|
23
|
+
|
|
24
|
+
methods = Capistrano::Configuration.public_instance_methods +
|
|
25
|
+
Capistrano::Configuration.protected_instance_methods +
|
|
26
|
+
Capistrano::Configuration.private_instance_methods
|
|
27
|
+
|
|
28
|
+
if methods.any? { |m| m.to_sym == name }
|
|
29
|
+
raise Capistrano::Error, "registering a plugin named `#{name}' would shadow a method on Capistrano::Configuration with the same name"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
Capistrano::Configuration.class_eval <<-STR, __FILE__, __LINE__+1
|
|
33
|
+
def #{name}
|
|
34
|
+
@__#{name}_proxy ||= Capistrano::ExtensionProxy.new(self, Capistrano::EXTENSIONS[#{name.inspect}])
|
|
35
|
+
end
|
|
36
|
+
STR
|
|
37
|
+
|
|
38
|
+
EXTENSIONS[name] = mod
|
|
39
|
+
return true
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Unregister the plugin with the given name.
|
|
43
|
+
def self.remove_plugin(name)
|
|
44
|
+
name = name.to_sym
|
|
45
|
+
if EXTENSIONS.delete(name)
|
|
46
|
+
Capistrano::Configuration.send(:remove_method, name)
|
|
47
|
+
return true
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
return false
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def self.configuration(*args) #:nodoc:
|
|
54
|
+
warn "[DEPRECATION] Capistrano.configuration is deprecated. Use Capistrano::Configuration.instance instead"
|
|
55
|
+
Capistrano::Configuration.instance(*args)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
module Capistrano
|
|
2
|
+
class Logger #:nodoc:
|
|
3
|
+
attr_accessor :level
|
|
4
|
+
attr_reader :device
|
|
5
|
+
|
|
6
|
+
IMPORTANT = 0
|
|
7
|
+
INFO = 1
|
|
8
|
+
DEBUG = 2
|
|
9
|
+
TRACE = 3
|
|
10
|
+
|
|
11
|
+
MAX_LEVEL = 3
|
|
12
|
+
|
|
13
|
+
def initialize(options={})
|
|
14
|
+
output = options[:output] || $stderr
|
|
15
|
+
if output.respond_to?(:puts)
|
|
16
|
+
@device = output
|
|
17
|
+
else
|
|
18
|
+
@device = File.open(output.to_str, "a")
|
|
19
|
+
@needs_close = true
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
@options = options
|
|
23
|
+
@level = 0
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def close
|
|
27
|
+
device.close if @needs_close
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def log(level, message, line_prefix=nil)
|
|
31
|
+
if level <= self.level
|
|
32
|
+
indent = "%*s" % [MAX_LEVEL, "*" * (MAX_LEVEL - level)]
|
|
33
|
+
(RUBY_VERSION >= "1.9" ? message.lines : message).each do |line|
|
|
34
|
+
if line_prefix
|
|
35
|
+
device.puts "#{indent} [#{line_prefix}] #{line.strip}\n"
|
|
36
|
+
else
|
|
37
|
+
device.puts "#{indent} #{line.strip}\n"
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def important(message, line_prefix=nil)
|
|
44
|
+
log(IMPORTANT, message, line_prefix)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def info(message, line_prefix=nil)
|
|
48
|
+
log(INFO, message, line_prefix)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def debug(message, line_prefix=nil)
|
|
52
|
+
log(DEBUG, message, line_prefix)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def trace(message, line_prefix=nil)
|
|
56
|
+
log(TRACE, message, line_prefix)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module Capistrano
|
|
2
|
+
module Processable
|
|
3
|
+
module SessionAssociation
|
|
4
|
+
def self.on(exception, session)
|
|
5
|
+
unless exception.respond_to?(:session)
|
|
6
|
+
exception.extend(self)
|
|
7
|
+
exception.session = session
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
return exception
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
attr_accessor :session
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def process_iteration(wait=nil, &block)
|
|
17
|
+
ensure_each_session { |session| session.preprocess }
|
|
18
|
+
|
|
19
|
+
return false if block && !block.call(self)
|
|
20
|
+
|
|
21
|
+
readers = sessions.map { |session| session.listeners.keys }.flatten.reject { |io| io.closed? }
|
|
22
|
+
writers = readers.select { |io| io.respond_to?(:pending_write?) && io.pending_write? }
|
|
23
|
+
|
|
24
|
+
if readers.any? || writers.any?
|
|
25
|
+
readers, writers, = IO.select(readers, writers, nil, wait)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
if readers
|
|
29
|
+
ensure_each_session do |session|
|
|
30
|
+
ios = session.listeners.keys
|
|
31
|
+
session.postprocess(ios & readers, ios & writers)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
true
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def ensure_each_session
|
|
39
|
+
errors = []
|
|
40
|
+
|
|
41
|
+
sessions.each do |session|
|
|
42
|
+
begin
|
|
43
|
+
yield session
|
|
44
|
+
rescue Exception => error
|
|
45
|
+
errors << SessionAssociation.on(error, session)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
raise errors.first if errors.any?
|
|
50
|
+
sessions
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|