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.
Files changed (139) hide show
  1. checksums.yaml +7 -0
  2. data/.gitattributes +17 -0
  3. data/.gitignore +197 -0
  4. data/.rspec +2 -0
  5. data/Gemfile +22 -0
  6. data/LICENSE +201 -0
  7. data/README.md +521 -0
  8. data/Rakefile +47 -0
  9. data/garcun.gemspec +83 -0
  10. data/lib/garcon.rb +290 -0
  11. data/lib/garcon/chef/chef_helpers.rb +343 -0
  12. data/lib/garcon/chef/coerce/coercer.rb +134 -0
  13. data/lib/garcon/chef/coerce/coercions/boolean_definitions.rb +34 -0
  14. data/lib/garcon/chef/coerce/coercions/date_definitions.rb +32 -0
  15. data/lib/garcon/chef/coerce/coercions/date_time_definitions.rb +32 -0
  16. data/lib/garcon/chef/coerce/coercions/fixnum_definitions.rb +34 -0
  17. data/lib/garcon/chef/coerce/coercions/float_definitions.rb +32 -0
  18. data/lib/garcon/chef/coerce/coercions/hash_definitions.rb +29 -0
  19. data/lib/garcon/chef/coerce/coercions/integer_definitions.rb +31 -0
  20. data/lib/garcon/chef/coerce/coercions/string_definitions.rb +45 -0
  21. data/lib/garcon/chef/coerce/coercions/time_definitions.rb +32 -0
  22. data/lib/garcon/chef/handler/devreporter.rb +127 -0
  23. data/lib/garcon/chef/log.rb +64 -0
  24. data/lib/garcon/chef/node.rb +100 -0
  25. data/lib/garcon/chef/provider/civilize.rb +209 -0
  26. data/lib/garcon/chef/provider/development.rb +159 -0
  27. data/lib/garcon/chef/provider/download.rb +420 -0
  28. data/lib/garcon/chef/provider/house_keeping.rb +265 -0
  29. data/lib/garcon/chef/provider/node_cache.rb +31 -0
  30. data/lib/garcon/chef/provider/partial.rb +183 -0
  31. data/lib/garcon/chef/provider/recovery.rb +80 -0
  32. data/lib/garcon/chef/provider/zip_file.rb +271 -0
  33. data/lib/garcon/chef/resource/attribute.rb +52 -0
  34. data/lib/garcon/chef/resource/base_dsl.rb +174 -0
  35. data/lib/garcon/chef/resource/blender.rb +140 -0
  36. data/lib/garcon/chef/resource/lazy_eval.rb +66 -0
  37. data/lib/garcon/chef/resource/resource_name.rb +109 -0
  38. data/lib/garcon/chef/secret_bag.rb +204 -0
  39. data/lib/garcon/chef/validations.rb +76 -0
  40. data/lib/garcon/chef_inclusions.rb +151 -0
  41. data/lib/garcon/configuration.rb +138 -0
  42. data/lib/garcon/core_ext.rb +39 -0
  43. data/lib/garcon/core_ext/array.rb +27 -0
  44. data/lib/garcon/core_ext/binding.rb +64 -0
  45. data/lib/garcon/core_ext/boolean.rb +66 -0
  46. data/lib/garcon/core_ext/duration.rb +271 -0
  47. data/lib/garcon/core_ext/enumerable.rb +34 -0
  48. data/lib/garcon/core_ext/file.rb +127 -0
  49. data/lib/garcon/core_ext/filetest.rb +62 -0
  50. data/lib/garcon/core_ext/hash.rb +279 -0
  51. data/lib/garcon/core_ext/kernel.rb +159 -0
  52. data/lib/garcon/core_ext/lazy.rb +222 -0
  53. data/lib/garcon/core_ext/method_access.rb +243 -0
  54. data/lib/garcon/core_ext/module.rb +92 -0
  55. data/lib/garcon/core_ext/nil.rb +53 -0
  56. data/lib/garcon/core_ext/numeric.rb +44 -0
  57. data/lib/garcon/core_ext/object.rb +342 -0
  58. data/lib/garcon/core_ext/pathname.rb +152 -0
  59. data/lib/garcon/core_ext/process.rb +41 -0
  60. data/lib/garcon/core_ext/random.rb +497 -0
  61. data/lib/garcon/core_ext/string.rb +312 -0
  62. data/lib/garcon/core_ext/struct.rb +49 -0
  63. data/lib/garcon/core_ext/symbol.rb +170 -0
  64. data/lib/garcon/core_ext/time.rb +234 -0
  65. data/lib/garcon/exceptions.rb +101 -0
  66. data/lib/garcon/inflections.rb +237 -0
  67. data/lib/garcon/inflections/defaults.rb +79 -0
  68. data/lib/garcon/inflections/inflections.rb +182 -0
  69. data/lib/garcon/inflections/rules_collection.rb +37 -0
  70. data/lib/garcon/secret.rb +271 -0
  71. data/lib/garcon/stash/format.rb +114 -0
  72. data/lib/garcon/stash/journal.rb +226 -0
  73. data/lib/garcon/stash/queue.rb +83 -0
  74. data/lib/garcon/stash/serializer.rb +86 -0
  75. data/lib/garcon/stash/store.rb +435 -0
  76. data/lib/garcon/task.rb +31 -0
  77. data/lib/garcon/task/atomic.rb +151 -0
  78. data/lib/garcon/task/atomic_boolean.rb +127 -0
  79. data/lib/garcon/task/condition.rb +99 -0
  80. data/lib/garcon/task/copy_on_notify_observer_set.rb +154 -0
  81. data/lib/garcon/task/copy_on_write_observer_set.rb +153 -0
  82. data/lib/garcon/task/count_down_latch.rb +92 -0
  83. data/lib/garcon/task/delay.rb +196 -0
  84. data/lib/garcon/task/dereferenceable.rb +144 -0
  85. data/lib/garcon/task/event.rb +119 -0
  86. data/lib/garcon/task/executor.rb +275 -0
  87. data/lib/garcon/task/executor_options.rb +59 -0
  88. data/lib/garcon/task/future.rb +107 -0
  89. data/lib/garcon/task/immediate_executor.rb +84 -0
  90. data/lib/garcon/task/ivar.rb +171 -0
  91. data/lib/garcon/task/lazy_reference.rb +74 -0
  92. data/lib/garcon/task/monotonic_time.rb +69 -0
  93. data/lib/garcon/task/obligation.rb +256 -0
  94. data/lib/garcon/task/observable.rb +101 -0
  95. data/lib/garcon/task/priority_queue.rb +234 -0
  96. data/lib/garcon/task/processor_count.rb +128 -0
  97. data/lib/garcon/task/read_write_lock.rb +304 -0
  98. data/lib/garcon/task/safe_task_executor.rb +58 -0
  99. data/lib/garcon/task/single_thread_executor.rb +97 -0
  100. data/lib/garcon/task/thread_pool/cached.rb +71 -0
  101. data/lib/garcon/task/thread_pool/executor.rb +294 -0
  102. data/lib/garcon/task/thread_pool/fixed.rb +61 -0
  103. data/lib/garcon/task/thread_pool/worker.rb +90 -0
  104. data/lib/garcon/task/timer.rb +44 -0
  105. data/lib/garcon/task/timer_set.rb +194 -0
  106. data/lib/garcon/task/timer_task.rb +377 -0
  107. data/lib/garcon/task/waitable_list.rb +58 -0
  108. data/lib/garcon/utility/ansi.rb +199 -0
  109. data/lib/garcon/utility/at_random.rb +77 -0
  110. data/lib/garcon/utility/crypto.rb +292 -0
  111. data/lib/garcon/utility/equalizer.rb +146 -0
  112. data/lib/garcon/utility/faker/extensions/array.rb +22 -0
  113. data/lib/garcon/utility/faker/extensions/symbol.rb +9 -0
  114. data/lib/garcon/utility/faker/faker.rb +164 -0
  115. data/lib/garcon/utility/faker/faker/company.rb +17 -0
  116. data/lib/garcon/utility/faker/faker/hacker.rb +30 -0
  117. data/lib/garcon/utility/faker/faker/version.rb +3 -0
  118. data/lib/garcon/utility/faker/locales/en-US.yml +83 -0
  119. data/lib/garcon/utility/faker/locales/en.yml +21 -0
  120. data/lib/garcon/utility/file_helper.rb +170 -0
  121. data/lib/garcon/utility/hookers.rb +178 -0
  122. data/lib/garcon/utility/interpolation.rb +90 -0
  123. data/lib/garcon/utility/memstash.rb +364 -0
  124. data/lib/garcon/utility/misc.rb +54 -0
  125. data/lib/garcon/utility/msg_from_god.rb +62 -0
  126. data/lib/garcon/utility/retry.rb +238 -0
  127. data/lib/garcon/utility/timeout.rb +58 -0
  128. data/lib/garcon/utility/uber/builder.rb +91 -0
  129. data/lib/garcon/utility/uber/callable.rb +7 -0
  130. data/lib/garcon/utility/uber/delegates.rb +13 -0
  131. data/lib/garcon/utility/uber/inheritable_attr.rb +37 -0
  132. data/lib/garcon/utility/uber/options.rb +101 -0
  133. data/lib/garcon/utility/uber/uber_version.rb +3 -0
  134. data/lib/garcon/utility/uber/version.rb +33 -0
  135. data/lib/garcon/utility/url_helper.rb +100 -0
  136. data/lib/garcon/utils.rb +29 -0
  137. data/lib/garcon/version.rb +62 -0
  138. data/lib/garcun.rb +24 -0
  139. 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