Module: Capistrano::Configuration::Loading
- Included in:
- Capistrano::Configuration
- Defined in:
- lib/capistrano/configuration/loading.rb
Defined Under Namespace
Modules: ClassMethods
Instance Attribute Summary collapse
-
#load_paths ⇒ Object
readonly
The load paths used for locating recipe files.
Class Method Summary collapse
-
.included(base) ⇒ Object
:nodoc:.
Instance Method Summary collapse
-
#load(*args, &block) ⇒ Object
Load a configuration file or string into this configuration.
-
#require(*args) ⇒ Object
Require another file.
Instance Attribute Details
#load_paths ⇒ Object (readonly)
The load paths used for locating recipe files.
53 54 55 |
# File 'lib/capistrano/configuration/loading.rb', line 53 def load_paths @load_paths end |
Class Method Details
.included(base) ⇒ Object
:nodoc:
4 5 6 7 8 |
# File 'lib/capistrano/configuration/loading.rb', line 4 def self.included(base) #:nodoc: base.send :alias_method, :initialize_without_loading, :initialize base.send :alias_method, :initialize, :initialize_with_loading base.extend ClassMethods end |
Instance Method Details
#load(*args, &block) ⇒ Object
Load a configuration file or string into this configuration.
Usage:
load("recipe"):
Look for and load the contents of 'recipe.rb' into this
configuration.
load(:file => "recipe"):
same as above
load(:string => "set :scm, :subversion"):
Load the given string as a configuration specification.
load { ... }
Load the block in the context of the configuration.
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/capistrano/configuration/loading.rb', line 78 def load(*args, &block) = args.last.is_a?(Hash) ? args.pop : {} if block raise ArgumentError, "loading a block requires 0 arguments" unless .empty? && args.empty? load(:proc => block) elsif args.any? args.each { |arg| load .merge(:file => arg) } elsif [:file] load_from_file([:file], [:name]) elsif [:string] remember_load() unless [:reloading] instance_eval([:string], [:name] || "<eval>") elsif [:proc] remember_load() unless [:reloading] instance_eval(&[:proc]) else raise ArgumentError, "don't know how to load #{.inspect}" end end |
#require(*args) ⇒ Object
Require another file. This is identical to the standard require method, with the exception that it sets the receiver as the “current” configuration so that third-party task bundles can include themselves relative to that configuration.
This is a bit more complicated than an initial review would seem to necessitate, but the use case that complicates things is this: An advanced user wants to embed capistrano, and needs to instantiate more than one capistrano configuration at a time. They also want each configuration to require a third-party capistrano extension. Using a naive require implementation, this would allow the first configuration to successfully load the third-party extension, but the require would fail for the second configuration because the extension has already been loaded.
To work around this, we do a few things:
-
Each time a ‘require’ is invoked inside of a capistrano recipe, we remember the arguments (see “current_feature”).
-
Each time a ‘load’ is invoked inside of a capistrano recipe, and “current_feature” is not nil (meaning we are inside of a pending require) we remember the options (see “remember_load” and “recipes_per_feature”).
-
Each time a ‘require’ is invoked inside of a capistrano recipe, we check to see if this particular configuration has ever seen these arguments to require (see @loaded_features), and if not, we proceed as if the file had never been required. If the superclass’ require returns false (meaning, potentially, that the file has already been required), then we look in the recipes_per_feature collection and load any remembered recipes from there.
It’s kind of a bear, but it works, and works transparently. Note that a simpler implementation would just muck with $“, allowing files to be required multiple times, but that will cause warnings (and possibly errors) if the file to be required contains constant definitions and such, alongside (or instead of) capistrano recipe definitions.
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/capistrano/configuration/loading.rb', line 140 def require(*args) #:nodoc: # look to see if this specific configuration instance has ever seen # these arguments to require before if @loaded_features.include?(args) return false end @loaded_features << args begin original_instance, self.class.instance = self.class.instance, self original_feature, self.class.current_feature = self.class.current_feature, args result = super if !result # file has been required previously, load up the remembered recipes list = self.class.recipes_per_feature[args] || [] list.each { || load(.merge(:reloading => true)) } end return result ensure # restore the original, so that require's can be nested self.class.instance = original_instance self.class.current_feature = original_feature end end |