gibbler 0.7.7 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.txt +7 -0
- data/README.rdoc +40 -40
- data/gibbler.gemspec +1 -1
- data/lib/gibbler.rb +68 -52
- metadata +2 -2
data/CHANGES.txt
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
GIBBLER, CHANGES
|
2
2
|
|
3
|
+
#### 0.8.0 (2010-04-??) ###############################
|
4
|
+
|
5
|
+
* CHANGE: Gibber::Object#__gibbler now accepts only 1 optional argument: digest_type
|
6
|
+
* ADDED: Gibbler::Digest#to_i which assumes base 16
|
7
|
+
* ADDED: Gibbler::Object#gibbler now accepts a digest type
|
8
|
+
* ADDED: Gibbler::Digest#to_s and #base can take a base argument
|
9
|
+
|
3
10
|
#### 0.7.7 (2010-03-29) ###############################
|
4
11
|
|
5
12
|
* ADDED: Gibbler::Digest#shorten
|
data/README.rdoc
CHANGED
@@ -1,12 +1,14 @@
|
|
1
|
-
= Gibbler - v0.
|
1
|
+
= Gibbler - v0.8
|
2
2
|
|
3
3
|
Git-like hashes and history for Ruby objects for Ruby 1.8, 1.9 and JRuby.
|
4
4
|
|
5
5
|
Check out the screencast[http://www.rubypulse.com/episode-0.3-gibbler.html] created by Alex Peuchert.
|
6
6
|
|
7
|
-
|
7
|
+
== Some things to keep in mind
|
8
8
|
|
9
|
-
|
9
|
+
* Digest calculation may change between minor releases (as it did between 0.6 and 0.7)
|
10
|
+
* Gibbler history is not suitable for very large objects since it keeps complete copies of the object in memory. This is a very early implementation of this feature so don't rely on it for production code.
|
11
|
+
* Don't forget to enjoy what you do!
|
10
12
|
|
11
13
|
|
12
14
|
== Example 1 -- Basic Usage
|
@@ -88,7 +90,7 @@ If you have control over the namespaces of your objects, you can use the method
|
|
88
90
|
a.changed? # => true
|
89
91
|
|
90
92
|
|
91
|
-
The history methods also have aliases which remove the "gibbler_".
|
93
|
+
The history methods also have aliases which remove the "gibbler_" prefix.
|
92
94
|
|
93
95
|
require 'gibbler/aliases'
|
94
96
|
require 'gibbler/history'
|
@@ -99,6 +101,40 @@ The history methods also have aliases which remove the "gibbler_".
|
|
99
101
|
a.revert!
|
100
102
|
# etc...
|
101
103
|
|
104
|
+
== Example 4 -- Different Digest types
|
105
|
+
|
106
|
+
By default Gibbler creates SHA1 hashes. You can change this globally or per instance.
|
107
|
+
|
108
|
+
require 'gibbler'
|
109
|
+
|
110
|
+
Gibbler.digest_type = Digest::MD5
|
111
|
+
|
112
|
+
:kimmy.gibbler # => 0c61ff17f46223f355759934154d5dcb
|
113
|
+
|
114
|
+
:kimmy.gibbler(Digest::SHA1) # => 52be7494a602d85ff5d8a8ab4ffe7f1b171587df
|
115
|
+
|
116
|
+
|
117
|
+
In Jruby, you can grab the digest types from the openssl library.
|
118
|
+
|
119
|
+
require 'openssl'
|
120
|
+
|
121
|
+
Gibbler.digest_type = OpenSSL::Digest::SHA256
|
122
|
+
|
123
|
+
:kimmy.gibbler # => 1069428e6273cf329436c3dce9b680d4d4e229d7b7...
|
124
|
+
|
125
|
+
|
126
|
+
== Example 5 -- All your base
|
127
|
+
|
128
|
+
require 'gibbler'
|
129
|
+
|
130
|
+
:kimmy.gibbler # => 52be7494a602d85ff5d8a8ab4ffe7f1b171587df
|
131
|
+
:kimmy.gibbler.base(16) # => 52be7494a602d85ff5d8a8ab4ffe7f1b171587df
|
132
|
+
:kimmy.gibbler.base(36) # => 9nydr6mpv6w4k8ngo3jtx0jz1n97h7j
|
133
|
+
|
134
|
+
:kimmy.gibbler.base(10) # => 472384540402900668368761869477227308873774630879
|
135
|
+
:kimmy.gibbler.to_i # => 472384540402900668368761869477227308873774630879
|
136
|
+
|
137
|
+
|
102
138
|
== Supported Classes
|
103
139
|
|
104
140
|
Gibbler methods are available only to the classes which explicitly include them (see RDocs[http://delano.github.com/gibbler] for details on which classes are supported by default). You can also extend custom objects:
|
@@ -127,42 +163,6 @@ Gibbler::String creates a digest based on the name of the class and the output o
|
|
127
163
|
As of 0.7 all Proc objects have the same digest: <tt>12075835e94be34438376cd7a54c8db7e746f15d</tt>.
|
128
164
|
|
129
165
|
|
130
|
-
== ALPHA Notice
|
131
|
-
|
132
|
-
This code is fresh so the interface may change. Some things to keep in mind:
|
133
|
-
|
134
|
-
* Gibbler history is not suitable for very large objects since it keeps complete copies of the object in memory. This is a very early implementation of this feature so don't rely on it for production code.
|
135
|
-
* Digest calculation may change between minor releases (e.g. 0.6 to 0.7, etc)
|
136
|
-
* Don't forget to enjoy what you do!
|
137
|
-
|
138
|
-
|
139
|
-
== News
|
140
|
-
|
141
|
-
=== 2009-10-07: Digest calculation for Proc objects has changed.
|
142
|
-
|
143
|
-
Proc digests are now based on the name of the class and the value of Proc#name (if available). Procs or objects containing Procs will have different digests than those created in previous releases.
|
144
|
-
|
145
|
-
After much deliberation, I realized that Gibbler cares about the data and not the code. Procs are code, but a reference to a Proc in an instance variable is data. With this change all Proc objects have the same digest. This decision has the side benefit of increasing compatibility between Ruby 1.8, 1.9 & JRuby.
|
146
|
-
|
147
|
-
This is the only change between 0.6.4 and 0.7.0 so if you prefer the previous calculation for Procs you can find it in that version.
|
148
|
-
|
149
|
-
Happy Digesting!
|
150
|
-
|
151
|
-
=== 2009-10-07: Support for freezing and Regexp
|
152
|
-
|
153
|
-
In 0.6.4, all Gibbler objects will create a new digest when <tt>obj.freeze</tt> is called. All subsequent calls to <tt>obj.gibbler</tt> will return the most recent digest without having to run the calculation again.
|
154
|
-
|
155
|
-
I've also added support for Regexp out of the box.
|
156
|
-
|
157
|
-
=== 2009-07-20: Digest change for instances of Class, Module, and Proc
|
158
|
-
|
159
|
-
Digest calculation has changed for Class, Module, and Proc objects. Digests created with Gibbler 0.5.x and earlier will not match the ones created by 0.6.
|
160
|
-
|
161
|
-
* Class and Module objects were calculating digests based on the output of <tt>self.to_s</tt>. This was a problem because that string contains a memory address which can change arbitrarily. The new calculation is based on the object class, the length of name, and the name itself. e.g. <tt>"Class:6:Object" # => '5620e4a8b10ec6830fece61d33f5d3e9a349b4c2'</tt>
|
162
|
-
* Proc objects were including the return value of <tt>self.binding</tt> in the digest calculation. This is not reliable because the binding includes an arbitrary address. The new calculation is based on the class name, the arity, and whether it was created with a lambda.
|
163
|
-
|
164
|
-
Also note that this change affects the digests for Hashes and Arrays that contain instances of Class, Module, or Proc.
|
165
|
-
|
166
166
|
|
167
167
|
== Known Issues
|
168
168
|
|
data/gibbler.gemspec
CHANGED
data/lib/gibbler.rb
CHANGED
@@ -15,7 +15,7 @@ require 'digest/sha1'
|
|
15
15
|
# "Hola, Tanneritos"
|
16
16
|
#
|
17
17
|
module Gibbler
|
18
|
-
VERSION = "0.
|
18
|
+
VERSION = "0.8.0"
|
19
19
|
|
20
20
|
require 'gibbler/mixins'
|
21
21
|
|
@@ -33,8 +33,23 @@ end
|
|
33
33
|
#
|
34
34
|
class Gibbler::Digest < String
|
35
35
|
|
36
|
+
# Return an integer assuming base 16.
|
37
|
+
def to_i(base=nil)
|
38
|
+
base ||= 16
|
39
|
+
super(base)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns a string. Takes an optional base.
|
43
|
+
def to_s(base=nil)
|
44
|
+
base.nil? ? super() : super().to_i(16).to_s(base)
|
45
|
+
end
|
46
|
+
|
47
|
+
def base(base=16)
|
48
|
+
self.class.new(self.to_i(16).to_s(base))
|
49
|
+
end
|
50
|
+
|
36
51
|
def base36
|
37
|
-
|
52
|
+
base(36)
|
38
53
|
end
|
39
54
|
|
40
55
|
# Shorten the digest to the given (optional) length.
|
@@ -127,11 +142,11 @@ module Gibbler
|
|
127
142
|
# If the object is frozen, this will return the value of
|
128
143
|
# <tt>gibbler_cache</tt>.
|
129
144
|
#
|
130
|
-
def gibbler
|
145
|
+
def gibbler(digest_type=nil)
|
131
146
|
#gibbler_debug caller[0]
|
132
147
|
gibbler_debug :GIBBLER, self.class, self
|
133
148
|
return self.gibbler_cache if self.frozen?
|
134
|
-
self.gibbler_cache = Gibbler::Digest.new self.__gibbler
|
149
|
+
self.gibbler_cache = Gibbler::Digest.new self.__gibbler(digest_type)
|
135
150
|
end
|
136
151
|
|
137
152
|
# Has this object been modified?
|
@@ -162,11 +177,11 @@ module Gibbler
|
|
162
177
|
# <b>This is a default method appropriate for only the most
|
163
178
|
# basic objects like Class and Module.</b>
|
164
179
|
#
|
165
|
-
def __gibbler(
|
166
|
-
klass =
|
167
|
-
nom =
|
180
|
+
def __gibbler(digest_type=nil)
|
181
|
+
klass = self.class
|
182
|
+
nom = self.name if self.respond_to?(:name)
|
168
183
|
nom ||= ''
|
169
|
-
a = Gibbler.digest '%s:%s:%s' % [klass, nom.size, nom]
|
184
|
+
a = Gibbler.digest '%s:%s:%s' % [klass, nom.size, nom], digest_type
|
170
185
|
gibbler_debug klass, a, [klass, nom.size, nom]
|
171
186
|
a
|
172
187
|
end
|
@@ -210,8 +225,9 @@ module Gibbler
|
|
210
225
|
# Sends +str+ to Digest::SHA1.hexdigest. If another digest class
|
211
226
|
# has been specified, that class will be used instead.
|
212
227
|
# See: digest_type
|
213
|
-
def self.digest(str)
|
214
|
-
@@gibbler_digest_type
|
228
|
+
def self.digest(str, digest_type=nil)
|
229
|
+
digest_type ||= @@gibbler_digest_type
|
230
|
+
digest_type.hexdigest str
|
215
231
|
end
|
216
232
|
|
217
233
|
def self.gibbler_debug(*args)
|
@@ -282,16 +298,16 @@ module Gibbler
|
|
282
298
|
end
|
283
299
|
|
284
300
|
# Creates a digest for the current state of self.
|
285
|
-
def __gibbler(
|
286
|
-
klass =
|
301
|
+
def __gibbler(digest_type=nil)
|
302
|
+
klass = self.class
|
287
303
|
d = []
|
288
304
|
gibbler_debug :gibbler_fields, gibbler_fields
|
289
305
|
gibbler_fields.each do |n|
|
290
306
|
value = instance_variable_get("@#{n}")
|
291
|
-
d << '%s:%s:%s' % [value.class, n, value.__gibbler]
|
307
|
+
d << '%s:%s:%s' % [value.class, n, value.__gibbler(digest_type)]
|
292
308
|
end
|
293
|
-
d = d.join(':').__gibbler
|
294
|
-
a = Gibbler.digest "%s:%d:%s" % [klass, d.size, d]
|
309
|
+
d = d.join(':').__gibbler(digest_type)
|
310
|
+
a = Gibbler.digest "%s:%d:%s" % [klass, d.size, d], digest_type
|
295
311
|
gibbler_debug klass, a, [klass, d.size, d]
|
296
312
|
a
|
297
313
|
end
|
@@ -330,10 +346,10 @@ module Gibbler
|
|
330
346
|
end
|
331
347
|
|
332
348
|
# Creates a digest for the current state of self.
|
333
|
-
def __gibbler(
|
334
|
-
klass =
|
335
|
-
value =
|
336
|
-
a = Gibbler.digest "%s:%d:%s" % [klass, value.size, value]
|
349
|
+
def __gibbler(digest_type=nil)
|
350
|
+
klass = self.class
|
351
|
+
value = self.nil? ? "\0" : self.to_s
|
352
|
+
a = Gibbler.digest "%s:%d:%s" % [klass, value.size, value], digest_type
|
337
353
|
gibbler_debug klass, a, [klass, value.size, value]
|
338
354
|
a
|
339
355
|
end
|
@@ -365,15 +381,15 @@ module Gibbler
|
|
365
381
|
end
|
366
382
|
|
367
383
|
# Creates a digest for the current state of self.
|
368
|
-
def __gibbler(
|
369
|
-
klass =
|
370
|
-
d =
|
384
|
+
def __gibbler(digest_type=nil)
|
385
|
+
klass = self.class
|
386
|
+
d = self.keys.sort { |a,b| a.inspect <=> b.inspect }
|
371
387
|
d.collect! do |name|
|
372
|
-
value =
|
373
|
-
'%s:%s:%s' % [value.class, name, value.__gibbler]
|
388
|
+
value = self[name]
|
389
|
+
'%s:%s:%s' % [value.class, name, value.__gibbler(digest_type)]
|
374
390
|
end
|
375
|
-
d = d.join(':').__gibbler
|
376
|
-
a = Gibbler.digest '%s:%s:%s' % [klass, d.size, d]
|
391
|
+
d = d.join(':').__gibbler(digest_type)
|
392
|
+
a = Gibbler.digest '%s:%s:%s' % [klass, d.size, d], digest_type
|
377
393
|
gibbler_debug klass, a, [klass, d.size, d]
|
378
394
|
a
|
379
395
|
end
|
@@ -405,15 +421,15 @@ module Gibbler
|
|
405
421
|
end
|
406
422
|
|
407
423
|
# Creates a digest for the current state of self.
|
408
|
-
def __gibbler(
|
409
|
-
klass =
|
424
|
+
def __gibbler(digest_type=nil)
|
425
|
+
klass = self.class
|
410
426
|
d, index = [], 0
|
411
|
-
|
412
|
-
d << '%s:%s:%s' % [value.class, index, value.__gibbler]
|
427
|
+
self.each do |value|
|
428
|
+
d << '%s:%s:%s' % [value.class, index, value.__gibbler(digest_type)]
|
413
429
|
index += 1
|
414
430
|
end
|
415
|
-
d = d.join(':').__gibbler
|
416
|
-
a = Gibbler.digest '%s:%s:%s' % [klass, d.size, d]
|
431
|
+
d = d.join(':').__gibbler(digest_type)
|
432
|
+
a = Gibbler.digest '%s:%s:%s' % [klass, d.size, d], digest_type
|
417
433
|
gibbler_debug klass, a, [klass, d.size, d]
|
418
434
|
a
|
419
435
|
end
|
@@ -441,10 +457,10 @@ module Gibbler
|
|
441
457
|
end
|
442
458
|
|
443
459
|
# Creates a digest for the current state of self.
|
444
|
-
def __gibbler(
|
445
|
-
klass =
|
446
|
-
value =
|
447
|
-
a = Gibbler.digest "%s:%d:%s" % [klass, value.size, value]
|
460
|
+
def __gibbler(digest_type=nil)
|
461
|
+
klass = self.class
|
462
|
+
value = self.nil? ? "\0" : self.utc.strftime('%Y-%m-%d %H:%M:%S UTC')
|
463
|
+
a = Gibbler.digest "%s:%d:%s" % [klass, value.size, value], digest_type
|
448
464
|
gibbler_debug klass, a, [klass, value.size, value]
|
449
465
|
a
|
450
466
|
end
|
@@ -472,10 +488,10 @@ module Gibbler
|
|
472
488
|
end
|
473
489
|
|
474
490
|
# Creates a digest for the current state of self.
|
475
|
-
def __gibbler(
|
476
|
-
klass =
|
477
|
-
value =
|
478
|
-
a = Gibbler.digest "%s:%d:%s" % [klass, value.size, value]
|
491
|
+
def __gibbler(digest_type=nil)
|
492
|
+
klass = self.class
|
493
|
+
value = self.nil? ? "\0" : self.new_offset(0).to_s
|
494
|
+
a = Gibbler.digest "%s:%d:%s" % [klass, value.size, value], digest_type
|
479
495
|
gibbler_debug klass, a, [klass, value.size, value]
|
480
496
|
a
|
481
497
|
end
|
@@ -505,11 +521,11 @@ module Gibbler
|
|
505
521
|
end
|
506
522
|
|
507
523
|
# Creates a digest for the current state of self.
|
508
|
-
def __gibbler(
|
509
|
-
klass =
|
510
|
-
value =
|
511
|
-
size =
|
512
|
-
a = Gibbler.digest "%s:%d:%s" % [klass, size, value]
|
524
|
+
def __gibbler(digest_type=nil)
|
525
|
+
klass = self.class
|
526
|
+
value = self.nil? ? "\0" : self.to_s
|
527
|
+
size = self.nil? ? 0 : self.to_a.size
|
528
|
+
a = Gibbler.digest "%s:%d:%s" % [klass, size, value], digest_type
|
513
529
|
gibbler_debug klass, a, [klass, size, value]
|
514
530
|
a
|
515
531
|
end
|
@@ -531,9 +547,9 @@ module Gibbler
|
|
531
547
|
end
|
532
548
|
|
533
549
|
# Creates a digest for the current state of self.
|
534
|
-
def __gibbler(
|
535
|
-
klass =
|
536
|
-
a = Gibbler.digest "%s:%s" % [klass, "\0"]
|
550
|
+
def __gibbler(digest_type=nil)
|
551
|
+
klass = self.class
|
552
|
+
a = Gibbler.digest "%s:%s" % [klass, "\0"], digest_type
|
537
553
|
gibbler_debug klass, a, [klass, "\0"]
|
538
554
|
a
|
539
555
|
end
|
@@ -566,10 +582,10 @@ module Gibbler
|
|
566
582
|
end
|
567
583
|
|
568
584
|
# Creates a digest for the current state of self.
|
569
|
-
def __gibbler(
|
570
|
-
klass =
|
571
|
-
value =
|
572
|
-
a = Gibbler.digest "%s:%d:%s" % [klass, value.size, value]
|
585
|
+
def __gibbler(digest_type=nil)
|
586
|
+
klass = self.class
|
587
|
+
value = self.nil? ? "\0" : self.path
|
588
|
+
a = Gibbler.digest "%s:%d:%s" % [klass, value.size, value], digest_type
|
573
589
|
gibbler_debug klass, a, [klass, value.size, value]
|
574
590
|
a
|
575
591
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gibbler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Delano Mandelbaum
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-
|
12
|
+
date: 2010-04-08 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|