gibbler 0.5.4 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.txt +11 -1
- data/README.rdoc +17 -10
- data/gibbler.gemspec +1 -1
- data/lib/gibbler/object.rb +22 -0
- data/lib/gibbler.rb +93 -72
- data/tryouts/10_basic_tryouts.rb +7 -1
- data/tryouts/11_basic_sha256_tryouts.rb +13 -13
- metadata +2 -2
data/CHANGES.txt
CHANGED
@@ -1,11 +1,21 @@
|
|
1
1
|
GIBBLER, CHANGES
|
2
2
|
|
3
3
|
|
4
|
+
#### 0.6.0 (2009-07-20) #################################
|
5
|
+
|
6
|
+
NOTE: Digest calculation for Proc and Class objects have changed.
|
7
|
+
Digests created for these types will not match previous releases.
|
8
|
+
|
9
|
+
* FIXED: Proc digests no longer refer to Proc#binding
|
10
|
+
* CHANGE: The Gibbler module now raises an exception if it's included
|
11
|
+
* CHANGE: Module and Class now use the default Gibbler::Object digest
|
12
|
+
* ADDED: Gibbler::Object now contains a default digest method
|
13
|
+
|
14
|
+
|
4
15
|
#### 0.5.4 (2009-07-17) #################################
|
5
16
|
|
6
17
|
* FIXED: Improved support for Symbol and Fixnum objects with Attic 0.4
|
7
18
|
|
8
|
-
|
9
19
|
#### 0.5.3 (2009-07-12) #################################
|
10
20
|
|
11
21
|
* FIXED: Updated gemspec to fix missing files (aliases)
|
data/README.rdoc
CHANGED
@@ -1,9 +1,8 @@
|
|
1
|
-
= Gibbler - v0.
|
1
|
+
= Gibbler - v0.6 ALPHA
|
2
2
|
|
3
|
-
Git-like hashes and history for Ruby objects.
|
4
|
-
|
5
|
-
NOTE: Gibbler supports Ruby 1.8, 1.9 and JRuby.
|
3
|
+
Git-like hashes and history for Ruby objects for Ruby 1.8, 1.9 and JRuby.
|
6
4
|
|
5
|
+
<b>NOTE: Digests changed in the 0.6 release for Class, Module, and Proc objects. See "News" below for more info.</b>
|
7
6
|
|
8
7
|
== Example 1 -- Basic Usage
|
9
8
|
|
@@ -122,26 +121,34 @@ Gibbler::String creates a digest based on the name of the class and the output o
|
|
122
121
|
|
123
122
|
== ALPHA Notice
|
124
123
|
|
125
|
-
This code is hella fresh (est 2009-06-25). It's barely tested and the interface may change, but it's fun to play with. I'll happily accept patches.
|
124
|
+
This code is hella fresh (est 2009-06-25). It's barely tested and the interface may change, but it's fun to play with. I'll happily accept patches. Some things to keep in mind:
|
126
125
|
|
127
|
-
|
126
|
+
* 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.
|
127
|
+
* Digest calculation may change between non-trivial releases.
|
128
|
+
* There has been very little testing for concurrency issues. (Anyone interested?)
|
128
129
|
|
129
130
|
|
130
131
|
== News
|
131
132
|
|
132
|
-
=== 2009-07-
|
133
|
+
=== 2009-07-20: Digest change for instances of Class, Module, and Proc
|
133
134
|
|
134
|
-
|
135
|
+
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.
|
135
136
|
|
137
|
+
* 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>
|
138
|
+
* 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.
|
136
139
|
|
137
|
-
|
140
|
+
Also note that this change affects the digests for Hashes and Arrays that contain instances of Class, Module, or Proc.
|
138
141
|
|
139
|
-
|
142
|
+
=== 2009-07-17: Improved support for Symbol and Fixnum
|
143
|
+
|
144
|
+
With the upgrade to Attic 0.4, the gibbled? method and object history is now available for Symbol and Fixnum objects.
|
140
145
|
|
141
146
|
|
142
147
|
== Known Issues
|
143
148
|
|
144
149
|
* gibbler or gibbled? must be called at least once before gibbled? will be able to return a useful value (otherwise there is no previous digest value to compare to)
|
150
|
+
* Digests for Bignum objects are different between (MRI) Ruby and JRuby. Does anyone know why?
|
151
|
+
* Digests for Proc objects are different between Ruby 1.8 and 1.9 because Proc.arity returns different values and 1.8 has no lambda? method.
|
145
152
|
|
146
153
|
|
147
154
|
== Installation
|
data/gibbler.gemspec
CHANGED
data/lib/gibbler/object.rb
CHANGED
@@ -4,6 +4,11 @@ module Gibbler
|
|
4
4
|
|
5
5
|
module Object
|
6
6
|
|
7
|
+
def self.included(obj)
|
8
|
+
obj.extend Attic
|
9
|
+
obj.attic :__gibbler_cache
|
10
|
+
end
|
11
|
+
|
7
12
|
# Calculates a digest for the current object instance.
|
8
13
|
# Objects that are a kind of Hash or Array are processed
|
9
14
|
# recursively. The length of the returned String depends
|
@@ -31,6 +36,23 @@ module Gibbler
|
|
31
36
|
p args
|
32
37
|
end
|
33
38
|
|
39
|
+
# Creates a digest for the current state of self based on:
|
40
|
+
# * Object#class
|
41
|
+
# * Length of Object#name || ''
|
42
|
+
# * Object#name || ''
|
43
|
+
#
|
44
|
+
# e.g. Digest::SHA1.hexdigest "Class:6:Object" #=>
|
45
|
+
#
|
46
|
+
# <b>This is a default method appropriate for only the most
|
47
|
+
# basic objects like Class and Module.</b>
|
48
|
+
#
|
49
|
+
def __gibbler(h=self)
|
50
|
+
klass = h.class
|
51
|
+
nom = h.name || ''
|
52
|
+
a = Gibbler.digest '%s:%s:%s' % [klass, nom.size, nom]
|
53
|
+
gibbler_debug klass, a, [klass, nom.size, nom]
|
54
|
+
a
|
55
|
+
end
|
34
56
|
end
|
35
57
|
|
36
58
|
end
|
data/lib/gibbler.rb
CHANGED
@@ -13,7 +13,7 @@ module Gibbler
|
|
13
13
|
#include Attic
|
14
14
|
extend Attic
|
15
15
|
|
16
|
-
VERSION = "0.
|
16
|
+
VERSION = "0.6.0"
|
17
17
|
|
18
18
|
require 'gibbler/object'
|
19
19
|
require 'gibbler/digest'
|
@@ -53,6 +53,33 @@ module Gibbler
|
|
53
53
|
p args
|
54
54
|
end
|
55
55
|
|
56
|
+
# Raises an exception. The correct usage is to include a Gibbler::Object:
|
57
|
+
# * Gibbler::Complex
|
58
|
+
# * Gibbler::String
|
59
|
+
# * Gibbler::Object
|
60
|
+
# * etc ...
|
61
|
+
def self.included(obj)
|
62
|
+
raise "You probably want to include Gibbler::Complex or Gibbler::Object"
|
63
|
+
end
|
64
|
+
|
65
|
+
# Creates a digest based on:
|
66
|
+
# * An Array of instance variable names and values in the format: <tt>CLASS:LENGTH:VALUE</tt>
|
67
|
+
# * The gibbler method is called on each element so if it is a Hash or Array etc it
|
68
|
+
# will be parsed recursively according to the gibbler method for that class type.
|
69
|
+
# * Digest the Array of digests
|
70
|
+
# * Return the digest for <tt>class:length:value</tt> where:
|
71
|
+
# * "class" is equal to the current object class (e.g. FullHouse).
|
72
|
+
# * "length" is the size of the Array of digests (which should equal
|
73
|
+
# the number of instance variables in the object).
|
74
|
+
# * "value" is the Array of digests joined with a colon (":").
|
75
|
+
#
|
76
|
+
# This method can be used by any class which stores values in instance variables.
|
77
|
+
#
|
78
|
+
# class Episodes
|
79
|
+
# include Gibbler::Complex
|
80
|
+
# attr_accessor :season, :year, :cast
|
81
|
+
# end
|
82
|
+
#
|
56
83
|
module Complex
|
57
84
|
include Gibbler::Object
|
58
85
|
|
@@ -61,19 +88,7 @@ module Gibbler
|
|
61
88
|
obj.attic :__gibbler_cache
|
62
89
|
end
|
63
90
|
|
64
|
-
# Creates a digest
|
65
|
-
# * An Array of instance variable names and values in the format: <tt>CLASS:LENGTH:VALUE</tt>
|
66
|
-
# * The gibbler method is called on each element so if it is a Hash or Array etc it
|
67
|
-
# will be parsed recursively according to the gibbler method for that class type.
|
68
|
-
# * Digest the Array of digests
|
69
|
-
# * Return the digest for <tt>class:length:value</tt> where:
|
70
|
-
# * "class" is equal to the current object class (e.g. FullHouse).
|
71
|
-
# * "length" is the size of the Array of digests (which should equal
|
72
|
-
# the number of instance variables in the object).
|
73
|
-
# * "value" is the Array of digests joined with a colon (":").
|
74
|
-
#
|
75
|
-
# This method can be used by any class which stores values in instance variables.
|
76
|
-
#
|
91
|
+
# Creates a digest for the current state of self.
|
77
92
|
def __gibbler(h=self)
|
78
93
|
klass = h.class
|
79
94
|
d = []
|
@@ -97,6 +112,21 @@ module Gibbler
|
|
97
112
|
|
98
113
|
end
|
99
114
|
|
115
|
+
# Creates a digest based on: <tt>CLASS:LENGTH:VALUE</tt>.
|
116
|
+
# This method can be used for any class where the <tt>to_s</tt>
|
117
|
+
# method returns an appropriate unique value for this instance.
|
118
|
+
# It's used by default for Symbol, Class, Fixnum, and Bignum.
|
119
|
+
# e.g.
|
120
|
+
#
|
121
|
+
# "str" => String:3:str => 509a839ca1744c72e37759e7684ff0daa3b61427
|
122
|
+
# :sym => Symbol:3:sym => f3b7b3ca9529002c6826b1ef609d3583c356c8c8
|
123
|
+
#
|
124
|
+
# To use use method in other classes simply:
|
125
|
+
#
|
126
|
+
# class MyStringLikeClass
|
127
|
+
# include Gibbler::String
|
128
|
+
# end
|
129
|
+
#
|
100
130
|
module String
|
101
131
|
include Gibbler::Object
|
102
132
|
|
@@ -105,21 +135,7 @@ module Gibbler
|
|
105
135
|
obj.attic :__gibbler_cache
|
106
136
|
end
|
107
137
|
|
108
|
-
# Creates a digest
|
109
|
-
# This method can be used for any class where the <tt>to_s</tt>
|
110
|
-
# method returns an appropriate unique value for this instance.
|
111
|
-
# It's used by default for Symbol, Class, Fixnum, and Bignum.
|
112
|
-
# e.g.
|
113
|
-
#
|
114
|
-
# "str" => String:3:str => 509a839ca1744c72e37759e7684ff0daa3b61427
|
115
|
-
# :sym => Symbol:3:sym => f3b7b3ca9529002c6826b1ef609d3583c356c8c8
|
116
|
-
#
|
117
|
-
# To use use method in other classes simply:
|
118
|
-
#
|
119
|
-
# class MyClass
|
120
|
-
# include Gibbler::String
|
121
|
-
# end
|
122
|
-
#
|
138
|
+
# Creates a digest for the current state of self.
|
123
139
|
def __gibbler(h=self)
|
124
140
|
klass = h.class
|
125
141
|
value = h.nil? ? "\0" : h.to_s
|
@@ -128,7 +144,24 @@ module Gibbler
|
|
128
144
|
a
|
129
145
|
end
|
130
146
|
end
|
131
|
-
|
147
|
+
|
148
|
+
# Creates a digest based on:
|
149
|
+
# * parse each key, value pair into an Array containing keys: <tt>CLASS:KEY:VALUE.__gibbler</tt>
|
150
|
+
# * The gibbler method is called on each element so if it is a Hash or Array etc it
|
151
|
+
# will be parsed recursively according to the gibbler method for that class type.
|
152
|
+
# * Digest the Array of digests
|
153
|
+
# * Return the digest for <tt>class:length:value</tt> where:
|
154
|
+
# * "class" is equal to the current object class (e.g. Hash).
|
155
|
+
# * "length" is the size of the Array of digests (which should equal
|
156
|
+
# the number of keys in the original Hash object).
|
157
|
+
# * "value" is the Array of digests joined with a colon (":").
|
158
|
+
#
|
159
|
+
# This method can be used by any class with a <tt>keys</tt> method.
|
160
|
+
#
|
161
|
+
# class MyOrderedHash
|
162
|
+
# include Gibbler::Hash
|
163
|
+
# end
|
164
|
+
#
|
132
165
|
module Hash
|
133
166
|
include Gibbler::Object
|
134
167
|
|
@@ -137,25 +170,7 @@ module Gibbler
|
|
137
170
|
obj.attic :__gibbler_cache
|
138
171
|
end
|
139
172
|
|
140
|
-
# Creates a digest
|
141
|
-
# * parse each key, value pair into an Array containing keys: <tt>CLASS:KEY:VALUE.__gibbler</tt>
|
142
|
-
# * The gibbler method is called on each element so if it is a Hash or Array etc it
|
143
|
-
# will be parsed recursively according to the gibbler method for that class type.
|
144
|
-
# * Digest the Array of digests
|
145
|
-
# * Return the digest for <tt>class:length:value</tt> where:
|
146
|
-
# * "class" is equal to the current object class (e.g. Hash).
|
147
|
-
# * "length" is the size of the Array of digests (which should equal
|
148
|
-
# the number of keys in the original Hash object).
|
149
|
-
# * "value" is the Array of digests joined with a colon (":").
|
150
|
-
#
|
151
|
-
# This method can be used by any class with a <tt>keys</tt> method.
|
152
|
-
#
|
153
|
-
# e.g.
|
154
|
-
#
|
155
|
-
# class OrderedHash
|
156
|
-
# include Gibbler::Hash
|
157
|
-
# end
|
158
|
-
#
|
173
|
+
# Creates a digest for the current state of self.
|
159
174
|
def __gibbler(h=self)
|
160
175
|
klass = h.class
|
161
176
|
d = h.keys.sort { |a,b| a.inspect <=> b.inspect }
|
@@ -170,6 +185,23 @@ module Gibbler
|
|
170
185
|
end
|
171
186
|
end
|
172
187
|
|
188
|
+
# Creates a digest based on:
|
189
|
+
# * parse each element into an Array of digests like: <tt>CLASS:INDEX:VALUE.__gibbler</tt>
|
190
|
+
# * The gibbler method is called on each element so if it is a Hash or Array etc it
|
191
|
+
# will be parsed recursively according to the gibbler method for that class type.
|
192
|
+
# * Digest the Array of digests
|
193
|
+
# * Return the digest for <tt>class:length:value</tt> where:
|
194
|
+
# * "class" is equal to the current object class (e.g. Array).
|
195
|
+
# * "length" is the size of the Array of digests (which should equal
|
196
|
+
# the number of elements in the original Array object).
|
197
|
+
# * "value" is the Array of digests joined with a colon (":").
|
198
|
+
#
|
199
|
+
# This method can be used by any class with an <tt>each</tt> method.
|
200
|
+
#
|
201
|
+
# class MyNamedArray
|
202
|
+
# include Gibbler::Array
|
203
|
+
# end
|
204
|
+
#
|
173
205
|
module Array
|
174
206
|
include Gibbler::Object
|
175
207
|
|
@@ -178,25 +210,7 @@ module Gibbler
|
|
178
210
|
obj.attic :__gibbler_cache
|
179
211
|
end
|
180
212
|
|
181
|
-
# Creates a digest
|
182
|
-
# * parse each element into an Array of digests like: <tt>CLASS:INDEX:VALUE.__gibbler</tt>
|
183
|
-
# * The gibbler method is called on each element so if it is a Hash or Array etc it
|
184
|
-
# will be parsed recursively according to the gibbler method for that class type.
|
185
|
-
# * Digest the Array of digests
|
186
|
-
# * Return the digest for <tt>class:length:value</tt> where:
|
187
|
-
# * "class" is equal to the current object class (e.g. Array).
|
188
|
-
# * "length" is the size of the Array of digests (which should equal
|
189
|
-
# the number of elements in the original Array object).
|
190
|
-
# * "value" is the Array of digests joined with a colon (":").
|
191
|
-
#
|
192
|
-
# This method can be used by any class with an <tt>each</tt> method.
|
193
|
-
#
|
194
|
-
# e.g.
|
195
|
-
#
|
196
|
-
# class NamedArray
|
197
|
-
# include Gibbler::Array
|
198
|
-
# end
|
199
|
-
#
|
213
|
+
# Creates a digest for the current state of self.
|
200
214
|
def __gibbler(h=self)
|
201
215
|
klass = h.class
|
202
216
|
d, index = [], 0
|
@@ -214,7 +228,7 @@ module Gibbler
|
|
214
228
|
# Return the digest for <tt>class:arity:binding</tt>, where:
|
215
229
|
# * class is the current class name (e.g. Proc)
|
216
230
|
# * arity is the value returned by <tt>Proc#arity</tt>
|
217
|
-
# *
|
231
|
+
# * value of lambda? if available (Ruby 1.9) or false otherwise
|
218
232
|
#
|
219
233
|
# This method can be used by any subclass of Proc.
|
220
234
|
#
|
@@ -235,14 +249,17 @@ module Gibbler
|
|
235
249
|
obj.attic :__gibbler_cache
|
236
250
|
end
|
237
251
|
|
252
|
+
# Creates a digest for the current state of self.
|
238
253
|
def __gibbler(h=self)
|
239
254
|
klass = h.class
|
240
|
-
|
241
|
-
|
255
|
+
is_lambda = h.respond_to?(:lambda?) ? h.lambda? : false
|
256
|
+
a = Gibbler.digest '%s:%s:%s' % [klass, h.arity, is_lambda]
|
257
|
+
gibbler_debug klass, a, [klass, h.arity, is_lambda]
|
242
258
|
a
|
243
259
|
end
|
244
260
|
end
|
245
261
|
|
262
|
+
|
246
263
|
##--
|
247
264
|
## NOTE: this was used when Gibbler supported "include Gibbler". We
|
248
265
|
## now recommend the "include Gibbler::String" approach. This was an
|
@@ -288,7 +305,11 @@ class Symbol
|
|
288
305
|
end
|
289
306
|
|
290
307
|
class Class
|
291
|
-
include Gibbler::
|
308
|
+
include Gibbler::Object
|
309
|
+
end
|
310
|
+
|
311
|
+
class Module
|
312
|
+
include Gibbler::Object
|
292
313
|
end
|
293
314
|
|
294
315
|
class Fixnum
|
data/tryouts/10_basic_tryouts.rb
CHANGED
@@ -1,11 +1,17 @@
|
|
1
1
|
|
2
|
-
library :gibbler,
|
2
|
+
library :gibbler, 'lib'
|
3
3
|
group "Gibbler Gazette"
|
4
4
|
|
5
5
|
Gibbler.enable_debug if Tryouts.verbose > 3
|
6
6
|
|
7
7
|
tryouts "Basic syntax with SHA1" do
|
8
8
|
|
9
|
+
dream :exception, RuntimeError
|
10
|
+
drill "include Gibbler raises exception" do
|
11
|
+
a = Class.new
|
12
|
+
a.send :include, Gibbler
|
13
|
+
end
|
14
|
+
|
9
15
|
dream :respond_to?, :gibbler
|
10
16
|
dream :gibbler, '52be7494a602d85ff5d8a8ab4ffe7f1b171587df'
|
11
17
|
drill "Symbol can gibbler", :kimmy
|
@@ -7,33 +7,33 @@ Gibbler.enable_debug if Tryouts.verbose > 3
|
|
7
7
|
|
8
8
|
tryouts "Basic syntax with SHA256" do
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
setup do
|
11
|
+
# NOTE: JRuby requires that we use OpenSSL::Digest::SHA256
|
12
|
+
if Tryouts.sysinfo.vm == :java
|
13
|
+
require 'openssl'
|
13
14
|
Gibbler.digest_type = OpenSSL::Digest::SHA256
|
14
|
-
|
15
|
-
else
|
16
|
-
drill "Can change Digest type", Digest::SHA256 do
|
15
|
+
else
|
17
16
|
Gibbler.digest_type = Digest::SHA256
|
18
17
|
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
clean do
|
22
|
+
Gibbler.digest_type = Digest::SHA1
|
19
23
|
end
|
20
24
|
|
21
|
-
dream :respond_to?, :gibbler
|
22
25
|
dream :gibbler, '754f87ca720ec256633a286d9270d68478850b2abd7b0ae65021cb769ae70c08'
|
23
26
|
drill "A Symbol can gibbler", :anything
|
24
27
|
|
25
|
-
dream :respond_to?, :gibbler
|
26
28
|
dream :gibbler, 'd345c0afb4e8da0133a3946d3bd9b2622b0acdd8d6cc1237470cc637a9e4777f'
|
27
29
|
drill "Class can gibbler", Class
|
28
30
|
|
29
|
-
dream :
|
31
|
+
dream :gibbler, 'b7b874a9bff7825caa57750a900652354ac601b77497b694d313f658c69d25b4'
|
32
|
+
drill "TrueClass can gibbler", TrueClass
|
33
|
+
|
30
34
|
dream :gibbler, '88d2bcbd68ce593fd2e0e06f276f7301357516291b95c0c53038e61a9bf091e5'
|
31
35
|
drill "Empty Hash instance", {}
|
32
36
|
|
33
|
-
drill "Can return Digest type", Digest::SHA1 do
|
34
|
-
Gibbler.digest_type = Digest::SHA1
|
35
|
-
end
|
36
|
-
|
37
37
|
end
|
38
38
|
|
39
39
|
|
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.6.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: 2009-07-
|
12
|
+
date: 2009-07-20 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|