hoodie 0.5.5 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
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