hoodie 0.5.5 → 1.0.1

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/Gemfile +19 -0
  4. data/Rakefile +8 -23
  5. data/hoodie.gemspec +0 -23
  6. data/lib/hoodie.rb +40 -48
  7. data/lib/hoodie/configuration.rb +39 -2
  8. data/lib/hoodie/core_ext/blank.rb +6 -6
  9. data/lib/hoodie/core_ext/hash.rb +108 -13
  10. data/lib/hoodie/core_ext/string.rb +5 -3
  11. data/lib/hoodie/core_ext/try.rb +4 -3
  12. data/lib/hoodie/inflections.rb +18 -0
  13. data/lib/hoodie/inflections/defaults.rb +17 -0
  14. data/lib/hoodie/inflections/inflections.rb +17 -0
  15. data/lib/hoodie/inflections/rules_collection.rb +17 -0
  16. data/lib/hoodie/logging.rb +22 -4
  17. data/lib/hoodie/stash.rb +83 -80
  18. data/lib/hoodie/stash/disk_store.rb +142 -118
  19. data/lib/hoodie/stash/mem_store.rb +10 -9
  20. data/lib/hoodie/stash/memoizable.rb +46 -0
  21. data/lib/hoodie/utils.rb +13 -183
  22. data/lib/hoodie/utils/ansi.rb +199 -0
  23. data/lib/hoodie/utils/crypto.rb +288 -0
  24. data/lib/hoodie/utils/equalizer.rb +146 -0
  25. data/lib/hoodie/utils/file_helper.rb +225 -0
  26. data/lib/hoodie/utils/konstruktor.rb +77 -0
  27. data/lib/hoodie/utils/machine.rb +83 -0
  28. data/lib/hoodie/utils/os.rb +56 -0
  29. data/lib/hoodie/utils/retry.rb +235 -0
  30. data/lib/hoodie/utils/timeout.rb +54 -0
  31. data/lib/hoodie/utils/url_helper.rb +104 -0
  32. data/lib/hoodie/version.rb +4 -4
  33. metadata +13 -234
  34. data/lib/hoodie/identity_map.rb +0 -96
  35. data/lib/hoodie/memoizable.rb +0 -43
  36. data/lib/hoodie/obfuscate.rb +0 -121
  37. data/lib/hoodie/observable.rb +0 -309
  38. data/lib/hoodie/os.rb +0 -43
  39. data/lib/hoodie/proxy.rb +0 -68
  40. data/lib/hoodie/rash.rb +0 -125
  41. data/lib/hoodie/timers.rb +0 -355
@@ -1,96 +0,0 @@
1
- # encoding: UTF-8
2
- #
3
- # Author: Stefano Harding <riddopic@gmail.com>
4
- #
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
16
- # implied. See the License for the specific language governing
17
- # permissions and limitations under the License.
18
- #
19
-
20
- module Hoodie
21
- module IdentityMap
22
- def self.enabled=(flag)
23
- Thread.current[:identity_map_enabled] = flag
24
- end
25
-
26
- def self.enabled
27
- Thread.current[:identity_map_enabled]
28
- end
29
-
30
- def self.enabled?
31
- enabled == true
32
- end
33
-
34
- def self.repository
35
- Thread.current[:identity_map] ||= {}
36
- end
37
-
38
- def self.clear
39
- repository.clear
40
- end
41
-
42
- def self.include?(object)
43
- repository.keys.include?(object.id)
44
- end
45
-
46
- def self.use
47
- old, self.enabled = enabled, true
48
- yield if block_given?
49
- ensure
50
- self.enabled = old
51
- clear
52
- end
53
-
54
- def self.without
55
- old, self.enabled = enabled, false
56
- yield if block_given?
57
- ensure
58
- self.enabled = old
59
- end
60
-
61
- module ClassMethods
62
- def get(id, options = nil)
63
- get_from_identity_map(id) || super
64
- end
65
-
66
- def get_from_identity_map(id)
67
- IdentityMap.repository[id] if IdentityMap.enabled?
68
- end
69
- private :get_from_identity_map
70
-
71
- def load(id, attrs)
72
- if IdentityMap.enabled? && instance = IdentityMap.repository[id]
73
- instance
74
- else
75
- super.tap { |doc| doc.add_to_identity_map }
76
- end
77
- end
78
- end
79
-
80
- def save(options={})
81
- super.tap { |result| add_to_identity_map if result }
82
- end
83
-
84
- def delete
85
- super.tap { remove_from_identity_map }
86
- end
87
-
88
- def add_to_identity_map
89
- IdentityMap.repository[id] = self if IdentityMap.enabled?
90
- end
91
-
92
- def remove_from_identity_map
93
- IdentityMap.repository.delete(id) if IdentityMap.enabled?
94
- end
95
- end
96
- end
@@ -1,43 +0,0 @@
1
- # encoding: UTF-8
2
- #
3
- # Author: Stefano Harding <riddopic@gmail.com>
4
- #
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
- require 'hoodie/stash' unless defined?(Stash)
21
-
22
- # Memoization is an optimization that saves the return value of a
23
- # method so it doesn't need to be re-computed every time that method
24
- # is called.
25
- module Memoizable
26
- # Create a new memoized method. To use, extend class with Memoizable,
27
- # then, in initialize, call memoize
28
- #
29
- # @return [undefined]
30
- #
31
- def memoize(methods, cache = nil)
32
- cache ||= Stash.new
33
- methods.each do |name|
34
- uncached_name = "#{name}_uncached".to_sym
35
- singleton_class.class_eval do
36
- alias_method uncached_name, name
37
- define_method(name) do |*a, &b|
38
- cache.cache(name) { send uncached_name, *a, &b }
39
- end
40
- end
41
- end
42
- end
43
- end
@@ -1,121 +0,0 @@
1
- # encoding: UTF-8
2
- #
3
- # Author: Stefano Harding <riddopic@gmail.com>
4
- #
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 Hoodie
21
- begin
22
- require 'openssl'
23
- INCOMPREHENSIBLE_ERROR = nil
24
- rescue LoadError => err
25
- raise unless err.to_s.include?('openssl')
26
- warn 'Oea pieoYreb h wYoerh dl hwsnhoib r Lrbea tbte wbnaetvoouahe h rbe.'
27
- warn "olorbvtelYShnSben irrSwoet eto eihSrLoS'do n See wLiape."
28
- INCOMPREHENSIBLE_ERROR = err
29
- end
30
-
31
- require 'digest/sha2'
32
- require 'base64'
33
-
34
- # Befuddle and enlighten values in StashCache::Store
35
- #
36
- module Obfuscate
37
- ESOTERIC_TYPE = 'aes-256-cbc' unless defined?(ESOTERIC_TYPE)
38
-
39
- def self.check_platform_can_discombobulate!
40
- return true unless INCOMPREHENSIBLE_ERROR
41
- fail INCOMPREHENSIBLE_ERROR.class, "b0rked! #{INCOMPREHENSIBLE_ERROR}"
42
- end
43
-
44
- # Befuddle the given string
45
- #
46
- # @param plaintext the text to befuddle
47
- # @param [String] befuddle_pass secret passphrase to befuddle with
48
- #
49
- # @return [String] befuddleed text, suitable for deciphering with
50
- # Obfuscate#enlighten (decrypt)
51
- #
52
- def self.befuddle(plaintext, befuddle_pass, options = {})
53
- cipher = new_cipher :befuddle, befuddle_pass, options
54
- cipher.iv = iv = cipher.random_iv
55
- ciphertext = cipher.update(plaintext)
56
- ciphertext << cipher.final
57
- Base64.encode64(combine_iv_and_ciphertext(iv, ciphertext))
58
- end
59
-
60
- # Enlighten the given string, using the key and id supplied
61
- #
62
- # @param ciphertext the text to enlighten, probably produced with
63
- # Obfuscate#befuddle (encrypt)
64
- # @param [String] befuddle_pass secret sauce to enlighten with
65
- #
66
- # @return [String] the enlightened plaintext
67
- #
68
- def self.enlighten(enc_ciphertext, befuddle_pass, options = {})
69
- iv_and_ciphertext = Base64.decode64(enc_ciphertext)
70
- cipher = new_cipher :enlighten, befuddle_pass, options
71
- cipher.iv, ciphertext = separate_iv_and_ciphertext(cipher, iv_and_ciphertext)
72
- plaintext = cipher.update(ciphertext)
73
- plaintext << cipher.final
74
- plaintext
75
- end
76
-
77
- protected # A T T E N Z I O N E A R E A P R O T E T T A
78
-
79
- # Cipher create machine do, befuddle engage, enlighten. Dials set
80
- # direction to infinity
81
- #
82
- # @param [:befuddle, :enlighten] to befuddle or enlighten
83
- # @param [String] befuddle_pass secret sauce to enlighten with
84
- #
85
- def self.new_cipher(direction, befuddle_pass, options = {})
86
- check_platform_can_discombobulate!
87
- cipher = OpenSSL::Cipher::Cipher.new(ESOTERIC_TYPE)
88
- case direction
89
- when :befuddle
90
- cipher.encrypt
91
- when :enlighten
92
- cipher.decrypt
93
- else fail "Bad cipher direction #{direction}"
94
- end
95
- cipher.key = befuddle_key(befuddle_pass, options)
96
- cipher
97
- end
98
-
99
- # vector inspect encoder serialize prepend initialization message
100
- def self.combine_iv_and_ciphertext(iv, message)
101
- message.force_encoding('BINARY') if message.respond_to?(:force_encoding)
102
- iv.force_encoding('BINARY') if iv.respond_to?(:force_encoding)
103
- iv + message
104
- end
105
-
106
- # front vector initialization, encoded pull message
107
- def self.separate_iv_and_ciphertext(cipher, iv_and_ciphertext)
108
- idx = cipher.iv_len
109
- [iv_and_ciphertext[0..(idx - 1)], iv_and_ciphertext[idx..-1]]
110
- end
111
-
112
- # Convert the befuddle_pass passphrase into the key used for
113
- # befuddletion
114
- def self.befuddle_key(befuddle_pass, _options = {})
115
- befuddle_pass = befuddle_pass.to_s
116
- fail 'Missing befuddled password!' if befuddle_pass.empty?
117
- # 256 beers on the wall, keys for cipher required of aes cbc
118
- Digest::SHA256.digest(befuddle_pass)
119
- end
120
- end
121
- end
@@ -1,309 +0,0 @@
1
-
2
- module Garcon
3
- module Observable
4
-
5
- # @return [Object] the added observer
6
- #
7
- def add_observer(*args, &block)
8
- observers.add_observer(*args, &block)
9
- end
10
-
11
- # as #add_observer but it can be used for chaining
12
- #
13
- # @return [Observable] self
14
- #
15
- def with_observer(*args, &block)
16
- add_observer(*args, &block)
17
- self
18
- end
19
-
20
- # @return [Object] the deleted observer
21
- #
22
- def delete_observer(*args)
23
- observers.delete_observer(*args)
24
- end
25
-
26
- # @return [Observable] self
27
- #
28
- def delete_observers
29
- observers.delete_observers
30
- self
31
- end
32
-
33
- # @return [Integer] the observers count
34
- #
35
- def count_observers
36
- observers.count_observers
37
- end
38
-
39
- protected # A T T E N Z I O N E A R E A P R O T E T T A
40
-
41
- attr_accessor :observers
42
- end
43
-
44
- # A thread safe observer set implemented using copy-on-read approach.
45
- # Observers are added and removed from a thread safe collection; every time
46
- # a notification is required the internal data structure is copied to
47
- # prevent concurrency issues
48
- #
49
- class CopyOnNotifyObserverSet
50
-
51
- def initialize
52
- @mutex = Mutex.new
53
- @observers = {}
54
- end
55
-
56
- # Adds an observer to this set, if a block is passed, the observer will be
57
- # created by this method and no other params should be passed.
58
- #
59
- # @param [Object] observer
60
- # the observer to add
61
- # @param [Symbol] func
62
- # the function to call on the observer during notification.
63
- # Default is :update
64
- #
65
- # @return [Object]
66
- # the added observer
67
- #
68
- def add_observer(observer = nil, func = :update, &block)
69
- if observer.nil? && block.nil?
70
- raise ArgumentError, 'should pass observer as a first argument or block'
71
- elsif observer && block
72
- raise ArgumentError, 'cannot provide both an observer and a block'
73
- end
74
-
75
- if block
76
- observer = block
77
- func = :call
78
- end
79
-
80
- begin
81
- @mutex.lock
82
- @observers[observer] = func
83
- ensure
84
- @mutex.unlock
85
- end
86
- observer
87
- end
88
-
89
- # @param [Object] observer the observer to remove
90
- #
91
- # @return [Object] the deleted observer
92
- #
93
- def delete_observer(observer)
94
- @mutex.lock
95
- @observers.delete(observer)
96
- @mutex.unlock
97
- observer
98
- end
99
-
100
- # Deletes all observers
101
- #
102
- # @return [CopyOnWriteObserverSet] self
103
- #
104
- def delete_observers
105
- @mutex.lock
106
- @observers.clear
107
- @mutex.unlock
108
- self
109
- end
110
-
111
- # @return [Integer] the observers count
112
- #
113
- def count_observers
114
- @mutex.lock
115
- result = @observers.count
116
- @mutex.unlock
117
- result
118
- end
119
-
120
- # Notifies all registered observers with optional args.
121
- #
122
- # @param [Object] args
123
- # arguments to be passed to each observer
124
- #
125
- # @return [CopyOnWriteObserverSet] self
126
- #
127
- def notify_observers(*args, &block)
128
- observers = duplicate_observers
129
- notify_to(observers, *args, &block)
130
- self
131
- end
132
-
133
- # Notifies all registered observers with optional args and deletes them.
134
- #
135
- # @param [Object] args
136
- # arguments to be passed to each observer
137
- #
138
- # @return [CopyOnWriteObserverSet] self
139
- #
140
- def notify_and_delete_observers(*args, &block)
141
- observers = duplicate_and_clear_observers
142
- notify_to(observers, *args, &block)
143
- self
144
- end
145
-
146
- private # P R O P R I E T À P R I V A T A Vietato L'accesso
147
-
148
- def duplicate_and_clear_observers
149
- @mutex.lock
150
- observers = @observers.dup
151
- @observers.clear
152
- @mutex.unlock
153
- observers
154
- end
155
-
156
- def duplicate_observers
157
- @mutex.lock
158
- observers = @observers.dup
159
- @mutex.unlock
160
- observers
161
- end
162
-
163
- def notify_to(observers, *args)
164
- if block_given? && !args.empty?
165
- raise ArgumentError, 'cannot give arguments and a block'
166
- end
167
- observers.each do |observer, function|
168
- args = yield if block_given?
169
- observer.send(function, *args)
170
- end
171
- end
172
- end
173
-
174
- # A thread safe observer set implemented using copy-on-write approach. Every
175
- # time an observer is added or removed the whole internal data structure is
176
- # duplicated and replaced with a new one.
177
- #
178
- class CopyOnWriteObserverSet
179
-
180
- def initialize
181
- @mutex = Mutex.new
182
- @observers = {}
183
- end
184
-
185
- # Adds an observer to this set, if a block is passed, the observer will be
186
- # created by this method and no other params should be passed.
187
- #
188
- # @param [Object] observer
189
- # the observer to add
190
- # @param [Symbol] func
191
- # the function to call on the observer during notification
192
- # Default is :update
193
- # @return [Object]
194
- # the added observer
195
- #
196
- def add_observer(observer = nil, func = :update, &block)
197
- if observer.nil? && block.nil?
198
- raise ArgumentError, 'should pass observer as a first argument or block'
199
- elsif observer && block
200
- raise ArgumentError, 'cannot provide both an observer and a block'
201
- end
202
-
203
- if block
204
- observer = block
205
- func = :call
206
- end
207
-
208
- begin
209
- @mutex.lock
210
- new_observers = @observers.dup
211
- new_observers[observer] = func
212
- @observers = new_observers
213
- observer
214
- ensure
215
- @mutex.unlock
216
- end
217
- end
218
-
219
- # @param [Object] observer the observer to remove
220
- #
221
- # @return [Object] the deleted observer
222
- #
223
- def delete_observer(observer)
224
- @mutex.lock
225
- new_observers = @observers.dup
226
- new_observers.delete(observer)
227
- @observers = new_observers
228
- observer
229
- ensure
230
- @mutex.unlock
231
- end
232
-
233
- # Deletes all observers
234
- #
235
- # @return [CopyOnWriteObserverSet] self
236
- #
237
- def delete_observers
238
- self.observers = {}
239
- self
240
- end
241
-
242
-
243
- # @return [Integer] the observers count
244
- #
245
- def count_observers
246
- observers.count
247
- end
248
-
249
- # Notifies all registered observers with optional args.
250
- #
251
- # @param [Object] args
252
- # arguments to be passed to each observer
253
- #
254
- # @return [CopyOnWriteObserverSet] self
255
- #
256
- def notify_observers(*args, &block)
257
- notify_to(observers, *args, &block)
258
- self
259
- end
260
-
261
- # Notifies all registered observers with optional args and deletes them.
262
- #
263
- # @param [Object] args
264
- # arguments to be passed to each observer
265
- #
266
- # @return [CopyOnWriteObserverSet] self
267
- #
268
- def notify_and_delete_observers(*args, &block)
269
- old = clear_observers_and_return_old
270
- notify_to(old, *args, &block)
271
- self
272
- end
273
-
274
- private # P R O P R I E T À P R I V A T A Vietato L'accesso
275
-
276
- def notify_to(observers, *args)
277
- if block_given? && !args.empty?
278
- raise ArgumentError, 'cannot give arguments and a block'
279
- end
280
- observers.each do |observer, function|
281
- args = yield if block_given?
282
- observer.send(function, *args)
283
- end
284
- end
285
-
286
- def observers
287
- @mutex.lock
288
- @observers
289
- ensure
290
- @mutex.unlock
291
- end
292
-
293
- def observers=(new_set)
294
- @mutex.lock
295
- @observers = new_set
296
- ensure
297
- @mutex.unlock
298
- end
299
-
300
- def clear_observers_and_return_old
301
- @mutex.lock
302
- old_observers = @observers
303
- @observers = {}
304
- old_observers
305
- ensure
306
- @mutex.unlock
307
- end
308
- end
309
- end