capistrano 2.1.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
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