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.
Files changed (166) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.travis.yml +7 -0
  4. data/CHANGELOG.md +89 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +674 -0
  7. data/README.md +226 -0
  8. data/Rakefile +5 -0
  9. data/bin/cap +2 -3
  10. data/bin/capify +7 -77
  11. data/capistrano-public_cert.pem +22 -0
  12. data/capistrano.gemspec +35 -0
  13. data/features/deploy.feature +52 -0
  14. data/features/installation.feature +16 -0
  15. data/features/remote_file_task.feature +14 -0
  16. data/features/step_definitions/assertions.rb +90 -0
  17. data/features/step_definitions/cap_commands.rb +8 -0
  18. data/features/step_definitions/setup.rb +25 -0
  19. data/features/support/env.rb +12 -0
  20. data/features/support/remote_command_helpers.rb +20 -0
  21. data/lib/Capfile +3 -0
  22. data/lib/capistrano/all.rb +16 -0
  23. data/lib/capistrano/application.rb +60 -0
  24. data/lib/capistrano/configuration/question.rb +42 -0
  25. data/lib/capistrano/configuration/server.rb +133 -0
  26. data/lib/capistrano/configuration/servers/role_filter.rb +86 -0
  27. data/lib/capistrano/configuration/servers.rb +53 -58
  28. data/lib/capistrano/configuration.rb +84 -30
  29. data/lib/capistrano/console.rb +1 -0
  30. data/lib/capistrano/defaults.rb +13 -0
  31. data/lib/capistrano/deploy.rb +3 -0
  32. data/lib/capistrano/dotfile.rb +3 -0
  33. data/lib/capistrano/dsl/env.rb +64 -0
  34. data/lib/capistrano/dsl/paths.rb +94 -0
  35. data/lib/capistrano/dsl/stages.rb +15 -0
  36. data/lib/capistrano/dsl/task_enhancements.rb +53 -0
  37. data/lib/capistrano/dsl.rb +48 -0
  38. data/lib/capistrano/git.rb +1 -0
  39. data/lib/capistrano/hg.rb +1 -0
  40. data/lib/capistrano/i18n.rb +34 -0
  41. data/lib/capistrano/install.rb +1 -0
  42. data/lib/capistrano/setup.rb +21 -0
  43. data/lib/capistrano/tasks/console.rake +21 -0
  44. data/lib/capistrano/tasks/deploy.rake +204 -0
  45. data/lib/capistrano/tasks/framework.rake +67 -0
  46. data/lib/capistrano/tasks/git.rake +62 -0
  47. data/lib/capistrano/tasks/hg.rake +39 -0
  48. data/lib/capistrano/tasks/install.rake +39 -0
  49. data/lib/capistrano/templates/Capfile +26 -0
  50. data/lib/capistrano/templates/deploy.rb.erb +40 -0
  51. data/lib/capistrano/templates/stage.rb.erb +42 -0
  52. data/lib/capistrano/version.rb +1 -20
  53. data/lib/capistrano/version_validator.rb +37 -0
  54. data/lib/capistrano.rb +0 -2
  55. data/spec/integration/dsl_spec.rb +344 -0
  56. data/spec/integration_spec_helper.rb +7 -0
  57. data/spec/lib/capistrano/application_spec.rb +61 -0
  58. data/spec/lib/capistrano/configuration/question_spec.rb +54 -0
  59. data/spec/lib/capistrano/configuration/server_spec.rb +249 -0
  60. data/spec/lib/capistrano/configuration/servers/role_filter_spec.rb +140 -0
  61. data/spec/lib/capistrano/configuration/servers_spec.rb +184 -0
  62. data/spec/lib/capistrano/configuration_spec.rb +101 -0
  63. data/spec/lib/capistrano/dsl/env_spec.rb +10 -0
  64. data/spec/lib/capistrano/dsl/paths_spec.rb +69 -0
  65. data/spec/lib/capistrano/dsl_spec.rb +63 -0
  66. data/spec/lib/capistrano/version_validator_spec.rb +103 -0
  67. data/spec/lib/capistrano_spec.rb +8 -0
  68. data/spec/spec_helper.rb +15 -0
  69. data/spec/support/.gitignore +1 -0
  70. data/spec/support/Vagrantfile +13 -0
  71. data/spec/support/matchers.rb +5 -0
  72. data/spec/support/tasks/database.cap +11 -0
  73. data/spec/support/test_app.rb +138 -0
  74. metadata +251 -179
  75. data/CHANGELOG +0 -512
  76. data/MIT-LICENSE +0 -20
  77. data/README +0 -43
  78. data/examples/sample.rb +0 -14
  79. data/lib/capistrano/callback.rb +0 -45
  80. data/lib/capistrano/cli/execute.rb +0 -82
  81. data/lib/capistrano/cli/help.rb +0 -102
  82. data/lib/capistrano/cli/help.txt +0 -53
  83. data/lib/capistrano/cli/options.rb +0 -183
  84. data/lib/capistrano/cli/ui.rb +0 -28
  85. data/lib/capistrano/cli.rb +0 -47
  86. data/lib/capistrano/command.rb +0 -161
  87. data/lib/capistrano/configuration/actions/file_transfer.rb +0 -35
  88. data/lib/capistrano/configuration/actions/inspect.rb +0 -46
  89. data/lib/capistrano/configuration/actions/invocation.rb +0 -134
  90. data/lib/capistrano/configuration/callbacks.rb +0 -148
  91. data/lib/capistrano/configuration/connections.rb +0 -159
  92. data/lib/capistrano/configuration/execution.rb +0 -126
  93. data/lib/capistrano/configuration/loading.rb +0 -198
  94. data/lib/capistrano/configuration/namespaces.rb +0 -196
  95. data/lib/capistrano/configuration/roles.rb +0 -51
  96. data/lib/capistrano/configuration/variables.rb +0 -127
  97. data/lib/capistrano/errors.rb +0 -15
  98. data/lib/capistrano/extensions.rb +0 -57
  99. data/lib/capistrano/gateway.rb +0 -131
  100. data/lib/capistrano/logger.rb +0 -59
  101. data/lib/capistrano/recipes/compat.rb +0 -32
  102. data/lib/capistrano/recipes/deploy/dependencies.rb +0 -44
  103. data/lib/capistrano/recipes/deploy/local_dependency.rb +0 -46
  104. data/lib/capistrano/recipes/deploy/remote_dependency.rb +0 -96
  105. data/lib/capistrano/recipes/deploy/scm/accurev.rb +0 -169
  106. data/lib/capistrano/recipes/deploy/scm/base.rb +0 -192
  107. data/lib/capistrano/recipes/deploy/scm/bzr.rb +0 -86
  108. data/lib/capistrano/recipes/deploy/scm/cvs.rb +0 -151
  109. data/lib/capistrano/recipes/deploy/scm/darcs.rb +0 -85
  110. data/lib/capistrano/recipes/deploy/scm/git.rb +0 -191
  111. data/lib/capistrano/recipes/deploy/scm/mercurial.rb +0 -129
  112. data/lib/capistrano/recipes/deploy/scm/perforce.rb +0 -126
  113. data/lib/capistrano/recipes/deploy/scm/subversion.rb +0 -114
  114. data/lib/capistrano/recipes/deploy/scm.rb +0 -19
  115. data/lib/capistrano/recipes/deploy/strategy/base.rb +0 -64
  116. data/lib/capistrano/recipes/deploy/strategy/checkout.rb +0 -20
  117. data/lib/capistrano/recipes/deploy/strategy/copy.rb +0 -144
  118. data/lib/capistrano/recipes/deploy/strategy/export.rb +0 -20
  119. data/lib/capistrano/recipes/deploy/strategy/remote.rb +0 -52
  120. data/lib/capistrano/recipes/deploy/strategy/remote_cache.rb +0 -47
  121. data/lib/capistrano/recipes/deploy/strategy.rb +0 -19
  122. data/lib/capistrano/recipes/deploy/templates/maintenance.rhtml +0 -53
  123. data/lib/capistrano/recipes/deploy.rb +0 -494
  124. data/lib/capistrano/recipes/standard.rb +0 -37
  125. data/lib/capistrano/recipes/templates/maintenance.rhtml +0 -53
  126. data/lib/capistrano/recipes/upgrade.rb +0 -33
  127. data/lib/capistrano/server_definition.rb +0 -51
  128. data/lib/capistrano/shell.rb +0 -256
  129. data/lib/capistrano/ssh.rb +0 -109
  130. data/lib/capistrano/task_definition.rb +0 -69
  131. data/lib/capistrano/upload.rb +0 -146
  132. data/test/cli/execute_test.rb +0 -132
  133. data/test/cli/help_test.rb +0 -139
  134. data/test/cli/options_test.rb +0 -226
  135. data/test/cli/ui_test.rb +0 -28
  136. data/test/cli_test.rb +0 -17
  137. data/test/command_test.rb +0 -309
  138. data/test/configuration/actions/file_transfer_test.rb +0 -40
  139. data/test/configuration/actions/inspect_test.rb +0 -62
  140. data/test/configuration/actions/invocation_test.rb +0 -202
  141. data/test/configuration/callbacks_test.rb +0 -206
  142. data/test/configuration/connections_test.rb +0 -288
  143. data/test/configuration/execution_test.rb +0 -159
  144. data/test/configuration/loading_test.rb +0 -127
  145. data/test/configuration/namespace_dsl_test.rb +0 -297
  146. data/test/configuration/roles_test.rb +0 -47
  147. data/test/configuration/servers_test.rb +0 -90
  148. data/test/configuration/variables_test.rb +0 -180
  149. data/test/configuration_test.rb +0 -81
  150. data/test/deploy/scm/accurev_test.rb +0 -23
  151. data/test/deploy/scm/base_test.rb +0 -55
  152. data/test/deploy/scm/git_test.rb +0 -112
  153. data/test/deploy/strategy/copy_test.rb +0 -147
  154. data/test/extensions_test.rb +0 -69
  155. data/test/fixtures/cli_integration.rb +0 -5
  156. data/test/fixtures/config.rb +0 -5
  157. data/test/fixtures/custom.rb +0 -3
  158. data/test/gateway_test.rb +0 -167
  159. data/test/logger_test.rb +0 -123
  160. data/test/server_definition_test.rb +0 -108
  161. data/test/shell_test.rb +0 -64
  162. data/test/ssh_test.rb +0 -97
  163. data/test/task_definition_test.rb +0 -101
  164. data/test/upload_test.rb +0 -131
  165. data/test/utils.rb +0 -42
  166. 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
@@ -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