garcun 0.0.2
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/.gitattributes +17 -0
- data/.gitignore +197 -0
- data/.rspec +2 -0
- data/Gemfile +22 -0
- data/LICENSE +201 -0
- data/README.md +521 -0
- data/Rakefile +47 -0
- data/garcun.gemspec +83 -0
- data/lib/garcon.rb +290 -0
- data/lib/garcon/chef/chef_helpers.rb +343 -0
- data/lib/garcon/chef/coerce/coercer.rb +134 -0
- data/lib/garcon/chef/coerce/coercions/boolean_definitions.rb +34 -0
- data/lib/garcon/chef/coerce/coercions/date_definitions.rb +32 -0
- data/lib/garcon/chef/coerce/coercions/date_time_definitions.rb +32 -0
- data/lib/garcon/chef/coerce/coercions/fixnum_definitions.rb +34 -0
- data/lib/garcon/chef/coerce/coercions/float_definitions.rb +32 -0
- data/lib/garcon/chef/coerce/coercions/hash_definitions.rb +29 -0
- data/lib/garcon/chef/coerce/coercions/integer_definitions.rb +31 -0
- data/lib/garcon/chef/coerce/coercions/string_definitions.rb +45 -0
- data/lib/garcon/chef/coerce/coercions/time_definitions.rb +32 -0
- data/lib/garcon/chef/handler/devreporter.rb +127 -0
- data/lib/garcon/chef/log.rb +64 -0
- data/lib/garcon/chef/node.rb +100 -0
- data/lib/garcon/chef/provider/civilize.rb +209 -0
- data/lib/garcon/chef/provider/development.rb +159 -0
- data/lib/garcon/chef/provider/download.rb +420 -0
- data/lib/garcon/chef/provider/house_keeping.rb +265 -0
- data/lib/garcon/chef/provider/node_cache.rb +31 -0
- data/lib/garcon/chef/provider/partial.rb +183 -0
- data/lib/garcon/chef/provider/recovery.rb +80 -0
- data/lib/garcon/chef/provider/zip_file.rb +271 -0
- data/lib/garcon/chef/resource/attribute.rb +52 -0
- data/lib/garcon/chef/resource/base_dsl.rb +174 -0
- data/lib/garcon/chef/resource/blender.rb +140 -0
- data/lib/garcon/chef/resource/lazy_eval.rb +66 -0
- data/lib/garcon/chef/resource/resource_name.rb +109 -0
- data/lib/garcon/chef/secret_bag.rb +204 -0
- data/lib/garcon/chef/validations.rb +76 -0
- data/lib/garcon/chef_inclusions.rb +151 -0
- data/lib/garcon/configuration.rb +138 -0
- data/lib/garcon/core_ext.rb +39 -0
- data/lib/garcon/core_ext/array.rb +27 -0
- data/lib/garcon/core_ext/binding.rb +64 -0
- data/lib/garcon/core_ext/boolean.rb +66 -0
- data/lib/garcon/core_ext/duration.rb +271 -0
- data/lib/garcon/core_ext/enumerable.rb +34 -0
- data/lib/garcon/core_ext/file.rb +127 -0
- data/lib/garcon/core_ext/filetest.rb +62 -0
- data/lib/garcon/core_ext/hash.rb +279 -0
- data/lib/garcon/core_ext/kernel.rb +159 -0
- data/lib/garcon/core_ext/lazy.rb +222 -0
- data/lib/garcon/core_ext/method_access.rb +243 -0
- data/lib/garcon/core_ext/module.rb +92 -0
- data/lib/garcon/core_ext/nil.rb +53 -0
- data/lib/garcon/core_ext/numeric.rb +44 -0
- data/lib/garcon/core_ext/object.rb +342 -0
- data/lib/garcon/core_ext/pathname.rb +152 -0
- data/lib/garcon/core_ext/process.rb +41 -0
- data/lib/garcon/core_ext/random.rb +497 -0
- data/lib/garcon/core_ext/string.rb +312 -0
- data/lib/garcon/core_ext/struct.rb +49 -0
- data/lib/garcon/core_ext/symbol.rb +170 -0
- data/lib/garcon/core_ext/time.rb +234 -0
- data/lib/garcon/exceptions.rb +101 -0
- data/lib/garcon/inflections.rb +237 -0
- data/lib/garcon/inflections/defaults.rb +79 -0
- data/lib/garcon/inflections/inflections.rb +182 -0
- data/lib/garcon/inflections/rules_collection.rb +37 -0
- data/lib/garcon/secret.rb +271 -0
- data/lib/garcon/stash/format.rb +114 -0
- data/lib/garcon/stash/journal.rb +226 -0
- data/lib/garcon/stash/queue.rb +83 -0
- data/lib/garcon/stash/serializer.rb +86 -0
- data/lib/garcon/stash/store.rb +435 -0
- data/lib/garcon/task.rb +31 -0
- data/lib/garcon/task/atomic.rb +151 -0
- data/lib/garcon/task/atomic_boolean.rb +127 -0
- data/lib/garcon/task/condition.rb +99 -0
- data/lib/garcon/task/copy_on_notify_observer_set.rb +154 -0
- data/lib/garcon/task/copy_on_write_observer_set.rb +153 -0
- data/lib/garcon/task/count_down_latch.rb +92 -0
- data/lib/garcon/task/delay.rb +196 -0
- data/lib/garcon/task/dereferenceable.rb +144 -0
- data/lib/garcon/task/event.rb +119 -0
- data/lib/garcon/task/executor.rb +275 -0
- data/lib/garcon/task/executor_options.rb +59 -0
- data/lib/garcon/task/future.rb +107 -0
- data/lib/garcon/task/immediate_executor.rb +84 -0
- data/lib/garcon/task/ivar.rb +171 -0
- data/lib/garcon/task/lazy_reference.rb +74 -0
- data/lib/garcon/task/monotonic_time.rb +69 -0
- data/lib/garcon/task/obligation.rb +256 -0
- data/lib/garcon/task/observable.rb +101 -0
- data/lib/garcon/task/priority_queue.rb +234 -0
- data/lib/garcon/task/processor_count.rb +128 -0
- data/lib/garcon/task/read_write_lock.rb +304 -0
- data/lib/garcon/task/safe_task_executor.rb +58 -0
- data/lib/garcon/task/single_thread_executor.rb +97 -0
- data/lib/garcon/task/thread_pool/cached.rb +71 -0
- data/lib/garcon/task/thread_pool/executor.rb +294 -0
- data/lib/garcon/task/thread_pool/fixed.rb +61 -0
- data/lib/garcon/task/thread_pool/worker.rb +90 -0
- data/lib/garcon/task/timer.rb +44 -0
- data/lib/garcon/task/timer_set.rb +194 -0
- data/lib/garcon/task/timer_task.rb +377 -0
- data/lib/garcon/task/waitable_list.rb +58 -0
- data/lib/garcon/utility/ansi.rb +199 -0
- data/lib/garcon/utility/at_random.rb +77 -0
- data/lib/garcon/utility/crypto.rb +292 -0
- data/lib/garcon/utility/equalizer.rb +146 -0
- data/lib/garcon/utility/faker/extensions/array.rb +22 -0
- data/lib/garcon/utility/faker/extensions/symbol.rb +9 -0
- data/lib/garcon/utility/faker/faker.rb +164 -0
- data/lib/garcon/utility/faker/faker/company.rb +17 -0
- data/lib/garcon/utility/faker/faker/hacker.rb +30 -0
- data/lib/garcon/utility/faker/faker/version.rb +3 -0
- data/lib/garcon/utility/faker/locales/en-US.yml +83 -0
- data/lib/garcon/utility/faker/locales/en.yml +21 -0
- data/lib/garcon/utility/file_helper.rb +170 -0
- data/lib/garcon/utility/hookers.rb +178 -0
- data/lib/garcon/utility/interpolation.rb +90 -0
- data/lib/garcon/utility/memstash.rb +364 -0
- data/lib/garcon/utility/misc.rb +54 -0
- data/lib/garcon/utility/msg_from_god.rb +62 -0
- data/lib/garcon/utility/retry.rb +238 -0
- data/lib/garcon/utility/timeout.rb +58 -0
- data/lib/garcon/utility/uber/builder.rb +91 -0
- data/lib/garcon/utility/uber/callable.rb +7 -0
- data/lib/garcon/utility/uber/delegates.rb +13 -0
- data/lib/garcon/utility/uber/inheritable_attr.rb +37 -0
- data/lib/garcon/utility/uber/options.rb +101 -0
- data/lib/garcon/utility/uber/uber_version.rb +3 -0
- data/lib/garcon/utility/uber/version.rb +33 -0
- data/lib/garcon/utility/url_helper.rb +100 -0
- data/lib/garcon/utils.rb +29 -0
- data/lib/garcon/version.rb +62 -0
- data/lib/garcun.rb +24 -0
- metadata +680 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
#
|
|
3
|
+
# Author: Stefano Harding <riddopic@gmail.com>
|
|
4
|
+
# License: Apache License, Version 2.0
|
|
5
|
+
# Copyright: (C) 2014-2015 Stefano Harding
|
|
6
|
+
#
|
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
# you may not use this file except in compliance with the License.
|
|
9
|
+
# You may obtain a copy of the License at
|
|
10
|
+
#
|
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
#
|
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
# See the License for the specific language governing permissions and
|
|
17
|
+
# limitations under the License.
|
|
18
|
+
#
|
|
19
|
+
|
|
20
|
+
module FileTest
|
|
21
|
+
|
|
22
|
+
SEPARATOR_PATTERN = (
|
|
23
|
+
if File::ALT_SEPARATOR
|
|
24
|
+
/[#{Regexp.quote File::ALT_SEPARATOR}#{Regexp.quote File::SEPARATOR}]/
|
|
25
|
+
else
|
|
26
|
+
/#{Regexp.quote File::SEPARATOR}/
|
|
27
|
+
end
|
|
28
|
+
).freeze
|
|
29
|
+
|
|
30
|
+
module_function
|
|
31
|
+
|
|
32
|
+
# Predicate method for testing whether a path is absolute.
|
|
33
|
+
# It returns +true+ if the pathname begins with a slash.
|
|
34
|
+
def absolute?(path)
|
|
35
|
+
!relative?(path)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# The opposite of #absolute?
|
|
39
|
+
def relative?(path)
|
|
40
|
+
while r = chop_basename(path.to_s)
|
|
41
|
+
path, _ = r
|
|
42
|
+
end
|
|
43
|
+
path == ''
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# List File.split, but preserves the file separators.
|
|
47
|
+
#
|
|
48
|
+
# FileTest.chop_basename('/usr/lib') #=> ['/usr/', 'lib']
|
|
49
|
+
# FileTest.chop_basename('/') #=> nil
|
|
50
|
+
#
|
|
51
|
+
# Returns Array of `[pre-basename, basename]` or `nil`.
|
|
52
|
+
#
|
|
53
|
+
# This method is here simply to support the #relative? and #absolute? methods.
|
|
54
|
+
def chop_basename(path)
|
|
55
|
+
base = File.basename(path)
|
|
56
|
+
if /\A#{SEPARATOR_PATTERN}?\z/ =~ base
|
|
57
|
+
return nil
|
|
58
|
+
else
|
|
59
|
+
return path[0, path.rindex(base)], base
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
#
|
|
3
|
+
# Author: Stefano Harding <riddopic@gmail.com>
|
|
4
|
+
# License: Apache License, Version 2.0
|
|
5
|
+
# Copyright: (C) 2014-2015 Stefano Harding
|
|
6
|
+
#
|
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
# you may not use this file except in compliance with the License.
|
|
9
|
+
# You may obtain a copy of the License at
|
|
10
|
+
#
|
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
#
|
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
# See the License for the specific language governing permissions and
|
|
17
|
+
# limitations under the License.
|
|
18
|
+
#
|
|
19
|
+
|
|
20
|
+
class Hash
|
|
21
|
+
|
|
22
|
+
# Turn a hash into a method arguments.
|
|
23
|
+
#
|
|
24
|
+
# h = { :list => [1,2], :base => "HI" }
|
|
25
|
+
#
|
|
26
|
+
# Without an argument field.
|
|
27
|
+
#
|
|
28
|
+
# h.argumentize #=> [ { :list => [1,2], :base => "HI" } ]
|
|
29
|
+
#
|
|
30
|
+
# With an argument field.
|
|
31
|
+
#
|
|
32
|
+
# h.argumentize(:list) #=> [ 1, 2, { :base => "HI" } ]
|
|
33
|
+
# h.argumentize(:base) #=> [ "HI", { :list => [1,2] } ]
|
|
34
|
+
#
|
|
35
|
+
def argumentize(args_field = nil)
|
|
36
|
+
config = dup
|
|
37
|
+
if args_field
|
|
38
|
+
args = [config.delete(args_field)].flatten.compact
|
|
39
|
+
else
|
|
40
|
+
args = []
|
|
41
|
+
end
|
|
42
|
+
args << config
|
|
43
|
+
return args
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# A method to convert a Hash into a Struct.
|
|
47
|
+
#
|
|
48
|
+
# h = { :name => "Earl", "age" => 20, "sex" => "lots", "worries" => "none" }
|
|
49
|
+
# s = h.to_struct("Foo")
|
|
50
|
+
#
|
|
51
|
+
def to_struct(struct_name)
|
|
52
|
+
Struct.new(struct_name,*keys).new(*values)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Get or set state of object. You can think of #object_state as an in-code
|
|
56
|
+
# form of marshalling.
|
|
57
|
+
#
|
|
58
|
+
def object_state(data=nil)
|
|
59
|
+
data ? replace(data) : dup
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# A hash is blank if it's empty:
|
|
63
|
+
#
|
|
64
|
+
# @example
|
|
65
|
+
# {}.blank? # => true
|
|
66
|
+
# { key: 'value' }.blank? # => false
|
|
67
|
+
#
|
|
68
|
+
# @api public
|
|
69
|
+
alias_method :blank?, :empty?
|
|
70
|
+
|
|
71
|
+
# Returns a compacted copy (contains no key/value pairs having
|
|
72
|
+
# nil? values)
|
|
73
|
+
#
|
|
74
|
+
# @example
|
|
75
|
+
# hash = { a: 100, b: nil, c: false, d: '' }
|
|
76
|
+
# hash.compact # => { a: 100, c: false, d: '' }
|
|
77
|
+
# hash # => { a: 100, b: nil, c: false, d: '' }
|
|
78
|
+
#
|
|
79
|
+
# @return [Hash]
|
|
80
|
+
#
|
|
81
|
+
# @api public
|
|
82
|
+
def compact
|
|
83
|
+
select { |_, value| !value.nil? }
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Returns a new hash with all keys converted using the block operation.
|
|
87
|
+
#
|
|
88
|
+
# @example
|
|
89
|
+
# hash = { name: 'Tiggy', age: '15' }
|
|
90
|
+
# hash.transform_keys{ |key| key.to_s.upcase }
|
|
91
|
+
# # => { "AGE" => "15", "NAME" => "Tiggy" }
|
|
92
|
+
#
|
|
93
|
+
# @return [Hash]
|
|
94
|
+
#
|
|
95
|
+
# @api public
|
|
96
|
+
def transform_keys
|
|
97
|
+
enum_for(:transform_keys) unless block_given?
|
|
98
|
+
result = self.class.new
|
|
99
|
+
each_key do |key|
|
|
100
|
+
result[yield(key)] = self[key]
|
|
101
|
+
end
|
|
102
|
+
result
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Returns a new hash, recursively converting all keys by the
|
|
106
|
+
# block operation.
|
|
107
|
+
#
|
|
108
|
+
# @return [Hash]
|
|
109
|
+
#
|
|
110
|
+
def recursively_transform_keys(&block)
|
|
111
|
+
_recursively_transform_keys_in_object(self, &block)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Returns a new hash with all keys downcased and converted
|
|
115
|
+
# to symbols.
|
|
116
|
+
#
|
|
117
|
+
# @return [Hash]
|
|
118
|
+
#
|
|
119
|
+
def normalize_keys
|
|
120
|
+
transform_keys { |key| key.downcase.to_sym rescue key }
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Returns a new Hash, recursively downcasing and converting all
|
|
124
|
+
# keys to symbols.
|
|
125
|
+
#
|
|
126
|
+
# @return [Hash]
|
|
127
|
+
#
|
|
128
|
+
def recursively_normalize_keys
|
|
129
|
+
recursively_transform_keys { |key| key.downcase.to_sym rescue key }
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Returns a new hash with all keys converted to symbols.
|
|
133
|
+
#
|
|
134
|
+
# @return [Hash]
|
|
135
|
+
#
|
|
136
|
+
def symbolize_keys
|
|
137
|
+
transform_keys { |key| key.to_sym rescue key }
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Returns a new Hash, recursively converting all keys to symbols.
|
|
141
|
+
#
|
|
142
|
+
# @return [Hash]
|
|
143
|
+
#
|
|
144
|
+
def recursively_symbolize_keys
|
|
145
|
+
recursively_transform_keys { |key| key.to_sym rescue key }
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Returns a new hash with all keys converted to strings.
|
|
149
|
+
#
|
|
150
|
+
# @return [Hash]
|
|
151
|
+
#
|
|
152
|
+
def stringify_keys
|
|
153
|
+
transform_keys { |key| key.to_s rescue key }
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# Returns a new Hash, recursively converting all keys to strings.
|
|
157
|
+
#
|
|
158
|
+
# @return [Hash]
|
|
159
|
+
#
|
|
160
|
+
def recursively_stringify_key
|
|
161
|
+
recursively_transform_keys { |key| key.to_s rescue key }
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Returns a new hash with all keys converted to strings and the
|
|
165
|
+
# first letter capitalized.
|
|
166
|
+
#
|
|
167
|
+
# @return [Hash]
|
|
168
|
+
#
|
|
169
|
+
def capitalize_keys
|
|
170
|
+
transform_keys { |key| key.to_s.capitalize rescue key }
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# Returns a new Hash, recursively converting all keys to strings
|
|
174
|
+
# and the first letter capitalized.
|
|
175
|
+
#
|
|
176
|
+
# @return [Hash]
|
|
177
|
+
#
|
|
178
|
+
def recursively_capitalize_key
|
|
179
|
+
recursively_transform_keys { |key| key.to_s.capitalize rescue key }
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Creates a new hash from two separate arrays, a +keys+ array and
|
|
183
|
+
# a +values+ array.
|
|
184
|
+
#
|
|
185
|
+
# @example
|
|
186
|
+
# Hash.zip(['a','b','c'], [1,2,3])
|
|
187
|
+
# # => { "a"=>1, "b"=>2, "c"=>3 }
|
|
188
|
+
#
|
|
189
|
+
def zip(col1, col2)
|
|
190
|
+
col1.zip(col2).inject({}) { |r, i| r[i[0]] = i[1]; r }
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# Create a hash with *only* key/value pairs in receiver and +allowed+
|
|
194
|
+
#
|
|
195
|
+
# { :one => 1, :two => 2, :three => 3 }.only(:one) # => { :one => 1 }
|
|
196
|
+
#
|
|
197
|
+
# @param [Array[String, Symbol]] *allowed The hash keys to include.
|
|
198
|
+
#
|
|
199
|
+
# @return [Hash] A new hash with only the selected keys.
|
|
200
|
+
#
|
|
201
|
+
# @api public
|
|
202
|
+
def only(*allowed)
|
|
203
|
+
hash = {}
|
|
204
|
+
allowed.each {|k| hash[k] = self[k] if self.has_key?(k) }
|
|
205
|
+
hash
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# Create a hash with all key/value pairs in receiver *except* +rejected+
|
|
209
|
+
#
|
|
210
|
+
# { :one => 1, :two => 2, :three => 3 }.except(:one)
|
|
211
|
+
# # => { :two => 2, :three => 3 }
|
|
212
|
+
#
|
|
213
|
+
# @param [Array[String, Symbol]] *rejected The hash keys to exclude.
|
|
214
|
+
#
|
|
215
|
+
# @return [Hash] A new hash without the selected keys.
|
|
216
|
+
#
|
|
217
|
+
# @api public
|
|
218
|
+
def except(*rejected)
|
|
219
|
+
hash = self.dup
|
|
220
|
+
rejected.each {|k| hash.delete(k) }
|
|
221
|
+
hash
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
class UndefinedPathError < StandardError; end
|
|
225
|
+
# Recursively searchs a nested datastructure for a key and returns
|
|
226
|
+
# the value. If a block is provided its value will be returned if
|
|
227
|
+
# the key does not exist
|
|
228
|
+
#
|
|
229
|
+
# @example
|
|
230
|
+
# options = { server: { location: { row: { rack: 34 } } } }
|
|
231
|
+
# options.recursive_fetch :server, :location, :row, :rack
|
|
232
|
+
# # => 34
|
|
233
|
+
# options.recursive_fetch(:non_existent_key) { 'default' }
|
|
234
|
+
# # => "default"
|
|
235
|
+
#
|
|
236
|
+
# @return [Hash, Array, String] value for key
|
|
237
|
+
#
|
|
238
|
+
def recursive_fetch(*args, &block)
|
|
239
|
+
args.reduce(self) do |obj, arg|
|
|
240
|
+
begin
|
|
241
|
+
arg = Integer(arg) if obj.is_a? Array
|
|
242
|
+
obj.fetch(arg)
|
|
243
|
+
rescue ArgumentError, IndexError, NoMethodError => e
|
|
244
|
+
break block.call(arg) if block
|
|
245
|
+
raise UndefinedPathError,
|
|
246
|
+
"Could not fetch path (#{args.join(' > ')}) at #{arg}", e.backtrace
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
def recursive_merge(other)
|
|
252
|
+
hash = self.dup
|
|
253
|
+
other.each do |key, value|
|
|
254
|
+
myval = self[key]
|
|
255
|
+
if value.is_a?(Hash) && myval.is_a?(Hash)
|
|
256
|
+
hash[key] = myval.recursive_merge(value)
|
|
257
|
+
else
|
|
258
|
+
hash[key] = value
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
hash
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
private # P R O P R I E T À P R I V A T A divieto di accesso
|
|
265
|
+
|
|
266
|
+
# support methods for recursively transforming nested hashes and arrays
|
|
267
|
+
def _recursively_transform_keys_in_object(object, &block)
|
|
268
|
+
case object
|
|
269
|
+
when Hash
|
|
270
|
+
object.each_with_object({}) do |(key, val), result|
|
|
271
|
+
result[yield(key)] = _recursively_transform_keys_in_object(val, &block)
|
|
272
|
+
end
|
|
273
|
+
when Array
|
|
274
|
+
object.map { |e| _recursively_transform_keys_in_object(e, &block) }
|
|
275
|
+
else
|
|
276
|
+
object
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
end
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
#
|
|
3
|
+
# Author: Stefano Harding <riddopic@gmail.com>
|
|
4
|
+
# License: Apache License, Version 2.0
|
|
5
|
+
# Copyright: (C) 2014-2015 Stefano Harding
|
|
6
|
+
#
|
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
# you may not use this file except in compliance with the License.
|
|
9
|
+
# You may obtain a copy of the License at
|
|
10
|
+
#
|
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
#
|
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
# See the License for the specific language governing permissions and
|
|
17
|
+
# limitations under the License.
|
|
18
|
+
#
|
|
19
|
+
|
|
20
|
+
# Add #maybe
|
|
21
|
+
module Kernel
|
|
22
|
+
|
|
23
|
+
# Random generator that returns true or false. Can also take a block that has
|
|
24
|
+
# a 50/50 chance to being executed.
|
|
25
|
+
#
|
|
26
|
+
def maybe(chance = 0.5, &block)
|
|
27
|
+
if block
|
|
28
|
+
yield if rand < chance
|
|
29
|
+
else
|
|
30
|
+
rand < chance
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Like #respond_to? but returns the result of the call if it does respond.
|
|
35
|
+
#
|
|
36
|
+
# class RespondExample
|
|
37
|
+
# def f; "f"; end
|
|
38
|
+
# end
|
|
39
|
+
#
|
|
40
|
+
# x = RespondExample.new
|
|
41
|
+
# x.respond(:f) # => "f"
|
|
42
|
+
# x.respond(:g) # => nil
|
|
43
|
+
#
|
|
44
|
+
# This method was known as #try until Rails defined #try
|
|
45
|
+
# to be something more akin to #ergo.
|
|
46
|
+
#
|
|
47
|
+
def respond(sym = nil, *args, &blk)
|
|
48
|
+
if sym
|
|
49
|
+
return nil unless respond_to?(sym)
|
|
50
|
+
__send__(sym, *args, &blk)
|
|
51
|
+
else
|
|
52
|
+
MsgFromGod.new(&method(:respond).to_proc)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# The opposite of #nil?.
|
|
57
|
+
#
|
|
58
|
+
# "hello".not_nil? # -> true
|
|
59
|
+
# nil.not_nil? # -> false
|
|
60
|
+
#
|
|
61
|
+
def not_nil?
|
|
62
|
+
! nil?
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Temporarily set variables while yielding a block, then return the
|
|
66
|
+
# variables to their original settings when complete.
|
|
67
|
+
#
|
|
68
|
+
# temporarily('$VERBOSE'=>false) do
|
|
69
|
+
# $VERBOSE.assert == false
|
|
70
|
+
# end
|
|
71
|
+
#
|
|
72
|
+
def temporarily(settings)
|
|
73
|
+
cache = {}
|
|
74
|
+
settings.each do |var, val|
|
|
75
|
+
cache[var] = eval("#{var}")
|
|
76
|
+
eval("proc{ |v| #{var} = v }").call(val)
|
|
77
|
+
end
|
|
78
|
+
yield
|
|
79
|
+
ensure
|
|
80
|
+
cache.each do |var, val|
|
|
81
|
+
eval("proc{ |v| #{var} = v }").call(val)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Invokes the method identified by the symbol +method+, passing it any
|
|
86
|
+
# arguments and/or the block specified, just like the regular Ruby
|
|
87
|
+
# `Object#send` does.
|
|
88
|
+
#
|
|
89
|
+
# *Unlike* that method however, a `NoMethodError` exception will *not*
|
|
90
|
+
# be raised and +nil+ will be returned instead, if the receiving object
|
|
91
|
+
# is a `nil` object or NilClass.
|
|
92
|
+
#
|
|
93
|
+
# For example, without try
|
|
94
|
+
#
|
|
95
|
+
# @example = Struct.new(:name).new("bob")
|
|
96
|
+
#
|
|
97
|
+
# @example && @example.name
|
|
98
|
+
#
|
|
99
|
+
# or:
|
|
100
|
+
#
|
|
101
|
+
# @example ? @example.name : nil
|
|
102
|
+
#
|
|
103
|
+
# But with try
|
|
104
|
+
#
|
|
105
|
+
# @example.try(:name) #=> "bob"
|
|
106
|
+
#
|
|
107
|
+
# or
|
|
108
|
+
#
|
|
109
|
+
# @example.try.name #=> "bob"
|
|
110
|
+
#
|
|
111
|
+
# It also accepts arguments and a block, for the method it is trying:
|
|
112
|
+
#
|
|
113
|
+
# @people.try(:collect){ |p| p.name }
|
|
114
|
+
#
|
|
115
|
+
def try(method=nil, *args, &block)
|
|
116
|
+
if method
|
|
117
|
+
__send__(method, *args, &block)
|
|
118
|
+
else
|
|
119
|
+
self
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Parse a caller string and break it into its components,
|
|
124
|
+
# returning an array composed of:
|
|
125
|
+
#
|
|
126
|
+
# * file (String)
|
|
127
|
+
# * lineno (Integer)
|
|
128
|
+
# * method (Symbol)
|
|
129
|
+
#
|
|
130
|
+
# For example, from irb
|
|
131
|
+
#
|
|
132
|
+
# callstack(1)
|
|
133
|
+
#
|
|
134
|
+
# _produces_ ...
|
|
135
|
+
#
|
|
136
|
+
# [["(irb)", 2, :irb_binding],
|
|
137
|
+
# ["/usr/lib/ruby/1.8/irb/workspace.rb", 52, :irb_binding],
|
|
138
|
+
# ["/usr/lib/ruby/1.8/irb/workspace.rb", 52, nil]]
|
|
139
|
+
#
|
|
140
|
+
# Note: If the user decides to redefine caller() to output data
|
|
141
|
+
# in a different format, _prior_ to requiring this, then the
|
|
142
|
+
# results will be indeterminate.
|
|
143
|
+
#
|
|
144
|
+
def callstack(level = 1)
|
|
145
|
+
call_str_array = pp_callstack(level)
|
|
146
|
+
stack = []
|
|
147
|
+
call_str_array.each{ |call_str|
|
|
148
|
+
file, lineno, method = call_str.split(':')
|
|
149
|
+
if method =~ /in `(.*)'/ then
|
|
150
|
+
method = $1.intern()
|
|
151
|
+
end
|
|
152
|
+
stack << [file, lineno.to_i, method]
|
|
153
|
+
}
|
|
154
|
+
stack
|
|
155
|
+
end
|
|
156
|
+
alias_method :call_stack, :callstack
|
|
157
|
+
alias_method :pp_callstack, :caller
|
|
158
|
+
alias_method :pp_call_stack, :caller
|
|
159
|
+
end
|