gibbler 0.8.10 → 0.10.0.pre.RC1

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.
data/lib/gibbler.rb CHANGED
@@ -1,40 +1,24 @@
1
- unless defined?(GIBBLER_LIB_HOME)
2
- GIBBLER_LIB_HOME = File.expand_path File.dirname(__FILE__)
3
- end
1
+ # frozen_string_literal: true
4
2
 
5
- %w{attic}.each do |dir|
6
- $:.unshift File.join(GIBBLER_LIB_HOME, '..', '..', dir, 'lib')
3
+ unless defined?(GIBBLER_LIB_HOME)
4
+ GIBBLER_LIB_HOME = File.expand_path File.dirname(__FILE__)
7
5
  end
8
-
9
- require 'thread'
10
- require 'attic'
11
6
  require 'digest/sha1'
12
7
 
13
- # = Gibbler
14
- #
8
+
9
+ # = Gibbler
10
+ #
15
11
  # "Hola, Tanneritos"
16
12
  #
17
- module Gibbler
18
- module VERSION
19
- def self.to_s
20
- load_config
21
- [@version[:MAJOR], @version[:MINOR], @version[:PATCH]].join('.')
22
- end
23
- alias_method :inspect, :to_s
24
- def self.load_config
25
- require 'yaml'
26
- @version ||= YAML.load_file(::File.join(GIBBLER_LIB_HOME, '..', 'VERSION.yml'))
27
- end
28
- end
29
-
13
+ class Gibbler < String
14
+
15
+
30
16
  @default_base = 16
31
17
  @secret = nil
32
18
  class << self
33
19
  attr_accessor :secret, :default_base
34
20
  end
35
-
36
- require 'gibbler/mixins'
37
-
21
+
38
22
  class Error < RuntimeError
39
23
  def initialize(obj); @obj = obj; end
40
24
  end
@@ -46,115 +30,118 @@ end
46
30
  # few digest related convenience methods.
47
31
  #
48
32
  class Gibbler::Digest < String
49
-
50
- # Return an integer assuming base is Gibbler.default_base.
51
- def to_i(base=nil)
52
- base ||= Gibbler.default_base
53
- super(base)
54
- end
55
-
56
- # Returns a string. Takes an optional base.
57
- def to_s(base=nil)
58
- base.nil? ? super() : super().to_i(Gibbler.default_base).to_s(base)
59
- end
60
-
61
- def base(base=Gibbler.default_base)
62
- self.class.new(self.to_i(Gibbler.default_base).to_s(base))
63
- end
64
-
65
- def base36
66
- base(36)
67
- end
68
-
69
- # Shorten the digest to the given (optional) length.
70
- def shorten(len=20)
71
- self[0..len-1]
72
- end
73
-
74
- # Returns the first 8 characters of itself (the digest).
75
- #
76
- # e.g.
77
- #
78
- # "kimmy".gibbler # => c8027100ecc54945ab15ddac529230e38b1ba6a1
79
- # "kimmy".gibbler.short # => c8027100
80
- #
81
- def short
82
- shorten(8)
83
- end
84
-
85
- # Returns the first 6 characters of itself (the digest).
86
- #
87
- # e.g.
88
- #
89
- # "kimmy".gibbler # => c8027100ecc54945ab15ddac529230e38b1ba6a1
90
- # "kimmy".gibbler.shorter # => c80271
91
- #
92
- def shorter
93
- shorten(6)
94
- end
95
-
96
- # Returns the first 4 characters of itself (the digest).
97
- #
98
- # e.g.
99
- #
100
- # "kimmy".gibbler # => c8027100ecc54945ab15ddac529230e38b1ba6a1
101
- # "kimmy".gibbler.tiny # => c802
102
- #
103
- def tiny
104
- shorten(4)
105
- end
106
-
107
- # Returns true when +ali+ matches +self+
108
- #
109
- # "kimmy".gibbler == "c8027100ecc54945ab15ddac529230e38b1ba6a1" # => true
110
- # "kimmy".gibbler == "c8027100" # => false
111
- #
112
- def ==(ali)
113
- return true if self.to_s == ali.to_s
114
- false
115
- end
116
-
117
- # Returns true when +g+ matches one of: +self+, +short+, +shorter+, +tiny+
118
- #
119
- # "kimmy".gibbler === "c8027100ecc54945ab15ddac529230e38b1ba6a1" # => true
120
- # "kimmy".gibbler === "c8027100" # => true
121
- # "kimmy".gibbler === "c80271" # => true
122
- # "kimmy".gibbler === "c802" # => true
123
- #
124
- def ===(g)
125
- return true if [to_s, short, shorter, tiny].member?(g.to_s)
126
- false
33
+
34
+ module InstanceMethods
35
+ # Return an integer assuming base is Gibbler.default_base.
36
+ def to_i(base=nil)
37
+ base ||= Gibbler.default_base
38
+ super(base)
39
+ end
40
+
41
+ # Returns a string. Takes an optional base.
42
+ def to_s(base=nil)
43
+ base.nil? ? super() : super().to_i(Gibbler.default_base).to_s(base)
44
+ end
45
+
46
+ def base(base=Gibbler.default_base)
47
+ v = self.to_i(Gibbler.default_base).to_s(base)
48
+ v.extend Gibbler::Digest::InstanceMethods
49
+ self.class.new v
50
+ end
51
+
52
+ def base36
53
+ base(36)
54
+ end
55
+
56
+ # Shorten the digest to the given (optional) length.
57
+ def shorten(len=20)
58
+ self[0..len-1]
59
+ end
60
+
61
+ # Returns the first 8 characters of itself (the digest).
62
+ #
63
+ # e.g.
64
+ #
65
+ # "kimmy".gibbler # => c8027100ecc54945ab15ddac529230e38b1ba6a1
66
+ # "kimmy".gibbler.short # => c8027100
67
+ #
68
+ def short
69
+ shorten(8)
70
+ end
71
+
72
+ # Returns the first 6 characters of itself (the digest).
73
+ #
74
+ # e.g.
75
+ #
76
+ # "kimmy".gibbler # => c8027100ecc54945ab15ddac529230e38b1ba6a1
77
+ # "kimmy".gibbler.shorter # => c80271
78
+ #
79
+ def shorter
80
+ shorten(6)
81
+ end
82
+
83
+ # Returns the first 4 characters of itself (the digest).
84
+ #
85
+ # e.g.
86
+ #
87
+ # "kimmy".gibbler # => c8027100ecc54945ab15ddac529230e38b1ba6a1
88
+ # "kimmy".gibbler.tiny # => c802
89
+ #
90
+ def tiny
91
+ shorten(4)
92
+ end
93
+
94
+ # Returns true when +ali+ matches +self+
95
+ #
96
+ # "kimmy".gibbler == "c8027100ecc54945ab15ddac529230e38b1ba6a1" # => true
97
+ # "kimmy".gibbler == "c8027100" # => false
98
+ #
99
+ def ==(ali)
100
+ return true if self.to_s == ali.to_s
101
+ false
102
+ end
103
+
104
+ # Returns true when +g+ matches one of: +self+, +short+, +shorter+, +tiny+
105
+ #
106
+ # "kimmy".gibbler === "c8027100ecc54945ab15ddac529230e38b1ba6a1" # => true
107
+ # "kimmy".gibbler === "c8027100" # => true
108
+ # "kimmy".gibbler === "c80271" # => true
109
+ # "kimmy".gibbler === "c802" # => true
110
+ #
111
+ def ===(g)
112
+ return true if [to_s, short, shorter, tiny].member?(g.to_s)
113
+ false
114
+ end
127
115
  end
116
+ include InstanceMethods
128
117
  end
129
118
 
130
- module Gibbler
119
+ class Gibbler < String
131
120
  module Object
132
-
121
+
133
122
  def self.included(obj)
134
123
  obj.extend Attic
135
124
  obj.attic :gibbler_cache
136
- # Backwards compatibility for <= 0.6.2
137
- obj.send :alias_method, :__gibbler_cache, :gibbler_cache
138
125
  end
139
-
126
+
140
127
  def self.gibbler_fields
141
128
  end
142
129
  def gibbler_fields
143
130
  end
144
-
145
- # Calculates a digest for the current object instance.
131
+
132
+ # Calculates a digest for the current object instance.
146
133
  # Objects that are a kind of Hash or Array are processed
147
- # recursively. The length of the returned String depends
134
+ # recursively. The length of the returned String depends
148
135
  # on the digest type. Also stores the value in the attic.
149
- #
136
+ #
150
137
  # obj.gibbler # => a5b1191a
151
138
  # obj.gibbler_cache # => a5b1191a
152
- #
139
+ #
153
140
  # Calling gibbler_cache returns the most recent digest
154
141
  # without calculation.
155
142
  #
156
143
  # If the object is frozen, this will return the value of
157
- # <tt>gibbler_cache</tt>.
144
+ # `gibbler_cache`.
158
145
  #
159
146
  def gibbler(digest_type=nil)
160
147
  #gibbler_debug caller[0]
@@ -165,9 +152,9 @@ module Gibbler
165
152
 
166
153
  # Has this object been modified?
167
154
  #
168
- # This method compares the return value from digest with the
155
+ # This method compares the return value from digest with the
169
156
  # previous value returned by gibbler (the value is stored in
170
- # the attic as <tt>gibbler_cache</tt>).
157
+ # the attic as `gibbler_cache`).
171
158
  # See Attic[http://github.com/delano/attic]
172
159
  def gibbled?
173
160
  self.gibbler_cache ||= self.gibbler
@@ -180,15 +167,15 @@ module Gibbler
180
167
  return unless Gibbler.debug?
181
168
  p args
182
169
  end
183
-
170
+
184
171
  # Creates a digest for the current state of self based on:
185
172
  # * Object#class
186
173
  # * Length of Object#name || 0
187
174
  # * Object#name || ''
188
- #
189
- # e.g. Digest::SHA1.hexdigest "Class:6:Object" #=>
190
175
  #
191
- # <b>This is a default method appropriate for only the most
176
+ # e.g. Digest::SHA1.hexdigest "Class:6:Object" #=>
177
+ #
178
+ # <b>This is a default method appropriate for only the most
192
179
  # basic objects like Class and Module.</b>
193
180
  #
194
181
  def __gibbler(digest_type=nil)
@@ -199,10 +186,10 @@ module Gibbler
199
186
  gibbler_debug klass, a, [klass, nom.size, nom]
200
187
  a
201
188
  end
202
-
189
+
203
190
  # A simple override on Object#freeze to create a digest
204
191
  # before the object is frozen. Once the object is frozen
205
- # <tt>obj.gibbler</tt> will return the cached value with
192
+ # `obj.gibbler` will return the cached value with
206
193
  # out calculation.
207
194
  def freeze()
208
195
  gibbler_debug :FREEZE, self.class, caller[0] if Gibbler.debug?
@@ -210,52 +197,84 @@ module Gibbler
210
197
  super
211
198
  self
212
199
  end
213
-
200
+
201
+ end
202
+
203
+ end
204
+
205
+ class Gibbler < String
206
+ include Gibbler::Digest::InstanceMethods
207
+ # Modify the digest type for this instance. See Gibbler.digest_type
208
+ attr_writer :digest_type
209
+ attr_reader :input
210
+ # Creates a digest from the given +input+. See Gibbler.digest.
211
+ #
212
+ # If only one argument is given and it's a digest, this will
213
+ # simply create an instance of that digest. In other words,
214
+ # it won't calculate a new digest based on that input.
215
+ def initialize *input
216
+ if input.size == 1 && Gibbler::Digest::InstanceMethods === input.first
217
+ super input.first
218
+ else
219
+ input.collect!(&:to_s)
220
+ super Gibbler.digest(input) || ''
221
+ end
214
222
  end
215
-
223
+ def digest_type
224
+ @digest_type || self.class.digest_type
225
+ end
226
+
227
+ def digest *input
228
+ replace Gibbler.digest(input, digest_type)
229
+ end
230
+
216
231
  end
217
232
 
233
+ class Gibbler < String
218
234
 
219
- module Gibbler
235
+ @debug = false
236
+ @digest_type = ::Digest::SHA1
237
+ @delimiter = ':'
220
238
 
221
- @@gibbler_debug = false
222
- @@gibbler_digest_type = ::Digest::SHA1
223
-
224
- # Specify a different digest class. The default is +Digest::SHA1+. You
225
- # could try +Digest::SHA256+ by doing this:
226
- #
227
- # Object.gibbler_digest_type = Digest::SHA256
228
- #
229
- def self.digest_type=(v)
230
- @@gibbler_digest_type = v
239
+ class << self
240
+ # Specify a different digest class. The default is +Digest::SHA1+. You
241
+ # could try +Digest::SHA256+ by doing this:
242
+ #
243
+ # Object.digest_type = Digest::SHA256
244
+ #
245
+ attr_accessor :digest_type
246
+ # The delimiter to use when joining Array values before creating a
247
+ # new digest hash. The default is ":".
248
+ attr_accessor :delimiter
249
+ # Set to true for debug output (including all digest inputs)
250
+ attr_accessor :debug
251
+ # Returns the current debug status (true or false)
252
+ def debug?; @debug != false; end
231
253
  end
232
- # Returns the current debug status (true or false)
233
- def self.debug?; @@gibbler_debug; end
234
- def self.enable_debug; @@gibbler_debug = true; end
235
- def self.disable_debug; @@gibbler_debug = false; end
236
- def self.debug=(v); @@gibbler_debug = v; end
237
- # Returns the current digest class.
238
- def self.digest_type; @@gibbler_digest_type; end
239
-
240
- # Sends +str+ to Digest::SHA1.hexdigest. If another digest class
241
- # has been specified, that class will be used instead.
254
+
255
+ # Sends +input+ to Digest::SHA1.hexdigest. If another digest class
256
+ # has been specified, that class will be used instead.
242
257
  # If Gibbler.secret is set, +str+ will be prepended with the
243
- # value.
258
+ # value.
259
+ #
260
+ # If +input+ is an Array, it will be flattened and joined.
244
261
  #
245
262
  # See: digest_type
246
- def self.digest(str, digest_type=nil)
247
- digest_type ||= @@gibbler_digest_type
248
- str = [Gibbler.secret, str].join(':') unless Gibbler.secret.nil?
249
- dig = digest_type.hexdigest(str)
263
+ def self.digest(input, digest_type=nil)
264
+ input = input.flatten.collect(&:to_s).join(delimiter) if ::Array === input
265
+ return if input.empty?
266
+ digest_type ||= @digest_type
267
+ input = [Gibbler.secret, input].join(delimiter) unless Gibbler.secret.nil?
268
+ dig = digest_type.hexdigest(input)
250
269
  dig = dig.to_i(16).to_s(Gibbler.default_base) if 16 != Gibbler.default_base
251
270
  dig
252
271
  end
253
-
272
+
254
273
  def self.gibbler_debug(*args)
255
274
  return unless Gibbler.debug?
256
275
  p args
257
276
  end
258
-
277
+
259
278
  # Raises an exception. The correct usage is to include a Gibbler::Object:
260
279
  # * Gibbler::Complex
261
280
  # * Gibbler::String
@@ -264,19 +283,20 @@ module Gibbler
264
283
  def self.included(obj)
265
284
  raise "You probably want to include Gibbler::Complex or Gibbler::Object"
266
285
  end
267
-
268
- # Creates a digest based on:
269
- # * An Array of instance variable names and values in the format: <tt>CLASS:LENGTH:VALUE</tt>
270
- # * The gibbler method is called on each element so if it is a Hash or Array etc it
286
+
287
+
288
+ # Creates a digest based on:
289
+ # * An Array of instance variable names or method names and values in the format: `CLASS:LENGTH:VALUE`
290
+ # * The gibbler method is called on each element so if it is a Hash or Array etc it
271
291
  # will be parsed recursively according to the gibbler method for that class type.
272
- # * Digest the Array of digests
273
- # * Return the digest for <tt>class:length:value</tt> where:
292
+ # * Digest the Array of digests
293
+ # * Return the digest for `class:length:value` where:
274
294
  # * "class" is equal to the current object class (e.g. FullHouse).
275
295
  # * "length" is the size of the Array of digests (which should equal
276
296
  # the number of instance variables in the object).
277
297
  # * "value" is the Array of digests joined with a colon (":").
278
298
  #
279
- # This method can be used by any class which stores values in instance variables.
299
+ # This method can be used by any class which stores values in instance variables.
280
300
  #
281
301
  # class Episodes
282
302
  # include Gibbler::Complex
@@ -285,7 +305,7 @@ module Gibbler
285
305
  #
286
306
  module Complex
287
307
  include Gibbler::Object
288
-
308
+
289
309
  def self.included(obj)
290
310
  obj.extend Attic
291
311
  obj.attic :gibbler_cache
@@ -307,7 +327,7 @@ module Gibbler
307
327
  end
308
328
  end
309
329
  end
310
-
330
+
311
331
  def gibbler_fields
312
332
  f = [self.class.gibbler_fields].compact.flatten
313
333
  if f.empty?
@@ -317,26 +337,26 @@ module Gibbler
317
337
  end
318
338
  f
319
339
  end
320
-
321
- # Creates a digest for the current state of self.
340
+
341
+ # Creates a digest for the current state of self.
322
342
  def __gibbler(digest_type=nil)
323
343
  klass = self.class
324
344
  d = []
325
345
  gibbler_debug :gibbler_fields, gibbler_fields
326
346
  gibbler_fields.each do |n|
327
- value = instance_variable_get("@#{n}")
347
+ value = respond_to?(n) ? send(n) : instance_variable_get("@#{n}")
328
348
  unless value.respond_to? :__gibbler
329
349
  gibbler_debug klass, :skipping, n
330
350
  next
331
351
  end
332
352
  d << '%s:%s:%s' % [value.class, n, value.__gibbler(digest_type)]
333
353
  end
334
- d = d.join(':').__gibbler(digest_type)
354
+ d = d.join(Gibbler.delimiter).__gibbler(digest_type)
335
355
  a = Gibbler.digest "%s:%d:%s" % [klass, d.size, d], digest_type
336
356
  gibbler_debug klass, a, [klass, d.size, d]
337
357
  a
338
358
  end
339
-
359
+
340
360
  def __gibbler_revert!
341
361
  state = self.gibbler_object self.gibbler_cache
342
362
  state.instance_variables do |n|
@@ -344,33 +364,32 @@ module Gibbler
344
364
  self.instance_variable_set v
345
365
  end
346
366
  end
347
-
348
367
  end
349
-
350
- # Creates a digest based on: <tt>CLASS:LENGTH:VALUE</tt>.
351
- # This method can be used for any class where the <tt>to_s</tt>
352
- # method returns an appropriate unique value for this instance.
353
- # It's used by default for Symbol, Class, Fixnum, and Bignum.
368
+
369
+ # Creates a digest based on: `CLASS:LENGTH:VALUE`.
370
+ # This method can be used for any class where the `to_s`
371
+ # method returns an appropriate unique value for this instance.
372
+ # It's used by default for Symbol, Class, Integer.
354
373
  # e.g.
355
- #
374
+ #
356
375
  # "str" => String:3:str => 509a839ca1744c72e37759e7684ff0daa3b61427
357
376
  # :sym => Symbol:3:sym => f3b7b3ca9529002c6826b1ef609d3583c356c8c8
358
377
  #
359
378
  # To use use method in other classes simply:
360
379
  #
361
- # class MyStringLikeClass
380
+ # class MyStringLikeClass
362
381
  # include Gibbler::String
363
382
  # end
364
383
  #
365
384
  module String
366
385
  include Gibbler::Object
367
-
386
+
368
387
  def self.included(obj)
369
388
  obj.extend Attic
370
389
  obj.attic :gibbler_cache
371
390
  end
372
-
373
- # Creates a digest for the current state of self.
391
+
392
+ # Creates a digest for the current state of self.
374
393
  def __gibbler(digest_type=nil)
375
394
  klass = self.class
376
395
  value = self.nil? ? "\0" : self.to_s
@@ -379,81 +398,81 @@ module Gibbler
379
398
  a
380
399
  end
381
400
  end
382
-
383
- # Creates a digest based on:
384
- # * parse each key, value pair into an Array containing keys: <tt>CLASS:KEY:VALUE.__gibbler</tt>
385
- # * The gibbler method is called on each element so if it is a Hash or Array etc it
401
+
402
+ # Creates a digest based on:
403
+ # * parse each key, value pair into an Array containing keys: `CLASS:KEY:VALUE.__gibbler`
404
+ # * The gibbler method is called on each element so if it is a Hash or Array etc it
386
405
  # will be parsed recursively according to the gibbler method for that class type.
387
- # * Digest the Array of digests
388
- # * Return the digest for <tt>class:length:value</tt> where:
406
+ # * Digest the Array of digests
407
+ # * Return the digest for `class:length:value` where:
389
408
  # * "class" is equal to the current object class (e.g. Hash).
390
409
  # * "length" is the size of the Array of digests (which should equal
391
410
  # the number of keys in the original Hash object).
392
411
  # * "value" is the Array of digests joined with a colon (":").
393
412
  #
394
- # This method can be used by any class with a <tt>keys</tt> method.
413
+ # This method can be used by any class with a `keys` method.
395
414
  #
396
415
  # class MyOrderedHash
397
416
  # include Gibbler::Hash
398
417
  # end
399
418
  #
400
- module Hash
419
+ module Hash
401
420
  include Gibbler::Object
402
-
421
+
403
422
  def self.included(obj)
404
423
  obj.extend Attic
405
424
  obj.attic :gibbler_cache
406
425
  end
407
-
408
- # Creates a digest for the current state of self.
426
+
427
+ # Creates a digest for the current state of self.
409
428
  def __gibbler(digest_type=nil)
410
429
  klass = self.class
411
430
  d = self.keys.sort { |a,b| a.inspect <=> b.inspect }
412
- d.collect! do |name|
431
+ d.collect! do |name|
413
432
  value = self[name]
414
433
  unless value.respond_to? :__gibbler
415
434
  gibbler_debug klass, :skipping, name
416
435
  next
417
436
  end
418
437
  '%s:%s:%s' % [value.class, name, value.__gibbler(digest_type)]
419
- end
420
- d = d.join(':').__gibbler(digest_type)
438
+ end
439
+ d = d.join(Gibbler.delimiter).__gibbler(digest_type)
421
440
  a = Gibbler.digest '%s:%s:%s' % [klass, d.size, d], digest_type
422
441
  gibbler_debug klass, a, [klass, d.size, d]
423
- a
442
+ a
424
443
  end
425
444
  end
426
-
445
+
427
446
  # Creates a digest based on:
428
- # * parse each element into an Array of digests like: <tt>CLASS:INDEX:VALUE.__gibbler</tt>
429
- # * The gibbler method is called on each element so if it is a Hash or Array etc it
430
- # will be parsed recursively according to the gibbler method for that class type.
431
- # * Digest the Array of digests
432
- # * Return the digest for <tt>class:length:value</tt> where:
447
+ # * parse each element into an Array of digests like: `CLASS:INDEX:VALUE.__gibbler`
448
+ # * The gibbler method is called on each element so if it is a Hash or Array etc it
449
+ # will be parsed recursively according to the gibbler method for that class type.
450
+ # * Digest the Array of digests
451
+ # * Return the digest for `class:length:value` where:
433
452
  # * "class" is equal to the current object class (e.g. Array).
434
453
  # * "length" is the size of the Array of digests (which should equal
435
454
  # the number of elements in the original Array object).
436
455
  # * "value" is the Array of digests joined with a colon (":").
437
456
  #
438
- # This method can be used by any class with an <tt>each</tt> method.
457
+ # This method can be used by any class with an `each` method.
439
458
  #
440
- # class MyNamedArray
459
+ # class MyNamedArray
441
460
  # include Gibbler::Array
442
461
  # end
443
462
  #
444
463
  module Array
445
464
  include Gibbler::Object
446
-
465
+
447
466
  def self.included(obj)
448
467
  obj.extend Attic
449
468
  obj.attic :gibbler_cache
450
469
  end
451
-
452
- # Creates a digest for the current state of self.
470
+
471
+ # Creates a digest for the current state of self.
453
472
  def __gibbler(digest_type=nil)
454
473
  klass = self.class
455
474
  d, index = [], 0
456
- self.each_with_index do |value,idx|
475
+ self.each_with_index do |value,idx|
457
476
  unless value.respond_to? :__gibbler
458
477
  gibbler_debug klass, :skipping, idx
459
478
  next
@@ -461,35 +480,35 @@ module Gibbler
461
480
  d << '%s:%s:%s' % [value.class, index, value.__gibbler(digest_type)]
462
481
  index += 1
463
482
  end
464
- d = d.join(':').__gibbler(digest_type)
483
+ d = d.join(Gibbler.delimiter).__gibbler(digest_type)
465
484
  a = Gibbler.digest '%s:%s:%s' % [klass, d.size, d], digest_type
466
485
  gibbler_debug klass, a, [klass, d.size, d]
467
486
  a
468
487
  end
469
488
  end
470
-
471
- # Creates a digest based on: <tt>CLASS:LENGTH:TIME</tt>.
472
- # Times are calculated based on the equivalent time in UTC.
489
+
490
+ # Creates a digest based on: `CLASS:LENGTH:TIME`.
491
+ # Times are calculated based on the equivalent time in UTC.
473
492
  # e.g.
474
- #
493
+ #
475
494
  # Time.parse('2009-08-25 16:43:53 UTC') => 73b4635f
476
495
  # Time.parse('2009-08-25 12:43:53 -04:00') => 73b4635f
477
496
  #
478
497
  # To use use method in other classes simply:
479
498
  #
480
- # class ClassLikeTime
499
+ # class ClassLikeTime
481
500
  # include Gibbler::Time
482
501
  # end
483
502
  #
484
503
  module Time
485
504
  include Gibbler::Object
486
-
505
+
487
506
  def self.included(obj)
488
507
  obj.extend Attic
489
508
  obj.attic :gibbler_cache
490
509
  end
491
-
492
- # Creates a digest for the current state of self.
510
+
511
+ # Creates a digest for the current state of self.
493
512
  def __gibbler(digest_type=nil)
494
513
  klass = self.class
495
514
  value = self.nil? ? "\0" : self.utc.strftime('%Y-%m-%d %H:%M:%S UTC')
@@ -498,29 +517,29 @@ module Gibbler
498
517
  a
499
518
  end
500
519
  end
501
-
502
- # Creates a digest based on: <tt>CLASS:LENGTH:DATETIME</tt>.
503
- # Dates are calculated based on the equivalent datetime in UTC.
520
+
521
+ # Creates a digest based on: `CLASS:LENGTH:DATETIME`.
522
+ # Dates are calculated based on the equivalent datetime in UTC.
504
523
  # e.g.
505
- #
524
+ #
506
525
  # DateTime.parse('2009-08-25T17:00:40+00:00') => ad64c769
507
526
  # DateTime.parse('2009-08-25T13:00:40-04:00') => ad64c769
508
527
  #
509
528
  # To use use method in other classes simply:
510
529
  #
511
- # class ClassLikeTime
530
+ # class ClassLikeTime
512
531
  # include Gibbler::Time
513
532
  # end
514
533
  #
515
534
  module DateTime
516
535
  include Gibbler::Object
517
-
536
+
518
537
  def self.included(obj)
519
538
  obj.extend Attic
520
539
  obj.attic :gibbler_cache
521
540
  end
522
-
523
- # Creates a digest for the current state of self.
541
+
542
+ # Creates a digest for the current state of self.
524
543
  def __gibbler(digest_type=nil)
525
544
  klass = self.class
526
545
  value = self.nil? ? "\0" : self.new_offset(0).to_s
@@ -528,36 +547,36 @@ module Gibbler
528
547
  gibbler_debug klass, a, [klass, value.size, value]
529
548
  a
530
549
  end
531
-
550
+
532
551
  end
533
-
534
- # Creates a digest based on: <tt>CLASS:EXCLUDE?:FIRST:LAST</tt>
552
+
553
+ # Creates a digest based on: `CLASS:EXCLUDE?:FIRST:LAST`
535
554
  # where EXCLUDE? is a boolean value whether the Range excludes
536
555
  # the last value (i.e. 1...100) and FIRST and LAST are the values
537
556
  # returned by Range#first and Range#last.
538
557
  # e.g.
539
- #
558
+ #
540
559
  # (1..100) => Range:false:1:100 => 54506352
541
560
  # (1...100) => Range:true:1:100 => f0cad8cc
542
561
  #
543
562
  # To use use method in other classes simply:
544
563
  #
545
- # class ClassLikeRange
564
+ # class ClassLikeRange
546
565
  # include Gibbler::Range
547
566
  # end
548
567
  #
549
568
  module Range
550
569
  include Gibbler::Object
551
-
570
+
552
571
  def self.included(obj)
553
572
  obj.extend Attic
554
573
  obj.attic :gibbler_cache
555
574
  end
556
-
557
- # Creates a digest for the current state of self.
575
+
576
+ # Creates a digest for the current state of self.
558
577
  def __gibbler(digest_type=nil)
559
578
  klass = self.class
560
- if self.nil?
579
+ if self.nil?
561
580
  first, last, exclude = "\0", "\0", "\0"
562
581
  else
563
582
  first, last, exclude = self.first, self.last, self.exclude_end?
@@ -566,10 +585,10 @@ module Gibbler
566
585
  gibbler_debug klass, a, [klass, exclude, first, last]
567
586
  a
568
587
  end
569
-
588
+
570
589
  end
571
-
572
- # Creates a digest based on: <tt>CLASS:\0</tt>
590
+
591
+ # Creates a digest based on: `CLASS:\0`
573
592
  #
574
593
  # e.g.
575
594
  #
@@ -583,7 +602,7 @@ module Gibbler
583
602
  obj.attic :gibbler_cache
584
603
  end
585
604
 
586
- # Creates a digest for the current state of self.
605
+ # Creates a digest for the current state of self.
587
606
  def __gibbler(digest_type=nil)
588
607
  klass = self.class
589
608
  a = Gibbler.digest "%s:%s" % [klass, "\0"], digest_type
@@ -591,34 +610,34 @@ module Gibbler
591
610
  a
592
611
  end
593
612
  end
594
-
595
- # Creates a digest based on: <tt>CLASS:PATHLENGTH:PATH</tt>
613
+
614
+ # Creates a digest based on: `CLASS:PATHLENGTH:PATH`
596
615
  # where PATHLENGTH is the length of the PATH string. PATH is
597
616
  # not modified in any way (it is not converted to an absolute
598
- # path).
599
- #
617
+ # path).
618
+ #
600
619
  # NOTE: You may expect this method to include other information
601
620
  # like the file contents and modified date (etc...). The reason
602
621
  # we do not is because Gibbler is concerned only about Ruby and
603
622
  # not the outside world. There are many complexities in parsing
604
623
  # file data and attributes which would make it difficult to run
605
- # across platforms and Ruby versions / engines. If you want to
624
+ # across platforms and Ruby versions / engines. If you want to
606
625
  #
607
626
  # e.g.
608
- #
627
+ #
609
628
  # File.new('.') # => c8bc8b3a
610
629
  # File.new('/tmp') # => 3af85a19
611
630
  # File.new('/tmp/') # => 92cbcb7d
612
- #
631
+ #
613
632
  module File
614
633
  include Gibbler::Object
615
-
634
+
616
635
  def self.included(obj)
617
636
  obj.extend Attic
618
637
  obj.attic :gibbler_cache
619
638
  end
620
-
621
- # Creates a digest for the current state of self.
639
+
640
+ # Creates a digest for the current state of self.
622
641
  def __gibbler(digest_type=nil)
623
642
  klass = self.class
624
643
  value = self.nil? ? "\0" : self.path
@@ -627,59 +646,13 @@ module Gibbler
627
646
  a
628
647
  end
629
648
  end
630
-
631
- ##--
632
- ## NOTE: this was used when Gibbler supported "include Gibbler". We
633
- ## now recommend the "include Gibbler::String" approach. This was an
634
- ## interesting approach so I'm keeping the code here for reference.
635
- ##def self.included(klass)
636
- ## # Find the appropriate Gibbler::* module for the inheriting class
637
- ## gibbler_module = Gibbler.const_get("#{klass}") rescue Gibbler::String
638
- ##
639
- ## # If a Gibbler module is not defined, const_get bubbles up
640
- ## # through the stack to find the constant. This will return
641
- ## # the global class (likely itself) so we enforce a default.
642
- ## gibbler_module = Gibbler::String if gibbler_module == klass
643
- ## gibbler_debug :constant, klass, gibbler_module
644
- ##
645
- ## klass.module_eval do
646
- ## include gibbler_module
647
- ## end
648
- ##
649
- ##end
650
- ##++
651
-
652
-
653
- end
654
-
655
-
656
- class NilClass; include Gibbler::Nil; end
657
- class Class; include Gibbler::Object; end
658
- class Module; include Gibbler::Object; end
659
- class Proc; include Gibbler::Object; end
660
- class String; include Gibbler::String; end
661
- class Regexp; include Gibbler::String; end
662
- class Fixnum; include Gibbler::String; end
663
- class Bignum; include Gibbler::String; end
664
- class TrueClass; include Gibbler::String; end
665
- class FalseClass; include Gibbler::String; end
666
- class Float; include Gibbler::String; end
667
- class Symbol; include Gibbler::String; end
668
- class Date; include Gibbler::String; end
669
- class Hash; include Gibbler::Hash; end
670
- class Array; include Gibbler::Array; end
671
- class Time; include Gibbler::Time; end
672
- class DateTime < Date; include Gibbler::DateTime; end
673
- class Range; include Gibbler::Range; end
674
- class File; include Gibbler::File; end
675
- class TempFile; include Gibbler::File; end
676
-
677
- # URI::Generic must be included towards the
678
- # end b/c it runs Object#freeze statically.
679
- module URI; class Generic; include Gibbler::String; end; end
680
-
681
- # Bundler calls freeze on an instance of Gem::Platform
682
- module Gem; class Platform; include Gibbler::Complex; end; end
683
-
684
649
 
650
+ end
685
651
 
652
+ class String
653
+ unless method_defined? :clear
654
+ def clear
655
+ replace ""
656
+ end
657
+ end
658
+ end