capistrano 3.4.1 → 3.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +7 -5
- data/.rubocop.yml +49 -0
- data/.travis.yml +5 -4
- data/CHANGELOG.md +72 -9
- data/CONTRIBUTING.md +61 -93
- data/DEVELOPMENT.md +122 -0
- data/Gemfile +2 -2
- data/LICENSE.txt +1 -1
- data/README.md +121 -43
- data/RELEASING.md +16 -0
- data/Rakefile +4 -1
- data/bin/cap +1 -1
- data/capistrano.gemspec +16 -21
- data/features/doctor.feature +11 -0
- data/features/step_definitions/assertions.rb +17 -17
- data/features/step_definitions/cap_commands.rb +0 -1
- data/features/step_definitions/setup.rb +12 -8
- data/features/support/env.rb +5 -5
- data/features/support/remote_command_helpers.rb +8 -6
- data/features/support/vagrant_helpers.rb +5 -4
- data/issue_template.md +21 -0
- data/lib/Capfile +5 -1
- data/lib/capistrano/all.rb +9 -10
- data/lib/capistrano/application.rb +36 -26
- data/lib/capistrano/configuration.rb +56 -41
- data/lib/capistrano/configuration/empty_filter.rb +9 -0
- data/lib/capistrano/configuration/filter.rb +18 -47
- data/lib/capistrano/configuration/host_filter.rb +30 -0
- data/lib/capistrano/configuration/null_filter.rb +9 -0
- data/lib/capistrano/configuration/plugin_installer.rb +33 -0
- data/lib/capistrano/configuration/question.rb +10 -7
- data/lib/capistrano/configuration/role_filter.rb +30 -0
- data/lib/capistrano/configuration/server.rb +22 -23
- data/lib/capistrano/configuration/servers.rb +6 -7
- data/lib/capistrano/configuration/variables.rb +136 -0
- data/lib/capistrano/defaults.rb +13 -3
- data/lib/capistrano/deploy.rb +1 -1
- data/lib/capistrano/doctor.rb +5 -0
- data/lib/capistrano/doctor/environment_doctor.rb +19 -0
- data/lib/capistrano/doctor/gems_doctor.rb +45 -0
- data/lib/capistrano/doctor/output_helpers.rb +79 -0
- data/lib/capistrano/doctor/variables_doctor.rb +66 -0
- data/lib/capistrano/dotfile.rb +1 -2
- data/lib/capistrano/dsl.rb +12 -14
- data/lib/capistrano/dsl/env.rb +11 -42
- data/lib/capistrano/dsl/paths.rb +12 -13
- data/lib/capistrano/dsl/stages.rb +2 -4
- data/lib/capistrano/dsl/task_enhancements.rb +5 -7
- data/lib/capistrano/framework.rb +1 -1
- data/lib/capistrano/git.rb +17 -9
- data/lib/capistrano/hg.rb +4 -4
- data/lib/capistrano/i18n.rb +24 -24
- data/lib/capistrano/immutable_task.rb +29 -0
- data/lib/capistrano/install.rb +1 -1
- data/lib/capistrano/plugin.rb +95 -0
- data/lib/capistrano/scm.rb +7 -20
- data/lib/capistrano/setup.rb +19 -5
- data/lib/capistrano/svn.rb +9 -5
- data/lib/capistrano/tasks/console.rake +4 -8
- data/lib/capistrano/tasks/deploy.rake +75 -62
- data/lib/capistrano/tasks/doctor.rake +19 -0
- data/lib/capistrano/tasks/framework.rake +13 -14
- data/lib/capistrano/tasks/git.rake +10 -11
- data/lib/capistrano/tasks/hg.rake +7 -7
- data/lib/capistrano/tasks/install.rake +14 -15
- data/lib/capistrano/tasks/svn.rake +7 -7
- data/lib/capistrano/templates/Capfile +3 -3
- data/lib/capistrano/templates/deploy.rb.erb +6 -5
- data/lib/capistrano/upload_task.rb +1 -1
- data/lib/capistrano/version.rb +1 -1
- data/lib/capistrano/version_validator.rb +4 -6
- data/spec/integration/dsl_spec.rb +286 -239
- data/spec/integration_spec_helper.rb +3 -5
- data/spec/lib/capistrano/application_spec.rb +22 -14
- data/spec/lib/capistrano/configuration/empty_filter_spec.rb +17 -0
- data/spec/lib/capistrano/configuration/filter_spec.rb +82 -84
- data/spec/lib/capistrano/configuration/host_filter_spec.rb +61 -0
- data/spec/lib/capistrano/configuration/null_filter_spec.rb +17 -0
- data/spec/lib/capistrano/configuration/question_spec.rb +12 -16
- data/spec/lib/capistrano/configuration/role_filter_spec.rb +64 -0
- data/spec/lib/capistrano/configuration/server_spec.rb +102 -110
- data/spec/lib/capistrano/configuration/servers_spec.rb +124 -141
- data/spec/lib/capistrano/configuration_spec.rb +150 -61
- data/spec/lib/capistrano/doctor/environment_doctor_spec.rb +44 -0
- data/spec/lib/capistrano/doctor/gems_doctor_spec.rb +61 -0
- data/spec/lib/capistrano/doctor/output_helpers_spec.rb +47 -0
- data/spec/lib/capistrano/doctor/variables_doctor_spec.rb +79 -0
- data/spec/lib/capistrano/dsl/paths_spec.rb +58 -50
- data/spec/lib/capistrano/dsl/task_enhancements_spec.rb +62 -32
- data/spec/lib/capistrano/dsl_spec.rb +6 -8
- data/spec/lib/capistrano/git_spec.rb +35 -7
- data/spec/lib/capistrano/hg_spec.rb +14 -5
- data/spec/lib/capistrano/immutable_task_spec.rb +31 -0
- data/spec/lib/capistrano/plugin_spec.rb +84 -0
- data/spec/lib/capistrano/scm_spec.rb +6 -7
- data/spec/lib/capistrano/svn_spec.rb +40 -14
- data/spec/lib/capistrano/upload_task_spec.rb +7 -7
- data/spec/lib/capistrano/version_validator_spec.rb +37 -45
- data/spec/lib/capistrano_spec.rb +2 -3
- data/spec/spec_helper.rb +8 -8
- data/spec/support/Vagrantfile +9 -10
- data/spec/support/tasks/database.rake +3 -3
- data/spec/support/tasks/fail.rake +4 -3
- data/spec/support/tasks/failed.rake +2 -2
- data/spec/support/tasks/plugin.rake +6 -0
- data/spec/support/tasks/root.rake +4 -4
- data/spec/support/test_app.rb +31 -30
- metadata +93 -14
@@ -1,55 +1,26 @@
|
|
1
|
-
require
|
1
|
+
require "capistrano/configuration"
|
2
|
+
require "capistrano/configuration/empty_filter"
|
3
|
+
require "capistrano/configuration/host_filter"
|
4
|
+
require "capistrano/configuration/null_filter"
|
5
|
+
require "capistrano/configuration/role_filter"
|
2
6
|
|
3
7
|
module Capistrano
|
4
8
|
class Configuration
|
5
9
|
class Filter
|
6
|
-
def initialize
|
7
|
-
raise "Invalid filter type #{type}" unless [:host
|
8
|
-
av = Array(values)
|
9
|
-
@
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
av.map!{|v| (v.is_a?(String) && v =~ /^(?<name>[-A-Za-z0-9.]+)(,\g<name>)*$/) ? v.split(',') : v }
|
17
|
-
av.flatten!
|
18
|
-
av.map! do |v|
|
19
|
-
case v
|
20
|
-
when Regexp then v
|
21
|
-
else
|
22
|
-
vs = v.to_s
|
23
|
-
vs =~ /^[-A-Za-z0-9.]+$/ ? vs : Regexp.new(vs)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
Regexp.union av
|
27
|
-
when :role
|
28
|
-
av.map!{|v| v.is_a?(String) ? v.split(',') : v }
|
29
|
-
av.flatten!
|
30
|
-
av.map! do |v|
|
31
|
-
case v
|
32
|
-
when Regexp then v
|
33
|
-
else
|
34
|
-
vs = v.to_s
|
35
|
-
vs =~ %r{^/(.+)/$} ? Regexp.new($1) : %r{^#{vs}$}
|
36
|
-
end
|
37
|
-
end
|
38
|
-
Regexp.union av
|
39
|
-
else
|
40
|
-
nil
|
41
|
-
end
|
10
|
+
def initialize(type, values=nil)
|
11
|
+
raise "Invalid filter type #{type}" unless [:host, :role].include? type
|
12
|
+
av = Array(values)
|
13
|
+
@strategy = case
|
14
|
+
when av.empty? then EmptyFilter.new
|
15
|
+
when av.include?(:all), av.include?("all") then NullFilter.new
|
16
|
+
when type == :host then HostFilter.new(values)
|
17
|
+
when type == :role then RoleFilter.new(values)
|
18
|
+
else NullFilter.new
|
19
|
+
end
|
42
20
|
end
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
when :none then return []
|
47
|
-
when :all then return servers
|
48
|
-
when :host
|
49
|
-
as.select {|s| @rex.match s.hostname}
|
50
|
-
when :role
|
51
|
-
as.select {|s| s.roles.any? {|r| @rex.match r} }
|
52
|
-
end
|
21
|
+
|
22
|
+
def filter(servers)
|
23
|
+
@strategy.filter servers
|
53
24
|
end
|
54
25
|
end
|
55
26
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Capistrano
|
2
|
+
class Configuration
|
3
|
+
class HostFilter
|
4
|
+
def initialize(values)
|
5
|
+
av = Array(values).dup
|
6
|
+
av.map! { |v| (v.is_a?(String) && v =~ /^(?<name>[-A-Za-z0-9.]+)(,\g<name>)*$/) ? v.split(",") : v }
|
7
|
+
av.flatten!
|
8
|
+
@rex = regex_matcher(av)
|
9
|
+
end
|
10
|
+
|
11
|
+
def filter(servers)
|
12
|
+
Array(servers).select { |s| @rex.match s.to_s }
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def regex_matcher(values)
|
18
|
+
values.map! do |v|
|
19
|
+
case v
|
20
|
+
when Regexp then v
|
21
|
+
else
|
22
|
+
vs = v.to_s
|
23
|
+
vs =~ /^[-A-Za-z0-9.]+$/ ? vs : Regexp.new(vs)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
Regexp.union values
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# Encapsulates the logic for installing plugins into Capistrano. Plugins must
|
2
|
+
# simply conform to a basic API; the PluginInstaller takes care of invoking the
|
3
|
+
# API at appropriate times.
|
4
|
+
#
|
5
|
+
# This class is not used directly; instead it is typically accessed via the
|
6
|
+
# `install_plugin` method of the Capistrano DSL.
|
7
|
+
#
|
8
|
+
module Capistrano
|
9
|
+
class Configuration
|
10
|
+
class PluginInstaller
|
11
|
+
# "Installs" a Plugin into Capistrano by loading its tasks, hooks, and
|
12
|
+
# defaults at the appropriate time. The hooks in particular can be
|
13
|
+
# skipped, if you want full control over when and how the plugin's tasks
|
14
|
+
# are executed. Simply pass `load_hooks:false` to opt out.
|
15
|
+
#
|
16
|
+
# The plugin class or instance may be provided. These are equivalent:
|
17
|
+
#
|
18
|
+
# install(Capistrano::SCM::Git)
|
19
|
+
# install(Capistrano::SCM::Git.new)
|
20
|
+
#
|
21
|
+
def install(plugin, load_hooks:true)
|
22
|
+
plugin = plugin.is_a?(Class) ? plugin.new : plugin
|
23
|
+
|
24
|
+
plugin.define_tasks
|
25
|
+
plugin.register_hooks if load_hooks
|
26
|
+
|
27
|
+
Rake::Task.define_task("load:defaults") do
|
28
|
+
plugin.set_defaults
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -1,9 +1,10 @@
|
|
1
1
|
module Capistrano
|
2
2
|
class Configuration
|
3
3
|
class Question
|
4
|
-
|
5
|
-
|
6
|
-
@
|
4
|
+
def initialize(key, default, options={})
|
5
|
+
@key = key
|
6
|
+
@default = default
|
7
|
+
@options = options
|
7
8
|
end
|
8
9
|
|
9
10
|
def call
|
@@ -12,6 +13,7 @@ module Capistrano
|
|
12
13
|
end
|
13
14
|
|
14
15
|
private
|
16
|
+
|
15
17
|
attr_reader :key, :default, :options
|
16
18
|
|
17
19
|
def ask_question
|
@@ -28,20 +30,21 @@ module Capistrano
|
|
28
30
|
|
29
31
|
def response
|
30
32
|
return @response if defined? @response
|
31
|
-
|
33
|
+
|
32
34
|
@response = (gets || "").chomp
|
33
35
|
end
|
34
|
-
|
36
|
+
|
35
37
|
def gets
|
36
38
|
if echo?
|
37
39
|
$stdin.gets
|
38
40
|
else
|
39
|
-
$stdin.noecho(&:gets).tap{ $stdout.print "\n" }
|
41
|
+
$stdin.noecho(&:gets).tap { $stdout.print "\n" }
|
40
42
|
end
|
41
43
|
rescue Errno::EIO
|
42
44
|
# when stdio gets closed
|
45
|
+
return
|
43
46
|
end
|
44
|
-
|
47
|
+
|
45
48
|
def question
|
46
49
|
I18n.t(:question, key: key, default_value: default, scope: :capistrano)
|
47
50
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Capistrano
|
2
|
+
class Configuration
|
3
|
+
class RoleFilter
|
4
|
+
def initialize(values)
|
5
|
+
av = Array(values).dup
|
6
|
+
av.map! { |v| v.is_a?(String) ? v.split(",") : v }
|
7
|
+
av.flatten!
|
8
|
+
@rex = regex_matcher(av)
|
9
|
+
end
|
10
|
+
|
11
|
+
def filter(servers)
|
12
|
+
Array(servers).select { |s| s.is_a?(String) ? false : s.roles.any? { |r| @rex.match r } }
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def regex_matcher(values)
|
18
|
+
values.map! do |v|
|
19
|
+
case v
|
20
|
+
when Regexp then v
|
21
|
+
else
|
22
|
+
vs = v.to_s
|
23
|
+
vs =~ %r{^/(.+)/$} ? Regexp.new($1) : /^#{vs}$/
|
24
|
+
end
|
25
|
+
end
|
26
|
+
Regexp.union values
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "set"
|
2
2
|
module Capistrano
|
3
3
|
class Configuration
|
4
4
|
class Server < SSHKit::Host
|
@@ -25,19 +25,21 @@ module Capistrano
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def select?(options)
|
28
|
-
options.each do |k,v|
|
29
|
-
callable = v.respond_to?(:call) ? v: ->(server){server.fetch(v)}
|
30
|
-
result =
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
28
|
+
options.each do |k, v|
|
29
|
+
callable = v.respond_to?(:call) ? v : ->(server) { server.fetch(v) }
|
30
|
+
result = \
|
31
|
+
case k
|
32
|
+
when :filter, :select
|
33
|
+
callable.call(self)
|
34
|
+
when :exclude
|
35
|
+
!callable.call(self)
|
36
|
+
else
|
37
|
+
fetch(k) == v
|
38
|
+
end
|
38
39
|
return false unless result
|
39
40
|
end
|
40
|
-
|
41
|
+
|
42
|
+
true
|
41
43
|
end
|
42
44
|
|
43
45
|
def primary
|
@@ -54,7 +56,7 @@ module Capistrano
|
|
54
56
|
end
|
55
57
|
|
56
58
|
def netssh_options
|
57
|
-
@netssh_options ||= super.merge(
|
59
|
+
@netssh_options ||= super.merge(fetch(:ssh_options) || {})
|
58
60
|
end
|
59
61
|
|
60
62
|
def roles_array
|
@@ -62,7 +64,7 @@ module Capistrano
|
|
62
64
|
end
|
63
65
|
|
64
66
|
def matches?(other)
|
65
|
-
hostname == other.hostname
|
67
|
+
hostname == other.hostname && port == other.port
|
66
68
|
end
|
67
69
|
|
68
70
|
private
|
@@ -76,18 +78,17 @@ module Capistrano
|
|
76
78
|
end
|
77
79
|
|
78
80
|
class Properties
|
79
|
-
|
80
81
|
def initialize
|
81
82
|
@properties = {}
|
82
83
|
end
|
83
84
|
|
84
85
|
def set(key, value)
|
85
86
|
pval = @properties[key]
|
86
|
-
if pval.is_a?
|
87
|
+
if pval.is_a?(Hash) && value.is_a?(Hash)
|
87
88
|
pval.merge!(value)
|
88
|
-
elsif pval.is_a?
|
89
|
+
elsif pval.is_a?(Set) && value.is_a?(Set)
|
89
90
|
pval.merge(value)
|
90
|
-
elsif pval.is_a?
|
91
|
+
elsif pval.is_a?(Array) && value.is_a?(Array)
|
91
92
|
pval.concat value
|
92
93
|
else
|
93
94
|
@properties[key] = value
|
@@ -98,8 +99,8 @@ module Capistrano
|
|
98
99
|
@properties[key]
|
99
100
|
end
|
100
101
|
|
101
|
-
def respond_to?(method,
|
102
|
-
@properties.
|
102
|
+
def respond_to?(method, _include_all=false)
|
103
|
+
@properties.key?(method)
|
103
104
|
end
|
104
105
|
|
105
106
|
def roles
|
@@ -121,11 +122,9 @@ module Capistrano
|
|
121
122
|
private
|
122
123
|
|
123
124
|
def lvalue(key)
|
124
|
-
key.to_s.chomp(
|
125
|
+
key.to_s.chomp("=").to_sym
|
125
126
|
end
|
126
|
-
|
127
127
|
end
|
128
|
-
|
129
128
|
end
|
130
129
|
end
|
131
130
|
end
|
@@ -1,6 +1,6 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require "set"
|
2
|
+
require "capistrano/configuration"
|
3
|
+
require "capistrano/configuration/filter"
|
4
4
|
|
5
5
|
module Capistrano
|
6
6
|
class Configuration
|
@@ -9,9 +9,8 @@ module Capistrano
|
|
9
9
|
|
10
10
|
def add_host(host, properties={})
|
11
11
|
new_host = Server[host]
|
12
|
-
if server = servers.find { |s| s.matches? new_host }
|
12
|
+
if (server = servers.find { |s| s.matches? new_host })
|
13
13
|
server.user = new_host.user if new_host.user
|
14
|
-
server.port = new_host.port if new_host.port
|
15
14
|
server.with(properties)
|
16
15
|
else
|
17
16
|
servers << new_host.with(properties)
|
@@ -38,12 +37,12 @@ module Capistrano
|
|
38
37
|
if block_given?
|
39
38
|
yield host, role, props
|
40
39
|
else
|
41
|
-
rps << (props || {}).merge(
|
40
|
+
rps << (props || {}).merge(role: role, hostname: host.hostname)
|
42
41
|
end
|
43
42
|
end
|
44
43
|
end
|
45
44
|
end
|
46
|
-
block_given? ? nil: rps
|
45
|
+
block_given? ? nil : rps
|
47
46
|
end
|
48
47
|
|
49
48
|
def fetch_primary(role)
|
@@ -0,0 +1,136 @@
|
|
1
|
+
module Capistrano
|
2
|
+
class Configuration
|
3
|
+
# Holds the variables assigned at Capistrano runtime via `set` and retrieved
|
4
|
+
# with `fetch`. Does internal bookkeeping to help identify user mistakes
|
5
|
+
# like spelling errors or unused variables that may lead to unexpected
|
6
|
+
# behavior. Also allows validation rules to be registered with `validate`.
|
7
|
+
class Variables
|
8
|
+
CAPISTRANO_LOCATION = File.expand_path("../..", __FILE__).freeze
|
9
|
+
IGNORED_LOCATIONS = [
|
10
|
+
"#{CAPISTRANO_LOCATION}/configuration/variables.rb:",
|
11
|
+
"#{CAPISTRANO_LOCATION}/configuration.rb:",
|
12
|
+
"#{CAPISTRANO_LOCATION}/dsl/env.rb:",
|
13
|
+
"/dsl.rb:",
|
14
|
+
"/forwardable.rb:"
|
15
|
+
].freeze
|
16
|
+
private_constant :CAPISTRANO_LOCATION, :IGNORED_LOCATIONS
|
17
|
+
|
18
|
+
def initialize(values={})
|
19
|
+
@trusted_keys = []
|
20
|
+
@fetched_keys = []
|
21
|
+
@locations = {}
|
22
|
+
@values = values
|
23
|
+
@trusted = true
|
24
|
+
end
|
25
|
+
|
26
|
+
def untrusted!
|
27
|
+
@trusted = false
|
28
|
+
yield
|
29
|
+
ensure
|
30
|
+
@trusted = true
|
31
|
+
end
|
32
|
+
|
33
|
+
def set(key, value=nil, &block)
|
34
|
+
invoke_validations(key, value, &block)
|
35
|
+
@trusted_keys << key if trusted?
|
36
|
+
remember_location(key)
|
37
|
+
values[key] = block || value
|
38
|
+
trace_set(key)
|
39
|
+
values[key]
|
40
|
+
end
|
41
|
+
|
42
|
+
def fetch(key, default=nil, &block)
|
43
|
+
fetched_keys << key
|
44
|
+
peek(key, default, &block)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Internal use only.
|
48
|
+
def peek(key, default=nil, &block)
|
49
|
+
value = fetch_for(key, default, &block)
|
50
|
+
while callable_without_parameters?(value)
|
51
|
+
value = (values[key] = value.call)
|
52
|
+
end
|
53
|
+
value
|
54
|
+
end
|
55
|
+
|
56
|
+
def fetch_for(key, default, &block)
|
57
|
+
block ? values.fetch(key, &block) : values.fetch(key, default)
|
58
|
+
end
|
59
|
+
|
60
|
+
def delete(key)
|
61
|
+
values.delete(key)
|
62
|
+
end
|
63
|
+
|
64
|
+
def validate(key, &validator)
|
65
|
+
vs = (validators[key] || [])
|
66
|
+
vs << validator
|
67
|
+
validators[key] = vs
|
68
|
+
end
|
69
|
+
|
70
|
+
def trusted_keys
|
71
|
+
@trusted_keys.dup
|
72
|
+
end
|
73
|
+
|
74
|
+
def untrusted_keys
|
75
|
+
keys - @trusted_keys
|
76
|
+
end
|
77
|
+
|
78
|
+
def keys
|
79
|
+
values.keys
|
80
|
+
end
|
81
|
+
|
82
|
+
# Keys that have been set, but which have never been fetched.
|
83
|
+
def unused_keys
|
84
|
+
keys - fetched_keys
|
85
|
+
end
|
86
|
+
|
87
|
+
# Returns an array of source file location(s) where the given key was
|
88
|
+
# assigned (i.e. where `set` was called). If the key was never assigned,
|
89
|
+
# returns `nil`.
|
90
|
+
def source_locations(key)
|
91
|
+
locations[key]
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
attr_reader :locations, :values, :fetched_keys
|
97
|
+
|
98
|
+
def trusted?
|
99
|
+
@trusted
|
100
|
+
end
|
101
|
+
|
102
|
+
def remember_location(key)
|
103
|
+
location = caller.find do |line|
|
104
|
+
IGNORED_LOCATIONS.none? { |i| line.include?(i) }
|
105
|
+
end
|
106
|
+
(locations[key] ||= []) << location
|
107
|
+
end
|
108
|
+
|
109
|
+
def callable_without_parameters?(x)
|
110
|
+
x.respond_to?(:call) && (!x.respond_to?(:arity) || x.arity == 0)
|
111
|
+
end
|
112
|
+
|
113
|
+
def validators
|
114
|
+
@validators ||= {}
|
115
|
+
end
|
116
|
+
|
117
|
+
def invoke_validations(key, value, &block)
|
118
|
+
unless value.nil? || block.nil?
|
119
|
+
raise Capistrano::ValidationError,
|
120
|
+
"Value and block both passed to Configuration#set"
|
121
|
+
end
|
122
|
+
|
123
|
+
return unless validators.key? key
|
124
|
+
|
125
|
+
validators[key].each do |validator|
|
126
|
+
validator.call(key, block || value)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def trace_set(key)
|
131
|
+
return unless fetch(:print_config_variables, false)
|
132
|
+
puts "Config variable set: #{key.inspect} => #{values[key].inspect}"
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|