capistrano 2.1.0 → 3.0.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.
- checksums.yaml +7 -0
- data/.gitignore +20 -0
- data/.travis.yml +7 -0
- data/CHANGELOG.md +89 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +674 -0
- data/README.md +226 -0
- data/Rakefile +5 -0
- data/bin/cap +2 -3
- data/bin/capify +7 -77
- data/capistrano-public_cert.pem +22 -0
- data/capistrano.gemspec +35 -0
- data/features/deploy.feature +52 -0
- data/features/installation.feature +16 -0
- data/features/remote_file_task.feature +14 -0
- data/features/step_definitions/assertions.rb +90 -0
- data/features/step_definitions/cap_commands.rb +8 -0
- data/features/step_definitions/setup.rb +25 -0
- data/features/support/env.rb +12 -0
- data/features/support/remote_command_helpers.rb +20 -0
- data/lib/Capfile +3 -0
- data/lib/capistrano/all.rb +16 -0
- data/lib/capistrano/application.rb +60 -0
- data/lib/capistrano/configuration/question.rb +42 -0
- data/lib/capistrano/configuration/server.rb +133 -0
- data/lib/capistrano/configuration/servers/role_filter.rb +86 -0
- data/lib/capistrano/configuration/servers.rb +53 -58
- data/lib/capistrano/configuration.rb +84 -30
- data/lib/capistrano/console.rb +1 -0
- data/lib/capistrano/defaults.rb +13 -0
- data/lib/capistrano/deploy.rb +3 -0
- data/lib/capistrano/dotfile.rb +3 -0
- data/lib/capistrano/dsl/env.rb +64 -0
- data/lib/capistrano/dsl/paths.rb +94 -0
- data/lib/capistrano/dsl/stages.rb +15 -0
- data/lib/capistrano/dsl/task_enhancements.rb +53 -0
- data/lib/capistrano/dsl.rb +48 -0
- data/lib/capistrano/git.rb +1 -0
- data/lib/capistrano/hg.rb +1 -0
- data/lib/capistrano/i18n.rb +34 -0
- data/lib/capistrano/install.rb +1 -0
- data/lib/capistrano/setup.rb +21 -0
- data/lib/capistrano/tasks/console.rake +21 -0
- data/lib/capistrano/tasks/deploy.rake +204 -0
- data/lib/capistrano/tasks/framework.rake +67 -0
- data/lib/capistrano/tasks/git.rake +62 -0
- data/lib/capistrano/tasks/hg.rake +39 -0
- data/lib/capistrano/tasks/install.rake +39 -0
- data/lib/capistrano/templates/Capfile +26 -0
- data/lib/capistrano/templates/deploy.rb.erb +40 -0
- data/lib/capistrano/templates/stage.rb.erb +42 -0
- data/lib/capistrano/version.rb +1 -20
- data/lib/capistrano/version_validator.rb +37 -0
- data/lib/capistrano.rb +0 -2
- data/spec/integration/dsl_spec.rb +344 -0
- data/spec/integration_spec_helper.rb +7 -0
- data/spec/lib/capistrano/application_spec.rb +61 -0
- data/spec/lib/capistrano/configuration/question_spec.rb +54 -0
- data/spec/lib/capistrano/configuration/server_spec.rb +249 -0
- data/spec/lib/capistrano/configuration/servers/role_filter_spec.rb +140 -0
- data/spec/lib/capistrano/configuration/servers_spec.rb +184 -0
- data/spec/lib/capistrano/configuration_spec.rb +101 -0
- data/spec/lib/capistrano/dsl/env_spec.rb +10 -0
- data/spec/lib/capistrano/dsl/paths_spec.rb +69 -0
- data/spec/lib/capistrano/dsl_spec.rb +63 -0
- data/spec/lib/capistrano/version_validator_spec.rb +103 -0
- data/spec/lib/capistrano_spec.rb +8 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/support/.gitignore +1 -0
- data/spec/support/Vagrantfile +13 -0
- data/spec/support/matchers.rb +5 -0
- data/spec/support/tasks/database.cap +11 -0
- data/spec/support/test_app.rb +138 -0
- metadata +251 -179
- data/CHANGELOG +0 -512
- data/MIT-LICENSE +0 -20
- data/README +0 -43
- data/examples/sample.rb +0 -14
- data/lib/capistrano/callback.rb +0 -45
- data/lib/capistrano/cli/execute.rb +0 -82
- data/lib/capistrano/cli/help.rb +0 -102
- data/lib/capistrano/cli/help.txt +0 -53
- data/lib/capistrano/cli/options.rb +0 -183
- data/lib/capistrano/cli/ui.rb +0 -28
- data/lib/capistrano/cli.rb +0 -47
- data/lib/capistrano/command.rb +0 -161
- data/lib/capistrano/configuration/actions/file_transfer.rb +0 -35
- data/lib/capistrano/configuration/actions/inspect.rb +0 -46
- data/lib/capistrano/configuration/actions/invocation.rb +0 -134
- data/lib/capistrano/configuration/callbacks.rb +0 -148
- data/lib/capistrano/configuration/connections.rb +0 -159
- data/lib/capistrano/configuration/execution.rb +0 -126
- data/lib/capistrano/configuration/loading.rb +0 -198
- data/lib/capistrano/configuration/namespaces.rb +0 -196
- data/lib/capistrano/configuration/roles.rb +0 -51
- data/lib/capistrano/configuration/variables.rb +0 -127
- data/lib/capistrano/errors.rb +0 -15
- data/lib/capistrano/extensions.rb +0 -57
- data/lib/capistrano/gateway.rb +0 -131
- data/lib/capistrano/logger.rb +0 -59
- data/lib/capistrano/recipes/compat.rb +0 -32
- data/lib/capistrano/recipes/deploy/dependencies.rb +0 -44
- data/lib/capistrano/recipes/deploy/local_dependency.rb +0 -46
- data/lib/capistrano/recipes/deploy/remote_dependency.rb +0 -96
- data/lib/capistrano/recipes/deploy/scm/accurev.rb +0 -169
- data/lib/capistrano/recipes/deploy/scm/base.rb +0 -192
- data/lib/capistrano/recipes/deploy/scm/bzr.rb +0 -86
- data/lib/capistrano/recipes/deploy/scm/cvs.rb +0 -151
- data/lib/capistrano/recipes/deploy/scm/darcs.rb +0 -85
- data/lib/capistrano/recipes/deploy/scm/git.rb +0 -191
- data/lib/capistrano/recipes/deploy/scm/mercurial.rb +0 -129
- data/lib/capistrano/recipes/deploy/scm/perforce.rb +0 -126
- data/lib/capistrano/recipes/deploy/scm/subversion.rb +0 -114
- data/lib/capistrano/recipes/deploy/scm.rb +0 -19
- data/lib/capistrano/recipes/deploy/strategy/base.rb +0 -64
- data/lib/capistrano/recipes/deploy/strategy/checkout.rb +0 -20
- data/lib/capistrano/recipes/deploy/strategy/copy.rb +0 -144
- data/lib/capistrano/recipes/deploy/strategy/export.rb +0 -20
- data/lib/capistrano/recipes/deploy/strategy/remote.rb +0 -52
- data/lib/capistrano/recipes/deploy/strategy/remote_cache.rb +0 -47
- data/lib/capistrano/recipes/deploy/strategy.rb +0 -19
- data/lib/capistrano/recipes/deploy/templates/maintenance.rhtml +0 -53
- data/lib/capistrano/recipes/deploy.rb +0 -494
- data/lib/capistrano/recipes/standard.rb +0 -37
- data/lib/capistrano/recipes/templates/maintenance.rhtml +0 -53
- data/lib/capistrano/recipes/upgrade.rb +0 -33
- data/lib/capistrano/server_definition.rb +0 -51
- data/lib/capistrano/shell.rb +0 -256
- data/lib/capistrano/ssh.rb +0 -109
- data/lib/capistrano/task_definition.rb +0 -69
- data/lib/capistrano/upload.rb +0 -146
- data/test/cli/execute_test.rb +0 -132
- data/test/cli/help_test.rb +0 -139
- data/test/cli/options_test.rb +0 -226
- data/test/cli/ui_test.rb +0 -28
- data/test/cli_test.rb +0 -17
- data/test/command_test.rb +0 -309
- data/test/configuration/actions/file_transfer_test.rb +0 -40
- data/test/configuration/actions/inspect_test.rb +0 -62
- data/test/configuration/actions/invocation_test.rb +0 -202
- data/test/configuration/callbacks_test.rb +0 -206
- data/test/configuration/connections_test.rb +0 -288
- data/test/configuration/execution_test.rb +0 -159
- data/test/configuration/loading_test.rb +0 -127
- data/test/configuration/namespace_dsl_test.rb +0 -297
- data/test/configuration/roles_test.rb +0 -47
- data/test/configuration/servers_test.rb +0 -90
- data/test/configuration/variables_test.rb +0 -180
- data/test/configuration_test.rb +0 -81
- data/test/deploy/scm/accurev_test.rb +0 -23
- data/test/deploy/scm/base_test.rb +0 -55
- data/test/deploy/scm/git_test.rb +0 -112
- data/test/deploy/strategy/copy_test.rb +0 -147
- data/test/extensions_test.rb +0 -69
- data/test/fixtures/cli_integration.rb +0 -5
- data/test/fixtures/config.rb +0 -5
- data/test/fixtures/custom.rb +0 -3
- data/test/gateway_test.rb +0 -167
- data/test/logger_test.rb +0 -123
- data/test/server_definition_test.rb +0 -108
- data/test/shell_test.rb +0 -64
- data/test/ssh_test.rb +0 -97
- data/test/task_definition_test.rb +0 -101
- data/test/upload_test.rb +0 -131
- data/test/utils.rb +0 -42
- data/test/version_test.rb +0 -24
@@ -1,198 +0,0 @@
|
|
1
|
-
module Capistrano
|
2
|
-
class Configuration
|
3
|
-
module Loading
|
4
|
-
def self.included(base) #:nodoc:
|
5
|
-
base.send :alias_method, :initialize_without_loading, :initialize
|
6
|
-
base.send :alias_method, :initialize, :initialize_with_loading
|
7
|
-
base.extend ClassMethods
|
8
|
-
end
|
9
|
-
|
10
|
-
module ClassMethods
|
11
|
-
# Used by third-party task bundles to identify the capistrano
|
12
|
-
# configuration that is loading them. Its return value is not reliable
|
13
|
-
# in other contexts. If +require_config+ is not false, an exception
|
14
|
-
# will be raised if the current configuration is not set.
|
15
|
-
def instance(require_config=false)
|
16
|
-
config = Thread.current[:capistrano_configuration]
|
17
|
-
if require_config && config.nil?
|
18
|
-
raise LoadError, "Please require this file from within a Capistrano recipe"
|
19
|
-
end
|
20
|
-
config
|
21
|
-
end
|
22
|
-
|
23
|
-
# Used internally by Capistrano to specify the current configuration
|
24
|
-
# before loading a third-party task bundle.
|
25
|
-
def instance=(config)
|
26
|
-
Thread.current[:capistrano_configuration] = config
|
27
|
-
end
|
28
|
-
|
29
|
-
# Used internally by Capistrano to track which recipes have been loaded
|
30
|
-
# via require, so that they may be successfully reloaded when require
|
31
|
-
# is called again.
|
32
|
-
def recipes_per_feature
|
33
|
-
@recipes_per_feature ||= {}
|
34
|
-
end
|
35
|
-
|
36
|
-
# Used internally to determine what the current "feature" being
|
37
|
-
# required is. This is used to track which files load which recipes
|
38
|
-
# via require.
|
39
|
-
def current_feature
|
40
|
-
Thread.current[:capistrano_current_feature]
|
41
|
-
end
|
42
|
-
|
43
|
-
# Used internally to specify the current file being required, so that
|
44
|
-
# any recipes loaded by that file can be remembered. This allows
|
45
|
-
# recipes loaded via require to be correctly reloaded in different
|
46
|
-
# Configuration instances in the same Ruby instance.
|
47
|
-
def current_feature=(feature)
|
48
|
-
Thread.current[:capistrano_current_feature] = feature
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
# The load paths used for locating recipe files.
|
53
|
-
attr_reader :load_paths
|
54
|
-
|
55
|
-
def initialize_with_loading(*args) #:nodoc:
|
56
|
-
initialize_without_loading(*args)
|
57
|
-
@load_paths = [".", File.expand_path(File.join(File.dirname(__FILE__), "../recipes"))]
|
58
|
-
@loaded_features = []
|
59
|
-
end
|
60
|
-
private :initialize_with_loading
|
61
|
-
|
62
|
-
# Load a configuration file or string into this configuration.
|
63
|
-
#
|
64
|
-
# Usage:
|
65
|
-
#
|
66
|
-
# load("recipe"):
|
67
|
-
# Look for and load the contents of 'recipe.rb' into this
|
68
|
-
# configuration.
|
69
|
-
#
|
70
|
-
# load(:file => "recipe"):
|
71
|
-
# same as above
|
72
|
-
#
|
73
|
-
# load(:string => "set :scm, :subversion"):
|
74
|
-
# Load the given string as a configuration specification.
|
75
|
-
#
|
76
|
-
# load { ... }
|
77
|
-
# Load the block in the context of the configuration.
|
78
|
-
def load(*args, &block)
|
79
|
-
options = args.last.is_a?(Hash) ? args.pop : {}
|
80
|
-
|
81
|
-
if block
|
82
|
-
raise ArgumentError, "loading a block requires 0 arguments" unless options.empty? && args.empty?
|
83
|
-
load(:proc => block)
|
84
|
-
|
85
|
-
elsif args.any?
|
86
|
-
args.each { |arg| load options.merge(:file => arg) }
|
87
|
-
|
88
|
-
elsif options[:file]
|
89
|
-
load_from_file(options[:file], options[:name])
|
90
|
-
|
91
|
-
elsif options[:string]
|
92
|
-
remember_load(options) unless options[:reloading]
|
93
|
-
instance_eval(options[:string], options[:name] || "<eval>")
|
94
|
-
|
95
|
-
elsif options[:proc]
|
96
|
-
remember_load(options) unless options[:reloading]
|
97
|
-
instance_eval(&options[:proc])
|
98
|
-
|
99
|
-
else
|
100
|
-
raise ArgumentError, "don't know how to load #{options.inspect}"
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
# Require another file. This is identical to the standard require method,
|
105
|
-
# with the exception that it sets the receiver as the "current" configuration
|
106
|
-
# so that third-party task bundles can include themselves relative to
|
107
|
-
# that configuration.
|
108
|
-
#
|
109
|
-
# This is a bit more complicated than an initial review would seem to
|
110
|
-
# necessitate, but the use case that complicates things is this: An
|
111
|
-
# advanced user wants to embed capistrano, and needs to instantiate
|
112
|
-
# more than one capistrano configuration at a time. They also want each
|
113
|
-
# configuration to require a third-party capistrano extension. Using a
|
114
|
-
# naive require implementation, this would allow the first configuration
|
115
|
-
# to successfully load the third-party extension, but the require would
|
116
|
-
# fail for the second configuration because the extension has already
|
117
|
-
# been loaded.
|
118
|
-
#
|
119
|
-
# To work around this, we do a few things:
|
120
|
-
#
|
121
|
-
# 1. Each time a 'require' is invoked inside of a capistrano recipe,
|
122
|
-
# we remember the arguments (see "current_feature").
|
123
|
-
# 2. Each time a 'load' is invoked inside of a capistrano recipe, and
|
124
|
-
# "current_feature" is not nil (meaning we are inside of a pending
|
125
|
-
# require) we remember the options (see "remember_load" and
|
126
|
-
# "recipes_per_feature").
|
127
|
-
# 3. Each time a 'require' is invoked inside of a capistrano recipe,
|
128
|
-
# we check to see if this particular configuration has ever seen these
|
129
|
-
# arguments to require (see @loaded_features), and if not, we proceed
|
130
|
-
# as if the file had never been required. If the superclass' require
|
131
|
-
# returns false (meaning, potentially, that the file has already been
|
132
|
-
# required), then we look in the recipes_per_feature collection and
|
133
|
-
# load any remembered recipes from there.
|
134
|
-
#
|
135
|
-
# It's kind of a bear, but it works, and works transparently. Note that
|
136
|
-
# a simpler implementation would just muck with $", allowing files to be
|
137
|
-
# required multiple times, but that will cause warnings (and possibly
|
138
|
-
# errors) if the file to be required contains constant definitions and
|
139
|
-
# such, alongside (or instead of) capistrano recipe definitions.
|
140
|
-
def require(*args) #:nodoc:
|
141
|
-
# look to see if this specific configuration instance has ever seen
|
142
|
-
# these arguments to require before
|
143
|
-
if !@loaded_features.include?(args)
|
144
|
-
@loaded_features << args
|
145
|
-
|
146
|
-
begin
|
147
|
-
original_instance, self.class.instance = self.class.instance, self
|
148
|
-
original_feature, self.class.current_feature = self.class.current_feature, args
|
149
|
-
|
150
|
-
result = super
|
151
|
-
if !result # file has been required previously, load up the remembered recipes
|
152
|
-
list = self.class.recipes_per_feature[args] || []
|
153
|
-
list.each { |options| load(options.merge(:reloading => true)) }
|
154
|
-
end
|
155
|
-
|
156
|
-
return result
|
157
|
-
ensure
|
158
|
-
# restore the original, so that require's can be nested
|
159
|
-
self.class.instance = original_instance
|
160
|
-
self.class.current_feature = original_feature
|
161
|
-
end
|
162
|
-
else
|
163
|
-
return false
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
private
|
168
|
-
|
169
|
-
# Load a recipe from the named file. If +name+ is given, the file will
|
170
|
-
# be reported using that name.
|
171
|
-
def load_from_file(file, name=nil)
|
172
|
-
file = find_file_in_load_path(file) unless file[0] == ?/
|
173
|
-
load :string => File.read(file), :name => name || file
|
174
|
-
end
|
175
|
-
|
176
|
-
def find_file_in_load_path(file)
|
177
|
-
load_paths.each do |path|
|
178
|
-
["", ".rb"].each do |ext|
|
179
|
-
name = File.join(path, "#{file}#{ext}")
|
180
|
-
return name if File.file?(name)
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
raise LoadError, "no such file to load -- #{file}"
|
185
|
-
end
|
186
|
-
|
187
|
-
# If a file is being required, the options associated with loading a
|
188
|
-
# recipe are remembered in the recipes_per_feature archive under the
|
189
|
-
# name of the file currently being required.
|
190
|
-
def remember_load(options)
|
191
|
-
if self.class.current_feature
|
192
|
-
list = (self.class.recipes_per_feature[self.class.current_feature] ||= [])
|
193
|
-
list << options
|
194
|
-
end
|
195
|
-
end
|
196
|
-
end
|
197
|
-
end
|
198
|
-
end
|
@@ -1,196 +0,0 @@
|
|
1
|
-
require 'capistrano/task_definition'
|
2
|
-
|
3
|
-
module Capistrano
|
4
|
-
class Configuration
|
5
|
-
module Namespaces
|
6
|
-
DEFAULT_TASK = :default
|
7
|
-
|
8
|
-
def self.included(base) #:nodoc:
|
9
|
-
base.send :alias_method, :initialize_without_namespaces, :initialize
|
10
|
-
base.send :alias_method, :initialize, :initialize_with_namespaces
|
11
|
-
end
|
12
|
-
|
13
|
-
# The name of this namespace. Defaults to +nil+ for the top-level
|
14
|
-
# namespace.
|
15
|
-
attr_reader :name
|
16
|
-
|
17
|
-
# The parent namespace of this namespace. Returns +nil+ for the top-level
|
18
|
-
# namespace.
|
19
|
-
attr_reader :parent
|
20
|
-
|
21
|
-
# The hash of tasks defined for this namespace.
|
22
|
-
attr_reader :tasks
|
23
|
-
|
24
|
-
# The hash of namespaces defined for this namespace.
|
25
|
-
attr_reader :namespaces
|
26
|
-
|
27
|
-
def initialize_with_namespaces(*args) #:nodoc:
|
28
|
-
@name = @parent = nil
|
29
|
-
initialize_without_namespaces(*args)
|
30
|
-
@tasks = {}
|
31
|
-
@namespaces = {}
|
32
|
-
end
|
33
|
-
private :initialize_with_namespaces
|
34
|
-
|
35
|
-
# Returns the top-level namespace (the one with no parent).
|
36
|
-
def top
|
37
|
-
return parent.top if parent
|
38
|
-
return self
|
39
|
-
end
|
40
|
-
|
41
|
-
# Returns the fully-qualified name of this namespace, or nil if the
|
42
|
-
# namespace is at the top-level.
|
43
|
-
def fully_qualified_name
|
44
|
-
return nil if name.nil?
|
45
|
-
[parent.fully_qualified_name, name].compact.join(":")
|
46
|
-
end
|
47
|
-
|
48
|
-
# Describe the next task to be defined. The given text will be attached to
|
49
|
-
# the next task that is defined and used as its description.
|
50
|
-
def desc(text)
|
51
|
-
@next_description = text
|
52
|
-
end
|
53
|
-
|
54
|
-
# Returns the value set by the last, pending "desc" call. If +reset+ is
|
55
|
-
# not false, the value will be reset immediately afterwards.
|
56
|
-
def next_description(reset=false)
|
57
|
-
@next_description
|
58
|
-
ensure
|
59
|
-
@next_description = nil if reset
|
60
|
-
end
|
61
|
-
|
62
|
-
# Open a namespace in which to define new tasks. If the namespace was
|
63
|
-
# defined previously, it will be reopened, otherwise a new namespace
|
64
|
-
# will be created for the given name.
|
65
|
-
def namespace(name, &block)
|
66
|
-
name = name.to_sym
|
67
|
-
raise ArgumentError, "expected a block" unless block_given?
|
68
|
-
|
69
|
-
namespace_already_defined = namespaces.key?(name)
|
70
|
-
if all_methods.include?(name.to_s) && !namespace_already_defined
|
71
|
-
thing = tasks.key?(name) ? "task" : "method"
|
72
|
-
raise ArgumentError, "defining a namespace named `#{name}' would shadow an existing #{thing} with that name"
|
73
|
-
end
|
74
|
-
|
75
|
-
namespaces[name] ||= Namespace.new(name, self)
|
76
|
-
namespaces[name].instance_eval(&block)
|
77
|
-
|
78
|
-
# make sure any open description gets terminated
|
79
|
-
namespaces[name].desc(nil)
|
80
|
-
|
81
|
-
if !namespace_already_defined
|
82
|
-
metaclass = class << self; self; end
|
83
|
-
metaclass.send(:define_method, name) { namespaces[name] }
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
# Describe a new task. If a description is active (see #desc), it is added
|
88
|
-
# to the options under the <tt>:desc</tt> key. The new task is added to
|
89
|
-
# the namespace.
|
90
|
-
def task(name, options={}, &block)
|
91
|
-
name = name.to_sym
|
92
|
-
raise ArgumentError, "expected a block" unless block_given?
|
93
|
-
|
94
|
-
task_already_defined = tasks.key?(name)
|
95
|
-
if all_methods.include?(name.to_s) && !task_already_defined
|
96
|
-
thing = namespaces.key?(name) ? "namespace" : "method"
|
97
|
-
raise ArgumentError, "defining a task named `#{name}' would shadow an existing #{thing} with that name"
|
98
|
-
end
|
99
|
-
|
100
|
-
tasks[name] = TaskDefinition.new(name, self, {:desc => next_description(:reset)}.merge(options), &block)
|
101
|
-
|
102
|
-
if !task_already_defined
|
103
|
-
metaclass = class << self; self; end
|
104
|
-
metaclass.send(:define_method, name) { execute_task(tasks[name]) }
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
# Find the task with the given name, where name is the fully-qualified
|
109
|
-
# name of the task. This will search into the namespaces and return
|
110
|
-
# the referenced task, or nil if no such task can be found. If the name
|
111
|
-
# refers to a namespace, the task in that namespace named "default"
|
112
|
-
# will be returned instead, if one exists.
|
113
|
-
def find_task(name)
|
114
|
-
parts = name.to_s.split(/:/)
|
115
|
-
tail = parts.pop.to_sym
|
116
|
-
|
117
|
-
ns = self
|
118
|
-
until parts.empty?
|
119
|
-
ns = ns.namespaces[parts.shift.to_sym]
|
120
|
-
return nil if ns.nil?
|
121
|
-
end
|
122
|
-
|
123
|
-
if ns.namespaces.key?(tail)
|
124
|
-
ns = ns.namespaces[tail]
|
125
|
-
tail = DEFAULT_TASK
|
126
|
-
end
|
127
|
-
|
128
|
-
ns.tasks[tail]
|
129
|
-
end
|
130
|
-
|
131
|
-
# Given a task name, this will search the current namespace, and all
|
132
|
-
# parent namespaces, looking for a task that matches the name, exactly.
|
133
|
-
# It returns the task, if found, or nil, if not.
|
134
|
-
def search_task(name)
|
135
|
-
name = name.to_sym
|
136
|
-
ns = self
|
137
|
-
|
138
|
-
until ns.nil?
|
139
|
-
return ns.tasks[name] if ns.tasks.key?(name)
|
140
|
-
ns = ns.parent
|
141
|
-
end
|
142
|
-
|
143
|
-
return nil
|
144
|
-
end
|
145
|
-
|
146
|
-
# Returns the default task for this namespace. This will be +nil+ if
|
147
|
-
# the namespace is at the top-level, and will otherwise return the
|
148
|
-
# task named "default". If no such task exists, +nil+ will be returned.
|
149
|
-
def default_task
|
150
|
-
return nil if parent.nil?
|
151
|
-
return tasks[DEFAULT_TASK]
|
152
|
-
end
|
153
|
-
|
154
|
-
# Returns the tasks in this namespace as an array of TaskDefinition
|
155
|
-
# objects. If a non-false parameter is given, all tasks in all
|
156
|
-
# namespaces under this namespace will be returned as well.
|
157
|
-
def task_list(all=false)
|
158
|
-
list = tasks.values
|
159
|
-
namespaces.each { |name,space| list.concat(space.task_list(:all)) } if all
|
160
|
-
list
|
161
|
-
end
|
162
|
-
|
163
|
-
private
|
164
|
-
|
165
|
-
def all_methods
|
166
|
-
public_methods.concat(protected_methods).concat(private_methods)
|
167
|
-
end
|
168
|
-
|
169
|
-
class Namespace
|
170
|
-
def initialize(name, parent)
|
171
|
-
@parent = parent
|
172
|
-
@name = name
|
173
|
-
end
|
174
|
-
|
175
|
-
def role(*args)
|
176
|
-
raise NotImplementedError, "roles cannot be defined in a namespace"
|
177
|
-
end
|
178
|
-
|
179
|
-
def respond_to?(sym)
|
180
|
-
super || parent.respond_to?(sym)
|
181
|
-
end
|
182
|
-
|
183
|
-
def method_missing(sym, *args, &block)
|
184
|
-
if parent.respond_to?(sym)
|
185
|
-
parent.send(sym, *args, &block)
|
186
|
-
else
|
187
|
-
super
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
include Capistrano::Configuration::Namespaces
|
192
|
-
undef :desc, :next_description
|
193
|
-
end
|
194
|
-
end
|
195
|
-
end
|
196
|
-
end
|
@@ -1,51 +0,0 @@
|
|
1
|
-
require 'capistrano/server_definition'
|
2
|
-
|
3
|
-
module Capistrano
|
4
|
-
class Configuration
|
5
|
-
module Roles
|
6
|
-
def self.included(base) #:nodoc:
|
7
|
-
base.send :alias_method, :initialize_without_roles, :initialize
|
8
|
-
base.send :alias_method, :initialize, :initialize_with_roles
|
9
|
-
end
|
10
|
-
|
11
|
-
# The hash of roles defined for this configuration. Each entry in the
|
12
|
-
# hash points to an array of server definitions that belong in that
|
13
|
-
# role.
|
14
|
-
attr_reader :roles
|
15
|
-
|
16
|
-
def initialize_with_roles(*args) #:nodoc:
|
17
|
-
initialize_without_roles(*args)
|
18
|
-
@roles = Hash.new { |h,k| h[k] = [] }
|
19
|
-
end
|
20
|
-
|
21
|
-
# Define a new role and its associated servers. You must specify at least
|
22
|
-
# one host for each role. Also, you can specify additional information
|
23
|
-
# (in the form of a Hash) which can be used to more uniquely specify the
|
24
|
-
# subset of servers specified by this specific role definition.
|
25
|
-
#
|
26
|
-
# Usage:
|
27
|
-
#
|
28
|
-
# role :db, "db1.example.com", "db2.example.com"
|
29
|
-
# role :db, "master.example.com", :primary => true
|
30
|
-
# role :app, "app1.example.com", "app2.example.com"
|
31
|
-
#
|
32
|
-
# You can also encode the username and port number for each host in the
|
33
|
-
# server string, if needed:
|
34
|
-
#
|
35
|
-
# role :web, "www@web1.example.com"
|
36
|
-
# role :file, "files.example.com:4144"
|
37
|
-
# role :db, "admin@db3.example.com:1234"
|
38
|
-
#
|
39
|
-
# Lastly, username and port number may be passed as options, if that is
|
40
|
-
# preferred; note that the options apply to all servers defined in
|
41
|
-
# that call to "role":
|
42
|
-
#
|
43
|
-
# role :web, "web2", "web3", :user => "www", :port => 2345
|
44
|
-
def role(which, *args)
|
45
|
-
options = args.last.is_a?(Hash) ? args.pop : {}
|
46
|
-
which = which.to_sym
|
47
|
-
args.each { |host| roles[which] << ServerDefinition.new(host, options) }
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
@@ -1,127 +0,0 @@
|
|
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) #:nodoc:
|
115
|
-
@variables.has_key?(sym) || respond_to_without_variables?(sym)
|
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
|
data/lib/capistrano/errors.rb
DELETED
@@ -1,15 +0,0 @@
|
|
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 UploadError < RemoteError; end
|
14
|
-
class CommandError < RemoteError; end
|
15
|
-
end
|
@@ -1,57 +0,0 @@
|
|
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.include?(name.to_s)
|
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
|